diff --git a/.gitignore b/.gitignore index ecbcef676bc..7186bd12f08 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ .*.swp *.ninja .ninja_* +*.mri +*.mri.tpl .gdb_history .vs/ errmsg.sys @@ -88,7 +90,7 @@ mysql-test/lib/My/SafeProcess/my_safe_process mysql-test/lib/My/SafeProcess/wsrep_check_version mysql-test/mtr mysql-test/mysql-test-run -mysql-test/var +mysql-test/var* mysql-test-gcov.err mysql-test-gcov.msg mysys/test_hash diff --git a/.gitmodules b/.gitmodules index eeee4802b2b..18bcb465fa2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ [submodule "storage/maria/libmarias3"] path = storage/maria/libmarias3 url = https://github.com/mariadb-corporation/libmarias3.git +[submodule "storage/columnstore/columnstore"] + path = storage/columnstore/columnstore + url = https://github.com/mariadb-corporation/mariadb-columnstore-engine.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d85d565e52..c52d6621bb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) IF(POLICY CMP0022) CMAKE_POLICY(SET CMP0022 NEW) ENDIF() +IF(POLICY CMP0048) + CMAKE_POLICY(SET CMP0048 NEW) +ENDIF() IF(POLICY CMP0054) CMAKE_POLICY(SET CMP0054 NEW) ENDIF() @@ -170,7 +173,6 @@ INCLUDE(systemd) INCLUDE(mysql_add_executable) INCLUDE(symlinks) INCLUDE(compile_flags) -INCLUDE(crc32) INCLUDE(pmem) # Handle options @@ -239,6 +241,9 @@ IF (WITH_MSAN) MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=memory -fsanitize-memory-track-origins -U_FORTIFY_SOURCE" DEBUG RELWITHDEBINFO) ENDIF() +# Be nice to profilers etc +MY_CHECK_AND_SET_COMPILER_FLAG("-fno-omit-frame-pointer" RELWITHDEBINFO) + # enable security hardening features, like most distributions do # in our benchmarks that costs about ~1% of performance, depending on the load OPTION(SECURITY_HARDENED "Use security-enhancing compiler features (stack protector, relro, etc)" ON) @@ -420,7 +425,7 @@ INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb) INCLUDE(cpack_rpm) INCLUDE(cpack_deb) -SET(PYTHON_SHEBANG "/usr/bin/env python" CACHE STRING "python shebang") +SET(PYTHON_SHEBANG "/usr/bin/env python3" CACHE STRING "python shebang") MARK_AS_ADVANCED(PYTHON_SHEBANG) # Add storage engines and plugins. diff --git a/client/mysql.cc b/client/mysql.cc index 99b4efc7012..dcd9dfecef9 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -92,6 +92,9 @@ extern "C" { #include #else #include +#if !defined(USE_LIBEDIT_INTERFACE) +#include +#endif #define HAVE_READLINE #define USE_POPEN #endif @@ -1043,22 +1046,6 @@ static const char *embedded_server_groups[]= { "server", "embedded", "mysql_SERVER", "mariadb_SERVER", 0 }; #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 (); static void fix_history(String *final_command); @@ -1300,8 +1287,8 @@ sig_handler mysql_end(int sig) { #ifndef _WIN32 /* - Ingnoring SIGQUIT and SIGINT signals when cleanup process starts. - This will help in resolving the double free issues, which occures in case + Ignoring SIGQUIT and SIGINT 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); @@ -4733,7 +4720,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, /* CLIENT_PROGRESS_OBSOLETE is set only if we requested it in mysql_real_connect() and the server also supports it - */ +*/ if (mysql.client_flag & CLIENT_PROGRESS_OBSOLETE) mysql_options(&mysql, MYSQL_PROGRESS_CALLBACK, (void*) report_progress); #else @@ -4802,7 +4789,7 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",mysql_thread_id(&mysql)); /* Don't remove "limit 1", - it is protection againts SQL_SELECT_LIMIT=0 + it is protection against SQL_SELECT_LIMIT=0 */ if (!mysql_store_result_for_lazy(&result)) { @@ -5151,7 +5138,7 @@ static const char *construct_prompt() time_t lclock = time(NULL); // Get the date struct struct tm *t = localtime(&lclock); - /* parse thru the settings for the prompt */ + /* parse through the settings for the prompt */ for (char *c = current_prompt; *c ; c++) { if (*c != PROMPT_CHAR) diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index 15bbc71183d..eddae6114e6 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -1024,7 +1024,7 @@ static int find_plugin(char *tp_path) /** - Build the boostrap file. + Build the bootstrap file. Create a new file and populate it with SQL commands to ENABLE or DISABLE the plugin via REPLACE and DELETE operations on the mysql.plugin table. @@ -1153,7 +1153,7 @@ exit: Create a command line sequence to launch mysqld in bootstrap mode. This will allow mysqld to launch a minimal server instance to read and - execute SQL commands from a file piped in (the boostrap file). We use + execute SQL commands from a file piped in (the bootstrap file). We use the --no-defaults option to skip reading values from the config file. The bootstrap mode skips loading of plugins and many other subsystems. diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ed0d9ef8ea4..a93d925db58 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -753,7 +753,7 @@ static bool shall_skip_database(const char *log_dbname) /** Print "use " statement when current db is to be changed. - We have to control emiting USE statements according to rewrite-db options. + We have to control emitting USE statements according to rewrite-db options. We have to do it here (see process_event() below) and to suppress producing USE statements by corresponding log event print-functions. */ @@ -785,7 +785,7 @@ print_use_stmt(PRINT_EVENT_INFO* pinfo, const Query_log_event *ev) // In case of rewrite rule print USE statement for db_to my_fprintf(result_file, "use %`s%s\n", db_to, pinfo->delimiter); - // Copy the *original* db to pinfo to suppress emiting + // Copy the *original* db to pinfo to suppress emitting // of USE stmts by log_event print-functions. memcpy(pinfo->db, db, db_len + 1); } diff --git a/client/mysqldump.c b/client/mysqldump.c index 161485ca125..4830a6c782b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -147,7 +147,7 @@ static char * opt_mysql_unix_port=0; static int first_error=0; /* multi_source is 0 if old server or 2 if server that support multi source - This is choosen this was as multi_source has 2 extra columns first in + This is chosen this was as multi_source has 2 extra columns first in SHOW ALL SLAVES STATUS. */ static uint multi_source= 0; @@ -2075,7 +2075,7 @@ static void print_xml_tag(FILE * xml_file, const char* sbeg, NOTE sval MUST be a NULL terminated string. - sval string will be qouted before output. + sval string will be quoted before output. */ static void print_xml_null_tag(FILE * xml_file, const char* sbeg, @@ -2147,7 +2147,7 @@ static void print_xml_cdata(FILE *xml_file, const char *str, ulong len) Print tag with many attribute to the xml_file. Format is: \t\t NOTE - All atributes and values will be quoted before output. + All attributes and values will be quoted before output. */ static void print_xml_row(FILE *xml_file, const char *row_name, @@ -2632,7 +2632,7 @@ static uint dump_routines_for_db(char *db) print_comment(sql_file, 1, "-- does %s have permissions on mysql.proc?\n\n", fix_for_comment(current_user)); - maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", + maybe_die(EX_MYSQLERR,"%s has insufficient privileges to %s!", current_user, query_buff); } else if (strlen(row[2])) @@ -4187,7 +4187,7 @@ static void dump_table(char *table, char *db, const uchar *hash_key, size_t len) } } - /* XML - close table tag and supress regular output */ + /* XML - close table tag and suppress regular output */ if (opt_xml) fputs("\t\n", md_result_file); else if (extended_insert && row_break) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 9e197e4e199..6cb32da2239 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -581,7 +581,7 @@ static char *field_escape(char *to,const char *from,uint length) else { if (*from == '\'' && !end_backslashes) - *to++= *from; /* We want a dublicate of "'" for MySQL */ + *to++= *from; /* We want a duplicate of "'" for MySQL */ end_backslashes=0; } } diff --git a/client/mysqlslap.c b/client/mysqlslap.c index ff08a8565c1..75cd7f14846 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -2283,7 +2283,7 @@ slap_connect(MYSQL *mysql) opt_mysql_unix_port, connect_flags)) { - /* Connect suceeded */ + /* Connect succeeded */ connect_error= 0; break; } diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 150c99f80c4..79ca4ed60e7 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -146,7 +146,7 @@ struct property { my_bool *var; /* Actual variable */ my_bool set; /* Has been set for ONE command */ my_bool old; /* If set, thus is the old value */ - my_bool reverse; /* Varible is true if disabled */ + my_bool reverse; /* Variable is true if disabled */ const char *env_name; /* Env. variable name */ }; @@ -566,7 +566,7 @@ DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */ Temporary storage areas for substitutions. To reduce unnessary copying and memory freeing/allocation, we pre-allocate two buffers, and alternate their use, one for input/one for output, the roles changing on the next -st_regex substition. At the end of substitutions buf points to the +st_regex substitution. At the end of substitutions buf points to the one containing the final result. */ char* buf; @@ -587,9 +587,10 @@ ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code); ATTRIBUTE_NORETURN -void really_die(const char *msg); +static void really_die(const char *msg); void report_or_die(const char *fmt, ...); -void die(const char *fmt, ...); +ATTRIBUTE_NORETURN +static void die(const char *fmt, ...); static void make_error_message(char *buf, size_t len, const char *fmt, va_list args); ATTRIBUTE_NORETURN ATTRIBUTE_FORMAT(printf, 1, 2) void abort_not_supported_test(const char *fmt, ...); @@ -1461,7 +1462,7 @@ void free_used_memory() } -static void cleanup_and_exit(int exit_code) +ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code) { free_used_memory(); @@ -1540,7 +1541,7 @@ static void make_error_message(char *buf, size_t len, const char *fmt, va_list a s+= my_snprintf(s, end -s, "\n"); } -void die(const char *fmt, ...) +static void die(const char *fmt, ...) { char buff[DIE_BUFF_SIZE]; va_list args; @@ -1549,7 +1550,7 @@ void die(const char *fmt, ...) really_die(buff); } -void really_die(const char *msg) +static void really_die(const char *msg) { static int dying= 0; fflush(stdout); @@ -3094,7 +3095,7 @@ void open_file(const char *name) strxnmov(buff, sizeof(buff), opt_overlay_dir, suffix, name, NullS); /* - Overlayed rty/include/thing.inc can contain the line + Overlaid rty/include/thing.inc can contain the line --source thing.inc which would mean to include qwe/include/thing.inc. But it looks like including "itself", so don't try to open the file, @@ -4802,7 +4803,7 @@ int do_save_master_pos() mysql_errno(mysql), mysql_error(mysql)); if (!(res = mysql_store_result(mysql))) - die("mysql_store_result() retuned NULL for '%s'", query); + die("mysql_store_result() returned NULL for '%s'", query); if (!(row = mysql_fetch_row(res))) die("empty result in show master status"); strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1); @@ -5349,7 +5350,7 @@ void do_get_errcodes(struct st_command *command) p++; } - /* Convert the sting to int */ + /* Convert the string to int */ if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val)) die("Invalid argument to error: '%s'", command->first_argument); @@ -5741,7 +5742,7 @@ int connect_n_handle_errors(struct st_command *command, dynstr_append_mem(ds, delimiter, delimiter_length); dynstr_append_mem(ds, "\n", 1); } - /* Simlified logging if enabled */ + /* Simplified logging if enabled */ if (!disable_connect_log && !disable_query_log) { replace_dynstr_append(ds, command->query); @@ -7710,6 +7711,28 @@ void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows, } +#ifndef EMBEDDED_LIBRARY +static const char *trking_info_desc[SESSION_TRACK_END + 1]= +{ + "Tracker : SESSION_TRACK_SYSTEM_VARIABLES\n", + "Tracker : SESSION_TRACK_SCHEMA\n", + "Tracker : SESSION_TRACK_STATE_CHANGE\n", + "Tracker : SESSION_TRACK_GTIDS\n", + "Tracker : SESSION_TRACK_TRANSACTION_CHARACTERISTICS\n", + "Tracker : SESSION_TRACK_TRANSACTION_TYPE\n" +#ifdef USER_VAR_TRACKING + , + "Tracker : SESSION_TRACK_MYSQL_RESERVED1\n", + "Tracker : SESSION_TRACK_MYSQL_RESERVED2\n", + "Tracker : SESSION_TRACK_MYSQL_RESERVED3\n", + "Tracker : SESSION_TRACK_MYSQL_RESERVED4\n", + "Tracker : SESSION_TRACK_MYSQL_RESERVED5\n", + "Tracker : SESSION_TRACK_MYSQL_RESERVED6\n", + "Tracker : SESSION_TRACK_USER_VARIABLES\n" +#endif // USER_VAR_TRACKING +}; +#endif // EMBEDDED_LIBRARY + /** @brief Append state change information (received through Ok packet) to the output. @@ -7730,31 +7753,15 @@ static void append_session_track_info(DYNAMIC_STRING *ds, MYSQL *mysql) &data, &data_length)) { dynstr_append(ds, "-- "); - switch (type) + if (type <= SESSION_TRACK_END) { - case SESSION_TRACK_SYSTEM_VARIABLES: - dynstr_append(ds, "Tracker : SESSION_TRACK_SYSTEM_VARIABLES\n"); - break; - case SESSION_TRACK_SCHEMA: - dynstr_append(ds, "Tracker : SESSION_TRACK_SCHEMA\n"); - break; - case SESSION_TRACK_STATE_CHANGE: - dynstr_append(ds, "Tracker : SESSION_TRACK_STATE_CHANGE\n"); - break; - case SESSION_TRACK_GTIDS: - dynstr_append(ds, "Tracker : SESSION_TRACK_GTIDS\n"); - break; - case SESSION_TRACK_TRANSACTION_CHARACTERISTICS: - dynstr_append(ds, "Tracker : SESSION_TRACK_TRANSACTION_CHARACTERISTICS\n"); - break; - case SESSION_TRACK_TRANSACTION_TYPE: - dynstr_append(ds, "Tracker : SESSION_TRACK_TRANSACTION_TYPE\n"); - break; - default: - DBUG_ASSERT(0); - dynstr_append(ds, "\n"); + dynstr_append(ds, trking_info_desc[type]); + } + else + { + DBUG_ASSERT(0); + dynstr_append(ds, "Tracker???\n"); } - dynstr_append(ds, "-- "); dynstr_append_mem(ds, data, data_length); @@ -7766,7 +7773,13 @@ static void append_session_track_info(DYNAMIC_STRING *ds, MYSQL *mysql) &data, &data_length)) { dynstr_append(ds, "\n-- "); - dynstr_append_mem(ds, data, data_length); + if (data == NULL) + { + DBUG_ASSERT(data_length == 0); + dynstr_append_mem(ds, "", sizeof("") - 1); + } + else + dynstr_append_mem(ds, data, data_length); } dynstr_append(ds, "\n\n"); } @@ -8206,7 +8219,7 @@ void handle_no_error(struct st_command *command) SYNPOSIS run_query_stmt mysql - mysql handle - command - currrent command pointer + command - current command pointer query - query string to execute query_len - length query string to execute ds - output buffer where to store result form query @@ -8446,7 +8459,7 @@ end: /* Create a util connection if one does not already exists and use that to run the query - This is done to avoid implict commit when creating/dropping objects such + This is done to avoid implicit commit when creating/dropping objects such as view, sp etc. */ @@ -8487,7 +8500,7 @@ int util_query(MYSQL* org_mysql, const char* query){ SYNPOSIS run_query() mysql mysql handle - command currrent command pointer + command current command pointer flags control the phased/stages of query execution to be performed if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG @@ -10244,7 +10257,7 @@ int multi_reg_replace(struct st_replace_regex* r,char* val) if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace, in_buf, re.icase)) { - /* if the buffer has been reallocated, make adjustements */ + /* if the buffer has been reallocated, make adjustments */ if (save_out_buf != out_buf) { if (save_out_buf == r->even_buf) @@ -10511,7 +10524,7 @@ typedef struct st_rep_set { uint found_len; /* Best match to date */ int found_offset; uint table_offset; - uint size_of_bits; /* For convinience */ + uint size_of_bits; /* For convenience */ } REP_SET; typedef struct st_rep_sets { @@ -10614,7 +10627,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count, DBUG_RETURN(0); } (void) make_new_set(&sets); /* Set starting set */ - make_sets_invisible(&sets); /* Hide previus sets */ + make_sets_invisible(&sets); /* Hide previous sets */ used_sets=-1; word_states=make_new_set(&sets); /* Start of new word */ start_states=make_new_set(&sets); /* This is first state */ diff --git a/cmake/FindBISON.cmake b/cmake/FindBISON.cmake new file mode 100644 index 00000000000..28ae3f8fecb --- /dev/null +++ b/cmake/FindBISON.cmake @@ -0,0 +1,8 @@ +IF(DEFINED BISON_EXECUTABLE) + SET(bison_quiet QUIET) +ENDIF() + +set(orig_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) +unset(CMAKE_MODULE_PATH) +find_package(BISON ${BISON_FIND_VERSION} ${bison_quiet} ${BISON_FIND_REQUIRED}) +set(CMAKE_MODULE_PATH ${orig_CMAKE_MODULE_PATH}) diff --git a/cmake/FindLZ4.cmake b/cmake/FindLZ4.cmake index e97dd63e2b0..46c1fdc1b9f 100644 --- a/cmake/FindLZ4.cmake +++ b/cmake/FindLZ4.cmake @@ -1,9 +1,9 @@ find_path(LZ4_INCLUDE_DIR NAMES lz4.h) -find_library(LZ4_LIBRARY NAMES lz4) +find_library(LZ4_LIBRARIES NAMES lz4) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS( LZ4 DEFAULT_MSG - LZ4_LIBRARY LZ4_INCLUDE_DIR) + LZ4_LIBRARIES LZ4_INCLUDE_DIR) -mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY) +mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARIES) diff --git a/cmake/Findzstd.cmake b/cmake/FindZSTD.cmake similarity index 80% rename from cmake/Findzstd.cmake rename to cmake/FindZSTD.cmake index 8cd4c248145..ede59010742 100644 --- a/cmake/Findzstd.cmake +++ b/cmake/FindZSTD.cmake @@ -5,10 +5,6 @@ # ZSTD_LIBRARIES - List of libraries when using zstd. # ZSTD_FOUND - True if zstd found. -if (DEFINED ZSTD_LIBRARIES) - return() -endif() - find_path(ZSTD_INCLUDE_DIR NAMES zstd.h HINTS ${ZSTD_ROOT_DIR}/include) @@ -18,7 +14,7 @@ find_library(ZSTD_LIBRARIES HINTS ${ZSTD_ROOT_DIR}/lib) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(zstd DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIR) +find_package_handle_standard_args(ZSTD DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIR) mark_as_advanced( ZSTD_LIBRARIES diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index d128416d966..0d4d0ffb445 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -108,6 +108,7 @@ ELSEIF(DEB) SET(WITH_PCRE system CACHE STRING "") ELSE() SET(WITH_SSL bundled CACHE STRING "") + SET(WITH_PCRE bundled CACHE STRING "") SET(WITH_ZLIB bundled CACHE STRING "") SET(WITH_JEMALLOC static CACHE STRING "") SET(PLUGIN_AUTH_SOCKET STATIC CACHE STRING "") @@ -145,7 +146,7 @@ IF(UNIX) RedHat/Fedora/Oracle Linux: yum install libaio-devel SuSE: zypper install libaio-devel - If you really do not want it, pass -DIGNORE_AIO_CHECK to cmake. + If you really do not want it, pass -DIGNORE_AIO_CHECK=ON to cmake. ") ENDIF() diff --git a/cmake/configure.pl b/cmake/configure.pl index a63ce5a483e..c296c5ba4b8 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. # diff --git a/cmake/cpack_deb.cmake b/cmake/cpack_deb.cmake index 22985e5ac56..0539bcdff23 100644 --- a/cmake/cpack_deb.cmake +++ b/cmake/cpack_deb.cmake @@ -6,5 +6,6 @@ IF(DEB) SET(CPACK_COMPONENT_SERVER_GROUP "server") SET(CPACK_COMPONENT_README_GROUP "server") SET(CPACK_COMPONENTS_ALL Server Test SharedLibraries) +SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang") ENDIF(DEB) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 683f8334b88..e988f781e6b 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -249,9 +249,7 @@ ELSEIF(RPM MATCHES "sles") "mariadb-server = %{version}-%{release}" ) ENDIF() -IF(RPM MATCHES "fedora31" OR RPM MATCHES "(rhel|centos)8") - SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang") -ENDIF() +SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang") # If we want to build build MariaDB-shared-compat, # extract compat libraries from MariaDB-shared-5.3 rpm diff --git a/cmake/cpack_source_ignore_files.cmake b/cmake/cpack_source_ignore_files.cmake index 5b103501a99..eb1ec191d17 100644 --- a/cmake/cpack_source_ignore_files.cmake +++ b/cmake/cpack_source_ignore_files.cmake @@ -15,6 +15,7 @@ SET(CPACK_SOURCE_IGNORE_FILES \\\\.git/ +\\\\.git$ \\\\.gitignore$ \\\\.gitattributes$ CMakeCache\\\\.txt$ diff --git a/cmake/crc32.cmake b/cmake/crc32.cmake deleted file mode 100644 index 78d57dec3fb..00000000000 --- a/cmake/crc32.cmake +++ /dev/null @@ -1,36 +0,0 @@ -IF(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64") - IF(CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) - include(CheckCXXSourceCompiles) - - CHECK_CXX_SOURCE_COMPILES(" - #define CRC32CX(crc, value) __asm__(\"crc32cx %w[c], %w[c], %x[v]\":[c]\"+r\"(crc):[v]\"r\"(value)) - asm(\".arch_extension crc\"); - unsigned int foo(unsigned int ret) { - CRC32CX(ret, 0); - return ret; - } - int main() { foo(0); }" HAVE_ARMV8_CRC) - - CHECK_CXX_SOURCE_COMPILES(" - asm(\".arch_extension crypto\"); - unsigned int foo(unsigned int ret) { - __asm__(\"pmull v2.1q, v2.1d, v1.1d\"); - return ret; - } - int main() { foo(0); }" HAVE_ARMV8_CRYPTO) - - CHECK_C_COMPILER_FLAG(-march=armv8-a+crc+crypto HAVE_ARMV8_CRC_CRYPTO_INTRINSICS) - IF(HAVE_ARMV8_CRC_CRYPTO_INTRINSICS) - SET(ARMV8_CRC_COMPILE_FLAGS "${ARMV8_CRC_COMPILE_FLAGS} -march=armv8-a+crc+crypto") - ENDIF() - - SET(CRC32_LIBRARY crc32_armv8_neon) - ADD_SUBDIRECTORY(extra/crc32_armv8_neon) - ENDIF() -ENDIF() - -IF(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64") - SET(HAVE_CRC32_VPMSUM 1) - SET(CRC32_LIBRARY crc32-vpmsum) - ADD_SUBDIRECTORY(extra/crc32-vpmsum) -ENDIF() diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake index 1e29ba685e0..dae3b56b584 100644 --- a/cmake/dtrace.cmake +++ b/cmake/dtrace.cmake @@ -43,7 +43,8 @@ MACRO(CHECK_DTRACE) IF(DTRACE AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD" AND NOT BUGGY_GCC_NO_DTRACE_MODULES AND NOT BUGGY_LINUX_DTRACE - AND NOT CMAKE_SYSTEM_NAME MATCHES "SunOS") + AND NOT CMAKE_SYSTEM_NAME MATCHES "SunOS" + AND NOT WIN32) SET(ENABLE_DTRACE ON CACHE BOOL "Enable dtrace") ENDIF() # On GNU/Hurd, dtrace is not supported diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 9e3549964e1..bbffc80ec0a 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -175,7 +175,7 @@ SET(INSTALL_BINDIR_DEB "bin") SET(INSTALL_SBINDIR_DEB "sbin") SET(INSTALL_SCRIPTDIR_DEB "bin") SET(INSTALL_SYSCONFDIR_DEB "/etc") -SET(INSTALL_SYSCONF2DIR_DEB "/etc/mysql/conf.d") +SET(INSTALL_SYSCONF2DIR_DEB "/etc/mysql/mariadb.conf.d") # SET(INSTALL_LIBDIR_DEB "lib/${CMAKE_CXX_LIBRARY_ARCHITECTURE}") SET(INSTALL_PLUGINDIR_DEB "lib/mysql/plugin") @@ -195,7 +195,7 @@ SET(INSTALL_SUPPORTFILESDIR_DEB "share/mysql") # SET(INSTALL_MYSQLDATADIR_DEB "/var/lib/mysql") -SET(INSTALL_UNIX_ADDRDIR_DEB "/var/run/mysqld/mysqld.sock") +SET(INSTALL_UNIX_ADDRDIR_DEB "/run/mysqld/mysqld.sock") SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d") diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index c7b01bf8429..92a5b9f564d 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -127,7 +127,8 @@ ENDMACRO() # Merge static libraries into a big static lib. The resulting library # should not not have dependencies on other static libraries. -# We use it in MySQL to merge mysys,dbug,vio etc into mysqlclient +# We use it in MariaDB to merge mysys,dbug,vio etc into the embedded server +# mariadbd. MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) # To produce a library we need at least one source file. @@ -164,8 +165,18 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) ENDIF() ENDIF() ENDFOREACH() + # With static libraries the order matter to some linkers. + # REMOVE_DUPLICATES will keep the first entry and because + # the linker requirement we want to keep the last. + IF(STATIC_LIBS) + LIST(REVERSE STATIC_LIBS) + LIST(REMOVE_DUPLICATES STATIC_LIBS) + LIST(REVERSE STATIC_LIBS) + ENDIF() IF(OSLIBS) + LIST(REVERSE OSLIBS) LIST(REMOVE_DUPLICATES OSLIBS) + LIST(REVERSE OSLIBS) TARGET_LINK_LIBRARIES(${TARGET} ${OSLIBS}) ENDIF() @@ -196,18 +207,34 @@ MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) ) ELSE() # Generic Unix, Cygwin or MinGW. In post-build step, call - # script, that extracts objects from archives with "ar x" - # and repacks them with "ar r" + # script, that uses a MRI script to append static archives. + IF(CMAKE_VERSION VERSION_LESS "3.0") + SET(MRI_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.mri") + ELSE() + SET(MRI_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}-$.mri") + ENDIF() + SET(MRI_SCRIPT_TPL "${MRI_SCRIPT}.tpl") + + SET(SCRIPT_CONTENTS "CREATE $\n") + FOREACH(LIB ${STATIC_LIBS}) + SET(SCRIPT_CONTENTS "${SCRIPT_CONTENTS}ADDLIB ${LIB}\n") + ENDFOREACH() + FILE(WRITE ${MRI_SCRIPT_TPL} "${SCRIPT_CONTENTS}\nSAVE\nEND\n") + FILE(GENERATE OUTPUT ${MRI_SCRIPT} INPUT ${MRI_SCRIPT_TPL}) + ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD + DEPENDS ${MRI_SCRIPT} COMMAND ${CMAKE_COMMAND} - -DTARGET_LOCATION="$" - -DTARGET="${TARGET}" - -DSTATIC_LIBS="${STATIC_LIBS}" - -DCMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}" + ARGS + -DTARGET_SCRIPT="${MRI_SCRIPT}" + -DTOP_DIR="${CMAKE_BINARY_DIR}" -DCMAKE_AR="${CMAKE_AR}" - -DCMAKE_RANLIB="${CMAKE_RANLIB}" -P "${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake" + COMMAND ${CMAKE_RANLIB} + ARGS $ ) + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${MRI_SCRIPT_TPL}) + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${MRI_SCRIPT}.mri) ENDIF() ENDIF() ENDMACRO() diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in index f471c6e53d0..941b64c811f 100644 --- a/cmake/make_dist.cmake.in +++ b/cmake/make_dist.cmake.in @@ -58,6 +58,14 @@ IF(GIT_EXECUTABLE) IF(NOT RESULT EQUAL 0) SET(GIT_EXECUTABLE) ENDIF() + EXECUTE_PROCESS( + COMMAND "${GIT_EXECUTABLE}" submodule foreach "${GIT_EXECUTABLE} checkout-index --all --prefix=${PACKAGE_DIR}/storage/columnstore/columnstore/$path/" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/storage/columnstore/columnstore + RESULT_VARIABLE RESULT + ) + IF(NOT RESULT EQUAL 0) + SET(GIT_EXECUTABLE) + ENDIF() ENDIF() CONFIGURE_FILE(${CMAKE_BINARY_DIR}/include/source_revision.h diff --git a/cmake/mariadb_connector_c.cmake b/cmake/mariadb_connector_c.cmake index b15b45acd44..b1d784ff39b 100644 --- a/cmake/mariadb_connector_c.cmake +++ b/cmake/mariadb_connector_c.cmake @@ -43,6 +43,8 @@ ADD_SUBDIRECTORY(libmariadb) IF(UNIX) INSTALL(CODE "EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E make_directory ${INSTALL_BINDIR} + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}) + EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E create_symlink mariadb_config ${INSTALL_BINDIR}/mariadb-config WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX})" COMPONENT Development) diff --git a/cmake/merge_archives_unix.cmake b/cmake/merge_archives_unix.cmake index 09f4fbf2506..a66daddaefc 100644 --- a/cmake/merge_archives_unix.cmake +++ b/cmake/merge_archives_unix.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2009 Sun Microsystems, Inc. +# Copyright (c) 2020 IBM # Use is subject to license terms. # # This program is free software; you can redistribute it and/or modify @@ -14,43 +14,21 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA -FILE(REMOVE "${TARGET_LOCATION}") -SET(TEMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}) -MAKE_DIRECTORY(${TEMP_DIR}) -# Extract each archive to its own subdirectory(avoid object filename clashes) -SEPARATE_ARGUMENTS(STATIC_LIBS UNIX_COMMAND "${STATIC_LIBS}") -FOREACH(LIB ${STATIC_LIBS}) - GET_FILENAME_COMPONENT(NAME_NO_EXT ${LIB} NAME_WE) - SET(TEMP_SUBDIR ${TEMP_DIR}/${NAME_NO_EXT}) - MAKE_DIRECTORY(${TEMP_SUBDIR}) - EXECUTE_PROCESS( - COMMAND ${CMAKE_AR} -x ${LIB} - WORKING_DIRECTORY ${TEMP_SUBDIR} - ) +# MRI scripts have a problem with +. It's a line contination character +# unfortunately there is no escape character. We know we don't have +# "+" in libraries or the MariaDB paths, but Ubuntu CI builds will have +# in their CI path due to the package names that Ubuntu generates. +# So here we replace the fully expanded paths in the TARGET_SCRIPT, +# strip off the TOP_DIR to make it a relative path to the top level directory +# and then execute AR on the top level directory. - FILE(GLOB_RECURSE LIB_OBJECTS "${TEMP_SUBDIR}/*") - SET(OBJECTS ${OBJECTS} ${LIB_OBJECTS}) -ENDFOREACH() +FILE(READ ${TARGET_SCRIPT} SCRIPT_CONTENTS) +STRING(REPLACE "${TOP_DIR}/" "" SCRIPT_CONTENTS_TRIMMED "${SCRIPT_CONTENTS}") +FILE(WRITE "${TARGET_SCRIPT}.mri" ${SCRIPT_CONTENTS_TRIMMED}) -# Use relative paths, makes command line shorter. -GET_FILENAME_COMPONENT(ABS_TEMP_DIR ${TEMP_DIR} ABSOLUTE) -FOREACH(OBJ ${OBJECTS}) - FILE(RELATIVE_PATH OBJ ${ABS_TEMP_DIR} ${OBJ}) - FILE(TO_NATIVE_PATH ${OBJ} OBJ) - SET(ALL_OBJECTS ${ALL_OBJECTS} ${OBJ}) -ENDFOREACH() - -FILE(TO_NATIVE_PATH ${TARGET_LOCATION} ${TARGET_LOCATION}) -# Now pack the objects into library with ar. EXECUTE_PROCESS( - COMMAND ${CMAKE_AR} -r ${TARGET_LOCATION} ${ALL_OBJECTS} - WORKING_DIRECTORY ${TEMP_DIR} + WORKING_DIRECTORY ${TOP_DIR} + COMMAND ${CMAKE_AR} -M + INPUT_FILE ${TARGET_SCRIPT}.mri ) -EXECUTE_PROCESS( - COMMAND ${CMAKE_RANLIB} ${TARGET_LOCATION} - WORKING_DIRECTORY ${TEMP_DIR} -) - -# Cleanup -FILE(REMOVE_RECURSE ${TEMP_DIR}) diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index 9c66b455497..189253c5b23 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -63,9 +63,9 @@ IF(MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 4) ADD_DEFINITIONS(-march=i486) ENDIF() -FUNCTION(ENABLE_ASAN) - IF(NOT CLANG_CL) - MESSAGE(FATAL_ERROR "clang-cl is necessary to enable asan") +MACRO(ENABLE_SANITIZERS) + IF(NOT MSVC) + MESSAGE(FATAL_ERROR "clang-cl or MSVC necessary to enable asan/ubsan") ENDIF() # currently, asan is broken with static CRT. IF(NOT(MSVC_CRT_TYPE STREQUAL "/MD")) @@ -74,25 +74,38 @@ FUNCTION(ENABLE_ASAN) ENDIF() ENDIF() IF(CMAKE_SIZEOF_VOID_P EQUAL 4) - MESSAGE(FATAL_ERROR "-DWITH_ASAN on Windows requires 64bit build") + SET(ASAN_ARCH i386) + ELSE() + IF(NOT CLANG_CL) + MESSAGE(FATAL_ERROR "sanitizers do not yet work on MSVC x64, try 32 bit or clang-cl") + ENDIF() + SET(ASAN_ARCH x86_64) ENDIF() - # After installation, clang lib directory should be added to PATH + + # After installation, clang lib directory should be added to PATH # (e.g C:/Program Files/LLVM/lib/clang/5.0.1/lib/windows) - FIND_LIBRARY(CLANG_RT_ASAN_DYNAMIC clang_rt.asan_dynamic-x86_64.lib) - IF(NOT CLANG_RT_ASAN_DYNAMIC) - MESSAGE(FATAL_ERROR "Can't enable ASAN : missing clang_rt.asan_dynamic-x86_64.lib") + SET(SANITIZER_LIBS) + SET(SANITIZER_LINK_LIBRARIES) + SET(SANITIZER_COMPILE_FLAGS) + IF(WITH_ASAN) + LIST(APPEND SANITIZER_LIBS + clang_rt.asan_dynamic-${ASAN_ARCH}.lib clang_rt.asan_dynamic_runtime_thunk-${ASAN_ARCH}.lib) + STRING(APPEND SANITIZER_COMPILE_FLAGS " -fsanitize=address") ENDIF() - - FIND_LIBRARY(CLANG_RT_ASAN_DYNAMIC_THUNK clang_rt.asan_dynamic_runtime_thunk-x86_64.lib) - IF(NOT CLANG_RT_ASAN_DYNAMIC_THUNK) - MESSAGE(FATAL_ERROR "Can't enable ASAN : missing clang_rt.asan_dynamic_runtime_thunk-x86_64.lib") + IF(WITH_UBSAN) + STRING(APPEND SANITIZER_COMPILE_FLAGS " -fsanitize=undefined -fno-sanitize=alignment") ENDIF() + FOREACH(lib ${SANITIZER_LIBS}) + FIND_LIBRARY(${lib}_fullpath ${lib}) + IF(NOT ${lib}_fullpath) + MESSAGE(FATAL_ERROR "Can't enable sanitizer : missing ${lib}") + ENDIF() + LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${${lib}_fullpath}) + STRING(APPEND CMAKE_C_STANDARD_LIBRARIES " \"${${lib}_fullpath}\" ") + STRING(APPEND CMAKE_CXX_STANDARD_LIBRARIES " \"${${lib}_fullpath}\" ") + ENDFOREACH() - STRING(APPEND CMAKE_C_FLAGS " -fsanitize=address") - STRING(APPEND CMAKE_CXX_FLAGS " -fsanitize=address") - - LINK_LIBRARIES(${CLANG_RT_ASAN_DYNAMIC} ${CLANG_RT_ASAN_DYNAMIC_THUNK}) -ENDFUNCTION() +ENDMACRO() IF(MSVC) @@ -120,12 +133,6 @@ IF(MSVC) OPTION(DYNAMIC_UCRT_LINK "Link Universal CRT dynamically, if MSVC_CRT_TYPE=/MT" ON) SET(DYNAMIC_UCRT_LINKER_OPTION " /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib") - IF(WITH_ASAN) - # Workaround something Linux specific - SET(SECURITY_HARDENED 0 CACHE INTERNAL "" FORCE) - ENABLE_ASAN() - ENDIF() - # Enable debug info also in Release build, # and create PDB to be able to analyze crashes. FOREACH(type EXE SHARED MODULE) @@ -141,7 +148,9 @@ IF(MSVC) FOREACH(lang C CXX) SET(CMAKE_${lang}_FLAGS_RELEASE "${CMAKE_${lang}_FLAGS_RELEASE} /Zi") ENDFOREACH() - FOREACH(flag + FOREACH(flag + CMAKE_C_FLAGS CMAKE_CXX_FLAGS + CMAKE_C_FLAGS_INIT CMAKE_CXX_FLAGS_INIT CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO @@ -155,6 +164,12 @@ IF(MSVC) ENDIF() ENDFOREACH() + IF(WITH_ASAN OR WITH_UBSAN) + # Workaround something Linux specific + SET(SECURITY_HARDENED 0 CACHE INTERNAL "" FORCE) + ENABLE_SANITIZERS() + ENDIF() + IF(CLANG_CL) SET(CLANG_CL_FLAGS "-Wno-unknown-warning-option -Wno-unused-private-field \ @@ -163,17 +178,16 @@ IF(MSVC) -Wno-deprecated-register -Wno-missing-braces \ -Wno-unused-function -Wno-unused-local-typedef -msse4.2 " ) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CLANG_CL_FLAGS}") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLANG_CL_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS " ${CLANG_CL_FLAGS} ${MSVC_CRT_TYPE}") + STRING(APPEND CMAKE_CXX_FLAGS " ${CLANG_CL_FLAGS} ${MSVC_CRT_TYPE}") ENDIF() FOREACH(type EXE SHARED MODULE) STRING(REGEX REPLACE "/STACK:([^ ]+)" "" CMAKE_${type}_LINKER_FLAGS "${CMAKE_${type}_LINKER_FLAGS}") STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}") STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}") - SET(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF") IF(NOT CLANG_CL) - SET(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /release") + STRING(APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /release /OPT:REF,ICF") ENDIF() IF(DYNAMIC_UCRT_LINK AND (MSVC_CRT_TYPE STREQUAL "/MT")) FOREACH(config RELEASE RELWITHDEBINFO DEBUG MINSIZEREL) @@ -186,25 +200,29 @@ IF(MSVC) # Mark 32 bit executables large address aware so they can # use > 2GB address space IF(CMAKE_SIZEOF_VOID_P MATCHES 4) - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") + STRING(APPEND CMAKE_EXE_LINKER_FLAGS " /LARGEADDRESSAWARE") ENDIF() # Speed up multiprocessor build IF (NOT CLANG_CL) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + STRING(APPEND CMAKE_C_FLAGS " /MP") + STRING(APPEND CMAKE_CXX_FLAGS " /MP") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /Gw") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /Gw") ENDIF() #TODO: update the code and remove the disabled warnings - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4700 /we4311 /we4477 /we4302 /we4090") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4099 /we4700 /we4311 /we4477 /we4302 /we4090") + STRING(APPEND CMAKE_C_FLAGS " /we4700 /we4311 /we4477 /we4302 /we4090") + STRING(APPEND CMAKE_CXX_FLAGS " /we4099 /we4700 /we4311 /we4477 /we4302 /we4090") IF(MSVC_VERSION GREATER 1910 AND NOT CLANG_CL) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-") + STRING(APPEND CMAKE_CXX_FLAGS " /permissive-") + STRING(APPEND CMAKE_C_FLAGS " /diagnostics:caret") + STRING(APPEND CMAKE_CXX_FLAGS " /diagnostics:caret") ENDIF() ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_WARNINGS) IF(MYSQL_MAINTAINER_MODE MATCHES "ERR") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + STRING(APPEND CMAKE_C_FLAGS " /WX") + STRING(APPEND CMAKE_CXX_FLAGS " /WX") FOREACH(type EXE SHARED MODULE) FOREACH(cfg RELEASE DEBUG RELWITHDEBINFO) SET(CMAKE_${type}_LINKER_FLAGS_${cfg} "${CMAKE_${type}_LINKER_FLAGS_${cfg}} /WX") @@ -214,9 +232,9 @@ IF(MSVC) IF(MSVC_VERSION LESS 1910) # Noisy warning C4800: 'type': forcing value to bool 'true' or 'false' (performance warning), # removed in VS2017 - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800") + STRING(APPEND CMAKE_CXX_FLAGS " /wd4800") ELSEIF (NOT CLANG_CL) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /d2OptimizeHugeFunctions") + STRING(APPEND CMAKE_CXX_FLAGS " /d2OptimizeHugeFunctions") ENDIF() ENDIF() @@ -305,6 +323,6 @@ MACRO(FORCE_STATIC_CRT) CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL ) STRING(REGEX REPLACE "/MD[d]?" "/MT" "${flag}" "${${flag}}" ) - STRING(REPLACE ${DYNAMIC_UCRT_LINKER_OPTION} "" "${flag}" "${${flag}}") + STRING(REPLACE "${DYNAMIC_UCRT_LINKER_OPTION}" "" "${flag}" "${${flag}}") ENDFOREACH() ENDMACRO() diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake index ecad590d4ef..0437eec284a 100644 --- a/cmake/pcre.cmake +++ b/cmake/pcre.cmake @@ -24,11 +24,13 @@ MACRO(BUNDLE_PCRE2) SET(byproducts ${byproducts} BUILD_BYPRODUCTS ${file} ${file_d}) SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION ${file}) ENDFOREACH() - FOREACH(v "" "_DEBUG" "_RELWITHDEBINFO" "_RELEASE" "_MINZISEREL") + FOREACH(v "" "_DEBUG" "_RELWITHDEBINFO" "_RELEASE" "_MINSIZEREL") STRING(REPLACE "/WX" "" pcre2_flags${v} "${CMAKE_C_FLAGS${v}}") IF(MSVC) # Suppress a warning STRING(APPEND pcre2_flags${v} " /wd4244 " ) + # Need this only for ASAN support + SET(stdlibs "-DCMAKE_C_STANDARD_LIBRARIES=${CMAKE_C_STANDARD_LIBRARIES}") ENDIF() ENDFOREACH() ExternalProject_Add( @@ -48,6 +50,7 @@ MACRO(BUNDLE_PCRE2) "-DCMAKE_C_FLAGS_RELEASE=${pcre2_flags_RELEASE}" "-DCMAKE_C_FLAGS_MINSIZEREL=${pcre2_flags_MINSIZEREL}" "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" + ${stdlibs} ${byproducts} ) SET_TARGET_PROPERTIES(pcre2 PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 7e9b80991ca..f2cba074397 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -252,7 +252,6 @@ MACRO(MYSQL_ADD_PLUGIN) SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.cnf") FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n") ENDIF() - INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR}) SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE) SET(CPACK_RPM_${ARG_COMPONENT}_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/plugin-postin.sh PARENT_SCOPE) SET(CPACK_RPM_${ARG_COMPONENT}_POST_TRANS_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-posttrans.sh PARENT_SCOPE) @@ -262,6 +261,9 @@ MACRO(MYSQL_ADD_PLUGIN) SET(ARG_COMPONENT Server) ENDIF() MYSQL_INSTALL_TARGETS(${target} DESTINATION ${INSTALL_PLUGINDIR} COMPONENT ${ARG_COMPONENT}) + IF(ARG_CONFIG AND INSTALL_SYSCONF2DIR) + INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR}) + ENDIF() ENDIF() GET_FILENAME_COMPONENT(subpath ${CMAKE_CURRENT_SOURCE_DIR} NAME) diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake index c8f7b3cc400..0eae3e1176b 100644 --- a/cmake/submodules.cmake +++ b/cmake/submodules.cmake @@ -19,11 +19,11 @@ IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git") SET(update_result 0) ELSEIF (cmake_update_submodules MATCHES force) MESSAGE(STATUS "Updating submodules (forced)") - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive --depth=1 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSEIF (cmake_update_submodules MATCHES yes) - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSE() diff --git a/config.h.cmake b/config.h.cmake index 942998b0544..5cced0f646f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -125,7 +125,6 @@ /* Functions we may want to use. */ #cmakedefine HAVE_ACCEPT4 1 #cmakedefine HAVE_ACCESS 1 -#cmakedefine HAVE_AIOWAIT 1 #cmakedefine HAVE_ALARM 1 #cmakedefine HAVE_ALLOCA 1 #cmakedefine HAVE_BFILL 1 diff --git a/configure.cmake b/configure.cmake index 4e198132f52..a7e044b13d2 100644 --- a/configure.cmake +++ b/configure.cmake @@ -316,7 +316,6 @@ ENDIF() # CHECK_FUNCTION_EXISTS (accept4 HAVE_ACCEPT4) CHECK_FUNCTION_EXISTS (access HAVE_ACCESS) -#CHECK_FUNCTION_EXISTS (aiowait HAVE_AIOWAIT) CHECK_FUNCTION_EXISTS (alarm HAVE_ALARM) SET(HAVE_ALLOCA 1) CHECK_FUNCTION_EXISTS (backtrace HAVE_BACKTRACE) diff --git a/dbug/dbug.c b/dbug/dbug.c index 847a8cc2b5d..011b932a721 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -490,6 +490,7 @@ static int DbugParse(CODE_STATE *cs, const char *control) rel= control[0] == '+' || control[0] == '-'; if ((!rel || (!stack->out_file && !stack->next))) { + LockIfInitSettings(cs); FreeState(cs, 0); stack->flags= 0; stack->delay= 0; @@ -497,10 +498,9 @@ static int DbugParse(CODE_STATE *cs, const char *control) stack->sub_level= 0; stack->out_file= sstderr; stack->functions= NULL; - LockIfInitSettings(cs); stack->keywords= NULL; - UnlockIfInitSettings(cs); stack->processes= NULL; + UnlockIfInitSettings(cs); } else if (!stack->out_file) { diff --git a/dbug/dbug_add_tags.pl b/dbug/dbug_add_tags.pl index 7be8fb9b18d..f117bdcd65b 100755 --- a/dbug/dbug_add_tags.pl +++ b/dbug/dbug_add_tags.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2002 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. diff --git a/dbug/remove_function_from_trace.pl b/dbug/remove_function_from_trace.pl index 380df168caf..67d7fa54b6a 100755 --- a/dbug/remove_function_from_trace.pl +++ b/dbug/remove_function_from_trace.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl die <= 5.6.25), ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) +Description: MariaDB common configuration files MariaDB is a fast, stable and true multi-user, multi-threaded SQL database server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/conf.d/mariadb.cnf). + This package includes configuration files common to all MariaDB programs. Package: mariadb-client-core-10.6 Architecture: any -Depends: libmariadb3, +Depends: libmariadb3 (>= 10.5.4), mariadb-common (>= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} @@ -636,6 +636,15 @@ Description: Connect storage engine for MariaDB other interesting features. This package contains the Connect plugin for MariaDB. +Package: mariadb-plugin-s3 +Architecture: any +Depends: libcurl4, + mariadb-server-10.6 (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} +Description: S3 storage engine for MariaDB + Read only table stored in S3. + Package: mariadb-plugin-rocksdb Architecture: amd64 arm64 mips64el ppc64el Depends: mariadb-server-10.6 (= ${binary:Version}), @@ -654,6 +663,25 @@ Description: RocksDB storage engine for MariaDB at maximising storage efficiency while maintaining InnoDB-like performance. This package contains the RocksDB plugin for MariaDB. +Package: mariadb-plugin-columnstore +Architecture: amd64 i386 +Depends: mariadb-server-10.6 (= ${binary:Version}), + net-tools, + binutils, + libsnappy1 | libsnappy1v5, + libjemalloc1 | libjemalloc2, + python3, + ${misc:Depends}, + ${shlibs:Depends} +Breaks: mariadb-columnstore-libs, + mariadb-columnstore-platform +Replaces: mariadb-columnstore-libs, + mariadb-columnstore-platform +Description: MariaDB ColumnStore storage engine + The MariaDB ColumnStore storage engine is a high-performance columnar + analytical engine, aimed at rapid processing of analytical queries on very + large amounts of data. + Package: mariadb-plugin-oqgraph Architecture: any Depends: libjudydebian1, diff --git a/debian/mariadb-client-10.6.install b/debian/mariadb-client-10.6.install index 35b614cd976..b299d3034c9 100644 --- a/debian/mariadb-client-10.6.install +++ b/debian/mariadb-client-10.6.install @@ -1,5 +1,8 @@ debian/additions/innotop/innotop usr/bin/ debian/additions/mariadb-report usr/bin/ +debian/additions/mariadb.conf.d/50-client.cnf etc/mysql/mariadb.conf.d +debian/additions/mariadb.conf.d/50-mysql-clients.cnf etc/mysql/mariadb.conf.d +debian/additions/mariadb.conf.d/60-galera.cnf etc/mysql/mariadb.conf.d usr/bin/mariadb-access usr/bin/mariadb-admin usr/bin/mariadb-conv diff --git a/debian/mariadb-common.dirs b/debian/mariadb-common.dirs index 87c71c1c2f5..8aba9560977 100644 --- a/debian/mariadb-common.dirs +++ b/debian/mariadb-common.dirs @@ -1 +1 @@ -etc/mysql/mariadb.conf.d/ +etc/mysql/mariadb.conf.d diff --git a/debian/mariadb-common.postinst b/debian/mariadb-common.postinst new file mode 100644 index 00000000000..2a8037e8c48 --- /dev/null +++ b/debian/mariadb-common.postinst @@ -0,0 +1,29 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + # New packaging paradigm for my.cnf handling among MySQL variants + # Used in Ubuntu since Dec-2014 and in Debian since Jul-2015 + # + # If the new mysql-common package does not provide + # the update-alternatives facility, notify user about manual fall back + if [ -f /usr/share/mysql-common/configure-symlinks ] + then + /usr/share/mysql-common/configure-symlinks install mariadb "/etc/mysql/mariadb.cnf" + else + # As configure can be called many times, don't re-create the symlink + # if it is there already + if [ ! -L /etc/mysql/my.cnf ] + then + echo "Notice: configure-symlinks trigger could not be called." + echo "Please manually create symlinks by running: " + echo " mv -f /etc/mysql/my.cnf /etc/mysql/my.cnf.old" + echo " ln -sf mariadb.cnf /etc/mysql/my.cnf" + fi + fi + ;; +esac + +#DEBHELPER# diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm index 14007fb9149..d0bfa266b7d 100644 --- a/debian/mariadb-common.postrm +++ b/debian/mariadb-common.postrm @@ -1,9 +1,16 @@ -#!/bin/bash +#!/bin/sh + set -e -if [ "$1" = "purge" ]; then - rmdir /etc/mysql/conf.d 2>/dev/null || true - rmdir /etc/mysql 2>/dev/null || true -fi +case "$1" in + remove|disappear) + # New packaging paradigm for my.cnf handling among MySQL variants + # Used in Ubuntu since Dec-2014 and in Debian since Jul-2015 + if [ -f /usr/share/mysql-common/configure-symlinks ] + then + /usr/share/mysql-common/configure-symlinks remove mariadb "/etc/mysql/mariadb.cnf" + fi + ;; +esac #DEBHELPER# diff --git a/debian/mariadb-plugin-columnstore.install b/debian/mariadb-plugin-columnstore.install new file mode 100644 index 00000000000..cd4461fe308 --- /dev/null +++ b/debian/mariadb-plugin-columnstore.install @@ -0,0 +1,160 @@ +etc/columnstore/AlarmConfig.xml +etc/columnstore/Columnstore.xml +etc/columnstore/ConsoleCmds.xml +etc/columnstore/ErrorMessage.txt +etc/columnstore/MessageFile.txt +etc/columnstore/ProcessConfig.xml +etc/columnstore/storagemanager.cnf +etc/mysql/mariadb.conf.d/columnstore.cnf +usr/bin/DDLProc +usr/bin/DMLProc +usr/bin/ExeMgr +usr/bin/MCSInstanceCmds.sh +usr/bin/MCSVolumeCmds.sh +usr/bin/MCSgetCredentials.sh +usr/bin/PrimProc +usr/bin/ProcMgr +usr/bin/ProcMon +usr/bin/ServerMonitor +usr/bin/StorageManager +usr/bin/WriteEngineServer +usr/bin/dbmsReport.sh +usr/bin/autoConfigure +usr/bin/bulklogReport.sh +usr/bin/clearShm +usr/bin/cleartablelock +usr/bin/columnstore +usr/bin/columnstore-post-install +usr/bin/columnstore-pre-uninstall +usr/bin/columnstoreClusterTester.sh +usr/bin/columnstoreDBWrite +usr/bin/columnstoreSupport +usr/bin/columnstoreSyslogSetup.sh +usr/bin/columnstore_installer +usr/bin/columnstore_module_installer.sh +usr/bin/columnstore_os_check.sh +usr/bin/columnstore_run.sh +usr/bin/colxml +usr/bin/configReport.sh +usr/bin/configxml.sh +usr/bin/controllernode +usr/bin/cpimport +usr/bin/cpimport.bin +usr/bin/cplogger +usr/bin/dbbuilder +usr/bin/dbrmctl +usr/bin/ddlcleanup +usr/bin/disable-rep-columnstore.sh +usr/bin/editem +usr/bin/getMySQLpw +usr/bin/hardwareReport.sh +usr/bin/idbmeminfo +usr/bin/load_brm +usr/bin/logReport.sh +usr/bin/mariadb-command-line.sh +usr/bin/master-rep-columnstore.sh +usr/bin/mcs-stop-controllernode.sh +usr/bin/mcsGetConfig +usr/bin/mcsSetConfig +usr/bin/mcs_module_installer.sh +usr/bin/mycnfUpgrade +usr/bin/os_detect.sh +usr/bin/post-mysql-install +usr/bin/post-mysqld-install +usr/bin/postConfigure +usr/bin/quick_installer_multi_server.sh +usr/bin/quick_installer_single_server.sh +usr/bin/remote_command.sh +usr/bin/remote_command_verify.sh +usr/bin/remote_scp_get.sh +usr/bin/remote_scp_put.sh +usr/bin/remotessh.exp +usr/bin/reset_locks +usr/bin/resourceReport.sh +usr/bin/rollback +usr/bin/rsync.sh +usr/bin/save_brm +usr/bin/slave-rep-columnstore.sh +usr/bin/smcat +usr/bin/smls +usr/bin/smput +usr/bin/smrm +usr/bin/startupTests.sh +usr/bin/viewtablelock +usr/bin/workernode +usr/bin/mcs-start-storagemanager.py +usr/bin/mcs-loadbrm.py +usr/bin/mariadb-columnstore-start.sh +usr/bin/mariadb-columnstore-stop.sh +usr/lib/*/libalarmmanager.so +usr/lib/*/libbatchloader.so +usr/lib/*/libbrm.so +usr/lib/*/libcacheutils.so +usr/lib/*/libcloudio.so +usr/lib/*/libcommon.so +usr/lib/*/libcompress.so +usr/lib/*/libconfigcpp.so +usr/lib/*/libdataconvert.so +usr/lib/*/libddlcleanuputil.so +usr/lib/*/libddlpackage.so +usr/lib/*/libddlpackageproc.so +usr/lib/*/libdmlpackage.so +usr/lib/*/libdmlpackageproc.so +usr/lib/*/libexecplan.so +usr/lib/*/libfuncexp.so +usr/lib/*/libidbdatafile.so +usr/lib/*/libjoblist.so +usr/lib/*/libjoiner.so +usr/lib/*/liblibmysql_client.so +usr/lib/*/libloggingcpp.so +usr/lib/*/libmarias3.so +usr/lib/*/libmessageqcpp.so +usr/lib/*/liboamcpp.so +usr/lib/*/libquerystats.so +usr/lib/*/libquerytele.so +usr/lib/*/libregr.so +usr/lib/*/librowgroup.so +usr/lib/*/librwlock.so +usr/lib/*/libstoragemanager.so +usr/lib/*/libthreadpool.so +usr/lib/*/libthrift.so +usr/lib/*/libudfsdk.so +usr/lib/*/libwindowfunction.so +usr/lib/*/libwriteengine.so +usr/lib/*/libwriteengineclient.so +usr/lib/*/libwriteengineredistribute.so +usr/lib/mysql/plugin/ha_columnstore.so +usr/lib/mysql/plugin/libregr_mysql.so +usr/lib/mysql/plugin/libudf_mysql.so +usr/sbin/install_mcs_mysql.sh +usr/share/columnstore/calremoveuserpriority.sql +usr/share/columnstore/calsetuserpriority.sql +usr/share/columnstore/calshowprocesslist.sql +usr/share/columnstore/columnstoreAlias +usr/share/columnstore/columnstoreLogRotate +usr/share/columnstore/columnstoreSyslog +usr/share/columnstore/columnstoreSyslog-ng +usr/share/columnstore/columnstoreSyslog7 +usr/share/columnstore/columnstore_functions +usr/share/columnstore/columnstore_info.sql +usr/share/columnstore/dumpcat_mysql.sql +usr/share/columnstore/gitversionEngine +usr/share/columnstore/mariadb-columnstore.service +usr/share/columnstore/mcs-controllernode.service +usr/share/columnstore/mcs-ddlproc.service +usr/share/columnstore/mcs-dmlproc.service +usr/share/columnstore/mcs-exemgr.service +usr/share/columnstore/mcs-loadbrm.service +usr/share/columnstore/mcs-primproc.service +usr/share/columnstore/mcs-workernode.service +usr/share/columnstore/mcs-writeengineserver.service +usr/share/columnstore/mcs-storagemanager.service +usr/share/columnstore/mcstest-001.sh +usr/share/columnstore/mcstest-002.sh +usr/share/columnstore/mcstest-003.sh +usr/share/columnstore/mcstest-004.sh +usr/share/columnstore/myCnf-exclude-args.text +usr/share/columnstore/myCnf-include-args.text +usr/share/columnstore/releasenum +usr/share/columnstore/syscatalog_mysql.sql +var/lib/columnstore/local/module diff --git a/debian/mariadb-plugin-columnstore.postinst b/debian/mariadb-plugin-columnstore.postinst new file mode 100644 index 00000000000..b482002c9dc --- /dev/null +++ b/debian/mariadb-plugin-columnstore.postinst @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +# Install ColumnStore +columnstore-post-install --rpmmode=install + +echo "MariaDB ColumnStore install completed" + +#DEBHELPER# diff --git a/debian/mariadb-plugin-columnstore.postrm b/debian/mariadb-plugin-columnstore.postrm new file mode 100644 index 00000000000..cd8decbfe76 --- /dev/null +++ b/debian/mariadb-plugin-columnstore.postrm @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +if [ "$1" = "purge" ]; then + rm -rf /var/lib/columnstore + rm -rf /etc/columnstore + rm -f /etc/mysql/mariadb.conf.d/columnstore.cnf.rpmsave +fi + +running_systemd() { + if [ "$(ps --no-headers -o comm 1)" = "systemd" ]; then + echo 0 + else + echo 1 + fi +} + +if [ ! -z "$(pgrep -x mysqld)" ];then + systemctl cat mariadb.service > /dev/null 2>&1 + if [ $? -eq 0 ] && [ $(running_systemd) -eq 0 ]; then + systemctl restart mariadb.service > /dev/null 2>&1 + else + pkill mysqld > /dev/null 2>&1 + /usr/bin/mysqld_safe & + fi +fi + +#DEBHELPER# diff --git a/debian/mariadb-plugin-columnstore.prerm b/debian/mariadb-plugin-columnstore.prerm new file mode 100644 index 00000000000..10e585a887b --- /dev/null +++ b/debian/mariadb-plugin-columnstore.prerm @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +columnstore-pre-uninstall + +exit 0 + +#DEBHELPER# diff --git a/debian/mariadb-plugin-connect.install b/debian/mariadb-plugin-connect.install index 22d73c7df05..e2500269438 100644 --- a/debian/mariadb-plugin-connect.install +++ b/debian/mariadb-plugin-connect.install @@ -1,2 +1,2 @@ -etc/mysql/conf.d/connect.cnf etc/mysql/mariadb.conf.d +etc/mysql/mariadb.conf.d/connect.cnf usr/lib/mysql/plugin/ha_connect.so diff --git a/debian/mariadb-plugin-cracklib-password-check.install b/debian/mariadb-plugin-cracklib-password-check.install index 7cc3fdc2b3e..5419f05ed3d 100644 --- a/debian/mariadb-plugin-cracklib-password-check.install +++ b/debian/mariadb-plugin-cracklib-password-check.install @@ -1,2 +1,2 @@ -etc/mysql/conf.d/cracklib_password_check.cnf etc/mysql/mariadb.conf.d +etc/mysql/mariadb.conf.d/cracklib_password_check.cnf usr/lib/mysql/plugin/cracklib_password_check.so diff --git a/debian/mariadb-plugin-gssapi-server.install b/debian/mariadb-plugin-gssapi-server.install index 537f459d2d2..70916b49052 100644 --- a/debian/mariadb-plugin-gssapi-server.install +++ b/debian/mariadb-plugin-gssapi-server.install @@ -1,2 +1,2 @@ -etc/mysql/conf.d/auth_gssapi.cnf etc/mysql/mariadb.conf.d +etc/mysql/mariadb.conf.d/auth_gssapi.cnf usr/lib/mysql/plugin/auth_gssapi.so diff --git a/debian/mariadb-plugin-oqgraph.install b/debian/mariadb-plugin-oqgraph.install index 5e2a892d9e9..675b73c5d76 100644 --- a/debian/mariadb-plugin-oqgraph.install +++ b/debian/mariadb-plugin-oqgraph.install @@ -1,2 +1,2 @@ -etc/mysql/conf.d/oqgraph.cnf etc/mysql/mariadb.conf.d +etc/mysql/mariadb.conf.d/oqgraph.cnf usr/lib/mysql/plugin/ha_oqgraph.so diff --git a/debian/mariadb-plugin-rocksdb.install b/debian/mariadb-plugin-rocksdb.install index dbfd246024b..dcc576ea937 100644 --- a/debian/mariadb-plugin-rocksdb.install +++ b/debian/mariadb-plugin-rocksdb.install @@ -1,4 +1,4 @@ -etc/mysql/conf.d/rocksdb.cnf etc/mysql/mariadb.conf.d +etc/mysql/mariadb.conf.d/rocksdb.cnf usr/bin/mariadb-ldb usr/bin/myrocks_hotbackup usr/lib/mysql/plugin/ha_rocksdb.so diff --git a/debian/mariadb-plugin-s3.install b/debian/mariadb-plugin-s3.install new file mode 100644 index 00000000000..a6f90b76f82 --- /dev/null +++ b/debian/mariadb-plugin-s3.install @@ -0,0 +1,3 @@ +etc/mysql/mariadb.conf.d/s3.cnf +usr/bin/aria_s3_copy +usr/lib/mysql/plugin/ha_s3.so diff --git a/debian/mariadb-plugin-spider.install b/debian/mariadb-plugin-spider.install index 89652fe2f3c..1ad1361b00e 100644 --- a/debian/mariadb-plugin-spider.install +++ b/debian/mariadb-plugin-spider.install @@ -1,2 +1,2 @@ +etc/mysql/mariadb.conf.d/spider.cnf usr/lib/mysql/plugin/ha_spider.so -usr/share/mysql/install_spider.sql diff --git a/debian/mariadb-plugin-spider.postinst b/debian/mariadb-plugin-spider.postinst deleted file mode 100644 index d4ddaa53156..00000000000 --- a/debian/mariadb-plugin-spider.postinst +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -set -e - -# Install Spider -mysql --defaults-file=/etc/mysql/debian.cnf < /usr/share/mysql/install_spider.sql || true -# Always exit with success instead of leaving dpkg in a broken state - - -#DEBHELPER# diff --git a/debian/additions/mysql.init b/debian/mariadb-server-10.5.mariadb.init old mode 100755 new mode 100644 similarity index 70% rename from debian/additions/mysql.init rename to debian/mariadb-server-10.5.mariadb.init index 980c6e832d5..a16e9f88edb --- a/debian/additions/mysql.init +++ b/debian/mariadb-server-10.5.mariadb.init @@ -1,7 +1,7 @@ #!/bin/bash # ### BEGIN INIT INFO -# Provides: mysql +# Provides: mariadb # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Should-Start: $network $named $time @@ -9,7 +9,7 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start and stop the mysql database server daemon -# Description: Controls the main MariaDB database server daemon "mysqld" +# Description: Controls the main MariaDB database server daemon "mariadbd" # and its wrapper script "mysqld_safe". ### END INIT INFO # @@ -17,7 +17,7 @@ set -e set -u ${DEBIAN_SCRIPT_DEBUG:+ set -v -x} -test -x /usr/sbin/mysqld || exit 0 +test -x /usr/sbin/mariadbd || exit 0 . /lib/lsb/init-functions @@ -26,12 +26,19 @@ SELF=$(cd $(dirname $0); pwd -P)/$(basename $0) MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" # priority can be overridden and "-s" adds output to stderr -ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mysql -i" +ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mariadb -i" if [ -f /etc/default/mysql ]; then . /etc/default/mysql fi +# Also source default/mariadb in case the installation was upgraded from +# packages originally installed from MariaDB.org repositories, which have +# had support for reading /etc/default/mariadb since March 2016. +if [ -f /etc/default/mariadb ]; then + . /etc/default/mariadb +fi + # Safeguard (relative paths, core dumps..) cd / umask 077 @@ -43,16 +50,16 @@ export HOME=/etc/mysql/ ## Fetch a particular option from mysql's invocation. # -# Usage: void mysqld_get_param option -mysqld_get_param() { - /usr/sbin/mysqld --print-defaults \ +# Usage: void mariadbd_get_param option +mariadbd_get_param() { + /usr/sbin/mariadbd --print-defaults \ | tr " " "\n" \ | grep -- "--$1" \ | tail -n 1 \ | cut -d= -f2 } -## Do some sanity checks before even trying to start mysqld. +## Do some sanity checks before even trying to start mariadbd. sanity_checks() { # check for config file if [ ! -r /etc/mysql/my.cnf ]; then @@ -61,7 +68,7 @@ sanity_checks() { fi # check for diskspace shortage - datadir=`mysqld_get_param datadir` + datadir=`mariadbd_get_param datadir` if LC_ALL=C BLOCKSIZE= df --portability $datadir/. | tail -n 1 | awk '{ exit ($4>4096) }'; then log_failure_msg "$0: ERROR: The partition with $datadir is too full!" echo "ERROR: The partition with $datadir is too full!" | $ERR_LOGGER @@ -72,14 +79,14 @@ sanity_checks() { ## Checks if there is a server running and if so if it is accessible. # # check_alive insists on a pingable server -# check_dead also fails if there is a lost mysqld in the process list +# check_dead also fails if there is a lost mariadbd in the process list # -# Usage: boolean mysqld_status [check_alive|check_dead] [warn|nowarn] -mysqld_status () { +# Usage: boolean mariadbd_status [check_alive|check_dead] [warn|nowarn] +mariadbd_status () { ping_output=`$MYADMIN ping 2>&1`; ping_alive=$(( ! $? )) ps_alive=0 - pidfile=`mysqld_get_param pid-file` + pidfile=`mariadbd_get_param pid-file` if [ -f "$pidfile" ] && ps `cat $pidfile` >/dev/null 2>&1; then ps_alive=1; fi if [ "$1" = "check_alive" -a $ping_alive = 1 ] || @@ -102,23 +109,23 @@ case "${1:-''}" in 'start') sanity_checks; # Start daemon - log_daemon_msg "Starting MariaDB database server" "mysqld" - if mysqld_status check_alive nowarn; then + log_daemon_msg "Starting MariaDB database server" "mariadbd" + if mariadbd_status check_alive nowarn; then log_progress_msg "already running" log_end_msg 0 else # Could be removed during boot - test -e /var/run/mysqld || install -m 755 -o mysql -g root -d /var/run/mysqld + test -e /run/mysqld || install -m 755 -o mysql -g root -d /run/mysqld # Start MariaDB! /usr/bin/mysqld_safe "${@:2}" 2>&1 >/dev/null | $ERR_LOGGER & for i in $(seq 1 "${MYSQLD_STARTUP_TIMEOUT:-30}"); do sleep 1 - if mysqld_status check_alive nowarn ; then break; fi + if mariadbd_status check_alive nowarn ; then break; fi log_progress_msg "." done - if mysqld_status check_alive warn; then + if mariadbd_status check_alive warn; then log_end_msg 0 # Now start mysqlcheck or whatever the admin wants. output=$(/etc/mysql/debian-start) @@ -137,26 +144,26 @@ case "${1:-''}" in # at least for cron, we can rely on it here, too. (although we have # to specify it explicit as e.g. sudo environments points to the normal # users home and not /root) - log_daemon_msg "Stopping MariaDB database server" "mysqld" - if ! mysqld_status check_dead nowarn; then + log_daemon_msg "Stopping MariaDB database server" "mariadbd" + if ! mariadbd_status check_dead nowarn; then set +e shutdown_out=`$MYADMIN shutdown 2>&1`; r=$? set -e if [ "$r" -ne 0 ]; then log_end_msg 1 [ "$VERBOSE" != "no" ] && log_failure_msg "Error: $shutdown_out" - log_daemon_msg "Killing MariaDB database server by signal" "mysqld" - killall -15 mysqld + log_daemon_msg "Killing MariaDB database server by signal" "mariadbd" + killall -15 mariadbd server_down= for i in `seq 1 600`; do sleep 1 - if mysqld_status check_dead nowarn; then server_down=1; break; fi + if mariadbd_status check_dead nowarn; then server_down=1; break; fi done - if test -z "$server_down"; then killall -9 mysqld; fi + if test -z "$server_down"; then killall -9 mariadbd; fi fi fi - if ! mysqld_status check_dead warn; then + if ! mariadbd_status check_dead warn; then log_end_msg 1 log_failure_msg "Please stop MariaDB manually and read /usr/share/doc/mariadb-server-10.6/README.Debian.gz!" exit -1 @@ -172,13 +179,13 @@ case "${1:-''}" in ;; 'reload'|'force-reload') - log_daemon_msg "Reloading MariaDB database server" "mysqld" + log_daemon_msg "Reloading MariaDB database server" "mariadbd" $MYADMIN reload log_end_msg 0 ;; 'status') - if mysqld_status check_alive nowarn; then + if mariadbd_status check_alive nowarn; then log_action_msg "$($MYADMIN version)" else log_action_msg "MariaDB is stopped." @@ -186,6 +193,13 @@ case "${1:-''}" in fi ;; + 'bootstrap') + # Bootstrap the cluster, start the first node + # that initiates the cluster + log_daemon_msg "Bootstrapping the cluster" "mariadbd" + $SELF start "${@:2}" --wsrep-new-cluster + ;; + *) echo "Usage: $SELF start|stop|restart|reload|force-reload|status" exit 1 diff --git a/debian/mariadb-server-10.6.install b/debian/mariadb-server-10.6.install index f2a8da01fe7..6bebde6ef3b 100644 --- a/debian/mariadb-server-10.6.install +++ b/debian/mariadb-server-10.6.install @@ -1,10 +1,10 @@ debian/additions/debian-start etc/mysql debian/additions/debian-start.inc.sh usr/share/mysql debian/additions/echo_stderr usr/share/mysql -debian/additions/mysql.init usr/share/mysql -debian/additions/mysqld_safe_syslog.cnf etc/mysql/conf.d +debian/additions/mariadb.conf.d/50-mysqld_safe.cnf etc/mysql/mariadb.conf.d +debian/additions/mariadb.conf.d/50-server.cnf etc/mysql/mariadb.conf.d debian/additions/source_mariadb-10.6.py usr/share/apport/package-hooks -etc/apparmor.d/usr.sbin.mysqld +etc/apparmor.d/usr.sbin.mariadbd etc/security/user_map.conf lib/*/security/pam_user_map.so lib/systemd/system/mariadb@bootstrap.service.d/use_galera_new_cluster.conf @@ -61,7 +61,7 @@ usr/lib/mysql/plugin/server_audit.so usr/lib/mysql/plugin/simple_password_check.so usr/lib/mysql/plugin/sql_errlog.so usr/lib/mysql/plugin/wsrep_info.so -usr/share/doc/mariadb-server-10.6/mysqld.sym.gz +usr/share/doc/mariadb-server-10.6/mariadbd.sym.gz usr/share/man/man1/aria_chk.1 usr/share/man/man1/aria_dump_log.1 usr/share/man/man1/aria_ftdump.1 @@ -104,4 +104,5 @@ usr/share/man/man1/wsrep_sst_mysqldump.1 usr/share/man/man1/wsrep_sst_rsync.1 usr/share/man/man1/wsrep_sst_rsync_wan.1 usr/share/mysql/errmsg-utf8.txt +usr/share/mysql/wsrep.cnf usr/share/mysql/wsrep_notify diff --git a/debian/mariadb-server-10.6.logcheck.ignore.paranoid b/debian/mariadb-server-10.6.logcheck.ignore.paranoid index 00cc5c3e29d..407d4063270 100644 --- a/debian/mariadb-server-10.6.logcheck.ignore.paranoid +++ b/debian/mariadb-server-10.6.logcheck.ignore.paranoid @@ -1,9 +1,9 @@ -/etc/init.d/mysql\[[0-9]+\]: Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists\!$ -/etc/init.d/mysql\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ +/etc/init.d/mariadb\[[0-9]+\]: Check that mariadbd is running and that the socket: '/run/mysqld/mysqld.sock' exists\!$ +/etc/init.d/mariadb\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ /etc/mysql/debian-start\[[0-9]+\]: Checking for crashed MySQL tables\.$ -mysqld\[[0-9]+\]: $ -mysqld\[[0-9]+\]: Version: .* socket: '/var/run/mysqld/mysqld.sock' port: 3306$ -mysqld\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ +mariadbd\[[0-9]+\]: $ +mariadbd\[[0-9]+\]: Version: .* socket: '/run/mysqld/mysqld.sock' port: 3306$ +mariadbd\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ mysqld_safe\[[0-9]+\]: started$ usermod\[[0-9]+\]: change user `mysql' GID from `([0-9]+)' to `\1'$ usermod\[[0-9]+\]: change user `mysql' shell from `/bin/false' to `/bin/false'$ diff --git a/debian/mariadb-server-10.6.logcheck.ignore.server b/debian/mariadb-server-10.6.logcheck.ignore.server index 5b7b0322fc3..a64fc54e15c 100644 --- a/debian/mariadb-server-10.6.logcheck.ignore.server +++ b/debian/mariadb-server-10.6.logcheck.ignore.server @@ -1,18 +1,18 @@ -/etc/init.d/mysql\[[0-9]+\]: [0-9]+ processes alive and '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ -/etc/init.d/mysql\[[0-9]+\]: Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists\!$ -/etc/init.d/mysql\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ +/etc/init.d/mariadb\[[0-9]+\]: [0-9]+ processes alive and '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ +/etc/init.d/mariadb\[[0-9]+\]: Check that mariadbd is running and that the socket: '/run/mysqld/mysqld.sock' exists\!$ +/etc/init.d/mariadb\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ /etc/mysql/debian-start\[[0-9]+\]: Checking for crashed MySQL tables\.$ -mysqld\[[0-9]+\]: ?$ -mysqld\[[0-9]+\]: .*InnoDB: Shutdown completed -mysqld\[[0-9]+\]: .*InnoDB: Started; -mysqld\[[0-9]+\]: .*InnoDB: Starting shutdown\.\.\.$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: Normal shutdown$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: ready for connections\.$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: Shutdown complete$ -mysqld\[[0-9]+\]: /usr/sbin/mysqld: ready for connections\.$ -mysqld\[[0-9]+\]: .*/usr/sbin/mysqld: Shutdown Complete$ -mysqld\[[0-9]+\]: Version: .* socket -mysqld\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ +mariadbd\[[0-9]+\]: ?$ +mariadbd\[[0-9]+\]: .*InnoDB: Shutdown completed +mariadbd\[[0-9]+\]: .*InnoDB: Started; +mariadbd\[[0-9]+\]: .*InnoDB: Starting shutdown\.\.\.$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: Normal shutdown$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: ready for connections\.$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: Shutdown complete$ +mariadbd\[[0-9]+\]: /usr/sbin/mariadbd: ready for connections\.$ +mariadbd\[[0-9]+\]: .*/usr/sbin/mariadbd: Shutdown Complete$ +mariadbd\[[0-9]+\]: Version: .* socket +mariadbd\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ mysqld_safe\[[0-9]+\]: ?$ mysqld_safe\[[0-9]+\]: able to use the new GRANT command!$ mysqld_safe\[[0-9]+\]: ended$ diff --git a/debian/mariadb-server-10.6.logcheck.ignore.workstation b/debian/mariadb-server-10.6.logcheck.ignore.workstation index 5b7b0322fc3..a64fc54e15c 100644 --- a/debian/mariadb-server-10.6.logcheck.ignore.workstation +++ b/debian/mariadb-server-10.6.logcheck.ignore.workstation @@ -1,18 +1,18 @@ -/etc/init.d/mysql\[[0-9]+\]: [0-9]+ processes alive and '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ -/etc/init.d/mysql\[[0-9]+\]: Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists\!$ -/etc/init.d/mysql\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ +/etc/init.d/mariadb\[[0-9]+\]: [0-9]+ processes alive and '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ +/etc/init.d/mariadb\[[0-9]+\]: Check that mariadbd is running and that the socket: '/run/mysqld/mysqld.sock' exists\!$ +/etc/init.d/mariadb\[[0-9]+\]: '/usr/bin/mysqladmin --defaults-(extra-)?file=/etc/mysql/debian.cnf ping' resulted in$ /etc/mysql/debian-start\[[0-9]+\]: Checking for crashed MySQL tables\.$ -mysqld\[[0-9]+\]: ?$ -mysqld\[[0-9]+\]: .*InnoDB: Shutdown completed -mysqld\[[0-9]+\]: .*InnoDB: Started; -mysqld\[[0-9]+\]: .*InnoDB: Starting shutdown\.\.\.$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: Normal shutdown$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: ready for connections\.$ -mysqld\[[0-9]+\]: .*\[Note\] /usr/sbin/mysqld: Shutdown complete$ -mysqld\[[0-9]+\]: /usr/sbin/mysqld: ready for connections\.$ -mysqld\[[0-9]+\]: .*/usr/sbin/mysqld: Shutdown Complete$ -mysqld\[[0-9]+\]: Version: .* socket -mysqld\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ +mariadbd\[[0-9]+\]: ?$ +mariadbd\[[0-9]+\]: .*InnoDB: Shutdown completed +mariadbd\[[0-9]+\]: .*InnoDB: Started; +mariadbd\[[0-9]+\]: .*InnoDB: Starting shutdown\.\.\.$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: Normal shutdown$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: ready for connections\.$ +mariadbd\[[0-9]+\]: .*\[Note\] /usr/sbin/mariadbd: Shutdown complete$ +mariadbd\[[0-9]+\]: /usr/sbin/mariadbd: ready for connections\.$ +mariadbd\[[0-9]+\]: .*/usr/sbin/mariadbd: Shutdown Complete$ +mariadbd\[[0-9]+\]: Version: .* socket +mariadbd\[[0-9]+\]: Warning: Ignoring user change to 'mysql' because the user was set to 'mysql' earlier on the command line$ mysqld_safe\[[0-9]+\]: ?$ mysqld_safe\[[0-9]+\]: able to use the new GRANT command!$ mysqld_safe\[[0-9]+\]: ended$ diff --git a/debian/mariadb-server-10.6.mysql-server.logrotate b/debian/mariadb-server-10.6.mysql-server.logrotate index 4111a276dc3..eed6fc5e88d 100644 --- a/debian/mariadb-server-10.6.mysql-server.logrotate +++ b/debian/mariadb-server-10.6.mysql-server.logrotate @@ -11,7 +11,7 @@ sharedscripts postrotate test -x /usr/bin/mysqladmin || exit 0 - if [ -f `my_print_defaults --mysqld | grep -oP "pid-file=\K[^$]+"` ]; then + if [ -f `my_print_defaults --mariadbd | grep -oP "pid-file=\K[^$]+"` ]; then # If this fails, check debian.conf! mysqladmin --defaults-file=/etc/mysql/debian.cnf --local flush-error-log \ flush-engine-log flush-general-log flush-slow-log diff --git a/debian/mariadb-server-10.6.postinst b/debian/mariadb-server-10.6.postinst index 9f301878d8c..6decee78766 100644 --- a/debian/mariadb-server-10.6.postinst +++ b/debian/mariadb-server-10.6.postinst @@ -18,17 +18,42 @@ ERR_LOGGER="logger -p daemon.err -t mariadb-server-$MAJOR_VER.postinst -i" # the install, rather than failing silently and leaving a broken install. set -o pipefail -invoke() { - systemctl $1 mysql -} - case "$1" in configure) - # This is needed because mysql_install_db removes the pid file in /var/run + # This is needed because mysql_install_db removes the pid file in /run # and because changed configuration options should take effect immediately. # In case the server wasn't running at all it should be ok if the stop - # script fails. I can't tell at this point because of the cleaned /var/run. - set +e; invoke stop; set -e + # script fails. I can't tell at this point because of the cleaned /run. + set +e; invoke-rc.d mariadb stop; set -e + + # An existing /etc/init.d/mysql might be on the system if there was a + # previous MySQL or MariaDB installation, since /etc/init.d files are + # considered config files and stay around even after the package is removed. + # + # The install step of this package adds a new /etc/init.d/mariadb file. As + # we also want to ensure that there are no old (and potentially outdated) + # versions of /etc/init.d/mysql we simply replace it using a copy of the + # latest 'mariadb' file. This has also the added benefit that anything that + # invokes traditional sysv init with either 'mysql' or 'mariadb' will end up + # controlling this newly installed MariaDB, and thus we maintain better + # backwards compatiblity. + # + # Note that the 'Provides' line is also updated to avoid 'insserv' exiting + # on failure (when it is run by update-rc.d) because of duplicate service + # names. + if [ -f "/etc/init.d/mysql" ] && [ -f "/etc/init.d/mariadb" ] + then + # Copy init file and rename the service name and filename on the fly + sed 's/Provides: mariadb/Provides: mysql/g' /etc/init.d/mariadb > /etc/init.d/mysql + # NOTE: Number of spaces/tabs is important here! + # Confirm if the sed worked + if ! grep --quiet "Provides: mysql" /etc/init.d/mysql + then + # If not, then delete the file to avoid failures later on + rm -f /etc/init.d/mysql + echo "Warning! Failed creating a mysql named copy of mariadb init.d file" + fi + fi mysql_statedir=/usr/share/mysql mysql_datadir=/var/lib/mysql @@ -126,7 +151,7 @@ EOF # initiate databases. Output is not allowed by debconf :-( # This will fail if we are upgrading an existing database; in this case - # mysql_upgrade, called from the /etc/init.d/mysql start script, will + # mysql_upgrade, called from the /etc/init.d/mariadb start script, will # handle things. # Debian: beware of the bashisms... # Debian: can safely run on upgrades with existing databases @@ -164,21 +189,21 @@ EOF # This allows upgrade from old versions (that have an apparmor profile # on by default) to work both to disable a default profile, and to keep # any profile installed and maintained by users themselves. - profile="/etc/apparmor.d/usr.sbin.mysqld" + profile="/etc/apparmor.d/usr.sbin.mariadbd" if [ -f "$profile" ] && aa-status --enabled 2>/dev/null; then - if grep -q /usr/sbin/mysqld "$profile" 2>/dev/null ; then + if grep -q /usr/sbin/mariadbd "$profile" 2>/dev/null ; then apparmor_parser -r "$profile" || true else - echo "/usr/sbin/mysqld { }" | apparmor_parser --remove 2>/dev/null || true + echo "/usr/sbin/mariadbd { }" | apparmor_parser --remove 2>/dev/null || true fi fi - # copy out any mysqld_safe settings - systemd_conf=/etc/systemd/system/mariadb.service.d/migrated-from-my.cnf-settings.conf - if [ -x /usr/bin/mariadb-service-convert -a ! -f "${systemd_conf}" ]; then - mkdir -p /etc/systemd/system/mariadb.service.d - /usr/bin/mariadb-service-convert > "${systemd_conf}" - fi + # @TODO: Remove once buildbot.askmonty.org has been updated not to expect this file + mkdir -p /etc/systemd/system/mariadb.service.d/ + # Note that file cannot be empty, otherwise systemd version in Ubuntu Bionic + # will think the service is masked + echo "# empty placeholder" > /etc/systemd/system/mariadb.service.d/migrated-from-my.cnf-settings.conf + ;; abort-upgrade|abort-remove|abort-configure) @@ -187,8 +212,9 @@ EOF triggered) if [ -x "$(command -v systemctl)" ]; then systemctl daemon-reload + else + invoke-rc.d mariadb restart fi - invoke restart ;; *) @@ -199,7 +225,7 @@ esac db_stop # in case invoke failes -# dh_systemd_start doesn't emit anything since we still ship /etc/init.d/mysql. +# dh_systemd_start doesn't emit anything since we still ship /etc/init.d/mariadb. # Thus MariaDB server is started via init.d script, which in turn redirects to # systemctl. If we upgrade from MySQL mysql.service may be masked, which also # means init.d script is disabled. Unmask mysql service explicitly. @@ -209,3 +235,14 @@ if [ -x "$(command -v deb-systemd-helper)" ]; then fi #DEBHELPER# + +# Modified dh_systemd_start snippet that's not added automatically +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true + deb-systemd-invoke start mariadb.service >/dev/null || true +# Modified dh_installinit snippet to only run with sysvinit +elif [ -x "/etc/init.d/mariadb" ]; then + if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then + invoke-rc.d mariadb start || exit $? + fi +fi diff --git a/debian/mariadb-server-10.6.postrm b/debian/mariadb-server-10.6.postrm index 5d1324cead1..00ff90dbb20 100644 --- a/debian/mariadb-server-10.6.postrm +++ b/debian/mariadb-server-10.6.postrm @@ -13,20 +13,28 @@ MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" # Try to stop the server in a sane way. If it does not success let the admin # do it himself. No database directories should be removed while the server -# is running! +# is running! Another mariadbd in e.g. a different chroot is fine for us. stop_server() { - set +e - systemctl stop mysql - errno=$? - set -e + # Return immediately if there are no mysql processes running + # as there is no point in trying to shutdown in that case. + if ! pgrep -x mariadbd > /dev/null; then return; fi - if [ "$?" != 0 ]; then - echo "Trying to stop the MySQL server resulted in exitcode $?." 1>&2 - echo "Stop it yourself and try again!" 1>&2 - exit 1 - fi + set +e + invoke-rc.d mariadb stop + errno=$? + set -e + + # systemctl could emit exit code 100=no init script (fresh install) + if [ "$errno" != 0 -a "$errno" != 100 ]; then + echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 + echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 + echo "Stop it yourself and try again!" 1>&2 + db_stop + exit 1 + fi } + case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) if [ -n "`$MYADMIN ping 2>/dev/null`" ]; then @@ -74,10 +82,15 @@ if [ "$1" = "purge" ] && [ -f "/var/lib/mysql/debian-$MAJOR_VER.flag" ]; then # /var/lib/mysql is a mount point rmdir --ignore-fail-on-non-empty /var/lib/mysql || true fi - rm -rf /var/run/mysqld # this directory is created by the init script, don't leave behind + rm -rf /run/mysqld # this directory is created by the init script, don't leave behind userdel mysql || true fi fi #DEBHELPER# + +# Modified dh_systemd_start snippet that's not added automatically +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true +fi diff --git a/debian/mariadb-server-10.6.preinst b/debian/mariadb-server-10.6.preinst index 947b4420ee6..ce4ca3fee9d 100644 --- a/debian/mariadb-server-10.6.preinst +++ b/debian/mariadb-server-10.6.preinst @@ -26,21 +26,21 @@ mysql_upgradedir=/var/lib/mysql-upgrade # Try to stop the server in a sane way. If it does not success let the admin # do it himself. No database directories should be removed while the server -# is running! Another mysqld in e.g. a different chroot is fine for us. +# is running! Another mariadbd in e.g. a different chroot is fine for us. stop_server() { # Return immediately if there are no mysql processes running # as there is no point in trying to shutdown in that case. - if ! pgrep -x --ns $$ mysqld > /dev/null; then return; fi + if ! pgrep -x --ns $$ mariadbd > /dev/null; then return; fi set +e - systemctl stop mysql + invoke-rc.d mariadb stop errno=$? set -e - # 0=ok, 100=no init script (fresh install) + # systemctl could emit exit code 100=no init script (fresh install) if [ "$errno" != 0 -a "$errno" != 100 ]; then - echo "'systemctl stop mysql' returned $errno" 1>&2 - echo "There is a MySQL server running, but we failed in our attempts to stop it." 1>&2 + echo "Attempt to stop MariaDB/MySQL server returned exitcode $errno" 1>&2 + echo "There is a MariaDB/MySQL server running, but we failed in our attempts to stop it." 1>&2 echo "Stop it yourself and try again!" 1>&2 db_stop exit 1 diff --git a/debian/mariadb-server-10.6.prerm b/debian/mariadb-server-10.6.prerm index 6060c4fb6b1..8fd172da9d2 100644 --- a/debian/mariadb-server-10.6.prerm +++ b/debian/mariadb-server-10.6.prerm @@ -2,3 +2,11 @@ set -e #DEBHELPER# + +# Modified dh_systemd_start snippet that's not added automatically +if [ -d /run/systemd/system ]; then + deb-systemd-invoke stop mariadb.service >/dev/null +# Modified dh_installinit snippet to only run with sysvinit +elif [ -x "/etc/init.d/mariadb" ]; then + invoke-rc.d mariadb stop || exit $? +fi diff --git a/debian/mysql-common.install b/debian/mysql-common.install deleted file mode 100644 index 56c1c4a03f6..00000000000 --- a/debian/mysql-common.install +++ /dev/null @@ -1 +0,0 @@ -debian/additions/my.cnf etc/mysql diff --git a/debian/mysql-common.links b/debian/mysql-common.links new file mode 100644 index 00000000000..5c45a67e4fc --- /dev/null +++ b/debian/mysql-common.links @@ -0,0 +1 @@ +etc/mysql/mariadb.cnf etc/mysql/my.cnf diff --git a/debian/rules b/debian/rules index 7d4fb9afa4e..458bfbfeabb 100755 --- a/debian/rules +++ b/debian/rules @@ -39,11 +39,7 @@ else TESTSUITE_FAIL_CMD:=exit 1 endif -ifeq (32,$(DEB_HOST_ARCH_BITS)) - CMAKEFLAGS += -DWITHOUT_ROCKSDB=true -endif - -# Add extra flag to avoid WolfSSL code crashing the entire mysqld on s390x. This +# Add extra flag to avoid WolfSSL code crashing the entire mariadbd on s390x. This # can be removed once upstream has made the code s390x compatible, see # https://jira.mariadb.org/browse/MDEV-21705 and # https://github.com/wolfSSL/wolfssl/issues/2828 @@ -85,7 +81,10 @@ endif -DSYSTEM_TYPE="debian-$(DEB_HOST_GNU_SYSTEM)" \ -DCMAKE_SYSTEM_PROCESSOR=$(DEB_HOST_ARCH) \ -DBUILD_CONFIG=mysql_release \ - -DWITHOUT_CASSANDRA=true \ + -DPLUGIN_TOKUDB=NO \ + -DPLUGIN_CASSANDRA=NO \ + -DPLUGIN_COLUMNSTORE=YES \ + -DPLUGIN_ROCKSDB=YES \ -DPLUGIN_AWS_KEY_MANAGEMENT=NO \ -WITH_EMBEDDED_SERVER=OFF \ -DDEB=$(DEB_VENDOR) ..' @@ -135,10 +134,10 @@ endif # nm numeric soft is not enough, therefore extra sort in command # to satisfy Debian reproducible build requirements - nm --defined-only $(BUILDDIR)/sql/mysqld | LC_ALL=C sort | gzip -n -9 > $(TMP)/usr/share/doc/mariadb-server-10.6/mysqld.sym.gz + nm --defined-only $(BUILDDIR)/sql/mariadbd | LC_ALL=C sort | gzip -n -9 > $(TMP)/usr/share/doc/mariadb-server-10.6/mariadbd.sym.gz # rename and install AppArmor profile - install -D -m 644 debian/apparmor-profile $(TMP)/etc/apparmor.d/usr.sbin.mysqld + install -D -m 644 debian/apparmor-profile $(TMP)/etc/apparmor.d/usr.sbin.mariadbd # Install libmariadbclient18 compatibility links ln -s libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmariadbclient.so @@ -169,7 +168,7 @@ override_dh_systemd_enable: # Start mysql at sequence number 19 before 20 where apache, proftpd etc gets # started which might depend on a running database server. override_dh_installinit-arch: - #dh_installinit --name=mysql -- defaults 19 21 + dh_installinit --name=mariadb --no-start -- defaults 19 21 dh_systemd_start --restart-after-upgrade diff --git a/debian/tests/smoke b/debian/tests/smoke index 86664110f6e..600864ff012 100644 --- a/debian/tests/smoke +++ b/debian/tests/smoke @@ -29,10 +29,10 @@ set -ex # be started manually. if ! which systemctl then - if ! /etc/init.d/mysql status + if ! /etc/init.d/mariadb status then echo "Did not find systemctl and deamon was not running, starting it.." - /etc/init.d/mysql start + /etc/init.d/mariadb start fi else # If systemd (and systemctl) is available, but the service did not start, then diff --git a/extra/comp_err.c b/extra/comp_err.c index 52353ac9eea..6fe26c4e4be 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -788,6 +788,7 @@ static ha_checksum checksum_format_specifier(const char* msg) case 'x': case 's': case 'M': + case 'T': start= 0; /* Not in format specifier anymore */ break; } diff --git a/extra/crc32-vpmsum/CMakeLists.txt b/extra/crc32-vpmsum/CMakeLists.txt deleted file mode 100644 index b4adebdadf5..00000000000 --- a/extra/crc32-vpmsum/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -ADD_CONVENIENCE_LIBRARY(${CRC32_LIBRARY} $ $) -ADD_LIBRARY(crc32c OBJECT vec_crc32.c) -ADD_LIBRARY(crc32ieee OBJECT vec_crc32.c) - -GET_PROPERTY(CFLAGS_CRC32_VPMSUM TARGET ${CRC32_LIBRARY} PROPERTY COMPILE_FLAGS) -SET_TARGET_PROPERTIES(crc32c crc32ieee PROPERTIES COMPILE_FLAGS "${CFLAGS_CRC32_VPMSUM} -maltivec -mvsx -mpower8-vector -mcrypto -mpower8-vector") -SET_TARGET_PROPERTIES(crc32ieee PROPERTIES COMPILE_DEFINITIONS "CRC32_FUNCTION=crc32ieee_vpmsum;CRC32_CONSTANTS_HEADER=\"crc32ieee_constants.h\"") -SET_TARGET_PROPERTIES(crc32c PROPERTIES COMPILE_DEFINITIONS "CRC32_FUNCTION=crc32c_vpmsum;CRC32_CONSTANTS_HEADER=\"crc32c_constants.h\"") - diff --git a/extra/crc32_armv8_neon/CMakeLists.txt b/extra/crc32_armv8_neon/CMakeLists.txt deleted file mode 100644 index ba1d34d7c2e..00000000000 --- a/extra/crc32_armv8_neon/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) - -ADD_CONVENIENCE_LIBRARY(${CRC32_LIBRARY} $) -ADD_LIBRARY(common_crc32c_armv8 OBJECT crc32_armv8.c) - -SET_TARGET_PROPERTIES(common_crc32c_armv8 PROPERTIES COMPILE_FLAGS "${ARMV8_CRC_COMPILE_FLAGS}") - diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index ad36d2fa6a6..561f2ab0500 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -33,7 +33,6 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/sql ${CMAKE_CURRENT_SOURCE_DIR}/quicklz ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/crc ) IF(NOT HAVE_SYSTEM_REGEX) @@ -84,9 +83,8 @@ MYSQL_ADD_EXECUTABLE(mariadb-backup # Export all symbols on Unix, for better crash callstacks SET_TARGET_PROPERTIES(mariadb-backup PROPERTIES ENABLE_EXPORTS TRUE) -ADD_SUBDIRECTORY(crc) -TARGET_LINK_LIBRARIES(mariadb-backup sql sql_builtins crc) +TARGET_LINK_LIBRARIES(mariadb-backup sql sql_builtins) IF(NOT HAVE_SYSTEM_REGEX) TARGET_LINK_LIBRARIES(mariadb-backup pcre2-posix) ENDIF() @@ -109,7 +107,6 @@ MYSQL_ADD_EXECUTABLE(mbstream TARGET_LINK_LIBRARIES(mbstream mysys - crc ) ADD_DEPENDENCIES(mbstream GenError) diff --git a/extra/mariabackup/crc/CMakeLists.txt b/extra/mariabackup/crc/CMakeLists.txt deleted file mode 100644 index c057e59a7b9..00000000000 --- a/extra/mariabackup/crc/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2017 Percona LLC 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 as published by -# the Free Software Foundation; version 2 of the License. - -# 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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -PROJECT(crc C) - -IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC) - STRING(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} processor) - IF(processor MATCHES "86" OR processor MATCHES "amd64" OR processor MATCHES "x64") - # Check for PCLMUL instruction - CHECK_C_SOURCE_RUNS(" - int main() - { - asm volatile (\"pclmulqdq \\$0x00, %%xmm1, %%xmm0\":::\"cc\"); - return 0; - }" HAVE_CLMUL_INSTRUCTION) - ENDIF() -ENDIF() -IF(HAVE_CLMUL_INSTRUCTION) - ADD_DEFINITIONS(-DHAVE_CLMUL_INSTRUCTION) -ENDIF() -ADD_LIBRARY(crc STATIC crc_glue.c crc-intel-pclmul.c) diff --git a/extra/mariabackup/crc/config.h.cmake b/extra/mariabackup/crc/config.h.cmake deleted file mode 100644 index beca62d1efb..00000000000 --- a/extra/mariabackup/crc/config.h.cmake +++ /dev/null @@ -1,21 +0,0 @@ -/****************************************************** -Copyright (c) 2017 Percona LLC and/or its affiliates. - -Zlib compatible CRC-32 implementation. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ - -#cmakedefine HAVE_CLMUL_INSTRUCTION 1 diff --git a/extra/mariabackup/crc/crc-intel-pclmul.h b/extra/mariabackup/crc/crc-intel-pclmul.h deleted file mode 100644 index c95c59601ae..00000000000 --- a/extra/mariabackup/crc/crc-intel-pclmul.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************** -Copyright (c) 2017 Percona LLC and/or its affiliates. - -CRC32 using Intel's PCLMUL instruction. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ - -#include -#include - -void -crc32_intel_pclmul(uint32_t *pcrc, const uint8_t *inbuf, size_t inlen); diff --git a/extra/mariabackup/crc/crc_glue.c b/extra/mariabackup/crc/crc_glue.c deleted file mode 100644 index bc14d0bb9df..00000000000 --- a/extra/mariabackup/crc/crc_glue.c +++ /dev/null @@ -1,72 +0,0 @@ -/****************************************************** -Copyright (c) 2017 Percona LLC and/or its affiliates. - -Zlib compatible CRC-32 implementation. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ -#include "my_config.h" -#include "crc_glue.h" -#include "crc-intel-pclmul.h" -#include -#include -#include - -#if defined(__GNUC__) && defined(__x86_64__) -static int pclmul_enabled = 0; -#endif - -#if defined(__GNUC__) && defined(__x86_64__) -static -uint32_t -cpuid(uint32_t* ecx, uint32_t* edx) -{ - uint32_t level; - - asm("cpuid" : "=a" (level) : "a" (0) : "ebx", "ecx", "edx"); - - if (level < 1) { - return level; - } - - asm("cpuid" : "=c" (*ecx), "=d" (*edx) - : "a" (1) - : "ebx"); - - return level; -} -#endif - -void crc_init() { -#if defined(__GNUC__) && defined(__x86_64__) - uint32_t ecx, edx; - - if (cpuid(&ecx, &edx) > 0) { - pclmul_enabled = ((ecx >> 19) & 1) && ((ecx >> 1) & 1); - } -#endif -} - -unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len) -{ -#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION) - if (pclmul_enabled) { - uint32_t crc_accum = (uint32_t) ~crc; - crc32_intel_pclmul(&crc_accum, buf, len); - return ~crc_accum; - } -#endif - return crc32(crc, buf, len); -} diff --git a/extra/mariabackup/crc/crc_glue.h b/extra/mariabackup/crc/crc_glue.h deleted file mode 100644 index 598330263b3..00000000000 --- a/extra/mariabackup/crc/crc_glue.h +++ /dev/null @@ -1,31 +0,0 @@ -/****************************************************** -Copyright (c) 2017 Percona LLC and/or its affiliates. - -Zlib compatible CRC-32 implementation. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ - - -#ifdef __cplusplus -extern "C" { -#endif - -void crc_init(); -unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len); - -#ifdef __cplusplus -} -#endif diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index 319399b97c5..9e95d2e6b16 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -112,6 +112,8 @@ bool ibx_partial_backup = false; char *ibx_position_arg = NULL; char *ibx_backup_directory = NULL; +extern bool xb_opt_destroy_password; + /* copy of proxied xtrabackup options */ my_bool ibx_xb_close_files; const char *ibx_xtrabackup_compress_alg; @@ -770,18 +772,7 @@ ibx_get_one_option(const struct my_option *opt, xtrabackup_compress = TRUE; break; case 'p': - if (argument) - { - char *start = argument; - my_free(opt_ibx_password); - opt_ibx_password= my_strdup(PSI_NOT_INSTRUMENTED, - argument, MYF(MY_FAE)); - /* Destroy argument */ - while (*argument) - *argument++= 'x'; - if (*start) - start[1]=0 ; - } + opt_ibx_password= argument; break; } return(0); diff --git a/extra/mariabackup/xbstream.cc b/extra/mariabackup/xbstream.cc index ba55141cdd9..761b8e69890 100644 --- a/extra/mariabackup/xbstream.cc +++ b/extra/mariabackup/xbstream.cc @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include "common.h" #include "xbstream.h" #include "datasink.h" -#include "crc_glue.h" #define XBSTREAM_VERSION "1.0" #define XBSTREAM_BUFFER_SIZE (10 * 1024 * 1024UL) @@ -98,7 +97,7 @@ main(int argc, char **argv) { MY_INIT(argv[0]); - crc_init(); + my_checksum_init(); if (get_options(&argc, &argv)) { goto err; diff --git a/extra/mariabackup/xbstream_read.cc b/extra/mariabackup/xbstream_read.cc index 3880dd50ed5..84bb279aba0 100644 --- a/extra/mariabackup/xbstream_read.cc +++ b/extra/mariabackup/xbstream_read.cc @@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include "common.h" #include "xbstream.h" -#include "crc_glue.h" /* Allocate 1 MB for the payload buffer initially */ #define INIT_BUFFER_LEN (1024 * 1024) @@ -71,8 +70,7 @@ xb_rstream_result_t xb_stream_validate_checksum(xb_rstream_chunk_t *chunk) { ulong checksum; - - checksum = crc32_iso3309(0, (unsigned char *)chunk->data, (uint)chunk->length); + checksum = my_checksum(0, chunk->data, chunk->length); if (checksum != chunk->checksum) { msg("xb_stream_read_chunk(): invalid checksum at offset " "0x%llx: expected 0x%lx, read 0x%lx.", diff --git a/extra/mariabackup/xbstream_write.cc b/extra/mariabackup/xbstream_write.cc index b6fd9c294a5..2c9ffde6c42 100644 --- a/extra/mariabackup/xbstream_write.cc +++ b/extra/mariabackup/xbstream_write.cc @@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include "common.h" #include "xbstream.h" -#include "crc_glue.h" /* Group writes smaller than this into a single chunk */ #define XB_STREAM_MIN_CHUNK_SIZE (10 * 1024 * 1024) @@ -216,7 +215,7 @@ xb_stream_write_chunk(xb_wstream_file_t *file, const void *buf, size_t len) int8store(ptr, len); /* Payload length */ ptr += 8; - checksum = crc32_iso3309(0, (const uchar *)buf, (uint)len); /* checksum */ + checksum = my_checksum(0, buf, len); pthread_mutex_lock(&stream->mutex); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 04b47c12e0a..f4c793fc1d8 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -101,7 +101,6 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include "encryption_plugin.h" #include #include -#include #include #include #include @@ -119,6 +118,8 @@ my_bool xtrabackup_copy_back; my_bool xtrabackup_move_back; my_bool xtrabackup_decrypt_decompress; my_bool xtrabackup_print_param; +my_bool xtrabackup_mysqld_args; +my_bool xtrabackup_help; my_bool xtrabackup_export; @@ -157,16 +158,16 @@ typedef std::list regex_list_t; static regex_list_t regex_include_list; static regex_list_t regex_exclude_list; -static hash_table_t* tables_include_hash = NULL; -static hash_table_t* tables_exclude_hash = NULL; +static hash_table_t tables_include_hash; +static hash_table_t tables_exclude_hash; char *xtrabackup_databases = NULL; char *xtrabackup_databases_file = NULL; char *xtrabackup_databases_exclude = NULL; -static hash_table_t* databases_include_hash = NULL; -static hash_table_t* databases_exclude_hash = NULL; +static hash_table_t databases_include_hash; +static hash_table_t databases_exclude_hash; -static hash_table_t* inc_dir_tables_hash; +static hash_table_t inc_dir_tables_hash; struct xb_filter_entry_struct{ char* name; @@ -798,7 +799,8 @@ enum options_xtrabackup OPT_LOCK_DDL_PER_TABLE, OPT_ROCKSDB_DATADIR, OPT_BACKUP_ROCKSDB, - OPT_XTRA_CHECK_PRIVILEGES + OPT_XTRA_CHECK_PRIVILEGES, + OPT_XTRA_MYSQLD_ARGS }; struct my_option xb_client_options[]= { @@ -1192,7 +1194,6 @@ struct my_option xb_client_options[]= { #define MYSQL_CLIENT #include "sslopt-longopts.h" #undef MYSQL_CLIENT - {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}}; uint xb_client_options_count = array_elements(xb_client_options); @@ -1408,6 +1409,18 @@ struct my_option xb_server_options[] = &opt_check_privileges, &opt_check_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + {"mysqld-args", OPT_XTRA_MYSQLD_ARGS, + "All arguments that follow this argument are considered as server " + "options, and if some of them are not supported by mariabackup, they " + "will be ignored.", + (G_PTR *) &xtrabackup_mysqld_args, (G_PTR *) &xtrabackup_mysqld_args, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + + {"help", '?', + "Display this help and exit.", + (G_PTR *) &xtrabackup_help, (G_PTR *) &xtrabackup_help, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1575,24 +1588,11 @@ end: return err; } +static const char *xb_client_default_groups[]= { + "client", "client-server", "client-mariadb", 0, 0, 0}; -static const char *xb_client_default_groups[]={ - "xtrabackup", "mariabackup", - "client", "client-server", - "client-mariadb", - 0, 0, 0 -}; - -static const char *xb_server_default_groups[]={ - "xtrabackup", "mariabackup", - "mysqld", "server", MYSQL_BASE_VERSION, - "mariadb", MARIADB_BASE_VERSION, - "client-server", - #ifdef WITH_WSREP - "galera", - #endif - 0, 0, 0 -}; +static const char *backup_default_groups[]= { + "xtrabackup", "mariabackup", "mariadb-backup", 0, 0, 0}; static void print_version(void) { @@ -1620,7 +1620,7 @@ GNU General Public License for more details.\n\ You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n"); printf("Usage: %s [--defaults-file=#] [--backup | --prepare | --copy-back | --move-back] [OPTIONS]\n",my_progname); - print_defaults("my", xb_server_default_groups); + print_defaults("my", load_default_groups); my_print_help(xb_client_options); my_print_help(xb_server_options); my_print_variables(xb_server_options); @@ -1755,15 +1755,7 @@ xb_get_one_option(const struct my_option *opt, } break; case 'p': - if (argument) - { - char *start= argument; - my_free(opt_password); - opt_password= my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE)); - while (*argument) *argument++= 'x'; // Destroy argument - if (*start) - start[1]=0 ; - } + opt_password = argument; break; case OPT_PROTOCOL: if (argument) @@ -2270,7 +2262,7 @@ check_if_table_matches_filters(const char *name, const regex_list_t& regex_list, hash_table_t* tables_hash) { - if (regex_list.empty() && !tables_hash) { + if (regex_list.empty() && !tables_hash->array) { return(FALSE); } @@ -2278,11 +2270,8 @@ check_if_table_matches_filters(const char *name, return(TRUE); } - if (tables_hash && find_filter_in_hashtable(name, tables_hash, NULL)) { - return(TRUE); - } - - return FALSE; + return tables_hash->array && + find_filter_in_hashtable(name, tables_hash, NULL); } enum skip_database_check_result { @@ -2308,8 +2297,8 @@ check_if_skip_database( /* There are some filters for databases, check them */ xb_filter_entry_t* database = NULL; - if (databases_exclude_hash && - find_filter_in_hashtable(name, databases_exclude_hash, + if (databases_exclude_hash.array && + find_filter_in_hashtable(name, &databases_exclude_hash, &database) && !database->has_tables) { /* Database is found and there are no tables specified, @@ -2317,8 +2306,8 @@ check_if_skip_database( return DATABASE_SKIP; } - if (databases_include_hash) { - if (!find_filter_in_hashtable(name, databases_include_hash, + if (databases_include_hash.array) { + if (!find_filter_in_hashtable(name, &databases_include_hash, &database)) { /* Database isn't found, skip the database */ return DATABASE_SKIP; @@ -2342,8 +2331,7 @@ check_if_skip_database_by_path( const char* path /*!< in: path to the db directory. */ ) { - if (databases_include_hash == NULL && - databases_exclude_hash == NULL) { + if (!databases_include_hash.array && !databases_exclude_hash.array) { return(FALSE); } @@ -2387,10 +2375,10 @@ check_if_skip_table( if (regex_exclude_list.empty() && regex_include_list.empty() && - tables_include_hash == NULL && - tables_exclude_hash == NULL && - databases_include_hash == NULL && - databases_exclude_hash == NULL) { + !tables_include_hash.array && + !tables_exclude_hash.array && + !databases_include_hash.array && + !databases_exclude_hash.array) { return(FALSE); } @@ -2422,22 +2410,22 @@ check_if_skip_table( without truncating the #P#... suffix so we can backup individual partitions with regexps like '^test[.]t#P#p5' */ if (check_if_table_matches_filters(buf, regex_exclude_list, - tables_exclude_hash)) { + &tables_exclude_hash)) { return(TRUE); } if (check_if_table_matches_filters(buf, regex_include_list, - tables_include_hash)) { + &tables_include_hash)) { return(FALSE); } if ((eptr = strstr(buf, "#P#")) != NULL) { *eptr = 0; if (check_if_table_matches_filters(buf, regex_exclude_list, - tables_exclude_hash)) { + &tables_exclude_hash)) { return (TRUE); } if (check_if_table_matches_filters(buf, regex_include_list, - tables_include_hash)) { + &tables_include_hash)) { return(FALSE); } } @@ -2450,7 +2438,7 @@ check_if_skip_table( if (skip_database == DATABASE_SKIP_SOME_TABLES || !regex_include_list.empty() || - tables_include_hash) { + tables_include_hash.array) { /* Include lists are present, but qualified name failed to match any.*/ @@ -3475,17 +3463,17 @@ xb_filter_entry_t* xb_add_filter( /*========================*/ const char* name, /*!< in: name of table/database */ - hash_table_t** hash) /*!< in/out: hash to insert into */ + hash_table_t* hash) /*!< in/out: hash to insert into */ { xb_filter_entry_t* entry; entry = xb_new_filter_entry(name); - if (UNIV_UNLIKELY(*hash == NULL)) { - *hash = hash_create(1000); + if (UNIV_UNLIKELY(!hash->array)) { + hash->create(1000); } HASH_INSERT(xb_filter_entry_t, - name_hash, *hash, + name_hash, hash, ut_fold_string(entry->name), entry); @@ -3523,8 +3511,8 @@ void xb_register_filter_entry( /*=====================*/ const char* name, /*!< in: name */ - hash_table_t** databases_hash, - hash_table_t** tables_hash + hash_table_t* databases_hash, + hash_table_t* tables_hash ) { const char* p; @@ -3541,8 +3529,8 @@ xb_register_filter_entry( strncpy(dbname, name, p - name); dbname[p - name] = 0; - if (*databases_hash) { - HASH_SEARCH(name_hash, (*databases_hash), + if (databases_hash) { + HASH_SEARCH(name_hash, databases_hash, ut_fold_string(dbname), xb_filter_entry_t*, db_entry, (void) 0, @@ -3741,7 +3729,7 @@ xb_filter_hash_free(hash_table_t* hash) ulint i; /* free the hash elements */ - for (i = 0; i < hash_get_n_cells(hash); i++) { + for (i = 0; i < hash->n_cells; i++) { xb_filter_entry_t* table; table = static_cast @@ -3759,8 +3747,7 @@ xb_filter_hash_free(hash_table_t* hash) } } - /* free hash */ - hash_table_free(hash); + hash->free(); } static void xb_regex_list_free(regex_list_t* list) @@ -3780,20 +3767,20 @@ xb_filters_free() xb_regex_list_free(®ex_include_list); xb_regex_list_free(®ex_exclude_list); - if (tables_include_hash) { - xb_filter_hash_free(tables_include_hash); + if (tables_include_hash.array) { + xb_filter_hash_free(&tables_include_hash); } - if (tables_exclude_hash) { - xb_filter_hash_free(tables_exclude_hash); + if (tables_exclude_hash.array) { + xb_filter_hash_free(&tables_exclude_hash); } - if (databases_include_hash) { - xb_filter_hash_free(databases_include_hash); + if (databases_include_hash.array) { + xb_filter_hash_free(&databases_include_hash); } - if (databases_exclude_hash) { - xb_filter_hash_free(databases_exclude_hash); + if (databases_exclude_hash.array) { + xb_filter_hash_free(&databases_exclude_hash); } } @@ -4034,7 +4021,7 @@ fail: trx_pool_init(); ut_crc32_init(); - crc_init(); + my_checksum_init(); recv_sys.create(); #ifdef WITH_INNODB_DISALLOW_WRITES @@ -4658,7 +4645,7 @@ exit: table->name = ((char*)table) + sizeof(xb_filter_entry_t); strcpy(table->name, dest_space_name); - HASH_INSERT(xb_filter_entry_t, name_hash, inc_dir_tables_hash, + HASH_INSERT(xb_filter_entry_t, name_hash, &inc_dir_tables_hash, ut_fold_string(table->name), table); mutex_enter(&fil_system.mutex); @@ -5048,7 +5035,7 @@ rm_if_not_found( /* Truncate ".ibd" */ name[strlen(name) - 4] = '\0'; - HASH_SEARCH(name_hash, inc_dir_tables_hash, ut_fold_string(name), + HASH_SEARCH(name_hash, &inc_dir_tables_hash, ut_fold_string(name), xb_filter_entry_t*, table, (void) 0, !strcmp(table->name, name)); @@ -5424,7 +5411,7 @@ static bool xtrabackup_prepare_func(char** argv) goto error_cleanup; } - inc_dir_tables_hash = hash_create(1000); + inc_dir_tables_hash.create(1000); ok = xtrabackup_apply_deltas(); @@ -5437,7 +5424,7 @@ static bool xtrabackup_prepare_func(char** argv) xb_process_datadir("./", ".ibd", rm_if_not_found); } - xb_filter_hash_free(inc_dir_tables_hash); + xb_filter_hash_free(&inc_dir_tables_hash); fil_system.close(); #ifdef WITH_INNODB_DISALLOW_WRITES @@ -5535,7 +5522,7 @@ static bool xtrabackup_prepare_func(char** argv) error_cleanup: xb_filters_free(); - return ok; + return ok && !ib::error::was_logged(); } /************************************************************************** @@ -5802,11 +5789,23 @@ void setup_error_messages() die("could not initialize error messages"); } -void -handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) +/** Handle mariabackup options. The options are handled with the following +order: + +1) Load server groups and process server options, ignore unknown options +2) Load client groups and process client options, ignore unknown options +3) Load backup groups and process client-server options, exit on unknown option +4) Process --mysqld-args options, ignore unknown options + +@param[in] argc arguments count +@param[in] argv arguments array +@param[out] argv_server server options including loaded from server groups +@param[out] argv_client client options including loaded from client groups +@param[out] argv_backup backup options including loaded from backup groups */ +void handle_options(int argc, char **argv, char ***argv_server, + char ***argv_client, char ***argv_backup) { /* Setup some variables for Innodb.*/ - srv_operation = SRV_OPERATION_RESTORE; files_charset_info = &my_charset_utf8mb3_general_ci; @@ -5833,49 +5832,64 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) bool prepare = false; char conf_file[FN_REFLEN]; - int argc_client = argc; - int argc_server = argc; - /* scan options for group and config file to load defaults from */ - for (i = 1; i < argc; i++) { + // array_elements() will not work for load_defaults, as it is defined + // as external symbol, so let's use dynamic array to have ability to + // add new server default groups + std::vector server_default_groups; - char *optend = strcend(argv[i], '='); + for (const char **default_group= load_default_groups; *default_group; + ++default_group) + server_default_groups.push_back(*default_group); - if (strncmp(argv[i], "--defaults-group", - optend - argv[i]) == 0) { - defaults_group = optend + 1; - append_defaults_group(defaults_group, - xb_server_default_groups, - array_elements(xb_server_default_groups)); - } + std::vector mysqld_args; + std::vector mariabackup_args; + mysqld_args.push_back(argv[0]); + mariabackup_args.push_back(argv[0]); - if (strncmp(argv[i], "--login-path", - optend - argv[i]) == 0) { - append_defaults_group(optend + 1, - xb_client_default_groups, - array_elements(xb_client_default_groups)); - } + /* scan options for group and config file to load defaults from */ + for (i= 1; i < argc; i++) + { + char *optend= strcend(argv[i], '='); + if (mysqld_args.size() > 1 || + strncmp(argv[i], "--mysqld-args", optend - argv[i]) == 0) + { + mysqld_args.push_back(argv[i]); + continue; + } + else + mariabackup_args.push_back(argv[i]); - if (!strncmp(argv[i], "--prepare", - optend - argv[i])) { - prepare = true; - } - - if (!strncmp(argv[i], "--apply-log", - optend - argv[i])) { - prepare = true; - } - - if (!strncmp(argv[i], "--target-dir", - optend - argv[i]) && *optend) { - target_dir = optend + 1; - } - - if (!*optend && argv[i][0] != '-') { - target_dir = argv[i]; - } - } + if (strncmp(argv[i], "--defaults-group", optend - argv[i]) == 0) + { + defaults_group= optend + 1; + server_default_groups.push_back(defaults_group); + } + else if (strncmp(argv[i], "--login-path", optend - argv[i]) == 0) + { + append_defaults_group(optend + 1, xb_client_default_groups, + array_elements(xb_client_default_groups)); + } + else if (!strncmp(argv[i], "--prepare", optend - argv[i])) + { + prepare= true; + } + else if (!strncmp(argv[i], "--apply-log", optend - argv[i])) + { + prepare= true; + } + else if (!strncmp(argv[i], "--target-dir", optend - argv[i]) && + *optend) + { + target_dir= optend + 1; + } + else if (!*optend && argv[i][0] != '-') + { + target_dir= argv[i]; + } + } + server_default_groups.push_back(NULL); snprintf(conf_file, sizeof(conf_file), "my"); if (prepare && target_dir) { @@ -5891,10 +5905,16 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) } } - *argv_client = argv; - *argv_server = argv; - load_defaults_or_exit(conf_file, xb_server_default_groups, - &argc_server, argv_server); + *argv_client= *argv_server= *argv_backup= &mariabackup_args[0]; + int argc_backup= static_cast(mariabackup_args.size()); + int argc_client= argc_backup; + int argc_server= argc_backup; + + /* 1) Load server groups and process server options, ignore unknown + options */ + + load_defaults_or_exit(conf_file, &server_default_groups[0], + &argc_server, argv_server); int n; for (n = 0; (*argv_server)[n]; n++) {}; @@ -5914,7 +5934,6 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) optp->u_max_value = (G_PTR *) &global_max_value; } - /* Throw a descriptive error if --defaults-file or --defaults-extra-file is not the first command line argument */ for (int i = 2 ; i < argc ; i++) { @@ -5936,6 +5955,9 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) xb_server_options, xb_get_one_option))) exit(ho_error); + /* 2) Load client groups and process client options, ignore unknown + options */ + load_defaults_or_exit(conf_file, xb_client_default_groups, &argc_client, argv_client); @@ -5943,8 +5965,6 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) argc_client = n; if (innobackupex_mode && argc_client > 0) { - /* emulate innobackupex script */ - innobackupex_mode = true; if (!ibx_handle_options(&argc_client, argv_client)) { exit(EXIT_FAILURE); } @@ -5955,18 +5975,76 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) xb_client_options, xb_get_one_option))) exit(ho_error); + /* 3) Load backup groups and process client-server options, exit on + unknown option */ + + load_defaults_or_exit(conf_file, backup_default_groups, &argc_backup, + argv_backup); + for (n= 0; (*argv_backup)[n]; n++) + { + }; + argc_backup= n; + + my_handle_options_init_variables = FALSE; + + if (argc_backup > 0 && + (ho_error= handle_options(&argc_backup, argv_backup, + xb_server_options, xb_get_one_option))) + exit(ho_error); + + /* Add back the program name handle_options removes */ + ++argc_backup; + --(*argv_backup); + + if (innobackupex_mode && argc_backup > 0 && + !ibx_handle_options(&argc_backup, argv_backup)) + exit(EXIT_FAILURE); + + my_getopt_skip_unknown = FALSE; + + if (argc_backup > 0 && + (ho_error= handle_options(&argc_backup, argv_backup, + xb_client_options, xb_get_one_option))) + exit(ho_error); + + if (opt_password) + { + char *argument= opt_password; + char *start= argument; + opt_password= my_strdup(PSI_NOT_INSTRUMENTED, opt_password, MYF(MY_FAE)); + while (*argument) + *argument++= 'x'; // Destroy argument + if (*start) + start[1]= 0; + } + + /* 4) Process --mysqld-args options, ignore unknown options */ + + my_getopt_skip_unknown = TRUE; + + int argc_mysqld = static_cast(mysqld_args.size()); + if (argc_mysqld > 1) + { + char **argv_mysqld= &mysqld_args[0]; + if ((ho_error= handle_options(&argc_mysqld, &argv_mysqld, + xb_server_options, xb_get_one_option))) + exit(ho_error); + } + + my_handle_options_init_variables = TRUE; + /* Reject command line arguments that don't look like options, i.e. are not of the form '-X' (single-character options) or '--option' (long options) */ - for (int i = 0 ; i < argc_client ; i++) { - const char * const opt = (*argv_client)[i]; + for (int i = 0 ; i < argc_backup ; i++) { + const char * const opt = (*argv_backup)[i]; if (strncmp(opt, "--", 2) && !(strlen(opt) == 2 && opt[0] == '-')) { bool server_option = true; - for (int j = 0; j < argc_server; j++) { - if (opt == (*argv_server)[j]) { + for (int j = 0; j < argc_backup; j++) { + if (opt == (*argv_backup)[j]) { server_option = false; break; } @@ -5987,7 +6065,9 @@ static int get_exepath(char *buf, size_t size, const char *argv0); /* ================= main =================== */ int main(int argc, char **argv) { - char **client_defaults, **server_defaults; + char **server_defaults; + char **client_defaults; + char **backup_defaults; if (get_exepath(mariabackup_exe,FN_REFLEN, argv[0])) strncpy(mariabackup_exe,argv[0], FN_REFLEN-1); @@ -6038,7 +6118,8 @@ int main(int argc, char **argv) mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST); - handle_options(argc, argv, &client_defaults, &server_defaults); + handle_options(argc, argv, &server_defaults, &client_defaults, + &backup_defaults); #ifndef DBUG_OFF if (dbug_option) { @@ -6058,8 +6139,9 @@ int main(int argc, char **argv) ibx_cleanup(); } - free_defaults(client_defaults); free_defaults(server_defaults); + free_defaults(client_defaults); + free_defaults(backup_defaults); #ifndef DBUG_OFF if (dbug_option) { diff --git a/extra/replace.c b/extra/replace.c index 0d35c6d0194..7e94bfc36c3 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -64,7 +64,7 @@ typedef struct st_pointer_array { /* when using array-strings */ #define LAST_CHAR_CODE 259 typedef struct st_replace { - my_bool found; + uint8 found; struct st_replace *next[256]; } REPLACE; @@ -654,7 +654,13 @@ static REPLACE *init_replace(char * *from, char * *to,uint count, for (i=1 ; i <= found_sets ; i++) { pos=from[found_set[i-1].table_offset]; - rep_str[i].found= (my_bool) (!memcmp(pos,"\\^",3) ? 2 : 1); + /* + Test if we are matching start of string (\^) + We can't use bcmp() here as pos may be only 1 character and + that would confuse MSAN. + */ + rep_str[i].found= (uint8) ((pos[0] == '\\' && pos[1] == '^' && + pos[2] == 0) ? 2 : 1); rep_str[i].replace_string=to_array[found_set[i-1].table_offset]; rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos); rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+ diff --git a/extra/wolfssl/CMakeLists.txt b/extra/wolfssl/CMakeLists.txt index e2ba345e3c8..8fe79dccf3d 100644 --- a/extra/wolfssl/CMakeLists.txt +++ b/extra/wolfssl/CMakeLists.txt @@ -1,6 +1,6 @@ IF(MSVC) PROJECT(wolfssl C ASM_MASM) -ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") PROJECT(wolfssl C ASM) ELSE() PROJECT(wolfssl C) @@ -9,7 +9,7 @@ ENDIF() IF(CMAKE_SIZEOF_VOID_P MATCHES 8) IF(MSVC) SET(WOLFSSL_INTELASM ON) -ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") IF(CMAKE_C_COMPILER_ID MATCHES GNU AND CMAKE_C_COMPILER_VERSION VERSION_LESS 4.9) MESSAGE_ONCE(NO_INTEL_ASSEMBLY "Disable Intel assembly for WolfSSL - compiler is too old") ELSEIF(WITH_MSAN) @@ -119,7 +119,7 @@ IF(WOLFSSL_INTELASM) SET(HAVE_INTEL_RDSEED 1) SET(WOLFSSL_X86_64_BUILD 1) ENDIF() - ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") SET(HAVE_INTEL_RDSEED 1) SET(USE_INTEL_SPEEDUP 1) LIST(APPEND WOLFCRYPT_SOURCES diff --git a/include/aria_backup.h b/include/aria_backup.h index 30c139c4234..f399f6a6f40 100644 --- a/include/aria_backup.h +++ b/include/aria_backup.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 MariaDB corporation +/* Copyright (C) 2018,2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/include/intrusive_list.h b/include/ilist.h similarity index 66% rename from include/intrusive_list.h rename to include/ilist.h index d745c6c6c62..74cb472cd4e 100644 --- a/include/intrusive_list.h +++ b/include/ilist.h @@ -21,26 +21,28 @@ #include #include -namespace intrusive -{ - // Derive your class from this struct to insert to a linked list. -template struct list_node +template struct ilist_node { - list_node(list_node *next= NULL, list_node *prev= NULL) - : next(next), prev(prev) + ilist_node() +#ifndef DBUG_OFF + : + next(NULL), prev(NULL) +#endif { } - list_node *next; - list_node *prev; + ilist_node(ilist_node *next, ilist_node *prev) : next(next), prev(prev) {} + + ilist_node *next; + ilist_node *prev; }; // Modelled after std::list -template class list +template class ilist { public: - typedef list_node ListNode; + typedef ilist_node ListNode; class Iterator; // All containers in C++ should define these types to implement generic @@ -97,16 +99,22 @@ public: reference operator*() { return *static_cast(node_); } pointer operator->() { return static_cast(node_); } - bool operator==(const Iterator &rhs) { return node_ == rhs.node_; } - bool operator!=(const Iterator &rhs) { return !(*this == rhs); } + friend bool operator==(const Iterator &lhs, const Iterator &rhs) + { + return lhs.node_ == rhs.node_; + } + friend bool operator!=(const Iterator &lhs, const Iterator &rhs) + { + return !(lhs == rhs); + } private: ListNode *node_; - friend class list; + friend class ilist; }; - list() : sentinel_(&sentinel_, &sentinel_), size_(0) {} + ilist() : sentinel_(&sentinel_, &sentinel_) {} reference front() { return *begin(); } reference back() { return *--end(); } @@ -129,14 +137,18 @@ public: reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return reverse_iterator(begin()); } - bool empty() const { return size_ == 0; } - size_type size() const { return size_; } + bool empty() const { return sentinel_.next == &sentinel_; } + + // Not implemented because it's O(N) + // size_type size() const + // { + // return static_cast(std::distance(begin(), end())); + // } void clear() { sentinel_.next= &sentinel_; sentinel_.prev= &sentinel_; - size_= 0; } iterator insert(iterator pos, reference value) @@ -150,7 +162,6 @@ public: static_cast(value).prev= prev; static_cast(value).next= curr; - ++size_; return iterator(&value); } @@ -162,13 +173,12 @@ public: prev->next= next; next->prev= prev; - // This is not required for list functioning. But maybe it'll prevent bugs - // and ease debugging. +#ifndef DBUG_OFF ListNode *curr= pos.node_; curr->prev= NULL; curr->next= NULL; +#endif - --size_; return next; } @@ -179,12 +189,63 @@ public: void pop_front() { erase(begin()); } // STL version is O(n) but this is O(1) because an element can't be inserted - // several times in the same intrusive list. + // several times in the same ilist. void remove(reference value) { erase(iterator(&value)); } private: ListNode sentinel_; - size_type size_; }; -} // namespace intrusive +// Similar to ilist but also has O(1) size() method. +template class sized_ilist : public ilist +{ + typedef ilist BASE; + +public: + // All containers in C++ should define these types to implement generic + // container interface. + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + typedef typename BASE::Iterator iterator; + typedef const typename BASE::Iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + sized_ilist() : size_(0) {} + + size_type size() const { return size_; } + + void clear() + { + BASE::clear(); + size_= 0; + } + + iterator insert(iterator pos, reference value) + { + ++size_; + return BASE::insert(pos, value); + } + + iterator erase(iterator pos) + { + --size_; + return BASE::erase(pos); + } + + void push_back(reference value) { insert(BASE::end(), value); } + void pop_back() { erase(BASE::end()); } + + void push_front(reference value) { insert(BASE::begin(), value); } + void pop_front() { erase(BASE::begin()); } + + void remove(reference value) { erase(iterator(&value)); } + +private: + size_type size_; +}; diff --git a/include/maria.h b/include/maria.h index a4c425ced47..7fdf95f7ac4 100644 --- a/include/maria.h +++ b/include/maria.h @@ -29,148 +29,19 @@ extern "C" { #endif -#define MARIA_CANNOT_ROLLBACK +#define MARIA_UNIQUE_HASH_LENGTH 4 +extern my_bool maria_delay_key_write; +uint maria_max_key_length(void); +#define maria_max_key_segments() HA_MAX_KEY_SEG -/* - Limit max keys according to HA_MAX_POSSIBLE_KEY; See myisamchk.h for details -*/ - -#if MAX_INDEXES > HA_MAX_POSSIBLE_KEY -#define MARIA_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ -#else -#define MARIA_MAX_KEY MAX_INDEXES /* Max allowed keys */ -#endif - -#define MARIA_NAME_IEXT ".MAI" -#define MARIA_NAME_DEXT ".MAD" -/* Max extra space to use when sorting keys */ -#define MARIA_MAX_TEMP_LENGTH (2*1024L*1024L*1024L) -/* Possible values for maria_block_size (must be power of 2) */ -#define MARIA_KEY_BLOCK_LENGTH 8192 /* default key block length */ -#define MARIA_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ -#define MARIA_MAX_KEY_BLOCK_LENGTH 32768 -/* Minimal page cache when we only want to be able to scan a table */ -#define MARIA_MIN_PAGE_CACHE_SIZE (8192L*16L) - -/* - In the following macros '_keyno_' is 0 .. keys-1. - If there can be more keys than bits in the key_map, the highest bit - is for all upper keys. They cannot be switched individually. - This means that clearing of high keys is ignored, setting one high key - sets all high keys. -*/ -#define MARIA_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) -#define MARIA_KEYMAP_HIGH_MASK (1ULL << (MARIA_KEYMAP_BITS - 1)) -#define maria_get_mask_all_keys_active(_keys_) \ - (((_keys_) < MARIA_KEYMAP_BITS) ? \ - ((1ULL << (_keys_)) - 1ULL) : \ - (~ 0ULL)) -#if MARIA_MAX_KEY > MARIA_KEYMAP_BITS -#define maria_is_key_active(_keymap_,_keyno_) \ - (((_keyno_) < MARIA_KEYMAP_BITS) ? \ - MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \ - MY_TEST((_keymap_) & MARIA_KEYMAP_HIGH_MASK)) -#define maria_set_key_active(_keymap_,_keyno_) \ - (_keymap_)|= (((_keyno_) < MARIA_KEYMAP_BITS) ? \ - (1ULL << (_keyno_)) : \ - MARIA_KEYMAP_HIGH_MASK) -#define maria_clear_key_active(_keymap_,_keyno_) \ - (_keymap_)&= (((_keyno_) < MARIA_KEYMAP_BITS) ? \ - (~ (1ULL << (_keyno_))) : \ - (~ (0ULL)) /*ignore*/ ) -#else -#define maria_is_key_active(_keymap_,_keyno_) \ - MY_TEST((_keymap_) & (1ULL << (_keyno_))) -#define maria_set_key_active(_keymap_,_keyno_) \ - (_keymap_)|= (1ULL << (_keyno_)) -#define maria_clear_key_active(_keymap_,_keyno_) \ - (_keymap_)&= (~ (1ULL << (_keyno_))) -#endif -#define maria_is_any_key_active(_keymap_) \ - MY_TEST((_keymap_)) -#define maria_is_all_keys_active(_keymap_,_keys_) \ - ((_keymap_) == maria_get_mask_all_keys_active(_keys_)) -#define maria_set_all_keys_active(_keymap_,_keys_) \ - (_keymap_)= maria_get_mask_all_keys_active(_keys_) -#define maria_clear_all_keys_active(_keymap_) \ - (_keymap_)= 0 -#define maria_intersect_keys_active(_to_,_from_) \ - (_to_)&= (_from_) -#define maria_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ - ((_keymap1_) & (_keymap2_) & \ - maria_get_mask_all_keys_active(_keys_)) -#define maria_copy_keys_active(_to_,_maxkeys_,_from_) \ - (_to_)= (maria_get_mask_all_keys_active(_maxkeys_) & \ - (_from_)) - - /* Param to/from maria_info */ - -typedef ulonglong MARIA_RECORD_POS; - -typedef struct st_maria_info -{ - ha_rows records; /* Records in database */ - ha_rows deleted; /* Deleted records in database */ - MARIA_RECORD_POS recpos; /* Pos for last used record */ - MARIA_RECORD_POS newrecpos; /* Pos if we write new record */ - MARIA_RECORD_POS dup_key_pos; /* Position to record with dup key */ - my_off_t data_file_length; /* Length of data file */ - my_off_t max_data_file_length, index_file_length; - my_off_t max_index_file_length, delete_length; - ulonglong auto_increment; - ulonglong key_map; /* Which keys are used */ - time_t create_time; /* When table was created */ - time_t check_time; - time_t update_time; - ulong record_offset; - double *rec_per_key; /* for sql optimizing */ - ulong reclength; /* Recordlength */ - ulong mean_reclength; /* Mean recordlength (if packed) */ - char *data_file_name, *index_file_name; - enum data_file_type data_file_type; - uint keys; /* Number of keys in use */ - uint options; /* HA_OPTION_... used */ - uint reflength; - int errkey, /* With key was dupplicated on err */ - sortkey; /* clustered by this key */ - File filenr; /* (uniq) filenr for datafile */ -} MARIA_INFO; - - -typedef struct st_maria_create_info -{ - const char *index_file_name, *data_file_name; /* If using symlinks */ - ha_rows max_rows; - ha_rows reloc_rows; - ulonglong auto_increment; - ulonglong data_file_length; - ulonglong key_file_length; - ulong s3_block_size; - /* Size of null bitmap at start of row */ - uint null_bytes; - uint old_options; - uint compression_algorithm; - enum data_file_type org_data_file_type; - uint16 language; - my_bool with_auto_increment, transactional, encrypted; -} MARIA_CREATE_INFO; - -struct st_maria_share; -struct st_maria_handler; /* For referense */ -typedef struct st_maria_handler MARIA_HA; -struct st_maria_s_param; -struct st_maria_keydef; +struct st_maria_bit_buff; struct st_maria_page; - -typedef struct st_maria_key /* Internal info about a key */ -{ - uchar *data; /* Data for key */ - struct st_maria_keydef *keyinfo; /* Definition for key */ - uint data_length; /* Length of key data */ - uint ref_length; /* record ref + transid */ - uint32 flag; /* 0 or SEARCH_PART_KEY */ -} MARIA_KEY; - +struct st_maria_s_param; +struct st_maria_share; +typedef struct st_maria_decode_tree MARIA_DECODE_TREE; +typedef struct st_maria_handler MARIA_HA; +typedef struct st_maria_key MARIA_KEY; +typedef ulonglong MARIA_RECORD_POS; typedef struct st_maria_keydef /* Key definition with open & info */ { @@ -213,8 +84,6 @@ typedef struct st_maria_keydef /* Key definition with open & info */ } MARIA_KEYDEF; -#define MARIA_UNIQUE_HASH_LENGTH 4 - typedef struct st_maria_unique_def /* Segment definition of unique */ { uint16 keysegs; /* Number of key-segment */ @@ -223,17 +92,6 @@ typedef struct st_maria_unique_def /* Segment definition of unique */ HA_KEYSEG *seg, *end; } MARIA_UNIQUEDEF; -typedef struct st_maria_decode_tree /* Decode huff-table */ -{ - uint16 *table; - uint quick_table_bits; - uchar *intervalls; -} MARIA_DECODE_TREE; - - -struct st_maria_bit_buff; -typedef struct s3_info S3_INFO; - /* Note that null markers should always be first in a row ! When creating a column, one should only specify: @@ -265,157 +123,32 @@ typedef struct st_maria_columndef /* column information */ } MARIA_COLUMNDEF; -extern ulong maria_block_size, maria_checkpoint_frequency; -extern ulong maria_concurrent_insert; -extern my_bool maria_flush, maria_single_user, maria_page_checksums; -extern my_bool maria_delay_key_write; -extern my_off_t maria_max_temp_length; -extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size; -extern MY_TMPDIR *maria_tmpdir; -extern my_bool maria_encrypt_tables; +typedef struct st_maria_create_info +{ + const char *index_file_name, *data_file_name; /* If using symlinks */ + ha_rows max_rows; + ha_rows reloc_rows; + ulonglong auto_increment; + ulonglong data_file_length; + ulonglong key_file_length; + ulong s3_block_size; + /* Size of null bitmap at start of row */ + uint null_bytes; + uint old_options; + uint compression_algorithm; + enum data_file_type org_data_file_type; + uint16 language; + my_bool with_auto_increment, transactional, encrypted; +} MARIA_CREATE_INFO; -/* - This is used to check if a symlink points into the mysql data home, - which is normally forbidden as it can be used to get access to - not privileged data -*/ -extern int (*maria_test_invalid_symlink)(const char *filename); - - /* Prototypes for maria-functions */ - -extern int maria_init(void); -extern void maria_end(void); -extern my_bool maria_upgrade(void); -extern int maria_close(MARIA_HA *file); -extern int maria_delete(MARIA_HA *file, const uchar *buff); -extern MARIA_HA *maria_open(const char *name, int mode, - uint wait_if_locked, S3_INFO *s3); -extern int maria_panic(enum ha_panic_function function); -extern int maria_rfirst(MARIA_HA *file, uchar *buf, int inx); -extern int maria_rkey(MARIA_HA *file, uchar *buf, int inx, - const uchar *key, key_part_map keypart_map, - enum ha_rkey_function search_flag); -extern int maria_rlast(MARIA_HA *file, uchar *buf, int inx); -extern int maria_rnext(MARIA_HA *file, uchar *buf, int inx); -extern int maria_rnext_same(MARIA_HA *info, uchar *buf); -extern int maria_rprev(MARIA_HA *file, uchar *buf, int inx); -extern int maria_rrnd(MARIA_HA *file, uchar *buf, - MARIA_RECORD_POS pos); -extern int maria_scan_init(MARIA_HA *file); -extern int maria_scan(MARIA_HA *file, uchar *buf); -extern void maria_scan_end(MARIA_HA *file); -extern int maria_rsame(MARIA_HA *file, uchar *record, int inx); -extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record, - int inx, MARIA_RECORD_POS pos); -extern int maria_update(MARIA_HA *file, const uchar *old, - const uchar *new_record); -extern int maria_write(MARIA_HA *file, const uchar *buff); -extern MARIA_RECORD_POS maria_position(MARIA_HA *file); -extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag); -extern int maria_lock_database(MARIA_HA *file, int lock_type); extern int maria_create(const char *name, enum data_file_type record_type, uint keys, MARIA_KEYDEF *keydef, - uint columns, MARIA_COLUMNDEF *columndef, - uint uniques, MARIA_UNIQUEDEF *uniquedef, - MARIA_CREATE_INFO *create_info, uint flags); -extern int maria_delete_table(const char *name); -extern int maria_rename(const char *from, const char *to); -extern int maria_extra(MARIA_HA *file, - enum ha_extra_function function, void *extra_arg); -extern int maria_reset(MARIA_HA *file); -extern ha_rows maria_records_in_range(MARIA_HA *info, int inx, - const key_range *min_key, - const key_range *max_key, - page_range *page); -extern int maria_is_changed(MARIA_HA *info); -extern int maria_delete_all_rows(MARIA_HA *info); -extern uint maria_get_pointer_length(ulonglong file_length, uint def); -extern int maria_commit(MARIA_HA *info); -extern int maria_begin(MARIA_HA *info); -extern void maria_disable_logging(MARIA_HA *info); -extern void maria_enable_logging(MARIA_HA *info); - -#define HA_RECOVER_NONE 0 /* No automatic recover */ -#define HA_RECOVER_DEFAULT 1 /* Automatic recover active */ -#define HA_RECOVER_BACKUP 2 /* Make a backupfile on recover */ -#define HA_RECOVER_FORCE 4 /* Recover even if we loose rows */ -#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */ - -#define HA_RECOVER_ANY (HA_RECOVER_DEFAULT | HA_RECOVER_BACKUP | HA_RECOVER_FORCE | HA_RECOVER_QUICK) - -/* this is used to pass to mysql_mariachk_table */ - -#define MARIA_CHK_REPAIR 1 /* equivalent to mariachk -r */ -#define MARIA_CHK_VERIFY 2 /* Verify, run repair if failure */ - -typedef uint maria_bit_type; - -typedef struct st_maria_bit_buff -{ /* Used for packing of record */ - maria_bit_type current_byte; - uint bits; - uchar *pos, *end, *blob_pos, *blob_end; - uint error; -} MARIA_BIT_BUFF; - -/* functions in maria_check */ -void maria_chk_init(HA_CHECK *param); -void maria_chk_init_for_check(HA_CHECK *param, MARIA_HA *info); -int maria_chk_status(HA_CHECK *param, MARIA_HA *info); -int maria_chk_del(HA_CHECK *param, MARIA_HA *info, ulonglong test_flag); -int maria_chk_size(HA_CHECK *param, MARIA_HA *info); -int maria_chk_key(HA_CHECK *param, MARIA_HA *info); -int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend); -int maria_repair(HA_CHECK *param, MARIA_HA *info, char * name, my_bool); -int maria_sort_index(HA_CHECK *param, MARIA_HA *info, char * name); -int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name); -int maria_repair_by_sort(HA_CHECK *param, MARIA_HA *info, - const char *name, my_bool rep_quick); -int maria_repair_parallel(HA_CHECK *param, MARIA_HA *info, - const char *name, my_bool rep_quick); -int maria_change_to_newfile(const char *filename, const char *old_ext, - const char *new_ext, time_t backup_time, - myf myflags); -void maria_lock_memory(HA_CHECK *param); -int maria_update_state_info(HA_CHECK *param, MARIA_HA *info, uint update); -void maria_update_key_parts(MARIA_KEYDEF *keyinfo, double *rec_per_key_part, - ulonglong *unique, ulonglong *notnull, - ulonglong records); -int maria_filecopy(HA_CHECK *param, File to, File from, my_off_t start, - my_off_t length, const char *type); -int maria_movepoint(MARIA_HA *info, uchar *record, my_off_t oldpos, - my_off_t newpos, uint prot_key); -int maria_test_if_almost_full(MARIA_HA *info); -int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename); -int maria_disable_indexes(MARIA_HA *info); -int maria_enable_indexes(MARIA_HA *info); -int maria_indexes_are_disabled(MARIA_HA *info); -void maria_disable_indexes_for_rebuild(MARIA_HA *info, ha_rows rows, - my_bool all_keys); -my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, ulonglong key_map, - my_bool force); - -int maria_init_bulk_insert(MARIA_HA *info, size_t cache_size, ha_rows rows); -void maria_flush_bulk_insert(MARIA_HA *info, uint inx); -int maria_end_bulk_insert(MARIA_HA *info, my_bool abort); -int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves); -void maria_versioning(MARIA_HA *info, my_bool versioning); -void maria_ignore_trids(MARIA_HA *info); -uint maria_max_key_length(void); -my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows); -#define maria_max_key_segments() HA_MAX_KEY_SEG - -/* fulltext functions */ -FT_INFO *maria_ft_init_search(uint,void *, uint, uchar *, size_t, - CHARSET_INFO *, uchar *); - -/* 'Almost-internal' Maria functions */ - -void _ma_update_auto_increment_key(HA_CHECK *param, MARIA_HA *info, - my_bool repair); - + uint columns, MARIA_COLUMNDEF *columndef, + uint uniques, MARIA_UNIQUEDEF *uniquedef, + MARIA_CREATE_INFO *create_info, uint flags); #ifdef __cplusplus } #endif #endif + diff --git a/include/my_alarm.h b/include/my_alarm.h index bc0004476ca..14a81c1ef17 100644 --- a/include/my_alarm.h +++ b/include/my_alarm.h @@ -31,7 +31,7 @@ extern ulong my_time_to_wait_for_lock; #include #ifdef HAVE_SIGHANDLER_T #define sig_return sighandler_t -#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) +#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || defined(__FreeBSD__) typedef void (*sig_return)(int); /* Returns type from signal */ #else typedef void (*sig_return)(void); /* Returns type from signal */ diff --git a/include/my_atomic.h b/include/my_atomic.h index 1c54c24d455..81da9e35cf9 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -2,6 +2,7 @@ #define MY_ATOMIC_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2018, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -168,5 +169,4 @@ #define my_atomic_casptr_strong_explicit(P, E, D, S, F) \ my_atomic_casptr((P), (E), (D)) #endif - #endif /* MY_ATOMIC_INCLUDED */ diff --git a/include/my_atomic_wrapper.h b/include/my_atomic_wrapper.h new file mode 100644 index 00000000000..61db886d53f --- /dev/null +++ b/include/my_atomic_wrapper.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2020, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + 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 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-1335 USA */ + +#ifdef __cplusplus +#include +/** + A wrapper for std::atomic, defaulting to std::memory_order_relaxed. + + When it comes to atomic loads or stores at std::memory_order_relaxed + on IA-32 or AMD64, this wrapper is only introducing some constraints + to the C++ compiler, to prevent some optimizations of loads or + stores. + + On POWER and ARM, atomic loads and stores involve different instructions + from normal loads and stores and will thus incur some overhead. + + Because atomic read-modify-write operations will always incur + overhead, we intentionally do not define + operator++(), operator--(), operator+=(), operator-=(), or similar, + to make the overhead stand out in the users of this code. +*/ +template class Atomic_relaxed +{ + std::atomic m; +public: + Atomic_relaxed(const Atomic_relaxed &rhs) + { m.store(rhs, std::memory_order_relaxed); } + Atomic_relaxed(Type val) : m(val) {} + Atomic_relaxed() {} + + operator Type() const { return m.load(std::memory_order_relaxed); } + Type operator=(const Type val) + { m.store(val, std::memory_order_relaxed); return val; } + Type operator=(const Atomic_relaxed &rhs) { return *this= Type{rhs}; } + Type fetch_add(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_add(i, o); } + Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_sub(i, o); } + bool compare_exchange_strong(Type& i1, const Type i2, + std::memory_order o1= std::memory_order_relaxed, + std::memory_order o2= std::memory_order_relaxed) + { return m.compare_exchange_strong(i1, i2, o1, o2); } + Type exchange(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.exchange(i, o); } +}; +#endif /* __cplusplus */ diff --git a/include/my_base.h b/include/my_base.h index 50a9abe0bc6..dc5b135628f 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -55,6 +55,10 @@ */ #define HA_OPEN_FOR_ALTER 8192U +/* Open table for FLUSH */ +#define HA_OPEN_FOR_FLUSH 8192U + + /* The following is parameter to ha_rkey() how to use key */ /* diff --git a/include/my_compiler.h b/include/my_compiler.h index 8e37f8bcd19..d35a9104c50 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -2,6 +2,7 @@ #define MY_COMPILER_INCLUDED /* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -156,6 +157,7 @@ struct my_aligned_storage #ifdef __GNUC__ # define ATTRIBUTE_NORETURN __attribute__((noreturn)) +# define ATTRIBUTE_NOINLINE __attribute__((noinline)) # if MY_GNUC_PREREQ(4,3) /** Starting with GCC 4.3, the "cold" attribute is used to inform the compiler that a function is unlikely executed. The function is @@ -169,8 +171,10 @@ rarely invoked function for size instead for speed. */ # endif #elif defined _MSC_VER # define ATTRIBUTE_NORETURN __declspec(noreturn) +# define ATTRIBUTE_NOINLINE __declspec(noinline) #else # define ATTRIBUTE_NORETURN /* empty */ +# define ATTRIBUTE_NOINLINE /* empty */ #endif #ifndef ATTRIBUTE_COLD diff --git a/include/my_dbug.h b/include/my_dbug.h index 09ccb6102fc..f0c74ab485c 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -52,7 +52,10 @@ extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, extern void _db_return_(struct _db_stack_frame_ *_stack_frame_); extern int _db_pargs_(uint _line_,const char *keyword); extern void _db_doprnt_(const char *format,...) - ATTRIBUTE_FORMAT(printf, 1, 2); +#ifdef WAITING_FOR_BUGFIX_TO_VSPRINTF + ATTRIBUTE_FORMAT(printf, 1, 2) +#endif + ; extern void _db_dump_(uint _line_,const char *keyword, const unsigned char *memory, size_t length); extern void _db_end_(void); diff --git a/include/my_getopt.h b/include/my_getopt.h index a299c315785..642fb344d92 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -106,6 +106,7 @@ extern char *autoset_my_option; extern my_bool my_getopt_print_errors; extern my_bool my_getopt_skip_unknown; extern my_bool my_getopt_prefix_matching; +extern my_bool my_handle_options_init_variables; extern my_error_reporter my_getopt_error_reporter; extern my_getopt_value my_getopt_get_addr; diff --git a/include/my_sys.h b/include/my_sys.h index ee1d08dc5e4..7cd417fd9cb 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -22,18 +22,9 @@ C_MODE_START -#ifdef HAVE_AIOWAIT -#include /* Used by record-cache */ -typedef struct my_aio_result { - aio_result_t result; - int pending; -} my_aio_result; -#endif #include - #include - #include /* for CHARSET_INFO */ #include #include @@ -67,6 +58,7 @@ typedef struct my_aio_result { #define MY_WME 16U /* Write message on error */ #define MY_WAIT_IF_FULL 32U /* Wait and try again if disk full error */ #define MY_IGNORE_BADFD 32U /* my_sync(): ignore 'bad descriptor' errors */ +#define MY_IGNORE_ENOENT 32U /* my_delete() ignores ENOENT (no such file) */ #define MY_ENCRYPT 64U /* Encrypt IO_CACHE temporary files */ #define MY_TEMPORARY 64U /* create_temp_file(): delete file at once */ #define MY_NOSYMLINKS 512U /* my_open(): don't follow symlinks */ @@ -315,10 +307,6 @@ typedef struct st_record_cache /* Used when caching records */ uint rc_length,read_length,reclength; my_off_t rc_record_pos,end_of_file; uchar *rc_buff,*rc_buff2,*rc_pos,*rc_end,*rc_request_pos; -#ifdef HAVE_AIOWAIT - int use_async_io; - my_aio_result aio_result; -#endif enum cache_type type; } RECORD_CACHE; @@ -487,15 +475,6 @@ typedef struct st_io_cache /* Used when caching files */ somewhere else */ my_bool alloced_buffer; -#ifdef HAVE_AIOWAIT - /* - As inidicated by ifdef, this is for async I/O, which is not currently - used (because it's not reliable on all systems) - */ - uint inited; - my_off_t aio_read_pos; - my_aio_result aio_result; -#endif } IO_CACHE; typedef int (*qsort2_cmp)(const void *, const void *, const void *); @@ -532,6 +511,7 @@ static inline int my_b_read(IO_CACHE *info, uchar *Buffer, size_t Count) static inline int my_b_write(IO_CACHE *info, const uchar *Buffer, size_t Count) { + MEM_CHECK_DEFINED(Buffer, Count); if (info->write_pos + Count <= info->write_end) { memcpy(info->write_pos, Buffer, Count); @@ -553,6 +533,7 @@ static inline int my_b_get(IO_CACHE *info) static inline my_bool my_b_write_byte(IO_CACHE *info, uchar chr) { + MEM_CHECK_DEFINED(&chr, 1); if (info->write_pos >= info->write_end) if (my_b_flush_io_cache(info, 1)) return 1; @@ -814,7 +795,6 @@ void end_slave_io_cache(IO_CACHE *cache); void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset); extern void remove_io_thread(IO_CACHE *info); -extern int _my_b_async_read(IO_CACHE *info,uchar *Buffer,size_t Count); extern int my_b_append(IO_CACHE *info,const uchar *Buffer,size_t Count); extern int my_b_safe_write(IO_CACHE *info,const uchar *Buffer,size_t Count); @@ -925,8 +905,18 @@ extern int my_compress_buffer(uchar *dest, size_t *destLen, extern int packfrm(const uchar *, size_t, uchar **, size_t *); extern int unpackfrm(uchar **, size_t *, const uchar *); -extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem, - size_t count); +void my_checksum_init(void); +#ifdef HAVE_CRC32_VPMSUM +extern ha_checksum my_checksum(ha_checksum, const void *, size_t); +#else +typedef ha_checksum (*my_crc32_t)(ha_checksum, const void *, size_t); +extern MYSQL_PLUGIN_IMPORT my_crc32_t my_checksum; +#endif + +#if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) +int crc32_aarch64_available(void); +#endif + #ifdef DBUG_ASSERT_EXISTS extern void my_debug_put_break_here(void); #else @@ -934,7 +924,6 @@ extern void my_debug_put_break_here(void); #endif extern void my_sleep(ulong m_seconds); -extern ulong crc32(ulong crc, const uchar *buf, uint len); extern uint my_set_max_open_files(uint files); void my_free_open_file_info(void); diff --git a/include/my_valgrind.h b/include/my_valgrind.h index 2c623a044f4..1de6714700b 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -32,11 +32,14 @@ #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined(HAVE_valgrind) # include +# define HAVE_valgrind_or_MSAN # define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len) # define MEM_MAKE_DEFINED(a,len) VALGRIND_MAKE_MEM_DEFINED(a,len) # define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len) # define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len) # define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len) +# define MEM_GET_VBITS(a,b,len) VALGRIND_GET_VBITS(a,b,len) +# define MEM_SET_VBITS(a,b,len) VALGRIND_SET_VBITS(a,b,len) # define REDZONE_SIZE 8 #elif defined(__SANITIZE_ADDRESS__) # include @@ -47,14 +50,19 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ # define MEM_NOACCESS(a,len) ASAN_POISON_MEMORY_REGION(a,len) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) # define MEM_CHECK_DEFINED(a,len) ((void) 0) +# define MEM_GET_VBITS(a,b,len) ((void) 0) +# define MEM_SET_VBITS(a,b,len) ((void) 0) # define REDZONE_SIZE 8 #elif __has_feature(memory_sanitizer) # include +# define HAVE_valgrind_or_MSAN # define MEM_UNDEFINED(a,len) __msan_allocated_memory(a,len) # define MEM_MAKE_DEFINED(a,len) __msan_unpoison(a,len) # define MEM_NOACCESS(a,len) ((void) 0) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) # define MEM_CHECK_DEFINED(a,len) __msan_check_mem_is_initialized(a,len) +# define MEM_GET_VBITS(a,b,len) __msan_copy_shadow(b,a,len) +# define MEM_SET_VBITS(a,b,len) __msan_copy_shadow(a,b,len) # define REDZONE_SIZE 8 #else # define MEM_UNDEFINED(a,len) ((void) (a), (void) (len)) @@ -62,19 +70,24 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ # define MEM_NOACCESS(a,len) ((void) 0) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) # define MEM_CHECK_DEFINED(a,len) ((void) 0) +# define MEM_GET_VBITS(a,b,len) ((void) 0) +# define MEM_SET_VBITS(a,b,len) ((void) 0) # define REDZONE_SIZE 0 #endif /* HAVE_VALGRIND_MEMCHECK_H */ -#if defined(TRASH_FREED_MEMORY) -/* NOTE: Do not invoke TRASH_FILL directly! Use TRASH_ALLOC or TRASH_FREE. - -The MEM_UNDEFINED() call before memset() is for canceling the effect -of any previous MEM_NOACCESS(). We must invoke MEM_UNDEFINED() after -writing the dummy pattern, unless MEM_NOACCESS() is going to be invoked. -On AddressSanitizer, the MEM_UNDEFINED() in TRASH_ALLOC() has no effect. */ +#ifdef TRASH_FREED_MEMORY +/* + TRASH_FILL() has to call MEM_UNDEFINED() to cancel any effect of TRASH_FREE(). + This can happen in the case one does + TRASH_ALLOC(A,B) ; TRASH_FREE(A,B) ; TRASH_ALLOC(A,B) + to reuse the same memory in an internal memory allocator like MEM_ROOT. + For my_malloc() and safemalloc() the extra MEM_UNDEFINED is bit of an + overkill. + TRASH_FILL() is an internal function and should not be used externally. +*/ #define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0) #else -#define TRASH_FILL(A,B,C) while (0) +#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0) #endif /** Note that some memory became allocated or uninitialized. */ #define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 051821c2d37..4e6240a19ac 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -113,7 +113,6 @@ enum enum_session_state_type SESSION_TRACK_GTIDS, SESSION_TRACK_TRANSACTION_CHARACTERISTICS, SESSION_TRACK_TRANSACTION_STATE, - SESSION_TRACK_USER_VARIABLES, SESSION_TRACK_always_at_the_end }; extern "C" { diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h index bd1f069c527..6757a658fb6 100644 --- a/include/mysql/service_my_snprintf.h +++ b/include/mysql/service_my_snprintf.h @@ -55,7 +55,8 @@ Supported formats are 's' (null pointer is accepted, printed as "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', - 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below). + 'X', 'p' (works as 0x%x), 'f', 'g', 'M' (extension, see below), + 'T' (extension, see below). Standard syntax for positional arguments $n is supported. @@ -69,6 +70,9 @@ Format 'M': takes one integer, prints this integer, space, double quote error message, double quote. In other words printf("%M", n) === printf("%d \"%s\"", n, strerror(n)) + + Format 'T': takes string and print it like s but if the strints should be + truncated puts "..." at the end. */ #ifdef __cplusplus diff --git a/include/mysql_com.h b/include/mysql_com.h index de9eb938f69..fa5960a377b 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -617,7 +617,15 @@ enum enum_session_state_type SESSION_TRACK_GTIDS, SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */ SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */ +#ifdef USER_VAR_TRACKING + SESSION_TRACK_MYSQL_RESERVED1, + SESSION_TRACK_MYSQL_RESERVED2, + SESSION_TRACK_MYSQL_RESERVED3, + SESSION_TRACK_MYSQL_RESERVED4, + SESSION_TRACK_MYSQL_RESERVED5, + SESSION_TRACK_MYSQL_RESERVED6, SESSION_TRACK_USER_VARIABLES, +#endif // USER_VAR_TRACKING SESSION_TRACK_always_at_the_end /* must be last */ }; diff --git a/include/scope.h b/include/scope.h new file mode 100644 index 00000000000..b9e2e96ae5c --- /dev/null +++ b/include/scope.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2020, MariaDB + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + 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 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-1335 USA +*/ + +#pragma once + +#include +#include + +namespace detail +{ + +template class scope_exit +{ +public: + template + explicit scope_exit(F &&f) : function_(std::forward(f)) + { + } + + scope_exit(scope_exit &&rhs) + : function_(std::move(rhs.function_)), engaged_(rhs.engaged_) + { + rhs.release(); + } + + scope_exit(const scope_exit &)= delete; + scope_exit &operator=(scope_exit &&)= delete; + scope_exit &operator=(const scope_exit &)= delete; + + void release() { engaged_= false; } + + ~scope_exit() + { + if (engaged_) + function_(); + } + +private: + Callable function_; + bool engaged_= true; +}; + +} // end namespace detail + +template +detail::scope_exit::type> +make_scope_exit(Callable &&f) +{ + return detail::scope_exit::type>( + std::forward(f)); +} diff --git a/include/span.h b/include/span.h index 0ed0158088c..0e8516933c6 100644 --- a/include/span.h +++ b/include/span.h @@ -24,11 +24,33 @@ this program; if not, write to the Free Software Foundation, Inc., namespace st_ { +namespace detail +{ + +template struct remove_cv +{ + typedef T type; +}; +template struct remove_cv +{ + typedef T type; +}; +template struct remove_cv +{ + typedef T type; +}; +template struct remove_cv +{ + typedef T type; +}; + +} // namespace detail + template class span { public: typedef ElementType element_type; - typedef ElementType value_type; + typedef typename detail::remove_cv::type value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef element_type *pointer; @@ -38,7 +60,6 @@ public: typedef pointer iterator; typedef const_pointer const_iterator; typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; span() : data_(NULL), size_(0) {} @@ -64,73 +85,72 @@ public: span &operator=(const span &other) { - data_= other.data_; - size_= other.size_; + data_= other.data(); + size_= other.size(); return *this; } template span first() const { assert(!empty()); - return span(data_, 1); + return span(data(), 1); } template span last() const { assert(!empty()); - return span(data_ + size() - 1, 1); + return span(data() + size() - 1, 1); } span first(size_type count) const { assert(!empty()); - return span(data_, 1); + return span(data(), 1); } span last(size_type count) const { assert(!empty()); - return span(data_ + size() - 1, 1); + return span(data() + size() - 1, 1); } span subspan(size_type offset, size_type count) const { assert(!empty()); assert(size() >= offset + count); - return span(data_ + offset, count); + return span(data() + offset, count); } size_type size() const { return size_; } - size_type size_bytes() const { return size_ * sizeof(ElementType); } - bool empty() const __attribute__((warn_unused_result)) { return size_ == 0; } + size_type size_bytes() const { return size() * sizeof(ElementType); } + bool empty() const __attribute__((warn_unused_result)) + { + return size() == 0; + } reference operator[](size_type idx) const { assert(size() > idx); - return data_[idx]; + return data()[idx]; } reference front() const { assert(!empty()); - return data_[0]; + return data()[0]; } reference back() const { assert(!empty()); - return data_[size() - 1]; - } - pointer data() const - { - assert(!empty()); - return data_; + return data()[size() - 1]; } + pointer data() const { return data_; } iterator begin() const { return data_; } iterator end() const { return data_ + size_; } reverse_iterator rbegin() const { - return std::reverse_iterator(std::advance(end(), -1)); + return std::reverse_iterator(end()); } reverse_iterator rend() const { - return std::reverse_iterator(std::advance(begin(), -1)); + return std::reverse_iterator(begin()); } private: diff --git a/include/thr_lock.h b/include/thr_lock.h index 2873d40c58a..1ea24132d90 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -126,7 +126,7 @@ typedef struct st_thr_lock { /* write_lock_count is incremented for write locks and reset on read locks */ ulong write_lock_count; uint read_no_write_count; - void (*get_status)(void*, my_bool); /* When one gets a lock */ + my_bool (*get_status)(void*, my_bool);/* Called when one gets a lock */ void (*copy_status)(void*,void*); void (*update_status)(void*); /* Before release of write */ void (*restore_status)(void*); /* Before release of read */ diff --git a/include/violite.h b/include/violite.h index c698153bb02..c7feca683cc 100644 --- a/include/violite.h +++ b/include/violite.h @@ -174,6 +174,8 @@ struct st_VioSSLFd int sslaccept(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); +void vio_check_ssl_init(); + struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, diff --git a/libmariadb b/libmariadb index 2759b87d729..a746c3af449 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 2759b87d72926b7c9b5426437a7c8dd15ff57945 +Subproject commit a746c3af449a8754e78ad7971e59e79af7957cdb diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index ae54fb4ef5f..57b468c7245 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2011, Oracle and/or its affiliates. -# Copyright (c) 2009, 2018, MariaDB Corporation +# Copyright (c) 2009, 2020, MariaDB Corporation # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -462,9 +462,8 @@ IF(NOT DISABLE_SHARED) # Clean direct output flags, as 2 targets have the same base name # libmysqld SET_TARGET_PROPERTIES(libmysqld PROPERTIES CLEAN_DIRECT_OUTPUT 1) - TARGET_LINK_LIBRARIES(libmysqld ${CRC32_LIBRARY}) SET_TARGET_PROPERTIES(mysqlserver PROPERTIES CLEAN_DIRECT_OUTPUT 1) - TARGET_LINK_LIBRARIES(mysqlserver ${CRC32_LIBRARY} tpool) + TARGET_LINK_LIBRARIES(mysqlserver tpool) IF(LIBMYSQLD_SO_EXTRA_LIBS) TARGET_LINK_LIBRARIES(libmysqld ${LIBMYSQLD_SO_EXTRA_LIBS}) ENDIF() diff --git a/mysql-test/include/commit.inc b/mysql-test/include/commit.inc index a28d3e5f3d1..865f3296b39 100644 --- a/mysql-test/include/commit.inc +++ b/mysql-test/include/commit.inc @@ -405,6 +405,11 @@ end| delimiter ;| --echo # Reset Handler_commit and Handler_prepare counters flush status; + +--echo # +--echo # Count of reading of p_verify_status_increment() from mysql.proc +call p_verify_status_increment(2, 0, 2, 0); + --echo # --echo # 1. Read-only statement: SELECT --echo # @@ -562,7 +567,7 @@ begin return 2; end| delimiter ;| -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(4, 0, 4, 0); --echo # 16. A function changes non-trans-table. --echo # @@ -571,7 +576,7 @@ call p_verify_status_increment(0, 0, 0, 0); --echo # the binary log. --echo # select f1(); -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(3, 0, 3, 0); commit; call p_verify_status_increment(1, 0, 1, 0); @@ -650,7 +655,7 @@ call p_verify_status_increment(0, 0, 0, 0); --echo # 24. DDL: TRUNCATE TEMPORARY TABLE --echo truncate table t2; -call p_verify_status_increment(4, 0, 4, 0); +call p_verify_status_increment(2, 0, 2, 0); commit; --echo # There is nothing left to commit call p_verify_status_increment(0, 0, 0, 0); @@ -763,7 +768,7 @@ call p_verify_status_increment(0, 0, 0, 0); truncate table t3; call p_verify_status_increment(2, 0, 2, 0); create view v1 as select * from t2; -call p_verify_status_increment(2, 0, 2, 0); +call p_verify_status_increment(4, 0, 4, 0); check table t1; call p_verify_status_increment(2, 0, 2, 0); --echo # Sic: after this bug is fixed, CHECK leaves no pending transaction @@ -774,7 +779,7 @@ call p_verify_status_increment(6, 0, 6, 0); commit; call p_verify_status_increment(0, 0, 0, 0); drop view v1; -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(2, 0, 2, 0); --echo # --echo # Cleanup diff --git a/mysql-test/include/ctype_ident_sys.inc b/mysql-test/include/ctype_ident_sys.inc new file mode 100644 index 00000000000..80ac962f031 --- /dev/null +++ b/mysql-test/include/ctype_ident_sys.inc @@ -0,0 +1,73 @@ +--echo # +--echo # SET STATEMENT (bad|good.bad|bad.good)=1 +--echo # + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); + + +--echo # +--echo # SET SESSION (bad|good.bad|bad.good)=1 +--echo # + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); + + +--echo # +--echo # SET (bad|good.bad|bad.good)=1 +--echo # + + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); + + +--echo # +--echo # Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +--echo # + +SET sql_mode=ORACLE; +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); + + +--echo # +--echo # Oracle assignment: (bad|good.bad|bad.good):= value +--echo # + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); + +--error ER_INVALID_CHARACTER_STRING +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); + + +SET sql_mode=DEFAULT; diff --git a/mysql-test/include/ctype_utf8mb4.inc b/mysql-test/include/ctype_utf8mb4.inc index 34ef983645b..10d4f99efba 100644 --- a/mysql-test/include/ctype_utf8mb4.inc +++ b/mysql-test/include/ctype_utf8mb4.inc @@ -1587,7 +1587,7 @@ drop table t1; --echo # --echo # Check strnxfrm() with odd length --echo # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; eval create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci) engine $engine; insert into t1 values ('a'),('b'),('c'); diff --git a/mysql-test/include/load_dump_and_upgrade.inc b/mysql-test/include/load_dump_and_upgrade.inc new file mode 100644 index 00000000000..52351ea473c --- /dev/null +++ b/mysql-test/include/load_dump_and_upgrade.inc @@ -0,0 +1,49 @@ +--source include/have_innodb.inc + +# ==== Usage ==== +# +# [--let $old_version= 10.2] +# --source include/load_dump_and_upgrade.inc + +# Dumps stored in std_data as mysql_database_.dump +# were pre-created by running mysqldump for `mysql` database +# on a freshly boostrapped instance of the corresponding version. +# On 10.4 the local root was additionally given an empty password, +# to avoid using unix_socket. + +# Backup the existing mysql schema, to restore it later +--exec $MYSQL_DUMP mysql > $MYSQL_TMP_DIR/mysql_database_backup + +--echo # +--echo # Upgrade from version $old_version +--echo # + +# Workaround for MDEV-22127 (can't import database dump created before 10.4) +# The most universal workaround suggested in the item is running +# DROP TABLE IF EXISTS `mysql`.`global_priv`; +# DROP VIEW IF EXISTS `mysql`.`user`; +# before the upgrade. For this test, it is better than creating the dumps +# with --add-drop-database, because +# a) it won't require re-creating the dump when the bug is fixed; +# b) it won't hide possible unrelated problems; +# c) add-drop-database doesn't work with logging into tables enabled (MDEV-4875 and more) + +--exec $MYSQL -e "DROP TABLE IF EXISTS mysql.global_priv; DROP VIEW IF EXISTS mysql.user" + +--echo # Loading dump of $old_version mysql schema +--exec $MYSQL mysql < $MYSQLTEST_VARDIR/std_data/mysql_database_$old_version.dump + +--echo # Running mysql_upgrade +--exec $MYSQL_UPGRADE --verbose > $MYSQL_TMP_DIR/upgrade.log + +--echo # Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; + +# Restore the backup of mysql schema +--exec $MYSQL mysql < $MYSQL_TMP_DIR/mysql_database_backup + +--let $ddir= `select @@datadir` + +# It will fail if the file doesn't exist, which is good, +# which is an extra check that it was written +--remove_file $ddir/mysql_upgrade_info diff --git a/mysql-test/include/percona_nonflushing_analyze_debug.inc b/mysql-test/include/percona_nonflushing_analyze_debug.inc new file mode 100644 index 00000000000..95621c70d5c --- /dev/null +++ b/mysql-test/include/percona_nonflushing_analyze_debug.inc @@ -0,0 +1,35 @@ +# +# Test ANALYZE TABLE that does not flush table definition cache +# Arguments: +# $percona_nonflushing_analyze_table - table to test +# + +--source include/count_sessions.inc + +--connect con1,localhost,root + +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; + +send_eval SELECT * FROM $percona_nonflushing_analyze_table; + +--connection default + +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; + +set @tmp=@@use_stat_tables; +set use_stat_tables='preferably_for_queries'; +eval ANALYZE TABLE $percona_nonflushing_analyze_table; + +set use_stat_tables=@tmp; +# With the bug fixed this should not block +eval SELECT * FROM $percona_nonflushing_analyze_table; + +SET DEBUG_SYNC="now SIGNAL finish_scan"; + +--connection con1 +reap; +--disconnect con1 +--connection default +SET DEBUG_SYNC='reset'; + +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 25d3256ca4e..32250802815 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -37,8 +37,20 @@ use My::Platform; use POSIX qw[ _exit ]; use IO::Handle qw[ flush ]; use mtr_results; - use Term::ANSIColor; +use English; + +my $tot_real_time= 0; +my $tests_done= 0; +my $tests_failed= 0; + +our $timestamp= 0; +our $timediff= 0; +our $name; +our $verbose; +our $verbose_restart= 0; +our $timer= 1; +our $tests_total; my %color_map = qw/pass green retry-pass green @@ -47,20 +59,39 @@ my %color_map = qw/pass green disabled bright_black skipped yellow reset reset/; -sub xterm_color { - if (-t STDOUT and defined $ENV{TERM} and $ENV{TERM} =~ /xterm/) { - syswrite STDOUT, color($color_map{$_[0]}); + +my $set_titlebar; +my $set_color= sub { }; + +if (-t STDOUT) { + if (IS_WINDOWS) { + eval { + require Win32::Console; + $set_titlebar = sub { &Win32::Console::Title($_[0]);}; + } + } elsif ($ENV{TERM} =~ /xterm/) { + $set_titlebar = sub { syswrite STDOUT, "\e]0;$_[0]\a"; }; + $set_color = sub { syswrite STDOUT, color($color_map{$_[0]}); } } } -my $tot_real_time= 0; +sub titlebar_stat($) { -our $timestamp= 0; -our $timediff= 0; -our $name; -our $verbose; -our $verbose_restart= 0; -our $timer= 1; + sub time_format($) { + sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60; + } + + $tests_done++; + $tests_failed++ if $_[0] =~ /fail/; + $tests_total++ if $_[0] =~ /retry/; + + my $spent = time - $BASETIME; + my $left = $tests_total - $tests_done; + + &$set_titlebar(sprintf "mtr: spent %s on %d tests. %s (%d tests) left, %d failed", + time_format($spent), $tests_done, + time_format($spent/$tests_done * $left), $left, $tests_failed); +} sub report_option { my ($opt, $value)= @_; @@ -321,8 +352,6 @@ sub mtr_report_stats ($$$$) { if ( $timer ) { - use English; - mtr_report("Spent", sprintf("%.3f", $tot_real_time),"of", time - $BASETIME, "seconds executing testcases"); } @@ -467,13 +496,23 @@ sub mtr_report_stats ($$$$) { $test_time = sprintf("%.3f", $test->{timer} / 1000); $test->{'name'} =~ s/$current_suite\.//; - $xml_report .= qq(\t\t{'retries'} > 0) { + $test_result = "MTR_RES_FAILED"; + } else { + $test_result = $test->{'result'}; + } + + $xml_report .= qq(\t\t{'comment'}; $comment =~ s/[\"]//g; # if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML - if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'}) { + if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'} > 0) { my $logcontents = $test->{'logfile-failed'} || $test->{'logfile'}; $xml_report .= qq(>\n\t\t\t\n\n\t\t\t\n\t\t\n); @@ -610,10 +649,11 @@ sub mtr_report (@) { my @s = split /\[ (\S+) \]/, _name() . "@_\n"; if (@s > 1) { print $s[0]; - xterm_color($s[1]); + &$set_color($s[1]); print "[ $s[1] ]"; - xterm_color('reset'); + &$set_color('reset'); print $s[2]; + titlebar_stat($s[1]) if $set_titlebar; } else { print $s[0]; } @@ -639,6 +679,8 @@ sub mtr_error (@) { } else { + use Carp qw(cluck); + cluck "Error happened" if $verbose > 0; exit(1); } } diff --git a/mysql-test/lib/process-purecov-annotations.pl b/mysql-test/lib/process-purecov-annotations.pl index d533bd02fd6..4381aae4c64 100755 --- a/mysql-test/lib/process-purecov-annotations.pl +++ b/mysql-test/lib/process-purecov-annotations.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # This script processes a .gcov coverage report to honor purecov diff --git a/mysql-test/lib/t/SafeProcessStress.pl b/mysql-test/lib/t/SafeProcessStress.pl index f591e9665dd..352b956d803 100755 --- a/mysql-test/lib/t/SafeProcessStress.pl +++ b/mysql-test/lib/t/SafeProcessStress.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007, 2008 MySQL AB diff --git a/mysql-test/lib/t/copytree.t b/mysql-test/lib/t/copytree.t index 15a41081b24..76a3d644751 100644 --- a/mysql-test/lib/t/copytree.t +++ b/mysql-test/lib/t/copytree.t @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB diff --git a/mysql-test/lib/t/dummyd.pl b/mysql-test/lib/t/dummyd.pl index 15164428b95..e78648cfacf 100644 --- a/mysql-test/lib/t/dummyd.pl +++ b/mysql-test/lib/t/dummyd.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB diff --git a/mysql-test/lib/t/rmtree.t b/mysql-test/lib/t/rmtree.t index 40c9e96eabd..033bc59ad21 100644 --- a/mysql-test/lib/t/rmtree.t +++ b/mysql-test/lib/t/rmtree.t @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB diff --git a/mysql-test/lib/t/testMyConfig.t b/mysql-test/lib/t/testMyConfig.t index cd0a3a41b7a..99647c14ba1 100755 --- a/mysql-test/lib/t/testMyConfig.t +++ b/mysql-test/lib/t/testMyConfig.t @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB diff --git a/mysql-test/lib/t/testMyConfigFactory.t b/mysql-test/lib/t/testMyConfigFactory.t index f38f660e85a..5ba63b3d823 100755 --- a/mysql-test/lib/t/testMyConfigFactory.t +++ b/mysql-test/lib/t/testMyConfigFactory.t @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB, 2009 Sun Microsystems, Inc. diff --git a/mysql-test/lib/t/test_child.pl b/mysql-test/lib/t/test_child.pl index efbec4a9620..8a23c3d7541 100755 --- a/mysql-test/lib/t/test_child.pl +++ b/mysql-test/lib/t/test_child.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2007 MySQL AB diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index af95ecbaa58..6b419aff3bf 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -1,17 +1,17 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. -# +# # 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 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-1335 USA @@ -572,7 +572,7 @@ sub command_line_setup () { 'valgrind-path=s' => \$opt_valgrind_path, 'callgrind' => \$opt_callgrind, - # Stress testing + # Stress testing 'stress' => \$opt_stress, 'stress-suite=s' => \$opt_stress_suite, 'stress-threads=i' => \$opt_stress_threads, @@ -655,7 +655,7 @@ sub command_line_setup () { $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; chomp($glob_mysql_test_dir); } - if (defined $ENV{MTR_BINDIR}) + if (defined $ENV{MTR_BINDIR}) { $default_vardir= "$ENV{MTR_BINDIR}/mysql-test/var"; } @@ -700,7 +700,7 @@ sub command_line_setup () { { my $lib_mysqld= mtr_path_exists(vs_config_dirs('libmysqld','')); - $lib_mysqld= $glob_cygwin_perl ? ":".`cygpath "$lib_mysqld"` + $lib_mysqld= $glob_cygwin_perl ? ":".`cygpath "$lib_mysqld"` : ";".$lib_mysqld; chomp($lib_mysqld); $ENV{'PATH'}="$ENV{'PATH'}".$lib_mysqld; @@ -738,7 +738,7 @@ sub command_line_setup () { "$glob_bindir/client", "$glob_bindir/bin"); } - + # Look for language files and charsetsdir, use same share $path_share= mtr_path_exists("$glob_bindir/share/mysql", "$glob_bindir/sql/share", @@ -761,8 +761,8 @@ sub command_line_setup () { "$path_client_bindir/mysqld-debug", "$path_client_bindir/mysqld-max", "$glob_bindir/libexec/mysqld", - "$glob_bindir/bin/mysqld", - "$glob_bindir/sbin/mysqld"); + "$glob_bindir/bin/mariadbd", + "$glob_bindir/sbin/mariadbd"); # Use the mysqld found above to find out what features are available collect_mysqld_features(); @@ -815,7 +815,7 @@ sub command_line_setup () { $used_binlog_format= $1; } } - if (defined $used_binlog_format) + if (defined $used_binlog_format) { mtr_report("Using binlog format '$used_binlog_format'"); } @@ -1619,7 +1619,7 @@ sub environment_setup () { $ENV{'CHARSETSDIR'}= $path_charsetsdir; $ENV{'UMASK'}= "0660"; # The octal *string* $ENV{'UMASK_DIR'}= "0770"; # The octal *string* - + # # MySQL tests can produce output in various character sets # (especially, ctype_xxx.test). To avoid confusing Perl @@ -1630,7 +1630,7 @@ sub environment_setup () { # $ENV{'LC_ALL'}= "C"; $ENV{'LC_CTYPE'}= "C"; - + $ENV{'LC_COLLATE'}= "C"; $ENV{'USE_RUNNING_SERVER'}= $opt_extern; $ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir; @@ -1803,7 +1803,7 @@ sub environment_setup () { $ENV{'MYSQLADMIN'}= mtr_native_path($exe_mysqladmin); # ---------------------------------------------------- - # Setup env so childs can execute perror + # Setup env so childs can execute perror # ---------------------------------------------------- $ENV{'MY_PERROR'}= mtr_native_path($exe_perror); @@ -2773,7 +2773,7 @@ sub run_testcase ($) { if ($glob_win32_perl) { #ActiveState perl hangs when using normal exit, use POSIX::_exit instead - use POSIX qw[ _exit ]; + use POSIX qw[ _exit ]; POSIX::_exit(0); } else @@ -3157,10 +3157,10 @@ sub mysqld_arguments ($$$$) { { # NOTE: the backport (see BUG#48048) originally removed the # commented out lines below. However, given that they are -# protected with a version check (< 50200) now, it should be -# safe to keep them. The problem is that the backported patch -# was into a 5.1 GA codebase - mysql-5.1-rep+2 tree - so -# version is 501XX, consequently check becomes worthless. It +# protected with a version check (< 50200) now, it should be +# safe to keep them. The problem is that the backported patch +# was into a 5.1 GA codebase - mysql-5.1-rep+2 tree - so +# version is 501XX, consequently check becomes worthless. It # should be safe to uncomment them when merging up to 5.5. # # RQG semisync test runs on the 5.1 GA tree and needs MTR v1. @@ -4322,4 +4322,3 @@ sub list_options ($) { mtr_exit(1); } - diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index b012fdde54b..197e52b35ca 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -272,8 +272,7 @@ ERROR 42000: Incorrect table name '' drop table t1; drop table if exists t1, t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' create table t1 ( a varchar(10) not null primary key ) engine=myisam; create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); flush tables; @@ -2564,6 +2563,49 @@ drop view v1; # End of 10.3 tests # # +# MDEV-22563 Segfault on duplicate free of Item_func_in::array +# +create or replace table person_principal ( +person_id bigint not null, +insurant_id varchar(10) not null, +principal_id bigint not null, +principal_officer_id bigint not null, +nursing_degree tinyint null, +nursing_degree_valid_from date not null default cast(current_timestamp(6) as date), +carma_user_id bigint not null, +current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6), +constraint pk_person_principal primary key (person_id asc), +constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5))); +Warnings: +Warning 1280 Name 'pk_person_principal' ignored for PRIMARY key. +create or replace table person_principal_hist ( +person_id bigint not null, +insurant_id varchar(10) not null, +principal_id bigint not null, +principal_officer_id bigint not null, +nursing_degree tinyint null, +nursing_degree_valid_from date not null default cast(now() as date), +carma_user_id bigint not null, +orig_date_time datetime(6) not null, +constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc), +constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5))); +Warnings: +Warning 1280 Name 'pk_person_principal_hist' ignored for PRIMARY key. +insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id) +values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1); +alter table person_principal add column if not exists date_mask tinyint null; +update person_principal set date_mask = 0; +alter table person_principal modify column date_mask tinyint not null; +drop tables person_principal_hist, person_principal; +CREATE OR REPLACE TABLE `t1` ( `id` varchar(64) NOT NULL, `name` varchar(255) NOT NULL, `extra` text DEFAULT NULL, `password` varchar(128) DEFAULT NULL, `enabled` tinyint(1) DEFAULT NULL, `domain_id` varchar(64) NOT NULL, `default_project_id` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT `CONSTRAINT_1` CHECK (`enabled` in (0,1)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into t1 (id,name,enabled,domain_id) values (1,"Monty",1,"domain_id"); +insert into t1 (id,name,enabled,domain_id) values (2,"Monty2",1,"domain_id2"); +ALTER TABLE t1 ADD CONSTRAINT ixu_user2_name_domain_id UNIQUE (domain_id, name); +DROP TABLE t1; +# +# End of 10.4 tests +# +# # MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax # SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE; @@ -3250,9 +3292,6 @@ i2 b PRIMARY a drop table t1; # -# End of 10.5 tests -# -# # ALTER TABLE IF EXISTS # create table t1 (a int); @@ -3271,3 +3310,17 @@ t2 CREATE TABLE `t2` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2; +# +# MDEV-22881 Unexpected errors, corrupt output, Valgrind / ASAN errors in Item_ident::print or append_identifier +# +create table t1 (a int check (a >= 0)); +lock tables t1 write; +alter table t1 rename column a to a; +alter table t1 rename key if exists x to xx; +Warnings: +Note 1176 Key 'x' doesn't exist in table 't1' +unlock tables; +drop table t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index 01ab0f99d45..6fe61a3222a 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2077,6 +2077,54 @@ drop view v1; --echo # End of 10.3 tests --echo # +--echo # +--echo # MDEV-22563 Segfault on duplicate free of Item_func_in::array +--echo # +create or replace table person_principal ( + person_id bigint not null, + insurant_id varchar(10) not null, + principal_id bigint not null, + principal_officer_id bigint not null, + nursing_degree tinyint null, + nursing_degree_valid_from date not null default cast(current_timestamp(6) as date), + carma_user_id bigint not null, + current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6), + constraint pk_person_principal primary key (person_id asc), + constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5))); + +create or replace table person_principal_hist ( + person_id bigint not null, + insurant_id varchar(10) not null, + principal_id bigint not null, + principal_officer_id bigint not null, + nursing_degree tinyint null, + nursing_degree_valid_from date not null default cast(now() as date), + carma_user_id bigint not null, + orig_date_time datetime(6) not null, + constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc), + constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5))); + +insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id) +values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1); +alter table person_principal add column if not exists date_mask tinyint null; +update person_principal set date_mask = 0; +alter table person_principal modify column date_mask tinyint not null; +drop tables person_principal_hist, person_principal; + +# +# The following ALTER TABLE caused crash in 10.4.13 (Reported on freenode) +# + +CREATE OR REPLACE TABLE `t1` ( `id` varchar(64) NOT NULL, `name` varchar(255) NOT NULL, `extra` text DEFAULT NULL, `password` varchar(128) DEFAULT NULL, `enabled` tinyint(1) DEFAULT NULL, `domain_id` varchar(64) NOT NULL, `default_project_id` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT `CONSTRAINT_1` CHECK (`enabled` in (0,1)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into t1 (id,name,enabled,domain_id) values (1,"Monty",1,"domain_id"); +insert into t1 (id,name,enabled,domain_id) values (2,"Monty2",1,"domain_id2"); +ALTER TABLE t1 ADD CONSTRAINT ixu_user2_name_domain_id UNIQUE (domain_id, name); +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # + --echo # --echo # MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax --echo # @@ -2457,10 +2505,6 @@ where t.name='test/t1' and t.table_id = i.table_id and i.index_id = f.index_id order by k, c; drop table t1; ---echo # ---echo # End of 10.5 tests ---echo # - --echo # --echo # ALTER TABLE IF EXISTS --echo # @@ -2472,3 +2516,19 @@ alter table if exists t9 rename t1; alter table if exists t1 rename t2; show create table t2; drop table t2; + +--echo # +--echo # MDEV-22881 Unexpected errors, corrupt output, Valgrind / ASAN errors in Item_ident::print or append_identifier +--echo # +create table t1 (a int check (a >= 0)); +lock tables t1 write; +alter table t1 rename column a to a; +alter table t1 rename key if exists x to xx; + +# cleanup +unlock tables; +drop table t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result index 95b2f520d90..96503814d00 100644 --- a/mysql-test/main/backup_lock.result +++ b/mysql-test/main/backup_lock.result @@ -192,28 +192,71 @@ BACKUP STAGE END; SET GLOBAL lock_wait_timeout=0; CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria transactional=1; +CREATE TABLE t_permanent_aria2 (col1 INT) ENGINE = Aria transactional=0; INSERT INTO t_permanent_innodb SET col1 = 1; INSERT INTO t_permanent_myisam SET col1 = 1; +INSERT INTO t_permanent_aria SET col1 = 1; +INSERT INTO t_permanent_aria2 SET col1 = 1; CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; connect con1,localhost,root,,; -SET AUTOCOMMIT = 0; connection default; BACKUP STAGE START; BACKUP STAGE FLUSH; BACKUP STAGE BLOCK_DDL; BACKUP STAGE BLOCK_COMMIT; connection con1; +SET AUTOCOMMIT = 1; +UPDATE t_permanent_aria SET col1 = 1; +UPDATE t_permanent_innodb SET col1 = 1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction UPDATE t_permanent_innodb SET col1 = 8; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction UPDATE t_permanent_myisam SET col1 = 8; ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UPDATE t_permanent_aria SET col1 = 8; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UPDATE t_permanent_aria2 SET col1 = 8; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t_permanent_innodb; +col1 +1 +select * from t_permanent_myisam; +col1 +1 +select * from t_permanent_aria; +col1 +8 +select * from t_permanent_aria2; +col1 +1 +SET AUTOCOMMIT = 0; +UPDATE t_permanent_innodb SET col1 = 9; +UPDATE t_permanent_aria SET col1 = 9; +UPDATE t_permanent_myisam SET col1 = 9; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UPDATE t_permanent_aria2 SET col1 = 9; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction DROP TABLE t_con1_innodb; ERROR HY000: Lock wait timeout exceeded; try restarting transaction DROP TABLE t_con1_myisam; ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection default; BACKUP STAGE END; -DROP TABLE t_permanent_myisam, t_permanent_innodb; +select * from t_permanent_innodb; +col1 +1 +select * from t_permanent_myisam; +col1 +1 +select * from t_permanent_aria; +col1 +9 +select * from t_permanent_aria2; +col1 +1 +DROP TABLE t_permanent_myisam, t_permanent_innodb, t_permanent_aria, t_permanent_aria2; DROP TABLE t_con1_innodb, t_con1_myisam; disconnect con1; set global lock_wait_timeout=default; diff --git a/mysql-test/main/backup_lock.test b/mysql-test/main/backup_lock.test index d6db7a6364e..0d4da8cb892 100644 --- a/mysql-test/main/backup_lock.test +++ b/mysql-test/main/backup_lock.test @@ -251,14 +251,17 @@ BACKUP STAGE END; SET GLOBAL lock_wait_timeout=0; CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria transactional=1; +CREATE TABLE t_permanent_aria2 (col1 INT) ENGINE = Aria transactional=0; INSERT INTO t_permanent_innodb SET col1 = 1; - INSERT INTO t_permanent_myisam SET col1 = 1; +INSERT INTO t_permanent_aria SET col1 = 1; +INSERT INTO t_permanent_aria2 SET col1 = 1; + CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; --connect(con1,localhost,root,,) -SET AUTOCOMMIT = 0; --connection default BACKUP STAGE START; @@ -267,9 +270,35 @@ BACKUP STAGE BLOCK_DDL; BACKUP STAGE BLOCK_COMMIT; --connection con1 +SET AUTOCOMMIT = 1; + +# These should work as values are not changed +UPDATE t_permanent_aria SET col1 = 1; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_innodb SET col1 = 1; + +--error ER_LOCK_WAIT_TIMEOUT UPDATE t_permanent_innodb SET col1 = 8; --error ER_LOCK_WAIT_TIMEOUT UPDATE t_permanent_myisam SET col1 = 8; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_aria SET col1 = 8; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_aria2 SET col1 = 8; + +select * from t_permanent_innodb; +select * from t_permanent_myisam; +select * from t_permanent_aria; +select * from t_permanent_aria2; + +SET AUTOCOMMIT = 0; +UPDATE t_permanent_innodb SET col1 = 9; +UPDATE t_permanent_aria SET col1 = 9; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_myisam SET col1 = 9; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_aria2 SET col1 = 9; + --error ER_LOCK_WAIT_TIMEOUT DROP TABLE t_con1_innodb; @@ -278,7 +307,13 @@ DROP TABLE t_con1_myisam; --connection default BACKUP STAGE END; -DROP TABLE t_permanent_myisam, t_permanent_innodb; + +select * from t_permanent_innodb; +select * from t_permanent_myisam; +select * from t_permanent_aria; +select * from t_permanent_aria2; + +DROP TABLE t_permanent_myisam, t_permanent_innodb, t_permanent_aria, t_permanent_aria2; DROP TABLE t_con1_innodb, t_con1_myisam; --disconnect con1 set global lock_wait_timeout=default; diff --git a/mysql-test/main/backup_stages.result b/mysql-test/main/backup_stages.result index caea1fda0b9..4704a4b6bd1 100644 --- a/mysql-test/main/backup_stages.result +++ b/mysql-test/main/backup_stages.result @@ -63,7 +63,7 @@ INSERT INTO t_permanent_myisam SET col1 = 1; connect backup,localhost,root,,; connect con11,localhost,root,,; SET AUTOCOMMIT = 0; -set session lock_wait_timeout=0; +set session lock_wait_timeout=1; connect con12,localhost,root,,; SET AUTOCOMMIT = 1; # Between (connection default) BACKUP STAGE START and FLUSH @@ -208,7 +208,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction DROP TABLE t_con1_myisam; ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection con12; -SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; +SET STATEMENT lock_wait_timeout=1 FOR UPDATE t_permanent_innodb SET col1 = 9; ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection backup; BACKUP STAGE END; diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test index ba9c15a1d7e..e8cc5f7a7b9 100644 --- a/mysql-test/main/backup_stages.test +++ b/mysql-test/main/backup_stages.test @@ -119,7 +119,7 @@ INSERT INTO t_permanent_myisam SET col1 = 1; --connect(backup,localhost,root,,) --connect(con11,localhost,root,,) SET AUTOCOMMIT = 0; -set session lock_wait_timeout=0; +set session lock_wait_timeout=1; --connect(con12,localhost,root,,) SET AUTOCOMMIT = 1; @@ -244,7 +244,7 @@ DROP TABLE t_con1_innodb; DROP TABLE t_con1_myisam; --connection con12 --error ER_LOCK_WAIT_TIMEOUT -SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; +SET STATEMENT lock_wait_timeout=1 FOR UPDATE t_permanent_innodb SET col1 = 9; --connection backup BACKUP STAGE END; diff --git a/mysql-test/main/comment_table.result b/mysql-test/main/comment_table.result index 99ecb04a362..d0af71b4540 100644 --- a/mysql-test/main/comment_table.result +++ b/mysql-test/main/comment_table.result @@ -1,4 +1,3 @@ -DROP TABLE IF EXISTS t1; create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INTEGER COMMENT '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, INDEX i1 (c1) COMMENT 'i1 comment',INDEX i2(c2) ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcd'; SELECT table_comment,char_length(table_comment) FROM information_schema.tables WHERE table_name='t1'; @@ -125,3 +124,7 @@ SELECT table_comment,char_length(table_comment) FROM information_schema.tables W table_comment char_length(table_comment) SELECT column_comment,char_length(column_comment) FROM information_schema.columns WHERE table_name='t1'; column_comment char_length(column_comment) +set names utf8; +create table t1 (x int comment 'a'); +ERROR HY000: Invalid utf8 character string: 'a' +set names latin1; diff --git a/mysql-test/main/comment_table.test b/mysql-test/main/comment_table.test index 6ab9f23b377..ba1ab9dda33 100644 --- a/mysql-test/main/comment_table.test +++ b/mysql-test/main/comment_table.test @@ -1,6 +1,3 @@ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings #1024 bytes create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INTEGER COMMENT '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, INDEX i1 (c1) COMMENT 'i1 comment',INDEX i2(c2) ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcd'; @@ -53,3 +50,11 @@ create table t1 (c1 VARCHAR(10) NOT NULL COMMENT 'c1 comment', c2 INTEGER,c3 INT ) COMMENT='abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcde'; SELECT table_comment,char_length(table_comment) FROM information_schema.tables WHERE table_name='t1'; SELECT column_comment,char_length(column_comment) FROM information_schema.columns WHERE table_name='t1'; + +# +# MDEV-22558 wrong error for invalid utf8 table comment +# +set names utf8; +--error ER_INVALID_CHARACTER_STRING +create table t1 (x int comment 'a'); +set names latin1; diff --git a/mysql-test/main/commit_1innodb.result b/mysql-test/main/commit_1innodb.result index 7d21540b548..cf673f81d82 100644 --- a/mysql-test/main/commit_1innodb.result +++ b/mysql-test/main/commit_1innodb.result @@ -385,6 +385,11 @@ end if; end| # Reset Handler_commit and Handler_prepare counters flush status; +# +# Count of reading of p_verify_status_increment() from mysql.proc +call p_verify_status_increment(2, 0, 2, 0); +SUCCESS + # # 1. Read-only statement: SELECT # @@ -568,7 +573,7 @@ begin insert t2 set a=2; return 2; end| -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(4, 0, 4, 0); SUCCESS # 16. A function changes non-trans-table. @@ -580,7 +585,7 @@ SUCCESS select f1(); f1() 2 -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(3, 0, 3, 0); SUCCESS commit; @@ -688,9 +693,9 @@ SUCCESS # 24. DDL: TRUNCATE TEMPORARY TABLE truncate table t2; -call p_verify_status_increment(4, 0, 4, 0); -ERROR -Expected commit increment: 4 actual: 2 +call p_verify_status_increment(2, 0, 2, 0); +SUCCESS + commit; # There is nothing left to commit call p_verify_status_increment(0, 0, 0, 0); @@ -855,7 +860,7 @@ call p_verify_status_increment(2, 0, 2, 0); SUCCESS create view v1 as select * from t2; -call p_verify_status_increment(2, 0, 2, 0); +call p_verify_status_increment(4, 0, 4, 0); SUCCESS check table t1; @@ -882,7 +887,7 @@ call p_verify_status_increment(0, 0, 0, 0); SUCCESS drop view v1; -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(2, 0, 2, 0); SUCCESS # diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index d22d55669ac..f863070c646 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -29,8 +29,7 @@ create table t2 select auto+1 from t1; ERROR 42S02: Table 'test.t1' doesn't exist drop table if exists t1,t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' create table t1 (b char(0) not null, index(b)); ERROR 42000: The storage engine MyISAM can't index column `b` create table t1 (a int not null,b text) engine=heap; diff --git a/mysql-test/main/create_drop_view.result b/mysql-test/main/create_drop_view.result index 9d7e42552bf..a62639545e1 100644 --- a/mysql-test/main/create_drop_view.result +++ b/mysql-test/main/create_drop_view.result @@ -52,8 +52,15 @@ id 50 80 40 +DROP TABLE IF EXISTS v1; +Warnings: +Note 1965 'test.v1' is a view DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1; Warnings: Note 4092 Unknown VIEW: 'test.v1' +DROP VIEW IF EXISTS t1; +Warnings: +Warning 1347 'test.t1' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.t1' DROP TABLE t1; diff --git a/mysql-test/main/create_drop_view.test b/mysql-test/main/create_drop_view.test index 5f5df43a7e0..0ebf643e1f1 100644 --- a/mysql-test/main/create_drop_view.test +++ b/mysql-test/main/create_drop_view.test @@ -22,6 +22,8 @@ INSERT INTO t1 VALUES (50), (80), (3), (2), (40); SELECT * FROM t1; SELECT * FROM v1; +DROP TABLE IF EXISTS v1; DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS t1; DROP TABLE t1; diff --git a/mysql-test/main/create_or_replace.result b/mysql-test/main/create_or_replace.result index 485091e5810..1eaf87d190d 100644 --- a/mysql-test/main/create_or_replace.result +++ b/mysql-test/main/create_or_replace.result @@ -255,8 +255,7 @@ drop table t1,t3,t4; create database mysqltest2; drop table if exists test.t1,mysqltest2.t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'mysqltest2.t2' +Note 1051 Unknown table 'test.t1,mysqltest2.t2' create table test.t1 (i int) engine=myisam; create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; diff --git a/mysql-test/main/cte_recursive.result b/mysql-test/main/cte_recursive.result index 2f00248fb55..deb791f25a3 100644 --- a/mysql-test/main/cte_recursive.result +++ b/mysql-test/main/cte_recursive.result @@ -691,13 +691,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 100.00 Using where 1 PRIMARY ref key0 key0 5 c.h_id 2 100.00 1 PRIMARY ref key0 key0 5 c.w_id 2 100.00 -2 DERIVED ALL NULL NULL NULL NULL 12 100.00 Using where 3 DERIVED folks ALL NULL NULL NULL NULL 12 100.00 Using where 4 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 4 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join) 5 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 5 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +2 DERIVED ALL NULL NULL NULL NULL 12 100.00 Using where Warnings: Note 1003 with recursive ancestor_couple_ids(`h_id`,`w_id`) as (/* select#2 */ select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors(`id`,`name`,`dob`,`father`,`mother`) as (/* select#3 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all /* select#4 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all /* select#5 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` = `ma`.`w_id`)/* select#1 */ select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id` # simple mutual recursion @@ -1302,12 +1302,12 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 24 4 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 6 RECURSIVE UNION ALL NULL NULL NULL NULL 12 +5 RECURSIVE UNION ALL NULL NULL NULL NULL 24 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL 3 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 2 RECURSIVE UNION folks ALL PRIMARY NULL NULL NULL 12 2 RECURSIVE UNION ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL -5 RECURSIVE UNION ALL NULL NULL NULL NULL 24 -NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain FORMAT=JSON with recursive prev_gen @@ -3093,7 +3093,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 4 DEPENDENT SUBQUERY ALL NULL NULL NULL NULL 16 100.00 Using where NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 with recursive destinations(`city`,`legs`) as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !(`test`.`b`.`arrival`,(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations` +Note 1003 with recursive destinations(`city`,`legs`) as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !((`test`.`b`.`arrival`,(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null)))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations` set standard_compliant_cte=default; drop table flights; # @@ -3372,13 +3372,13 @@ select * from cte1, cte2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 6 100.00 1 PRIMARY ALL NULL NULL NULL NULL 6 100.00 Using join buffer (flat, BNL join) +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL 4 DERIVED ALL NULL NULL NULL NULL 2 100.00 Using where 4 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 5 DERIVED ALL NULL NULL NULL NULL 2 100.00 Using where 5 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) -2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used -3 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 Using where -NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 with recursive rcte(`a`) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte1`.`c1` AS `c1`,`cte2`.`c2` AS `c2` from `cte1` join `cte2` prepare stmt from "with recursive @@ -3437,6 +3437,65 @@ cte2 as (select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) select * from cte1, cte2 where cte1.c1 = 3; c1 c2 +with recursive +rcte(a) as +(select 1 union select cast(a+1 as unsigned) from rcte where a < 10), +cte1 as +(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3), +cte2 as +(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) +select * from cte2, cte1; +c2 c1 +1 2 +explain extended with recursive +rcte(a) as +(select 1 union select cast(a+1 as unsigned) from rcte where a < 10), +cte1 as +(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3), +cte2 as +(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) +select * from cte2, cte1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 6 100.00 +1 PRIMARY ALL NULL NULL NULL NULL 6 100.00 Using join buffer (flat, BNL join) +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +5 DERIVED ALL NULL NULL NULL NULL 2 100.00 Using where +5 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +4 DERIVED ALL NULL NULL NULL NULL 2 100.00 Using where +4 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 with recursive rcte(`a`) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte2`.`c2` AS `c2`,`cte1`.`c1` AS `c1` from `cte2` join `cte1` +prepare stmt from "with recursive +rcte(a) as +(select 1 union select cast(a+1 as unsigned) from rcte where a < 10), +cte1 as +(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3), +cte2 as +(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) +select * from cte2, cte1"; +execute stmt; +c2 c1 +1 2 +execute stmt; +c2 c1 +1 2 +drop procedure p; +drop table t2; +create table t2 (c1 int, c2 int); +create procedure p() insert into t2 with recursive +rcte(a) as +(select 1 union select cast(a+1 as unsigned) from rcte where a < 10), +cte1 as +(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3), +cte2 as +(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) +select * from cte2, cte1; +call p(); +select * from t2; +c1 c2 +1 2 drop procedure p; drop table t1,t2; # @@ -3694,8 +3753,254 @@ select * from t1 as t; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t ALL NULL NULL NULL NULL 4 drop table t1,t2; +# +# MDEV-22042: ANALYZE of query using stored function and recursive CTE +# +create table t1 (a1 varchar(20),a2 varchar(20)) engine=myisam; +insert into t1 values (1,1),(2,2),(3,3); +create table t2 ( +a2 varchar(20) primary key, b1 varchar(20), key (b1) +) engine=myisam; +insert into t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +insert into t2 values (11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17); +create function f1(id varchar(20)) returns varchar(50) +begin +declare res varchar (50); +select a2 into res from t2 where a2=id and b1=1 limit 1; +return res; +end$$ +select fv +from (select t1.a1, f1(t1.a2) fv from t1) dt +where (dt.a1) in (with recursive cte as (select a2 from t2 where a2='2' + union select tt2.a2 from t2 tt2 join cte on tt2.b1=cte.a2) +select a2 from cte); +fv +NULL +explain select fv +from (select t1.a1, f1(t1.a2) fv from t1) dt +where (dt.a1) in (with recursive cte as (select a2 from t2 where a2='2' + union select tt2.a2 from t2 tt2 join cte on tt2.b1=cte.a2) +select a2 from cte); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY ref key0 key0 23 test.t1.a1 1 FirstMatch(t1) +3 DERIVED t2 const PRIMARY PRIMARY 22 const 1 Using index +4 RECURSIVE UNION ALL NULL NULL NULL NULL 2 Using where +4 RECURSIVE UNION tt2 ref b1 b1 23 cte.a2 2 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +analyze format=json select fv +from (select t1.a1, f1(t1.a2) fv from t1) dt +where (dt.a1) in (with recursive cte as (select a2 from t2 where a2='2' + union select tt2.a2 from t2 tt2 join cte on tt2.b1=cte.a2) +select a2 from cte); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 3, + "r_rows": 3, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "attached_condition": "t1.a1 is not null" + }, + "table": { + "table_name": "", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "23", + "used_key_parts": ["a2"], + "ref": ["test.t1.a1"], + "r_loops": 3, + "rows": 1, + "r_rows": 0.333333333, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "first_match": "t1", + "materialized": { + "query_block": { + "recursive_union": { + "table_name": "", + "access_type": "ALL", + "r_loops": 0, + "r_rows": null, + "query_specifications": [ + { + "query_block": { + "select_id": 3, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "const", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "22", + "used_key_parts": ["a2"], + "ref": ["const"], + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null, + "using_index": true + } + } + }, + { + "query_block": { + "select_id": 4, + "operation": "UNION", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 1, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "attached_condition": "cte.a2 is not null" + }, + "table": { + "table_name": "tt2", + "access_type": "ref", + "possible_keys": ["b1"], + "key": "b1", + "key_length": "23", + "used_key_parts": ["b1"], + "ref": ["cte.a2"], + "r_loops": 1, + "rows": 2, + "r_rows": 1, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + ] + } + } + } + } + } +} +drop function f1; +drop table t1,t2; +# +# MDEV-22748: two materialized CTEs using the same recursive CTE +# (see also test case for MDEV-17024) +# +CREATE TABLE t1 (YEAR int(4), d1 date , d2 date) ; +INSERT INTO t1 VALUES (2018,'2018-01-01','2018-09-20'); +CREATE TABLE t2 (id int, tm date); +INSERT INTO t2 VALUES (1,'2018-08-30'),(2,'2018-08-30'),(3,'2018-08-30'); +CREATE TABLE t3 (id int, tm date); +INSERT INTO t3 VALUES (1,'2018-08-30'),(2,'2018-08-30'); +WITH RECURSIVE +cte AS +(SELECT YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn +FROM t1 +UNION ALL +SELECT YEAR(cte.st + INTERVAL 1 MONTH), +cte.st + INTERVAL 1 MONTH, t1.d2 + INTERVAL 1 DAY +FROM cte JOIN t1 +WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ), +cte2 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn), +cte3 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn) +SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR); +YEAR d1 d2 +2018 2018-01-01 2018-09-20 +EXPLAIN EXTENDED WITH RECURSIVE +cte AS +(SELECT YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn +FROM t1 +UNION ALL +SELECT YEAR(cte.st + INTERVAL 1 MONTH), +cte.st + INTERVAL 1 MONTH, t1.d2 + INTERVAL 1 DAY +FROM cte JOIN t1 +WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ), +cte2 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn), +cte3 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn) +SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 +1 PRIMARY ref key0 key0 5 const 0 0.00 +1 PRIMARY ref key0 key0 5 const 0 0.00 +2 DERIVED t1 system NULL NULL NULL NULL 1 100.00 +3 RECURSIVE UNION t1 system NULL NULL NULL NULL 1 100.00 +3 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +4 DERIVED ALL NULL NULL NULL NULL 2 100.00 +4 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +5 DERIVED ALL NULL NULL NULL NULL 2 100.00 +5 DERIVED t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 with recursive cte as (/* select#2 */ select year(`test`.`t1`.`d1`) AS `YEAR`,`test`.`t1`.`d1` AS `st`,`test`.`t1`.`d1` + interval 1 month AS `fn` from `test`.`t1` union all /* select#3 */ select year(`cte`.`st` + interval 1 month) AS `YEAR(cte.st + INTERVAL 1 MONTH)`,`cte`.`st` + interval 1 month AS `cte.st + INTERVAL 1 MONTH`,`test`.`t1`.`d2` + interval 1 day AS `t1.d2 + INTERVAL 1 DAY` from `cte` join `test`.`t1` where `cte`.`st` + interval 1 month < `test`.`t1`.`d2`), cte2 as (/* select#4 */ select `cte`.`YEAR` AS `YEAR`,count(0) AS `COUNT(*)` from `cte` join `test`.`t2` where `test`.`t2`.`tm` between `cte`.`st` and `cte`.`fn`), cte3 as (/* select#5 */ select `cte`.`YEAR` AS `YEAR`,count(0) AS `COUNT(*)` from `cte` join `test`.`t3` where `test`.`t3`.`tm` between `cte`.`st` and `cte`.`fn`)/* select#1 */ select 2018 AS `YEAR`,'2018-01-01' AS `d1`,'2018-09-20' AS `d2` from `cte2` join `cte3` where `cte3`.`YEAR` = 2018 and `cte2`.`YEAR` = 2018 +PREPARE stmt FROM "WITH RECURSIVE +cte AS +(SELECT YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn +FROM t1 +UNION ALL +SELECT YEAR(cte.st + INTERVAL 1 MONTH), +cte.st + INTERVAL 1 MONTH, t1.d2 + INTERVAL 1 DAY +FROM cte JOIN t1 +WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ), +cte2 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn), +cte3 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn) +SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR)"; +EXECUTE stmt; +YEAR d1 d2 +2018 2018-01-01 2018-09-20 +EXECUTE stmt; +YEAR d1 d2 +2018 2018-01-01 2018-09-20 +CREATE TABLE t4 (YEAR int(4), d1 date , d2 date); +CREATE PROCEDURE p() INSERT INTO t4 WITH RECURSIVE +cte AS +(SELECT YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn +FROM t1 +UNION ALL +SELECT YEAR(cte.st + INTERVAL 1 MONTH), +cte.st + INTERVAL 1 MONTH, t1.d2 + INTERVAL 1 DAY +FROM cte JOIN t1 +WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ), +cte2 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn), +cte3 AS (SELECT YEAR, COUNT(*) +FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn) +SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR); +CALL p(); +SELECT * FROM t4; +YEAR d1 d2 +2018 2018-01-01 2018-09-20 +DROP PROCEDURE p; +DROP TABLE t1,t2,t3,t4; +# # End of 10.2 tests # +# # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field # CREATE TEMPORARY TABLE a_tbl ( diff --git a/mysql-test/main/cte_recursive.test b/mysql-test/main/cte_recursive.test index ce3b817a937..023d961ce5e 100644 --- a/mysql-test/main/cte_recursive.test +++ b/mysql-test/main/cte_recursive.test @@ -2424,6 +2424,30 @@ select * from cte1, cte2 where cte1.c1 = 3; eval $q3; +let $q4= +with recursive +rcte(a) as +(select 1 union select cast(a+1 as unsigned) from rcte where a < 10), +cte1 as +(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3), +cte2 as +(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7) +select * from cte2, cte1; + +eval $q4; +eval explain extended $q4; +eval prepare stmt from "$q4"; +execute stmt; +execute stmt; + +drop procedure p; +drop table t2; + +create table t2 (c1 int, c2 int); +eval create procedure p() insert into t2 $q4; +call p(); +select * from t2; + drop procedure p; drop table t1,t2; @@ -2571,7 +2595,89 @@ select * from t1 as t; drop table t1,t2; + +--echo # +--echo # MDEV-22042: ANALYZE of query using stored function and recursive CTE +--echo # + +create table t1 (a1 varchar(20),a2 varchar(20)) engine=myisam; +insert into t1 values (1,1),(2,2),(3,3); + +create table t2 ( +a2 varchar(20) primary key, b1 varchar(20), key (b1) +) engine=myisam; +insert into t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +insert into t2 values (11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17); + +delimiter $$; +create function f1(id varchar(20)) returns varchar(50) +begin + declare res varchar (50); + select a2 into res from t2 where a2=id and b1=1 limit 1; + return res; +end$$ +delimiter ;$$ + +let q= +select fv +from (select t1.a1, f1(t1.a2) fv from t1) dt +where (dt.a1) in (with recursive cte as (select a2 from t2 where a2='2' + union select tt2.a2 from t2 tt2 join cte on tt2.b1=cte.a2) +select a2 from cte); + +eval $q; +eval explain $q; +--source include/analyze-format.inc +eval analyze format=json $q; + +drop function f1; +drop table t1,t2; + +--echo # +--echo # MDEV-22748: two materialized CTEs using the same recursive CTE +--echo # (see also test case for MDEV-17024) +--echo # + +CREATE TABLE t1 (YEAR int(4), d1 date , d2 date) ; +INSERT INTO t1 VALUES (2018,'2018-01-01','2018-09-20'); +CREATE TABLE t2 (id int, tm date); +INSERT INTO t2 VALUES (1,'2018-08-30'),(2,'2018-08-30'),(3,'2018-08-30'); +CREATE TABLE t3 (id int, tm date); +INSERT INTO t3 VALUES (1,'2018-08-30'),(2,'2018-08-30'); + +let $q= +WITH RECURSIVE +cte AS + (SELECT YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn + FROM t1 + UNION ALL + SELECT YEAR(cte.st + INTERVAL 1 MONTH), + cte.st + INTERVAL 1 MONTH, t1.d2 + INTERVAL 1 DAY + FROM cte JOIN t1 + WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ), +cte2 AS (SELECT YEAR, COUNT(*) + FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn), +cte3 AS (SELECT YEAR, COUNT(*) + FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn) +SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR); + +eval $q; +eval EXPLAIN EXTENDED $q; +eval PREPARE stmt FROM "$q"; +EXECUTE stmt; +EXECUTE stmt; + +CREATE TABLE t4 (YEAR int(4), d1 date , d2 date); +eval CREATE PROCEDURE p() INSERT INTO t4 $q; +CALL p(); +SELECT * FROM t4; + +DROP PROCEDURE p; +DROP TABLE t1,t2,t3,t4; + +--echo # --echo # End of 10.2 tests +--echo # --echo # --echo # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field diff --git a/mysql-test/main/ctype_big5.result b/mysql-test/main/ctype_big5.result index 95d1f10349e..41ce8f0b82e 100644 --- a/mysql-test/main/ctype_big5.result +++ b/mysql-test/main/ctype_big5.result @@ -5384,3 +5384,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES big5; +SET @seq=_big5 0xA3C0; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid big5 character string: '\xA3\xC0' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_big5.test b/mysql-test/main/ctype_big5.test index 410203c7c86..41991258886 100644 --- a/mysql-test/main/ctype_big5.test +++ b/mysql-test/main/ctype_big5.test @@ -269,3 +269,20 @@ let $coll_pad='big5_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES big5; +SET @seq=_big5 0xA3C0; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result index 77157a4da0a..c0bbb8ff4ff 100644 --- a/mysql-test/main/ctype_binary.result +++ b/mysql-test/main/ctype_binary.result @@ -1,7 +1,4 @@ set names binary; -# -# Start of 5.5 tests -# SET TIME_ZONE = _latin1 '+03:00'; # # Start of WL#2649 Number-to-string conversions @@ -2925,9 +2922,6 @@ SET sql_mode=default; # # End of 5.5 tests # -# -# Start of 10.0 tests -# SET NAMES binary; # # MDEV-7149 Constant condition propagation erroneously applied for LIKE @@ -3075,9 +3069,6 @@ SET optimizer_switch=@save_optimizer_switch; # End of 10.0 tests # # -# Start of 10.1 tests -# -# # MDEV-8695 Wrong result for SELECT..WHERE varchar_column='a' AND CRC32(varchar_column)=3904355907 # CREATE TABLE t1 (a VARBINARY(10)); @@ -3172,9 +3163,148 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' and weight_string(`test`.`t1`.`a`,0,0,1) = 'a' DROP TABLE t1; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# +CREATE TABLE t1(a ENUM(0x6100,0x6200,0x6300) CHARACTER SET 'Binary'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0','b\0','c\0') CHARACTER SET binary DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1),(2),(3); +SELECT HEX(a) FROM t1 ORDER BY a; +HEX(a) +6100 +6200 +6300 +DROP TABLE t1; +0x00 in the middle or in the end of a value +CREATE TABLE t1 (a ENUM(0x6100)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +HEX(a) +6100 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM(0x610062)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a\0b') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +HEX(a) +610062 +DROP TABLE t1; +0x00 in the beginning of the first value: +CREATE TABLE t1 (a ENUM(0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(1); +SELECT HEX(a) FROM t1; +HEX(a) +0061 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM(0x0061), b ENUM('b')); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('\0a') DEFAULT NULL, + `b` enum('b') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +SELECT HEX(a), HEX(b) FROM t1; +HEX(a) HEX(b) +0061 62 +DROP TABLE t1; +# 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table: +CREATE TABLE t1 (a ENUM('a',0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a','\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1),(2); +SELECT HEX(a) FROM t1 ORDER BY a; +HEX(a) +61 +0061 +DROP TABLE t1; +CREATE TABLE t1 (a ENUM('a'), b ENUM('b',0x0061)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('a') DEFAULT NULL, + `b` enum('b','\0a') DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +INSERT INTO t1 VALUES (1,2); +SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b; +HEX(a) HEX(b) +61 62 +61 0061 +DROP TABLE t1; +0x00 in the beginning of a value of a non-last ENUM/SET causes an error: +CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b')); +ERROR HY000: Incorrect information in file: 'DIR/t1.frm' +# # End of 10.1 tests # # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES latin1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary', d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061 +DROP TABLE t1; +CREATE TABLE t1( +c ENUM(0x0061) CHARACTER SET 'Binary', +d INT DEFAULT NULL CHECK (d>0) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL, + `d` int(11) DEFAULT NULL CHECK (`d` > 0) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1,1); +SELECT HEX(c), d FROM t1; +HEX(c) d +0061 1 +DROP TABLE t1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary' CHECK (c>0)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a') CHARACTER SET binary DEFAULT NULL CHECK (`c` > 0) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061 +DROP TABLE t1; +# +# End of 10.2 tests +# +# # Start of 10.5 tests # # diff --git a/mysql-test/main/ctype_binary.test b/mysql-test/main/ctype_binary.test index a466329a48a..3cf184576b4 100644 --- a/mysql-test/main/ctype_binary.test +++ b/mysql-test/main/ctype_binary.test @@ -1,10 +1,6 @@ set names binary; ---echo # ---echo # Start of 5.5 tests ---echo # - --source include/ctype_numconv.inc --echo # @@ -12,10 +8,6 @@ set names binary; --echo # ---echo # ---echo # Start of 10.0 tests ---echo # - SET NAMES binary; --source include/ctype_like_cond_propagation.inc @@ -31,10 +23,6 @@ SET NAMES utf8, character_set_connection=binary; --echo # End of 10.0 tests --echo # ---echo # ---echo # Start of 10.1 tests ---echo # - --echo # --echo # MDEV-8695 Wrong result for SELECT..WHERE varchar_column='a' AND CRC32(varchar_column)=3904355907 --echo # @@ -74,10 +62,101 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE COERCIBILITY(a)=2 AND a='a'; EXPLAIN EXTENDED SELECT * FROM t1 WHERE WEIGHT_STRING(a)='a' AND a='a'; DROP TABLE t1; + +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # + +CREATE TABLE t1(a ENUM(0x6100,0x6200,0x6300) CHARACTER SET 'Binary'); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1),(2),(3); +SELECT HEX(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +--echo 0x00 in the middle or in the end of a value + +CREATE TABLE t1 (a ENUM(0x6100)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM(0x610062)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +--echo 0x00 in the beginning of the first value: + +CREATE TABLE t1 (a ENUM(0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(1); +SELECT HEX(a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM(0x0061), b ENUM('b')); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +SELECT HEX(a), HEX(b) FROM t1; +DROP TABLE t1; + +--echo # 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table: + +CREATE TABLE t1 (a ENUM('a',0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1),(2); +SELECT HEX(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +CREATE TABLE t1 (a ENUM('a'), b ENUM('b',0x0061)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +INSERT INTO t1 VALUES (1,2); +SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b; +DROP TABLE t1; + +--echo 0x00 in the beginning of a value of a non-last ENUM/SET causes an error: +--replace_regex /'.*t1.frm'/'DIR\/t1.frm'/ +--error ER_NOT_FORM_FILE +CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b')); + + --echo # --echo # End of 10.1 tests --echo # +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES latin1; +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary', d JSON); +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1( + c ENUM(0x0061) CHARACTER SET 'Binary', + d INT DEFAULT NULL CHECK (d>0) +); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1,1); +SELECT HEX(c), d FROM t1; +DROP TABLE t1; + +CREATE TABLE t1(c ENUM(0x0061) CHARACTER SET 'Binary' CHECK (c>0)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.2 tests +--echo # + --echo # --echo # Start of 10.5 tests --echo # @@ -104,4 +183,3 @@ DROP TABLE t1; --echo # --echo # End of 10.5 tests --echo # - diff --git a/mysql-test/main/ctype_cp932.result b/mysql-test/main/ctype_cp932.result index dcb94d95c50..952130cf11c 100644 --- a/mysql-test/main/ctype_cp932.result +++ b/mysql-test/main/ctype_cp932.result @@ -597,3 +597,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES cp932; +SET @seq=_cp932 0x81AD; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid cp932 character string: '\x81\xAD' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_cp932.test b/mysql-test/main/ctype_cp932.test index 2486ca8a79e..0f5ff437d33 100644 --- a/mysql-test/main/ctype_cp932.test +++ b/mysql-test/main/ctype_cp932.test @@ -47,3 +47,20 @@ let $coll_pad='cp932_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES cp932; +SET @seq=_cp932 0x81AD; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_dec8.result b/mysql-test/main/ctype_dec8.result new file mode 100644 index 00000000000..f0522494bb2 --- /dev/null +++ b/mysql-test/main/ctype_dec8.result @@ -0,0 +1,58 @@ +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES dec8; +SET @seq=_dec8 0xD0; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid dec8 character string: '\xD0' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid dec8 character string: '\xD0' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_dec8.test b/mysql-test/main/ctype_dec8.test new file mode 100644 index 00000000000..869d6242225 --- /dev/null +++ b/mysql-test/main/ctype_dec8.test @@ -0,0 +1,15 @@ +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES dec8; +SET @seq=_dec8 0xD0; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_eucjpms.result b/mysql-test/main/ctype_eucjpms.result index 1a40490308e..ba91abca96f 100644 --- a/mysql-test/main/ctype_eucjpms.result +++ b/mysql-test/main/ctype_eucjpms.result @@ -34491,3 +34491,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES eucjpms; +SET @seq=_eucjpms 0x8FA1A1; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_eucjpms.test b/mysql-test/main/ctype_eucjpms.test index 867ca809dbf..6af72270853 100644 --- a/mysql-test/main/ctype_eucjpms.test +++ b/mysql-test/main/ctype_eucjpms.test @@ -596,3 +596,20 @@ let $coll_pad='eucjpms_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES eucjpms; +SET @seq=_eucjpms 0x8FA1A1; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_euckr.result b/mysql-test/main/ctype_euckr.result index 9f98e39c59e..5bfcc7071f3 100644 --- a/mysql-test/main/ctype_euckr.result +++ b/mysql-test/main/ctype_euckr.result @@ -26009,3 +26009,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES euckr; +SET @seq=_euckr 0xA2E8; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid euckr character string: '\xA2\xE8' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_euckr.test b/mysql-test/main/ctype_euckr.test index 46955360217..1154047fdb0 100644 --- a/mysql-test/main/ctype_euckr.test +++ b/mysql-test/main/ctype_euckr.test @@ -227,3 +227,20 @@ let $coll_pad='euckr_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES euckr; +SET @seq=_euckr 0xA2E8; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_gb2312.result b/mysql-test/main/ctype_gb2312.result index 49db390cee4..d6066f82db9 100644 --- a/mysql-test/main/ctype_gb2312.result +++ b/mysql-test/main/ctype_gb2312.result @@ -5079,3 +5079,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES gb2312; +SET @seq=_gb2312 0xA2A1; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_gb2312.test b/mysql-test/main/ctype_gb2312.test index 4489168a163..07460116ade 100644 --- a/mysql-test/main/ctype_gb2312.test +++ b/mysql-test/main/ctype_gb2312.test @@ -180,3 +180,20 @@ let $coll_pad='gb2312_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES gb2312; +SET @seq=_gb2312 0xA2A1; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index fb66631c5cb..7b54794a884 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -6542,3 +6542,61 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES gbk; +SET @seq=_gbk 0xAAA1; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid gbk character string: '\xAA\xA1' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_gbk.test b/mysql-test/main/ctype_gbk.test index d9d0a4d0ee4..c63c331c643 100644 --- a/mysql-test/main/ctype_gbk.test +++ b/mysql-test/main/ctype_gbk.test @@ -484,3 +484,20 @@ let $coll_pad='gbk_bin'; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES gbk; +SET @seq=_gbk 0xAAA1; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_sjis.result b/mysql-test/main/ctype_sjis.result index fae022b60e1..638f9bc21c7 100644 --- a/mysql-test/main/ctype_sjis.result +++ b/mysql-test/main/ctype_sjis.result @@ -19318,3 +19318,61 @@ SET NAMES sjis; # # End of 10.5 tests # +# +# Start of 10.5 tests +# +# +# MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +# +SET NAMES sjis; +SET @seq=_sjis 0x81AD; +# +# SET STATEMENT (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET STATEMENT a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +# +# SET SESSION (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET SESSION ',@seq, '.a=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET SESSION a.',@seq, '=1 SELECT 1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +# +# SET (bad|good.bad|bad.good)=1 +# +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET ', @seq, '.a=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('SET a.', @seq, '=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +# +# Oracle SP call: BEGIN (bad|good.bad|bad.good)(params); END +# +SET sql_mode=ORACLE; +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '(1); END;'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('BEGIN ',@seq, '.a(1); END;'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('BEGIN a.',@seq, '(1); END;'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +# +# Oracle assignment: (bad|good.bad|bad.good):= value +# +EXECUTE IMMEDIATE CONCAT(@seq, ':=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT(@seq, '.a:=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); +ERROR HY000: Invalid sjis character string: '_x81_xAD' +SET sql_mode=DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_sjis.test b/mysql-test/main/ctype_sjis.test index 804ba557faa..8ca423bb7c1 100644 --- a/mysql-test/main/ctype_sjis.test +++ b/mysql-test/main/ctype_sjis.test @@ -290,3 +290,20 @@ SET NAMES sjis; --echo # --echo # End of 10.5 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-22625 SIGSEGV in intern_find_sys_var (optimized builds) +--echo # + +SET NAMES sjis; +SET @seq=_sjis 0x81AD; +--source include/ctype_ident_sys.inc + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_utf16.result b/mysql-test/main/ctype_utf16.result index 94ad141313d..653f18e0ce6 100644 --- a/mysql-test/main/ctype_utf16.result +++ b/mysql-test/main/ctype_utf16.result @@ -1491,7 +1491,7 @@ ab ab AE AE -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; s1 ab @@ -2815,6 +2815,31 @@ SET DEFAULT_STORAGE_ENGINE=Default; # End of 10.2 tests # # +# Start of 10.3 tests +# +# +# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +# +SET NAMES utf8; +CREATE TABLE t1 (a TEXT CHARACTER SET utf16); +SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t; +1 +1 +DROP TABLE t1; +VALUES (1) UNION SELECT _utf16 0x0020; +1 +1 + +VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin; + + +VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin); + + +# +# End of 10.3 tests +# +# # Start of 10.5 tests # # diff --git a/mysql-test/main/ctype_utf16.test b/mysql-test/main/ctype_utf16.test index b22d2c69541..c2807a19215 100644 --- a/mysql-test/main/ctype_utf16.test +++ b/mysql-test/main/ctype_utf16.test @@ -723,7 +723,7 @@ CREATE TABLE t1 AS SELECT repeat('a',2) as s1 LIMIT 0; SHOW CREATE TABLE t1; INSERT INTO t1 VALUES ('ab'),('AE'),('ab'),('AE'); SELECT * FROM t1 ORDER BY s1; -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; DROP TABLE t1; SET max_sort_length=DEFAULT; @@ -935,6 +935,27 @@ let $coll_pad='utf16_bin'; --echo # End of 10.2 tests --echo # +--echo # +--echo # Start of 10.3 tests +--echo # + +--echo # +--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +--echo # + +SET NAMES utf8; +CREATE TABLE t1 (a TEXT CHARACTER SET utf16); +SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t; +DROP TABLE t1; +VALUES (1) UNION SELECT _utf16 0x0020; +VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin; +VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin); + + +--echo # +--echo # End of 10.3 tests +--echo # + --echo # --echo # Start of 10.5 tests diff --git a/mysql-test/main/ctype_utf16_uca.result b/mysql-test/main/ctype_utf16_uca.result index 1b5224e2179..d1dbd498064 100644 --- a/mysql-test/main/ctype_utf16_uca.result +++ b/mysql-test/main/ctype_utf16_uca.result @@ -7899,5 +7899,46 @@ a b DROP TABLE t1; SET NAMES utf8; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES utf8, COLLATION_CONNECTION=utf16_hungarian_ci; +CREATE TABLE t1(c ENUM('aaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +00610061006100610061006100610061 +DROP TABLE t1; +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +006100610061006100610061006100610061 +DROP TABLE t1; +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaaa') CHARACTER SET 'Binary',d JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` enum('\0a\0a\0a\0a\0a\0a\0a\0a\0a\0a') CHARACTER SET binary DEFAULT NULL, + `d` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`d`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +HEX(c) +0061006100610061006100610061006100610061 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/main/ctype_utf16_uca.test b/mysql-test/main/ctype_utf16_uca.test index 3b54e0deead..cb00ccc0c61 100644 --- a/mysql-test/main/ctype_utf16_uca.test +++ b/mysql-test/main/ctype_utf16_uca.test @@ -243,6 +243,31 @@ SET NAMES utf8, collation_connection=utf16_unicode_520_nopad_ci; SET NAMES utf8; +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES utf8, COLLATION_CONNECTION=utf16_hungarian_ci; +CREATE TABLE t1(c ENUM('aaaaaaaa') CHARACTER SET 'Binary',d JSON); # ERROR 1064 (42000): You have an error in your SQL syntax +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaa') CHARACTER SET 'Binary',d JSON); # ERROR 1033 (HY000): Incorrect information in file: './test/t.frm' +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1(c ENUM('aaaaaaaaaa') CHARACTER SET 'Binary',d JSON); # Sig 11 +SHOW CREATE TABLE t1; +INSERT INTO t1 (c) VALUES (1); +SELECT HEX(c) FROM t1; +DROP TABLE t1; + + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/ctype_utf16le.result b/mysql-test/main/ctype_utf16le.result index 3e4f2faf453..38d61bd4f1b 100644 --- a/mysql-test/main/ctype_utf16le.result +++ b/mysql-test/main/ctype_utf16le.result @@ -1764,7 +1764,7 @@ ab ab AE AE -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; s1 ab diff --git a/mysql-test/main/ctype_utf16le.test b/mysql-test/main/ctype_utf16le.test index 643e8559d97..6f8fd71ec34 100644 --- a/mysql-test/main/ctype_utf16le.test +++ b/mysql-test/main/ctype_utf16le.test @@ -685,7 +685,7 @@ CREATE TABLE t1 AS SELECT REPEAT('a',2) as s1 LIMIT 0; SHOW CREATE TABLE t1; INSERT INTO t1 VALUES ('ab'),('AE'),('ab'),('AE'); SELECT * FROM t1 ORDER BY s1; -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; DROP TABLE t1; SET max_sort_length=DEFAULT; diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index f98eedc2464..5cbc1b66e40 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -1504,7 +1504,7 @@ ab ab AE AE -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; s1 ab @@ -2868,5 +2868,25 @@ DROP TABLE t1; # SET DEFAULT_STORAGE_ENGINE=Default; # +# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +# 10.2 tests +# +SET NAMES utf8, COLLATION_CONNECTION=utf32_bin; +CREATE TABLE t1(c1 ENUM('a','b','ac') CHARACTER SET 'Binary',c2 JSON,c3 INT); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` enum('\0\0\0a','\0\0\0b','\0\0\0a\0\0\0c') CHARACTER SET binary DEFAULT NULL, + `c2` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)), + `c3` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 (c1) VALUES (1),(2),(3); +SELECT HEX(c1) FROM t1 ORDER BY c1; +HEX(c1) +00000061 +00000062 +0000006100000063 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test index 902647ec522..59cc13015af 100644 --- a/mysql-test/main/ctype_utf32.test +++ b/mysql-test/main/ctype_utf32.test @@ -779,7 +779,7 @@ CREATE TABLE t1 AS SELECT repeat('a',2) as s1 LIMIT 0; SHOW CREATE TABLE t1; INSERT INTO t1 VALUES ('ab'),('AE'),('ab'),('AE'); SELECT * FROM t1 ORDER BY s1; -SET max_sort_length=4; +SET max_sort_length=8; SELECT * FROM t1 ORDER BY s1; DROP TABLE t1; SET max_sort_length=DEFAULT; @@ -1035,6 +1035,19 @@ let $coll='utf32_nopad_bin'; let $coll_pad='utf32_bin'; --source include/ctype_pad_all_engines.inc + +--echo # +--echo # MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed +--echo # 10.2 tests +--echo # + +SET NAMES utf8, COLLATION_CONNECTION=utf32_bin; +CREATE TABLE t1(c1 ENUM('a','b','ac') CHARACTER SET 'Binary',c2 JSON,c3 INT); +SHOW CREATE TABLE t1; +INSERT INTO t1 (c1) VALUES (1),(2),(3); +SELECT HEX(c1) FROM t1 ORDER BY c1; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/ctype_utf32_uca.result b/mysql-test/main/ctype_utf32_uca.result index e623d322d62..a344672579e 100644 --- a/mysql-test/main/ctype_utf32_uca.result +++ b/mysql-test/main/ctype_utf32_uca.result @@ -7921,3 +7921,21 @@ SET NAMES utf8; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-22499 Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed in TABLE_SHARE::init_from_binary_frm_image +# +SET @@SESSION.collation_connection=utf32_estonian_ci; +CREATE TABLE t1(c1 SET('a') COLLATE 'Binary',c2 JSON); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` set('\0\0\0a') CHARACTER SET binary DEFAULT NULL, + `c2` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/ctype_utf32_uca.test b/mysql-test/main/ctype_utf32_uca.test index 7849ddbca6f..f84093c4587 100644 --- a/mysql-test/main/ctype_utf32_uca.test +++ b/mysql-test/main/ctype_utf32_uca.test @@ -268,3 +268,21 @@ SET NAMES utf8; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-22499 Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed in TABLE_SHARE::init_from_binary_frm_image +--echo # + +SET @@SESSION.collation_connection=utf32_estonian_ci; +CREATE TABLE t1(c1 SET('a') COLLATE 'Binary',c2 JSON); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index 3a6c591d6d0..bc951600319 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -6757,10 +6757,10 @@ DFFFDFFF9CFF9DFF9EFF # # Checking strnxfrm() with odd length # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; @@max_sort_length -5 +9 create table t1 (a varchar(128) character set utf8 collate utf8_general_ci); insert into t1 values ('a'),('b'),('c'); select * from t1 order by a; @@ -11324,6 +11324,18 @@ SELECT x AS 5天内最近一次登录时间 FROM t1; 1 DROP TABLE t1; # +# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +# +SET NAMES utf8; +VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin; +_latin1 0xDF +ß +a +VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin); +_latin1 0xDF +ß +a +# # End of 10.3 tests # # diff --git a/mysql-test/main/ctype_utf8.test b/mysql-test/main/ctype_utf8.test index ea24561b75c..5fd19d1b245 100644 --- a/mysql-test/main/ctype_utf8.test +++ b/mysql-test/main/ctype_utf8.test @@ -1768,7 +1768,7 @@ set @@collation_connection=utf8_bin; --echo # --echo # Checking strnxfrm() with odd length --echo # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; create table t1 (a varchar(128) character set utf8 collate utf8_general_ci); insert into t1 values ('a'),('b'),('c'); @@ -2257,6 +2257,13 @@ INSERT INTO t1 VALUES (1); SELECT x AS 5天内最近一次登录时间 FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +--echo # + +SET NAMES utf8; +VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin; +VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin); --echo # --echo # End of 10.3 tests diff --git a/mysql-test/main/ctype_utf8mb4.result b/mysql-test/main/ctype_utf8mb4.result index df40016100e..20842b37abb 100644 --- a/mysql-test/main/ctype_utf8mb4.result +++ b/mysql-test/main/ctype_utf8mb4.result @@ -2371,10 +2371,10 @@ drop table t1; # # Check strnxfrm() with odd length # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; @@max_sort_length -5 +9 create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci); insert into t1 values ('a'),('b'),('c'); select * from t1 order by a; diff --git a/mysql-test/main/ctype_utf8mb4.test b/mysql-test/main/ctype_utf8mb4.test index 88fb3d23b62..532729dafde 100644 --- a/mysql-test/main/ctype_utf8mb4.test +++ b/mysql-test/main/ctype_utf8mb4.test @@ -1520,7 +1520,7 @@ drop table t1; --echo # --echo # Check strnxfrm() with odd length --echo # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci); insert into t1 values ('a'),('b'),('c'); diff --git a/mysql-test/main/ctype_utf8mb4_heap.result b/mysql-test/main/ctype_utf8mb4_heap.result index 127b72674ac..4aef2d8cb66 100644 --- a/mysql-test/main/ctype_utf8mb4_heap.result +++ b/mysql-test/main/ctype_utf8mb4_heap.result @@ -2203,10 +2203,10 @@ drop table t1; # # Check strnxfrm() with odd length # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; @@max_sort_length -5 +9 create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci) engine heap; insert into t1 values ('a'),('b'),('c'); select * from t1 order by a; diff --git a/mysql-test/main/ctype_utf8mb4_innodb.result b/mysql-test/main/ctype_utf8mb4_innodb.result index c5fa569bd77..3c7d0ba2fb7 100644 --- a/mysql-test/main/ctype_utf8mb4_innodb.result +++ b/mysql-test/main/ctype_utf8mb4_innodb.result @@ -2329,10 +2329,10 @@ drop table t1; # # Check strnxfrm() with odd length # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; @@max_sort_length -5 +9 create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci) engine InnoDB; insert into t1 values ('a'),('b'),('c'); select * from t1 order by a; diff --git a/mysql-test/main/ctype_utf8mb4_myisam.result b/mysql-test/main/ctype_utf8mb4_myisam.result index 260f3b639bf..fd8d7adf3a0 100644 --- a/mysql-test/main/ctype_utf8mb4_myisam.result +++ b/mysql-test/main/ctype_utf8mb4_myisam.result @@ -2336,10 +2336,10 @@ drop table t1; # # Check strnxfrm() with odd length # -set max_sort_length=5; +set max_sort_length=9; select @@max_sort_length; @@max_sort_length -5 +9 create table t1 (a varchar(128) character set utf8mb4 collate utf8mb4_general_ci) engine MyISAM; insert into t1 values ('a'),('b'),('c'); select * from t1 order by a; diff --git a/mysql-test/main/custom_aggregate_functions.result b/mysql-test/main/custom_aggregate_functions.result index b98954b920e..884bd8b555f 100644 --- a/mysql-test/main/custom_aggregate_functions.result +++ b/mysql-test/main/custom_aggregate_functions.result @@ -1154,6 +1154,41 @@ NULL 8 drop function agg_sum; drop table t1; # +# User defined aggregate functions not working correctly when the schema is changed +# +CREATE SCHEMA IF NOT EXISTS common_schema; +CREATE SCHEMA IF NOT EXISTS another_schema; +DROP FUNCTION IF EXISTS common_schema.add_ints | +Warnings: +Note 1305 FUNCTION common_schema.add_ints does not exist +CREATE FUNCTION common_schema.add_ints(int_1 INT, int_2 INT) RETURNS INT NO SQL +BEGIN +RETURN int_1 + int_2; +END | +DROP FUNCTION IF EXISTS common_schema.sum_ints | +Warnings: +Note 1305 FUNCTION common_schema.sum_ints does not exist +CREATE AGGREGATE FUNCTION common_schema.sum_ints(int_val INT) RETURNS INT +BEGIN +DECLARE result INT DEFAULT 0; +DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN result; +LOOP FETCH GROUP NEXT ROW; +SET result = common_schema.add_ints(result, int_val); +END LOOP; +END | +use common_schema; +SELECT common_schema.sum_ints(seq) FROM (SELECT 1 seq UNION ALL SELECT 2) t; +common_schema.sum_ints(seq) +3 +USE another_schema; +SELECT common_schema.sum_ints(seq) FROM (SELECT 1 seq UNION ALL SELECT 2) t; +common_schema.sum_ints(seq) +3 +drop database common_schema; +drop database another_schema; +USE test; +# End of 10.3 tests +# # MDEV-18813 PROCEDURE and anonymous blocks silently ignore FETCH GROUP NEXT ROW # CREATE PROCEDURE p1() @@ -1186,3 +1221,4 @@ STARTS CURRENT_TIMESTAMP + INTERVAL 1 MONTH ENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH + INTERVAL 1 WEEK DO FETCH GROUP NEXT ROW; ERROR HY000: Aggregate specific instruction (FETCH GROUP NEXT ROW) used in a wrong context +# End of 10.4 tests diff --git a/mysql-test/main/custom_aggregate_functions.test b/mysql-test/main/custom_aggregate_functions.test index a10ea44af60..4b6129b5974 100644 --- a/mysql-test/main/custom_aggregate_functions.test +++ b/mysql-test/main/custom_aggregate_functions.test @@ -966,6 +966,42 @@ select i, sum(i) from t1 group by i with rollup; drop function agg_sum; drop table t1; +--echo # +--echo # User defined aggregate functions not working correctly when the schema is changed +--echo # + +CREATE SCHEMA IF NOT EXISTS common_schema; +CREATE SCHEMA IF NOT EXISTS another_schema; +DELIMITER |; +DROP FUNCTION IF EXISTS common_schema.add_ints | +CREATE FUNCTION common_schema.add_ints(int_1 INT, int_2 INT) RETURNS INT NO SQL +BEGIN + RETURN int_1 + int_2; +END | +DROP FUNCTION IF EXISTS common_schema.sum_ints | +CREATE AGGREGATE FUNCTION common_schema.sum_ints(int_val INT) RETURNS INT +BEGIN + DECLARE result INT DEFAULT 0; + DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN result; + LOOP FETCH GROUP NEXT ROW; + SET result = common_schema.add_ints(result, int_val); + END LOOP; +END | + +DELIMITER ;| + +use common_schema; +SELECT common_schema.sum_ints(seq) FROM (SELECT 1 seq UNION ALL SELECT 2) t; + +USE another_schema; +SELECT common_schema.sum_ints(seq) FROM (SELECT 1 seq UNION ALL SELECT 2) t; + +drop database common_schema; +drop database another_schema; + +USE test; + +--echo # End of 10.3 tests --echo # --echo # MDEV-18813 PROCEDURE and anonymous blocks silently ignore FETCH GROUP NEXT ROW @@ -1016,3 +1052,5 @@ CREATE EVENT ev1 STARTS CURRENT_TIMESTAMP + INTERVAL 1 MONTH ENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH + INTERVAL 1 WEEK DO FETCH GROUP NEXT ROW; + +--echo # End of 10.4 tests diff --git a/mysql-test/main/delete_innodb.result b/mysql-test/main/delete_innodb.result new file mode 100644 index 00000000000..b9f4c8bdaf5 --- /dev/null +++ b/mysql-test/main/delete_innodb.result @@ -0,0 +1,26 @@ +# Tests for delete with INNODB +# +# MDEV-22187: SIGSEGV in ha_innobase::cmp_ref on DELETE +# +SET @save_sort_buffer_size= @@sort_buffer_size; +SET sort_buffer_size=1024; +CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0), ('a'), ('b'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +c1 +0 +a +b +EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE a index NULL PRIMARY 255 NULL 3 Using index +1 SIMPLE b ALL NULL NULL NULL NULL 3 +DELETE b FROM t1 AS a JOIN t1 AS b; +SELECT * FROM t1; +c1 +SET sort_buffer_size=@save_sort_buffer_size; +DROP TABLE t1; diff --git a/mysql-test/main/delete_innodb.test b/mysql-test/main/delete_innodb.test new file mode 100644 index 00000000000..c5c5c5d0172 --- /dev/null +++ b/mysql-test/main/delete_innodb.test @@ -0,0 +1,22 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc + +--echo # Tests for delete with INNODB + +--echo # +--echo # MDEV-22187: SIGSEGV in ha_innobase::cmp_ref on DELETE +--echo # + +SET @save_sort_buffer_size= @@sort_buffer_size; +SET sort_buffer_size=1024; +CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (0), ('a'), ('b'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT * FROM t1; +EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b; +DELETE b FROM t1 AS a JOIN t1 AS b; +SELECT * FROM t1; + +SET sort_buffer_size=@save_sort_buffer_size; +DROP TABLE t1; diff --git a/mysql-test/main/drop.result b/mysql-test/main/drop.result index b239dce4e62..4755965cbb2 100644 --- a/mysql-test/main/drop.result +++ b/mysql-test/main/drop.result @@ -205,14 +205,10 @@ Warnings: Note 1051 Unknown table 'test.table1' DROP TABLE IF EXISTS table1,table2; Warnings: -Note 1051 Unknown table 'test.table1' -Note 1051 Unknown table 'test.table2' +Note 1051 Unknown table 'test.table1,test.table2' DROP VIEW IF EXISTS view1,view2,view3,view4; Warnings: -Note 4092 Unknown VIEW: 'test.view1' -Note 4092 Unknown VIEW: 'test.view2' -Note 4092 Unknown VIEW: 'test.view3' -Note 4092 Unknown VIEW: 'test.view4' +Note 4092 Unknown VIEW: 'test.view1,test.view2,test.view3,test.view4' # Test error message when trigger does not find table CREATE TABLE table1(a int); diff --git a/mysql-test/main/drop.test b/mysql-test/main/drop.test index 923ec676d18..2a2d2715185 100644 --- a/mysql-test/main/drop.test +++ b/mysql-test/main/drop.test @@ -1,3 +1,5 @@ +--source include/have_innodb.inc + call mtr.add_suppression("table or database name 'abc`def'"); # Initialise diff --git a/mysql-test/main/drop_combinations.inc b/mysql-test/main/drop_combinations.inc new file mode 100644 index 00000000000..f1d8627f04f --- /dev/null +++ b/mysql-test/main/drop_combinations.inc @@ -0,0 +1,24 @@ +# +# Create all tables, sequences and views needed for drop combinations; +# + +if ($create_option != 'temporary') +{ + show tables; +} + +--echo # Generating test tables +--disable_query_log +--disable_warnings +eval create $create_option table if not exists t1 (a int); +eval create $create_option table if not exists t2 (a int); +eval create $create_option sequence if not exists s1; +eval create $create_option sequence if not exists s2; +if ($create_option != 'temporary') +{ + eval create view if not exists v1 as SELECT * from t1; + eval create view if not exists v2 as SELECT * from t2; +} + +--enable_warnings +--enable_query_log diff --git a/mysql-test/main/drop_combinations.result b/mysql-test/main/drop_combinations.result new file mode 100644 index 00000000000..eb6d70e0704 --- /dev/null +++ b/mysql-test/main/drop_combinations.result @@ -0,0 +1,873 @@ +SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE; +SET default_storage_engine=myisam; +show tables; +Tables_in_test +# Generating test tables +# +# DROP TABLE +# +drop table t1,t2,t3; +ERROR 42S02: Unknown table 'test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table t1,t3,t2; +ERROR 42S02: Unknown table 'test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table t1,t4,t2,t3; +ERROR 42S02: Unknown table 'test.t4,test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t4,test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table t1,s1,s2,t2; +show tables; +Tables_in_test +v1 +v2 +# Generating test tables +drop table t1,v1,v2,t2; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Error 1965 'test.v1' is a view +Error 1965 'test.v2' is a view +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table v1,s1,s2,v2,t2; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Error 1965 'test.v1' is a view +Error 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +v1 +v2 +# Generating test tables +drop table t1,s1,v1,t3,t4; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +Error 1965 'test.v1' is a view +Error 1051 Unknown table 'test.t3,test.t4' +drop table s2,v2,t2,t1; +ERROR 42S02: 'test.v2' is a view +show warnings; +Level Code Message +Error 1965 'test.v2' is a view +Error 1051 Unknown table 'test.t1' +show tables; +Tables_in_test +v1 +v2 +# Generating test tables +drop table s1,v1,s2,v2; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Error 1965 'test.v1' is a view +Error 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +# +# DROP TABLE with if exists +# +drop table if exists t1,t2,t3; +Warnings: +Note 1051 Unknown table 'test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table if exists t1,t3,t2; +Warnings: +Note 1051 Unknown table 'test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table if exists t1,t4,t2,t3; +Warnings: +Note 1051 Unknown table 'test.t4,test.t3' +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table if exists t1,s1,s2,t2; +show tables; +Tables_in_test +v1 +v2 +# Generating test tables +drop table if exists t1,v1,v2,t2; +Warnings: +Note 1965 'test.v1' is a view +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +s1 +s2 +v1 +v2 +# Generating test tables +drop table if exists v1,s1,s2,v2,t2; +Warnings: +Note 1965 'test.v1' is a view +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +v1 +v2 +# Generating test tables +drop table if exists t1,s1,v1,t3,t4; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +Note 1965 'test.v1' is a view +Note 1965 'test.t3' is a view +Note 1965 'test.t4' is a view +drop table if exists s2,v2,t2,t1; +Warnings: +Note 1965 'test.v2' is a view +Note 1051 Unknown table 'test.t1' +show tables; +Tables_in_test +v1 +v2 +# Generating test tables +drop table if exists s1,v1,s2,v2; +Warnings: +Note 1965 'test.v1' is a view +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +# +# DROP TEMPORARY TABLE +# +drop table if exists t1,t2; +drop temporary table if exists tt1,tt2; +drop sequence if exists s1,s2; +drop temporary sequence if exists ss1,ss2; +drop view if exists v1,v2; +drop temporary table t1,t2,t3; +ERROR 42S02: Unknown table 'test.t1,test.t2,test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t1,test.t2,test.t3' +# Generating test tables +drop temporary table t1,t3,t2; +ERROR 42S02: Unknown table 'test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t3' +# Generating test tables +drop temporary table t1,t4,t2,t3; +ERROR 42S02: Unknown table 'test.t4,test.t3' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t4,test.t3' +# Generating test tables +drop temporary table t1,s1,s2,t2; +# Generating test tables +drop temporary table t1,v1,v2,t2; +ERROR 42S02: Unknown table 'test.v1,test.v2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +drop temporary table v1,s1,s2,v2,t2; +ERROR 42S02: Unknown table 'test.v1,test.v2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +drop temporary table t1,s1,v1,t3,t4; +ERROR 42S02: Unknown table 'test.v1,test.t3,test.t4' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.v1,test.t3,test.t4' +# Generating test tables +drop temporary table s2,v2,t2,t1; +ERROR 42S02: Unknown table 'test.v2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.v2' +# Generating test tables +drop temporary table s1,v1,s2,v2; +ERROR 42S02: Unknown table 'test.v1,test.v2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +# +# DROP TEMPORARY TABLE with if exists +# +drop temporary table if exists t1,t2,t3; +Warnings: +Note 1051 Unknown table 'test.t3' +# Generating test tables +drop temporary table if exists t1,t3,t2; +Warnings: +Note 1051 Unknown table 'test.t3' +# Generating test tables +drop temporary table if exists t1,t4,t2,t3; +Warnings: +Note 1051 Unknown table 'test.t4,test.t3' +# Generating test tables +drop temporary table if exists t1,s1,s2,t2; +# Generating test tables +drop temporary table if exists t1,v1,v2,t2; +Warnings: +Note 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +drop temporary table if exists v1,s1,s2,v2,t2; +Warnings: +Note 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +drop temporary table if exists t1,s1,v1,t3,t4; +Warnings: +Note 1051 Unknown table 'test.v1,test.t3,test.t4' +drop temporary table if exists s2,v2,t2,t1; +Warnings: +Note 1051 Unknown table 'test.v2,test.t1' +# Generating test tables +drop temporary table if exists s1,v1,s2,v2; +Warnings: +Note 1051 Unknown table 'test.v1,test.v2' +# Generating test tables +drop temporary table t1,t2; +drop temporary sequence s1,s2; +show tables; +Tables_in_test +# Generating test tables +# +# DROP SEQUENCE +# +drop sequence s1,s2,s3; +ERROR 42S02: Unknown SEQUENCE: 'test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence s1,s3,s2; +ERROR 42S02: Unknown SEQUENCE: 'test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence s1,s4,s2,s3; +ERROR 42S02: Unknown SEQUENCE: 'test.s4,test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s4,test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence s1,t1,t2,s2,s3,s4; +ERROR 42S02: 'test.t1' is not a SEQUENCE +show warnings; +Level Code Message +Error 4090 'test.t1' is not a SEQUENCE +Error 4090 'test.t2' is not a SEQUENCE +Error 4091 Unknown SEQUENCE: 'test.s3,test.s4' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence s1,v1,v2,s2; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Error 1965 'test.v1' is a view +Error 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence v1,t1,t2,v2,s2; +ERROR 42S02: 'test.v1' is a view +show warnings; +Level Code Message +Error 1965 'test.v1' is a view +Error 4090 'test.t1' is not a SEQUENCE +Error 4090 'test.t2' is not a SEQUENCE +Error 1965 'test.v2' is a view +drop sequence t1,v1,t2,v2,s2; +ERROR 42S02: 'test.t1' is not a SEQUENCE +show warnings; +Level Code Message +Error 4090 'test.t1' is not a SEQUENCE +Error 1965 'test.v1' is a view +Error 4090 'test.t2' is not a SEQUENCE +Error 1965 'test.v2' is a view +Error 4091 Unknown SEQUENCE: 'test.s2' +show tables; +Tables_in_test +s1 +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence s1,t1,v1,t3,s4; +ERROR 42S02: 'test.t1' is not a SEQUENCE +show warnings; +Level Code Message +Warning 1017 Can't find file: './test/s1.MYI' (errno: 2 "No such file or directory") +Error 4090 'test.t1' is not a SEQUENCE +Error 1965 'test.v1' is a view +Error 4091 Unknown SEQUENCE: 'test.t3,test.s4' +drop sequence t2,v2,s2,s1; +ERROR 42S02: 'test.t2' is not a SEQUENCE +show warnings; +Level Code Message +Error 4090 'test.t2' is not a SEQUENCE +Error 1965 'test.v2' is a view +Error 4091 Unknown SEQUENCE: 'test.s1' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence t1,v1,t2,v2; +ERROR 42S02: 'test.t1' is not a SEQUENCE +show warnings; +Level Code Message +Error 4090 'test.t1' is not a SEQUENCE +Error 1965 'test.v1' is a view +Error 4090 'test.t2' is not a SEQUENCE +Error 1965 'test.v2' is a view +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +v1 +v2 +# Generating test tables +# +# DROP SEQUENCE with if exists +# +drop sequence if exists s1,s2,s3; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists s1,s3,s2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists s1,s4,s2,s3; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s4,test.s3' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists s1,t1,t2,s2; +Warnings: +Note 4090 'test.t1' is not a SEQUENCE +Note 4090 'test.t2' is not a SEQUENCE +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists s1,v1,v2,s2; +Warnings: +Note 1965 'test.v1' is a view +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists v1,t1,t2,v2,s2; +Warnings: +Note 1965 'test.v1' is a view +Note 4090 'test.t1' is not a SEQUENCE +Note 4090 'test.t2' is not a SEQUENCE +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +s1 +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists s1,t1,v1,t3,s4; +Warnings: +Warning 1017 Can't find file: './test/s1.MYI' (errno: 2 "No such file or directory") +Note 4090 'test.t1' is not a SEQUENCE +Note 1965 'test.v1' is a view +Note 1965 'test.t3' is a view +Note 1965 'test.s4' is a view +drop sequence if exists t2,v2,s2,s1; +Warnings: +Note 4090 'test.t2' is not a SEQUENCE +Note 1965 'test.v2' is a view +Note 4091 Unknown SEQUENCE: 'test.s1' +show tables; +Tables_in_test +t1 +t2 +v1 +v2 +# Generating test tables +drop sequence if exists t1,v1,t2,v2; +Warnings: +Note 4090 'test.t1' is not a SEQUENCE +Note 1965 'test.v1' is a view +Note 4090 'test.t2' is not a SEQUENCE +Note 1965 'test.v2' is a view +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +v1 +v2 +# Generating test tables +# +# DROP TEMPORARY SEQUENCE +# +drop table if exists t1,t2; +drop temporary table if exists tt1,tt2; +drop sequence if exists s1,s2; +drop temporary sequence if exists ss1,ss2; +drop view if exists v1,v2; +# Generating test tables +drop temporary sequence s1,s2,s3; +ERROR 42S02: Unknown SEQUENCE: 'test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s3' +# Generating test tables +drop temporary sequence s1,s3,s2; +ERROR 42S02: Unknown SEQUENCE: 'test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s3' +# Generating test tables +drop temporary sequence s1,s4,s2,s3; +ERROR 42S02: Unknown SEQUENCE: 'test.s4,test.s3' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.s4,test.s3' +# Generating test tables +drop temporary sequence s1,t1,t2,s2; +ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.t2' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.t1,test.t2' +# Generating test tables +drop temporary sequence s1,v1,v2,s2; +ERROR 42S02: Unknown SEQUENCE: 'test.v1,test.v2' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.v1,test.v2' +# Generating test tables +drop temporary sequence v1,t1,t2,v2,s2; +ERROR 42S02: Unknown SEQUENCE: 'test.v1,test.t1,test.t2,test.v2' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.v1,test.t1,test.t2,test.v2' +# Generating test tables +drop temporary sequence s1,t1,v1,t3,s4; +ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.v1,test.t3,test.s4' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.t1,test.v1,test.t3,test.s4' +drop temporary sequence t2,v2,s2,s1; +ERROR 42S02: Unknown SEQUENCE: 'test.t2,test.v2,test.s1' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.t2,test.v2,test.s1' +# Generating test tables +drop temporary sequence t1,v1,t2,v2; +ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.v1,test.t2,test.v2' +show warnings; +Level Code Message +Error 4091 Unknown SEQUENCE: 'test.t1,test.v1,test.t2,test.v2' +# Generating test tables +# +# DROP TEMPORARY SEQUENCE with if exists +# +drop temporary sequence if exists s1,s2,s3; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s3' +# Generating test tables +drop temporary sequence if exists s1,s3,s2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s3' +# Generating test tables +drop temporary sequence if exists s1,s4,s2,s3; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.s4,test.s3' +# Generating test tables +drop temporary sequence if exists s1,t1,t2,s2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.t1,test.t2' +# Generating test tables +drop temporary sequence if exists s1,v1,v2,s2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.v1,test.v2' +# Generating test tables +drop temporary sequence if exists v1,t1,t2,v2,s2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.v1,test.t1,test.t2,test.v2' +# Generating test tables +drop temporary sequence if exists s1,t1,v1,t3,s4; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.t1,test.v1,test.t3,test.s4' +drop temporary sequence if exists t2,v2,s2,s1; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.t2,test.v2,test.s1' +# Generating test tables +drop temporary sequence if exists t1,v1,t2,v2; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.t1,test.v1,test.t2,test.v2' +# Generating test tables +drop temporary table t1,t2; +drop temporary sequence s1,s2; +show tables; +Tables_in_test +# Generating test tables +# +# DROP VIEW +# +drop view v1,v2,v3; +ERROR 42S02: Unknown VIEW: 'test.v3' +show warnings; +Level Code Message +Error 4092 Unknown VIEW: 'test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view v1,v3,v2; +ERROR 42S02: Unknown VIEW: 'test.v3' +show warnings; +Level Code Message +Error 4092 Unknown VIEW: 'test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view v1,v4,v2,v3; +ERROR 42S02: Unknown VIEW: 'test.v4,test.v3' +show warnings; +Level Code Message +Error 4092 Unknown VIEW: 'test.v4,test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view v1,t1,t2,v2; +ERROR 42S02: Unknown VIEW: 'test.t1,test.t2' +show warnings; +Level Code Message +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.t1,test.t2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view v1,s1,s2,v2; +ERROR 42S02: Unknown VIEW: 'test.s1,test.s2' +show warnings; +Level Code Message +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.s1,test.s2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view s1,t1,t2,s2,v2; +ERROR 42S02: Unknown VIEW: 'test.s1,test.t1,test.t2,test.s2' +show warnings; +Level Code Message +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.s1,test.t1,test.t2,test.s2' +drop table t1; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +show warnings; +Level Code Message +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +drop view v1,t1; +ERROR 42S02: Unknown VIEW: 'test.t1' +show warnings; +Level Code Message +Error 4092 Unknown VIEW: 'test.t1' +show tables; +Tables_in_test +s1 +s2 +t2 +# Generating test tables +drop view v1,t1,s1,t3,v4; +ERROR 42S02: Unknown VIEW: 'test.t1,test.s1,test.t3,test.v4' +show warnings; +Level Code Message +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.s1' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.t1,test.s1,test.t3,test.v4' +drop view t2,s2,v2,v1; +ERROR 42S02: Unknown VIEW: 'test.t2,test.s2,test.v1' +show warnings; +Level Code Message +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.t2,test.s2,test.v1' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view t1,s1,t2,s2; +ERROR 42S02: Unknown VIEW: 'test.t1,test.s1,test.t2,test.s2' +show warnings; +Level Code Message +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.t1,test.s1,test.t2,test.s2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +v1 +v2 +# Generating test tables +# +# DROP VIEW with if exists +# +drop view if exists v1,v2,v3; +Warnings: +Note 4092 Unknown VIEW: 'test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists v1,v3,v2; +Warnings: +Note 4092 Unknown VIEW: 'test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists v1,v4,v2,v3; +Warnings: +Note 4092 Unknown VIEW: 'test.v4,test.v3' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists v1,t1,t2,v2; +Warnings: +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.t1,test.t2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists v1,s1,s2,v2; +Warnings: +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.s1,test.s2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists s1,t1,t2,s2,v2; +Warnings: +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.s1,test.t1,test.t2,test.s2' +drop table t1; +drop view if exists v1,t1; +Warnings: +Note 4092 Unknown VIEW: 'test.t1' +show tables; +Tables_in_test +s1 +s2 +t2 +# Generating test tables +drop view if exists v1,t1,s1,t3,v4; +Warnings: +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.s1' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.t1,test.s1,test.t3,test.v4' +drop view if exists t2,s2,v2,v1; +Warnings: +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.t2,test.s2,test.v1' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +# Generating test tables +drop view if exists t1,s1,t2,s2; +Warnings: +Warning 1347 'test.t1' is not of type 'VIEW' +Warning 1347 'test.s1' is not of type 'VIEW' +Warning 1347 'test.t2' is not of type 'VIEW' +Warning 1347 'test.s2' is not of type 'VIEW' +Note 4092 Unknown VIEW: 'test.t1,test.s1,test.t2,test.s2' +show tables; +Tables_in_test +s1 +s2 +t1 +t2 +v1 +v2 +# Generating test tables +# cleanup +drop table if exists t1,t2; +drop sequence if exists s1,s2; +drop view if exists v1,v2; +SET default_storage_engine=@save_default_engine; diff --git a/mysql-test/main/drop_combinations.test b/mysql-test/main/drop_combinations.test new file mode 100644 index 00000000000..8b3ad43793b --- /dev/null +++ b/mysql-test/main/drop_combinations.test @@ -0,0 +1,425 @@ +# +# Test different combinations of doing DROP TABLE/SEQUENCE/VIEW +# + +SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE; +SET default_storage_engine=myisam; +let $DATADIR= `select @@datadir`; + +# Create tables t1,t2, sequences s1,s2 and views v1,v2 +let $create_option=; +--source drop_combinations.inc + +--echo # +--echo # DROP TABLE +--echo # + +--error ER_BAD_TABLE_ERROR +drop table t1,t2,t3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop table t1,t3,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop table t1,t4,t2,t3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +drop table t1,s1,s2,t2; +--source drop_combinations.inc +--error ER_IT_IS_A_VIEW +drop table t1,v1,v2,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_IT_IS_A_VIEW +drop table v1,s1,s2,v2,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--remove_file $DATADIR/test/t1.MYD +--replace_result $DATADIR ./ +--error ER_IT_IS_A_VIEW +drop table t1,s1,v1,t3,t4; +--replace_result $DATADIR ./ +show warnings; +--error ER_IT_IS_A_VIEW +drop table s2,v2,t2,t1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--replace_result $DATADIR ./ +--error ER_IT_IS_A_VIEW +drop table s1,v1,s2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc + +--echo # +--echo # DROP TABLE with if exists +--echo # + +drop table if exists t1,t2,t3; +--source drop_combinations.inc +drop table if exists t1,t3,t2; +--source drop_combinations.inc +drop table if exists t1,t4,t2,t3; +--source drop_combinations.inc +drop table if exists t1,s1,s2,t2; +--source drop_combinations.inc +drop table if exists t1,v1,v2,t2; +--source drop_combinations.inc +drop table if exists v1,s1,s2,v2,t2; +--source drop_combinations.inc +--remove_file $DATADIR/test/t1.MYD +--replace_result \\ / +--replace_result $DATADIR ./ +drop table if exists t1,s1,v1,t3,t4; +drop table if exists s2,v2,t2,t1; +--source drop_combinations.inc +--replace_result $DATADIR ./ +drop table if exists s1,v1,s2,v2; +--source drop_combinations.inc + +--echo # +--echo # DROP TEMPORARY TABLE +--echo # + +--disable_warnings +drop table if exists t1,t2; +drop temporary table if exists tt1,tt2; +drop sequence if exists s1,s2; +drop temporary sequence if exists ss1,ss2; +drop view if exists v1,v2; +--enable_warnings +let $create_option=temporary; + +--error ER_BAD_TABLE_ERROR +drop temporary table t1,t2,t3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table t1,t3,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table t1,t4,t2,t3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +drop temporary table t1,s1,s2,t2; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table t1,v1,v2,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table v1,s1,s2,v2,t2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table t1,s1,v1,t3,t4; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table s2,v2,t2,t1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_BAD_TABLE_ERROR +drop temporary table s1,v1,s2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc + +--echo # +--echo # DROP TEMPORARY TABLE with if exists +--echo # + +drop temporary table if exists t1,t2,t3; +--source drop_combinations.inc +drop temporary table if exists t1,t3,t2; +--source drop_combinations.inc +drop temporary table if exists t1,t4,t2,t3; +--source drop_combinations.inc +drop temporary table if exists t1,s1,s2,t2; +--source drop_combinations.inc +drop temporary table if exists t1,v1,v2,t2; +--source drop_combinations.inc +drop temporary table if exists v1,s1,s2,v2,t2; +--source drop_combinations.inc +drop temporary table if exists t1,s1,v1,t3,t4; +drop temporary table if exists s2,v2,t2,t1; +--source drop_combinations.inc +drop temporary table if exists s1,v1,s2,v2; +--source drop_combinations.inc + +let $create_option=; +drop temporary table t1,t2; +drop temporary sequence s1,s2; +--source drop_combinations.inc + +--echo # +--echo # DROP SEQUENCE +--echo # + +--error ER_UNKNOWN_SEQUENCES +drop sequence s1,s2,s3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop sequence s1,s3,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop sequence s1,s4,s2,s3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_NOT_SEQUENCE2 +drop sequence s1,t1,t2,s2,s3,s4; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_IT_IS_A_VIEW +drop sequence s1,v1,v2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_IT_IS_A_VIEW +drop sequence v1,t1,t2,v2,s2; +--replace_result $DATADIR ./ +show warnings; +--error ER_NOT_SEQUENCE2 +drop sequence t1,v1,t2,v2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--remove_file $DATADIR/test/s1.MYD +--replace_result \\ / +--error ER_NOT_SEQUENCE2 +drop sequence s1,t1,v1,t3,s4; +--replace_result $DATADIR ./ +show warnings; +--error ER_NOT_SEQUENCE2 +drop sequence t2,v2,s2,s1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_NOT_SEQUENCE2 +drop sequence t1,v1,t2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc + +--echo # +--echo # DROP SEQUENCE with if exists +--echo # + +drop sequence if exists s1,s2,s3; +--source drop_combinations.inc +drop sequence if exists s1,s3,s2; +--source drop_combinations.inc +drop sequence if exists s1,s4,s2,s3; +--source drop_combinations.inc +drop sequence if exists s1,t1,t2,s2; +--source drop_combinations.inc +drop sequence if exists s1,v1,v2,s2; +--source drop_combinations.inc +drop sequence if exists v1,t1,t2,v2,s2; +--source drop_combinations.inc +--remove_file $DATADIR/test/s1.MYD +--replace_result \\ / +--replace_result $DATADIR ./ +drop sequence if exists s1,t1,v1,t3,s4; +drop sequence if exists t2,v2,s2,s1; +--source drop_combinations.inc +drop sequence if exists t1,v1,t2,v2; +--source drop_combinations.inc + +--echo # +--echo # DROP TEMPORARY SEQUENCE +--echo # + +--disable_warnings +drop table if exists t1,t2; +drop temporary table if exists tt1,tt2; +drop sequence if exists s1,s2; +drop temporary sequence if exists ss1,ss2; +drop view if exists v1,v2; +--enable_warnings +let $create_option=temporary; +--source drop_combinations.inc + +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,s2,s3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,s3,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,s4,s2,s3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,t1,t2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,v1,v2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence v1,t1,t2,v2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence s1,t1,v1,t3,s4; +--replace_result $DATADIR ./ +show warnings; +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence t2,v2,s2,s1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_SEQUENCES +drop temporary sequence t1,v1,t2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc + +--echo # +--echo # DROP TEMPORARY SEQUENCE with if exists +--echo # + +drop temporary sequence if exists s1,s2,s3; +--source drop_combinations.inc +drop temporary sequence if exists s1,s3,s2; +--source drop_combinations.inc +drop temporary sequence if exists s1,s4,s2,s3; +--source drop_combinations.inc +drop temporary sequence if exists s1,t1,t2,s2; +--source drop_combinations.inc +drop temporary sequence if exists s1,v1,v2,s2; +--source drop_combinations.inc +drop temporary sequence if exists v1,t1,t2,v2,s2; +--source drop_combinations.inc +drop temporary sequence if exists s1,t1,v1,t3,s4; +drop temporary sequence if exists t2,v2,s2,s1; +--source drop_combinations.inc +drop temporary sequence if exists t1,v1,t2,v2; +--source drop_combinations.inc + +let $create_option=; +drop temporary table t1,t2; +drop temporary sequence s1,s2; +--source drop_combinations.inc + +--echo # +--echo # DROP VIEW +--echo # + +--error ER_UNKNOWN_VIEW +drop view v1,v2,v3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view v1,v3,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view v1,v4,v2,v3; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view v1,t1,t2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view v1,s1,s2,v2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--remove_file $DATADIR/test/t1.MYD +--replace_result \\ / +--error ER_UNKNOWN_VIEW +drop view s1,t1,t2,s2,v2; +--replace_result $DATADIR ./ +show warnings; +--replace_result $DATADIR ./ +drop table t1; +--replace_result $DATADIR ./ +show warnings; +--error ER_UNKNOWN_VIEW +drop view v1,t1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view v1,t1,s1,t3,v4; +--replace_result $DATADIR ./ +show warnings; +--error ER_UNKNOWN_VIEW +drop view t2,s2,v2,v1; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc +--error ER_UNKNOWN_VIEW +drop view t1,s1,t2,s2; +--replace_result $DATADIR ./ +show warnings; +--source drop_combinations.inc + +--echo # +--echo # DROP VIEW with if exists +--echo # + +drop view if exists v1,v2,v3; +--source drop_combinations.inc +drop view if exists v1,v3,v2; +--source drop_combinations.inc +drop view if exists v1,v4,v2,v3; +--source drop_combinations.inc +drop view if exists v1,t1,t2,v2; +--source drop_combinations.inc +drop view if exists v1,s1,s2,v2; +--source drop_combinations.inc +drop view if exists s1,t1,t2,s2,v2; +drop table t1; +drop view if exists v1,t1; +--source drop_combinations.inc +drop view if exists v1,t1,s1,t3,v4; +drop view if exists t2,s2,v2,v1; +--source drop_combinations.inc +drop view if exists t1,s1,t2,s2; +--source drop_combinations.inc + +--echo # cleanup +drop table if exists t1,t2; +drop sequence if exists s1,s2; +drop view if exists v1,v2; + +SET default_storage_engine=@save_default_engine; diff --git a/mysql-test/main/drop_table_force.result b/mysql-test/main/drop_table_force.result new file mode 100644 index 00000000000..bb4ecc060b0 --- /dev/null +++ b/mysql-test/main/drop_table_force.result @@ -0,0 +1,133 @@ +CALL mtr.add_suppression("Operating system error number"); +CALL mtr.add_suppression("The error means the system cannot"); +CALL mtr.add_suppression("returned OS error 71"); +#Test1: table with missing .ibd can be dropped directly +create table t1(a int)engine=innodb; +drop table t1; +db.opt +# Test droping table without frm without super privilege +create table t1(a int) engine=innodb; +create user test identified by '123456'; +grant all privileges on test.t1 to 'test'@'%'identified by '123456' with grant option; +connect con_test, localhost, test,'123456', ; +connection con_test; +drop table t1; +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +connection default; +disconnect con_test; +drop user test; +db.opt +#Test4: drop table can drop consistent table as well +create table t1(a int) engine=innodb; +drop table t1; +db.opt +#Test5: drop table with triger, and with missing frm +create table t1(a int)engine=innodb; +create trigger t1_trg before insert on t1 for each row begin end; +drop table t1; +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +db.opt +#Test6: table with foreign key references can not be dropped +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table child; +drop table parent; +db.opt +#Test7: drop table twice +create table t1(a int)engine=innodb; +drop table t1; +db.opt +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +db.opt +#Test8: check compatibility with if exists +create table t1(a int)engine=innodb; +drop table t1; +db.opt +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +#Test9: check compatibility with restrict/cascade +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent restrict; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent cascade; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent restrict; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent cascade; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table child; +drop table parent; +#Test10: drop non-innodb engine table returns ok +create table t1(a int) engine=myisam; +drop table t1; +create table t1(a int) engine=myisam; +drop table t1; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +create table t1(a int) engine=myisam; +drop table t1; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +db.opt +create table t1(a int) engine=aria; +db.opt +t1.MAI +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +show warnings; +Level Code Message +Error 29 File './test/t1.MAD' not found (Errcode: 2 "No such file or directory") +Error 1051 Unknown table 'test.t1' +db.opt +create table t2(a int) engine=aria; +flush tables; +db.opt +t2.MAD +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t2' +db.opt +create table t2(a int) engine=aria; +flush tables; +db.opt +t2.frm +drop table t2; +Warnings: +Warning 1017 Can't find file: './test/t2.MAI' (errno: 2 "No such file or directory") +create table t2(a int not null) engine=CSV; +flush tables; +drop table t2; +db.opt +create table t2(a int not null) engine=CSV; +flush tables; +drop table t2; +db.opt +create table t2(a int not null) engine=archive; +flush tables; +select * from t2; +a +flush tables; +select * from t2; +ERROR 42S02: Table 'test.t2' doesn't exist +db.opt +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +create table t2(a int not null) engine=archive; +flush tables; +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +db.opt diff --git a/mysql-test/main/drop_table_force.test b/mysql-test/main/drop_table_force.test new file mode 100644 index 00000000000..bb735309167 --- /dev/null +++ b/mysql-test/main/drop_table_force.test @@ -0,0 +1,235 @@ +--source include/have_log_bin.inc +--source include/have_innodb.inc +--source include/have_archive.inc +# +# This test is based on the orginal test from Tencent for DROP TABLE ... FORCE +# In MariaDB we did reuse the code but MariaDB does not require the FORCE +# keyword to drop a table even if the .frm file or some engine files are +# missing. +# To make it easy to see the differences between the orginal code and +# the new one, we have left some references to the original test case +# + +CALL mtr.add_suppression("Operating system error number"); +CALL mtr.add_suppression("The error means the system cannot"); +CALL mtr.add_suppression("returned OS error 71"); + +let $DATADIR= `select @@datadir`; + +--echo #Test1: table with missing .ibd can be dropped directly +# drop table without ibd +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.ibd +drop table t1; +--list_files $DATADIR/test/ + +# Original DROP TABLE .. FORCE required SUPER privilege. MariaDB doesn't +--echo # Test droping table without frm without super privilege + +# create table t1 and rm frm +create table t1(a int) engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# create test user +create user test identified by '123456'; +grant all privileges on test.t1 to 'test'@'%'identified by '123456' with grant option; + +# connect as test +connect (con_test, localhost, test,'123456', ); +--connection con_test + +# drop table with user test +drop table t1; +--error ER_BAD_TABLE_ERROR +drop table t1; + +# connect as root +--connection default + +--disconnect con_test +drop user test; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test4: drop table can drop consistent table as well +create table t1(a int) engine=innodb; +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test5: drop table with triger, and with missing frm +# create table t1 with triger and rm frm +create table t1(a int)engine=innodb; +create trigger t1_trg before insert on t1 for each row begin end; + +let $DATADIR= `select @@datadir`; +--remove_file $DATADIR/test/t1.frm + +drop table t1; +--error ER_BAD_TABLE_ERROR +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test6: table with foreign key references can not be dropped +# create table with foreign key reference and rm frm +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +--remove_file $DATADIR/test/parent.frm + +# parent can not be dropped when there are foreign key references +--error ER_ROW_IS_REFERENCED_2 +drop table parent; + +# parent can be dropped when there are no foreign key references +drop table child; +drop table parent; + +# check files in datadir about child and parent +--list_files $DATADIR/test/ + +--echo #Test7: drop table twice +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# first drop table will success +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +# second drop with if exists will also ok +drop table if exists t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test8: check compatibility with if exists +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# first drop will success +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +# second drop with if exists will success +drop table if exists t1; + +--echo #Test9: check compatibility with restrict/cascade +# create table with foreign key reference and rm frm +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; + +# parent can not be dropped when there are foreign key references +--error ER_ROW_IS_REFERENCED_2 +drop table parent; +--error ER_ROW_IS_REFERENCED_2 +drop table parent restrict; +--error ER_ROW_IS_REFERENCED_2 +drop table parent cascade; +--error ER_ROW_IS_REFERENCED_2 +drop table parent; +--error ER_ROW_IS_REFERENCED_2 +drop table parent restrict; +--error ER_ROW_IS_REFERENCED_2 +drop table parent cascade; + +# parent can be dropped when there are no foreign key references +drop table child; +drop table parent; + +--echo #Test10: drop non-innodb engine table returns ok +# create myisam table t1 and rm .frm +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.frm +--replace_result \\ / +drop table t1; + +# create myisam table t1 and rm .MYD +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.MYD +--replace_result \\ / +drop table t1; + +# create myisam table t1 and rm .MYI +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.MYI +--replace_result \\ / +drop table t1; +--list_files $DATADIR/test/ + +# create Aria table t1 and rm .frm and .MAD +create table t1(a int) engine=aria; +--remove_file $DATADIR/test/t1.frm +--remove_file $DATADIR/test/t1.MAD +--list_files $DATADIR/test/ +--error ER_BAD_TABLE_ERROR +drop table t1; +--replace_result \\ / +show warnings; +--list_files $DATADIR/test/ + +# create Aria table t2 and rm .frm and .MAI +create table t2(a int) engine=aria; +flush tables; +--remove_file $DATADIR/test/t2.frm +--remove_file $DATADIR/test/t2.MAI +--list_files $DATADIR/test/ +--error ER_BAD_TABLE_ERROR +drop table t2; +--replace_result \\ / +show warnings; +--list_files $DATADIR/test/ + +# create Aria table t2 and rm .MAI and .MAD +create table t2(a int) engine=aria; +flush tables; +--remove_file $DATADIR/test/t2.MAD +--remove_file $DATADIR/test/t2.MAI +--list_files $DATADIR/test/ +--replace_result \\ / +drop table t2; + +# create CVS table t2 and rm .frm +create table t2(a int not null) engine=CSV; +flush tables; +--remove_file $DATADIR/test/t2.frm +drop table t2; +--list_files $DATADIR/test/ + +# create CVS table t2 and rm .frm +create table t2(a int not null) engine=CSV; +flush tables; +--remove_file $DATADIR/test/t2.CSV +drop table t2; +--list_files $DATADIR/test/ + +# create Archive table t2 and rm +# Note that as Archive has discovery, removing the +# ARZ will automatically remove the .frm + +create table t2(a int not null) engine=archive; +flush tables; +--error 1 +--remove_file $DATADIR/test/t2.frm +select * from t2; +flush tables; +--remove_file $DATADIR/test/t2.ARZ +--error ER_NO_SUCH_TABLE +select * from t2; +--list_files $DATADIR/test/ +--replace_result \\ / +--error ER_BAD_TABLE_ERROR +drop table t2; + +create table t2(a int not null) engine=archive; +flush tables; +--remove_file $DATADIR/test/t2.ARZ +--error ER_BAD_TABLE_ERROR +drop table t2; +--list_files $DATADIR/test/ diff --git a/mysql-test/main/flush_read_lock.result b/mysql-test/main/flush_read_lock.result index be710050139..9a81cae1724 100644 --- a/mysql-test/main/flush_read_lock.result +++ b/mysql-test/main/flush_read_lock.result @@ -49,6 +49,7 @@ set local sql_mode=""; # used in this test in order to be able to # check that DDL statements on temporary tables # are compatible with FTRWL. +call mtr.add_suppression("BINLOG_BASE64_EVENT: Error executing row event.*error code: 1223"); drop tables if exists t1_base, t2_base, t3_trans; drop tables if exists tm_base, tm_base_temp; drop database if exists mysqltest1; @@ -438,7 +439,6 @@ Success: Was able to run 'execute stmt1' under FTWRL. Success: Was able to run 'execute stmt1' with FTWRL active in another connection. Success: Was able to run FTWRL while 'execute stmt1' was active in another connection. deallocate prepare stmt1; -call mtr.add_suppression("Slave SQL.*Can.t execute the query because you have a conflicting read lock., error.* 1223"); # # 9.2.b) EXECUTE for statement which is incompatible with FTWRL # should be also incompatible. @@ -1391,9 +1391,11 @@ insert into t3_trans values (2); xa end 'test2'; xa prepare 'test2'; # Disconnect temporary connection +set debug_sync='thread_end SIGNAL detached'; disconnect con_tmp; # Switching to connection 'con1'. connection con1; +set debug_sync='now WAIT_FOR detached'; flush tables with read lock; # Switching to connection 'default'. connection default; diff --git a/mysql-test/main/flush_read_lock.test b/mysql-test/main/flush_read_lock.test index 4283358770c..205b8b302ea 100644 --- a/mysql-test/main/flush_read_lock.test +++ b/mysql-test/main/flush_read_lock.test @@ -65,6 +65,9 @@ set local sql_mode=""; --echo # used in this test in order to be able to --echo # check that DDL statements on temporary tables --echo # are compatible with FTRWL. + +call mtr.add_suppression("BINLOG_BASE64_EVENT: Error executing row event.*error code: 1223"); + --disable_warnings drop tables if exists t1_base, t2_base, t3_trans; drop tables if exists tm_base, tm_base_temp; @@ -300,7 +303,6 @@ set debug_sync= "RESET"; --echo # We don't run similar test for BEGIN and ROLLBACK as --echo # they release metadata locks in non-standard place. - --echo # --echo # 4) BINLOG statement should be incompatible with FTWRL. --echo # @@ -544,8 +546,6 @@ let $cleanup_stmt= ; --source include/check_ftwrl_compatible.inc deallocate prepare stmt1; -call mtr.add_suppression("Slave SQL.*Can.t execute the query because you have a conflicting read lock., error.* 1223"); - --echo # --echo # 9.2.b) EXECUTE for statement which is incompatible with FTWRL --echo # should be also incompatible. @@ -1698,9 +1698,11 @@ insert into t3_trans values (2); xa end 'test2'; xa prepare 'test2'; --echo # Disconnect temporary connection +set debug_sync='thread_end SIGNAL detached'; disconnect con_tmp; --echo # Switching to connection '$con_aux1'. connection $con_aux1; +set debug_sync='now WAIT_FOR detached'; flush tables with read lock; --echo # Switching to connection 'default'. connection default; diff --git a/mysql-test/main/frm-debug.result b/mysql-test/main/frm-debug.result index caf344e241d..332d7e00a8f 100644 --- a/mysql-test/main/frm-debug.result +++ b/mysql-test/main/frm-debug.result @@ -13,8 +13,8 @@ CREATE TABLE t1 (c01 INT, c02 CHAR(20), c03 TEXT, c04 DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 14 Note 1105 DBUG: [0] name='c01' type_info='' -Note 1105 DBUG: [1] name='c02' type_info='xc...' -Note 1105 DBUG: [2] name='c03' type_info='xb...' +Note 1105 DBUG: [1] name='c02' type_info='xchar' +Note 1105 DBUG: [2] name='c03' type_info='xblob' Note 1105 DBUG: [3] name='c04' type_info='' SET SESSION debug_dbug="-d,frm_data_type_info_emulate"; SET SESSION debug_dbug="-d,frm_data_type_info"; diff --git a/mysql-test/main/func_bit.result b/mysql-test/main/func_bit.result new file mode 100644 index 00000000000..4eb44f76ef3 --- /dev/null +++ b/mysql-test/main/func_bit.result @@ -0,0 +1,367 @@ +# +# Start of 10.5 tests +# +# +# MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT +# +CREATE PROCEDURE p1(type VARCHAR(64), val VARCHAR(64)) +BEGIN +EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', type, ')'); +SHOW CREATE TABLE t1; +EXECUTE IMMEDIATE CONCAT('INSERT INTO t1 VALUES (', val, ')'); +SELECT +a, +~a, +a & 18446744073709551615, +18446744073709551615 & a, +0 | a, +a | 0, +a << 0, +a >> 0, +a ^ 1, +1 ^ a, +BIT_COUNT(a) +FROM t1; +SHOW WARNINGS; +DROP TABLE t1; +END; +$$ +CALL p1('BIGINT UNSIGNED', 18446744073709551615); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 18446744073709551615 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +CALL p1('DOUBLE', 18446744073709551615); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` double DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 1.8446744073709552e19 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +CALL p1('DECIMAL(30,0)', 18446744073709551615); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` decimal(30,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 18446744073709551615 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +CALL p1('BIGINT', -1); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` bigint(20) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -1 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +CALL p1('DOUBLE', -1); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` double DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -1 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +CALL p1('DECIMAL(30,0)', -1); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` decimal(30,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -1 +~a 0 +a & 18446744073709551615 18446744073709551615 +18446744073709551615 & a 18446744073709551615 +0 | a 18446744073709551615 +a | 0 18446744073709551615 +a << 0 18446744073709551615 +a >> 0 18446744073709551615 +a ^ 1 18446744073709551614 +1 ^ a 18446744073709551614 +BIT_COUNT(a) 64 +CALL p1('BIGINT', -9223372036854775808); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` bigint(20) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -9223372036854775808 +~a 9223372036854775807 +a & 18446744073709551615 9223372036854775808 +18446744073709551615 & a 9223372036854775808 +0 | a 9223372036854775808 +a | 0 9223372036854775808 +a << 0 9223372036854775808 +a >> 0 9223372036854775808 +a ^ 1 9223372036854775809 +1 ^ a 9223372036854775809 +BIT_COUNT(a) 1 +CALL p1('DOUBLE', -9223372036854775808); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` double DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -9.223372036854776e18 +~a 9223372036854775807 +a & 18446744073709551615 9223372036854775808 +18446744073709551615 & a 9223372036854775808 +0 | a 9223372036854775808 +a | 0 9223372036854775808 +a << 0 9223372036854775808 +a >> 0 9223372036854775808 +a ^ 1 9223372036854775809 +1 ^ a 9223372036854775809 +BIT_COUNT(a) 1 +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +Level Warning +Code 1916 +Message Got overflow when converting '-9223372036854776000' to INT. Value truncated +CALL p1('DECIMAL(30,0)', -9223372036854775808); +Table t1 +Create Table CREATE TABLE `t1` ( + `a` decimal(30,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a -9223372036854775808 +~a 9223372036854775807 +a & 18446744073709551615 9223372036854775808 +18446744073709551615 & a 9223372036854775808 +0 | a 9223372036854775808 +a | 0 9223372036854775808 +a << 0 9223372036854775808 +a >> 0 9223372036854775808 +a ^ 1 9223372036854775809 +1 ^ a 9223372036854775809 +BIT_COUNT(a) 1 +DROP PROCEDURE p1; +SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DECIMAL(32))<<0 AS c1; +c1 +18446744073709551615 +SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DOUBLE)<<0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DECIMAL(32))) << 0 AS c1; +c1 +18446744073709551615 +SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DOUBLE)) << 0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615 ^ 1 AS c1; +c1 +18446744073709551614 +SELECT 18446744073709551615.0 ^ 1 AS c1; +c1 +18446744073709551614 +SELECT 18446744073709551615e0 ^ 1 AS c1; +c1 +18446744073709551614 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT LAST_VALUE(18446744073709551615) ^ 1 AS c1; +c1 +18446744073709551614 +SELECT LAST_VALUE(18446744073709551615.0) ^ 1 AS c1; +c1 +18446744073709551614 +SELECT LAST_VALUE(18446744073709551615e0) ^ 1 AS c1; +c1 +18446744073709551614 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615 & 18446744073709551615 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615 & 18446744073709551615.0 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615 & 18446744073709551615e0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615.0 & 18446744073709551615 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615.0 & 18446744073709551615.0 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615.0 & 18446744073709551615e0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615e0 & 18446744073709551615 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615e0 & 18446744073709551615.0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615e0 & 18446744073709551615e0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 0 | 18446744073709551615 AS c1; +c1 +18446744073709551615 +SELECT 0 | 18446744073709551615.0 AS c1; +c1 +18446744073709551615 +SELECT 0 | 18446744073709551615e0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT 18446744073709551615 | 0 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615.0 | 0 AS c1; +c1 +18446744073709551615 +SELECT 18446744073709551615e0 | 0 AS c1; +c1 +18446744073709551615 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT ~18446744073709551615 AS c1; +c1 +0 +SELECT ~18446744073709551615.0 AS c1; +c1 +0 +SELECT ~18446744073709551615e0 AS c1; +c1 +0 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT BIT_COUNT(18446744073709551615) AS c1; +c1 +64 +SELECT BIT_COUNT(18446744073709551615.0) AS c1; +c1 +64 +SELECT BIT_COUNT(18446744073709551615e0) AS c1; +c1 +64 +Warnings: +Warning 1916 Got overflow when converting '18446744073709552000' to UNSIGNED INT. Value truncated +SELECT BIT_COUNT(-9223372036854775808) AS c1; +c1 +1 +SELECT BIT_COUNT(-9223372036854775808.0) AS c1; +c1 +1 +SELECT BIT_COUNT(-9223372036854775808e0) AS c1; +c1 +1 +Warnings: +Warning 1916 Got overflow when converting '-9223372036854776000' to INT. Value truncated +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_bit.test b/mysql-test/main/func_bit.test new file mode 100644 index 00000000000..e4f3189eafc --- /dev/null +++ b/mysql-test/main/func_bit.test @@ -0,0 +1,97 @@ +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(type VARCHAR(64), val VARCHAR(64)) +BEGIN + EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', type, ')'); + SHOW CREATE TABLE t1; + EXECUTE IMMEDIATE CONCAT('INSERT INTO t1 VALUES (', val, ')'); + SELECT + a, + ~a, + a & 18446744073709551615, + 18446744073709551615 & a, + 0 | a, + a | 0, + a << 0, + a >> 0, + a ^ 1, + 1 ^ a, + BIT_COUNT(a) + FROM t1; + SHOW WARNINGS; + DROP TABLE t1; +END; +$$ +DELIMITER ;$$ + +--vertical_results +CALL p1('BIGINT UNSIGNED', 18446744073709551615); +CALL p1('DOUBLE', 18446744073709551615); +CALL p1('DECIMAL(30,0)', 18446744073709551615); + +CALL p1('BIGINT', -1); +CALL p1('DOUBLE', -1); +CALL p1('DECIMAL(30,0)', -1); + +CALL p1('BIGINT', -9223372036854775808); +CALL p1('DOUBLE', -9223372036854775808); +CALL p1('DECIMAL(30,0)', -9223372036854775808); +--horizontal_results + +DROP PROCEDURE p1; + + +SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DECIMAL(32))<<0 AS c1; +SELECT CAST(CAST(18446744073709551615 AS UNSIGNED) AS DOUBLE)<<0 AS c1; + +SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DECIMAL(32))) << 0 AS c1; +SELECT COALESCE(CAST(CAST(0xFFFFFFFFFFFFFFFF AS UNSIGNED) AS DOUBLE)) << 0 AS c1; + +SELECT 18446744073709551615 ^ 1 AS c1; +SELECT 18446744073709551615.0 ^ 1 AS c1; +SELECT 18446744073709551615e0 ^ 1 AS c1; + +SELECT LAST_VALUE(18446744073709551615) ^ 1 AS c1; +SELECT LAST_VALUE(18446744073709551615.0) ^ 1 AS c1; +SELECT LAST_VALUE(18446744073709551615e0) ^ 1 AS c1; + +SELECT 18446744073709551615 & 18446744073709551615 AS c1; +SELECT 18446744073709551615 & 18446744073709551615.0 AS c1; +SELECT 18446744073709551615 & 18446744073709551615e0 AS c1; +SELECT 18446744073709551615.0 & 18446744073709551615 AS c1; +SELECT 18446744073709551615.0 & 18446744073709551615.0 AS c1; +SELECT 18446744073709551615.0 & 18446744073709551615e0 AS c1; +SELECT 18446744073709551615e0 & 18446744073709551615 AS c1; +SELECT 18446744073709551615e0 & 18446744073709551615.0 AS c1; +SELECT 18446744073709551615e0 & 18446744073709551615e0 AS c1; + + +SELECT 0 | 18446744073709551615 AS c1; +SELECT 0 | 18446744073709551615.0 AS c1; +SELECT 0 | 18446744073709551615e0 AS c1; +SELECT 18446744073709551615 | 0 AS c1; +SELECT 18446744073709551615.0 | 0 AS c1; +SELECT 18446744073709551615e0 | 0 AS c1; + +SELECT ~18446744073709551615 AS c1; +SELECT ~18446744073709551615.0 AS c1; +SELECT ~18446744073709551615e0 AS c1; + +SELECT BIT_COUNT(18446744073709551615) AS c1; +SELECT BIT_COUNT(18446744073709551615.0) AS c1; +SELECT BIT_COUNT(18446744073709551615e0) AS c1; + +SELECT BIT_COUNT(-9223372036854775808) AS c1; +SELECT BIT_COUNT(-9223372036854775808.0) AS c1; +SELECT BIT_COUNT(-9223372036854775808e0) AS c1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/func_gconcat.result b/mysql-test/main/func_gconcat.result index e0da659f750..01bf45056c3 100644 --- a/mysql-test/main/func_gconcat.result +++ b/mysql-test/main/func_gconcat.result @@ -363,8 +363,8 @@ bb,ccc,a,bb,ccc BB,CCC,A,BB,CCC select group_concat(distinct b) from t1 group by a; group_concat(distinct b) -bb,ccc,a -BB,CCC,A +a,bb,ccc +A,BB,CCC select group_concat(b order by b) from t1 group by a; group_concat(b order by b) a,bb,bb,ccc,ccc @@ -383,11 +383,11 @@ Warning 1260 Row 2 was cut by GROUP_CONCAT() Warning 1260 Row 4 was cut by GROUP_CONCAT() select group_concat(distinct b) from t1 group by a; group_concat(distinct b) -bb,c -BB,C +a,bb +A,BB Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() +Warning 1260 Row 6 was cut by GROUP_CONCAT() select group_concat(b order by b) from t1 group by a; group_concat(b order by b) a,bb @@ -413,8 +413,8 @@ bb,ccc,a,bb,ccc,1111111111111111111111111111111111111111111111111111111111111111 BB,CCC,A,BB,CCC,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 select group_concat(distinct b) from t1 group by a; group_concat(distinct b) -bb,ccc,a,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 -BB,CCC,A,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,a,bb,ccc +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,A,BB,CCC select group_concat(b order by b) from t1 group by a; group_concat(b order by b) 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,a,bb,bb,ccc,ccc @@ -433,11 +433,11 @@ Warning 1260 Row 7 was cut by GROUP_CONCAT() Warning 1260 Row 14 was cut by GROUP_CONCAT() select group_concat(distinct b) from t1 group by a; group_concat(distinct b) -bb,ccc,a,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -BB,CCC,A,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Warnings: -Warning 1260 Row 5 was cut by GROUP_CONCAT() -Warning 1260 Row 10 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 4 was cut by GROUP_CONCAT() select group_concat(b order by b) from t1 group by a; group_concat(b order by b) 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 @@ -520,9 +520,9 @@ a group_concat(b) NULL 3,4,2,1,2,7,3,3 select a, group_concat(distinct b) from t1 group by a with rollup; a group_concat(distinct b) -1 3,4,2,1 -2 7,3 -NULL 3,4,2,1,7 +1 1,2,3,4 +2 3,7 +NULL 1,2,3,4,7 select a, group_concat(b order by b) from t1 group by a with rollup; a group_concat(b order by b) 1 1,2,2,3,4 @@ -745,10 +745,10 @@ CREATE TABLE t1(a TEXT, b CHAR(20)); INSERT INTO t1 VALUES ("one.1","one.1"),("two.2","two.2"),("one.3","one.3"); SELECT GROUP_CONCAT(DISTINCT UCASE(a)) FROM t1; GROUP_CONCAT(DISTINCT UCASE(a)) -ONE.1,TWO.2,ONE.3 +ONE.1,ONE.3,TWO.2 SELECT GROUP_CONCAT(DISTINCT UCASE(b)) FROM t1; GROUP_CONCAT(DISTINCT UCASE(b)) -ONE.1,TWO.2,ONE.3 +ONE.1,ONE.3,TWO.2 DROP TABLE t1; CREATE TABLE t1( a VARCHAR( 10 ), b INT ); INSERT INTO t1 VALUES ( repeat( 'a', 10 ), 1), @@ -847,7 +847,7 @@ create table t1(a bit(2) not null); insert into t1 values (1), (0), (0), (3), (1); select group_concat(distinct a) from t1; group_concat(distinct a) -1,0,3 +0,1,3 select group_concat(distinct a order by a) from t1; group_concat(distinct a order by a) 0,1,3 @@ -860,13 +860,13 @@ insert into t1 values (1, 'a', 0), (0, 'b', 1), (0, 'c', 0), (3, 'd', 1), (1, 'e', 1), (3, 'f', 1), (0, 'g', 1); select group_concat(distinct a, c) from t1; group_concat(distinct a, c) -10,01,00,31,11 +00,01,10,11,31 select group_concat(distinct a, c order by a) from t1; group_concat(distinct a, c order by a) 00,01,11,10,31 select group_concat(distinct a, c) from t1; group_concat(distinct a, c) -10,01,00,31,11 +00,01,10,11,31 select group_concat(distinct a, c order by a, c) from t1; group_concat(distinct a, c order by a, c) 00,01,10,11,31 @@ -1333,8 +1333,8 @@ select grp,group_concat(c limit 5.5...' at line 1 select grp,group_concat(distinct c limit 1,10 ) from t1 group by grp; grp group_concat(distinct c limit 1,10 ) 1 c -2 b -3 C,D +2 c +3 D,E select grp,group_concat(c order by a) from t1 group by grp; grp group_concat(c order by a) 1 b,c @@ -1370,6 +1370,15 @@ grp group_concat(c order by c desc limit 2) 1 c,b 2 c,b 3 E,E +# +# Empty results for group concat as offset is greater than the rows +# for a group +# +select grp,group_concat(distinct c limit 10,1 ) from t1 group by grp; +grp group_concat(distinct c limit 10,1 ) +1 +2 +3 drop table t1; create table t2 (a int, b varchar(10)); insert into t2 values(1,'a'),(1,'b'),(NULL,'c'),(2,'x'),(2,'y'); diff --git a/mysql-test/main/func_gconcat.test b/mysql-test/main/func_gconcat.test index a76568bdae3..2ab856e0edd 100644 --- a/mysql-test/main/func_gconcat.test +++ b/mysql-test/main/func_gconcat.test @@ -986,6 +986,13 @@ select grp,group_concat(c order by c limit 2) from t1 group by grp; select grp,group_concat(c order by c desc) from t1 group by grp; select grp,group_concat(c order by c desc limit 2) from t1 group by grp; +--echo # +--echo # Empty results for group concat as offset is greater than the rows +--echo # for a group +--echo # + +select grp,group_concat(distinct c limit 10,1 ) from t1 group by grp; + drop table t1; create table t2 (a int, b varchar(10)); diff --git a/mysql-test/main/func_group.result b/mysql-test/main/func_group.result index 088ddf22e59..1fc92ba90cc 100644 --- a/mysql-test/main/func_group.result +++ b/mysql-test/main/func_group.result @@ -2326,7 +2326,7 @@ SELECT MAX('x') << 1, CAST(MAX('x') AS DOUBLE), CAST(MAX('x') AS DECIMAL); MAX('x') << 1 CAST(MAX('x') AS DOUBLE) CAST(MAX('x') AS DECIMAL) 0 0 0 Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'x' +Warning 1292 Truncated incorrect DECIMAL value: 'x' Warning 1292 Truncated incorrect DOUBLE value: 'x' Warning 1292 Truncated incorrect DECIMAL value: 'x' # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index cc87a935a85..523048ccb7a 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -916,6 +916,19 @@ NULL Warnings: Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_merge_patch' # +# MDEV-22976 CAST(JSON_EXTRACT() AS DECIMAL) does not handle boolean values +# +SELECT +CAST(JSON_EXTRACT('{"x":true}', '$.x') AS DOUBLE) AS cf, +CAST(JSON_EXTRACT('{"x":true}', '$.x') AS DECIMAL) AS cd; +cf cd +1 1 +SELECT +CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DOUBLE) AS cf, +CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DECIMAL) AS cd; +cf cd +0 0 +# # End of 10.2 tests # # @@ -1160,13 +1173,13 @@ JSON_ARRAYAGG(DISTINCT a) [1,2,3] SELECT JSON_ARRAYAGG(DISTINCT b) FROM t1; JSON_ARRAYAGG(DISTINCT b) -["Hello","World","This","Will","Work","!",null] +[null,"!","Hello","This","Will","Work","World"] SELECT JSON_ARRAYAGG(DISTINCT a LIMIT 2) FROM t1; JSON_ARRAYAGG(DISTINCT a LIMIT 2) [1,2] SELECT JSON_ARRAYAGG(DISTINCT b LIMIT 2) FROM t1; JSON_ARRAYAGG(DISTINCT b LIMIT 2) -["Hello","World"] +[null,"!"] # # JSON aggregation # @@ -1229,6 +1242,119 @@ select json_arrayagg(a) over () from (select 1 a) t; ERROR 42000: This version of MariaDB doesn't yet support 'JSON_ARRAYAGG() aggregate as window function' select json_objectagg(a, b) over () from (select 1 a, 2 b) t; ERROR 42000: This version of MariaDB doesn't yet support 'JSON_OBJECTAGG() aggregate as window function' +SELECT JSON_ARRAYAGG(NULL) FROM (SELECT 1 AS t) AS A; +JSON_ARRAYAGG(NULL) +[null] +SELECT JSON_ARRAYAGG("null") FROM (SELECT 1 AS t) AS A; +JSON_ARRAYAGG("null") +["null"] +create view v as (select json_arrayagg(json_object("type", "permPeriod", "id", "asd")) as JSON_DATA); +select * from v; +JSON_DATA +[{"type": "permPeriod", "id": "asd"}] +drop view v; +select json_arrayagg(a order by a asc) from (select 1 a union select 2 a) t; +json_arrayagg(a order by a asc) +[1,2] +select json_object('x', json_arrayagg(json_object('a', 1))); +json_object('x', json_arrayagg(json_object('a', 1))) +{"x": [{"a": 1}]} +# +# MDEV-22011: DISTINCT with JSON_ARRAYAGG gives wrong results +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +[1,2,3,1,2,3] +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; +JSON_ARRAYAGG(DISTINCT a) +[1,2,3] +INSERT INTO t1 VALUES (NULL,NULL), (NULL,NULL); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +[1,2,3,1,2,3,null,null] +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; +JSON_ARRAYAGG(DISTINCT a) +[null,1,2,3] +DROP TABLE t1; +CREATE TABLE t1(a VARCHAR(10), b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +["1","2","3","1","2","3"] +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; +JSON_ARRAYAGG(DISTINCT a) +["1","2","3"] +INSERT INTO t1 VALUES (NULL,NULL), (NULL,NULL); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +["1","2","3","1","2","3",null,null] +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; +JSON_ARRAYAGG(DISTINCT a) +[null,"1","2","3"] +DROP TABLE t1; +# +# MDEV-22840: JSON_ARRAYAGG gives wrong results with NULL values and ORDER by clause +# +CREATE TABLE t1(a VARCHAR(255)); +INSERT INTO t1 VALUES ('red'),('blue'); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +["red","blue"] +SELECT JSON_ARRAYAGG(a ORDER BY a DESC) FROM t1; +JSON_ARRAYAGG(a ORDER BY a DESC) +["red","blue"] +SELECT JSON_ARRAYAGG(a ORDER BY a ASC) FROM t1; +JSON_ARRAYAGG(a ORDER BY a ASC) +["blue","red"] +INSERT INTO t1 VALUES (NULL); +SELECT JSON_ARRAYAGG(a) FROM t1; +JSON_ARRAYAGG(a) +["red","blue",null] +SELECT JSON_ARRAYAGG(a ORDER BY a DESC) FROM t1; +JSON_ARRAYAGG(a ORDER BY a DESC) +["red","blue",null] +SELECT JSON_ARRAYAGG(a ORDER BY a ASC) FROM t1; +JSON_ARRAYAGG(a ORDER BY a ASC) +[null,"blue","red"] +DROP TABLE t1; +set group_concat_max_len=64; +create table t1 (a varchar(254)); +insert into t1 values (concat('x64-', repeat('a', 60))); +insert into t1 values (concat('x64-', repeat('b', 60))); +insert into t1 values (concat('x64-', repeat('c', 60))); +select json_arrayagg(a) from t1; +json_arrayagg(a) +["x64-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] +Warnings: +Warning 1260 Row 1 was cut by JSON_ARRAYAGG() +drop table t1; +SET group_concat_max_len= default; +create table t1 (col1 json); +insert into t1 values('{"color":"red", "size":1}' ); +insert into t1 values('{"color":"blue", "size":2}' ); +select JSON_ARRAYAGG(col1) from t1; +JSON_ARRAYAGG(col1) +[{"color":"red", "size":1},{"color":"blue", "size":2}] +drop table t1; +# +# MDEV-23029: JSON_OBJECTAGG returns NULL when used together with GROUP BY +# +CREATE TABLE t1 (e INT, a VARCHAR(255), v VARCHAR(255)); +INSERT INTO t1 VALUES (0, 'a1', '1') , (0, 'a2', '2') , (1, 'b1', '3'); +EXPLAIN SELECT B.e, JSON_OBJECTAGG(B.a, B.v) FROM t1 A, t1 B GROUP BY B.e, B.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE A ALL NULL NULL NULL NULL 3 Using temporary; Using filesort +1 SIMPLE B ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) +SELECT B.e, JSON_OBJECTAGG(B.a, B.v) FROM t1 A, t1 B GROUP BY B.e, B.a; +e JSON_OBJECTAGG(B.a, B.v) +0 {"a1":"1", "a1":"1", "a1":"1"} +0 {"a2":"2", "a2":"2", "a2":"2"} +1 {"b1":"3", "b1":"3", "b1":"3"} +DROP TABLE t1; # # End of 10.5 tests # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 216d51b4c36..68d381f5c07 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -537,6 +537,19 @@ SELECT JSON_MERGE_PATCH('{}'); SELECT JSON_MERGE_PATCH('{', '[1,2,3]'); SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,'); +--echo # +--echo # MDEV-22976 CAST(JSON_EXTRACT() AS DECIMAL) does not handle boolean values +--echo # + +SELECT + CAST(JSON_EXTRACT('{"x":true}', '$.x') AS DOUBLE) AS cf, + CAST(JSON_EXTRACT('{"x":true}', '$.x') AS DECIMAL) AS cd; + +SELECT + CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DOUBLE) AS cf, + CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DECIMAL) AS cd; + + --echo # --echo # End of 10.2 tests --echo # @@ -752,6 +765,92 @@ select json_arrayagg(a) over () from (select 1 a) t; --error ER_NOT_SUPPORTED_YET select json_objectagg(a, b) over () from (select 1 a, 2 b) t; +SELECT JSON_ARRAYAGG(NULL) FROM (SELECT 1 AS t) AS A; +SELECT JSON_ARRAYAGG("null") FROM (SELECT 1 AS t) AS A; + +create view v as (select json_arrayagg(json_object("type", "permPeriod", "id", "asd")) as JSON_DATA); +select * from v; +drop view v; + +select json_arrayagg(a order by a asc) from (select 1 a union select 2 a) t; + +select json_object('x', json_arrayagg(json_object('a', 1))); + +--echo # +--echo # MDEV-22011: DISTINCT with JSON_ARRAYAGG gives wrong results +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; + +INSERT INTO t1 VALUES (NULL,NULL), (NULL,NULL); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1(a VARCHAR(10), b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; + +INSERT INTO t1 VALUES (NULL,NULL), (NULL,NULL); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(DISTINCT a) FROM t1; + +DROP TABLE t1; + +--echo # +--echo # MDEV-22840: JSON_ARRAYAGG gives wrong results with NULL values and ORDER by clause +--echo # + +CREATE TABLE t1(a VARCHAR(255)); +INSERT INTO t1 VALUES ('red'),('blue'); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(a ORDER BY a DESC) FROM t1; +SELECT JSON_ARRAYAGG(a ORDER BY a ASC) FROM t1; + +INSERT INTO t1 VALUES (NULL); + +SELECT JSON_ARRAYAGG(a) FROM t1; +SELECT JSON_ARRAYAGG(a ORDER BY a DESC) FROM t1; +SELECT JSON_ARRAYAGG(a ORDER BY a ASC) FROM t1; +DROP TABLE t1; + +set group_concat_max_len=64; +create table t1 (a varchar(254)); +insert into t1 values (concat('x64-', repeat('a', 60))); +insert into t1 values (concat('x64-', repeat('b', 60))); insert into t1 values (concat('x64-', repeat('c', 60))); +select json_arrayagg(a) from t1; +drop table t1; +SET group_concat_max_len= default; + +create table t1 (col1 json); +insert into t1 values('{"color":"red", "size":1}' ); +insert into t1 values('{"color":"blue", "size":2}' ); +select JSON_ARRAYAGG(col1) from t1; +drop table t1; + +--echo # +--echo # MDEV-23029: JSON_OBJECTAGG returns NULL when used together with GROUP BY +--echo # + +CREATE TABLE t1 (e INT, a VARCHAR(255), v VARCHAR(255)); +INSERT INTO t1 VALUES (0, 'a1', '1') , (0, 'a2', '2') , (1, 'b1', '3'); + +EXPLAIN SELECT B.e, JSON_OBJECTAGG(B.a, B.v) FROM t1 A, t1 B GROUP BY B.e, B.a; +SELECT B.e, JSON_OBJECTAGG(B.a, B.v) FROM t1 A, t1 B GROUP BY B.e, B.a; + +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/func_math.result b/mysql-test/main/func_math.result index 50936e10cb6..547339e56ac 100644 --- a/mysql-test/main/func_math.result +++ b/mysql-test/main/func_math.result @@ -1015,6 +1015,742 @@ SELECT -9223372036854775808 MOD -9223372036854775808; -9223372036854775808 MOD -9223372036854775808 0 # +# MDEV-22502 MDB crashes in CREATE TABLE AS SELECT when the precision of returning type = 0 +# +CREATE TABLE t1 (d decimal(5,5)); +INSERT INTO t1 VALUES (0.55555); +SELECT TRUNCATE(d,0) FROM t1; +TRUNCATE(d,0) +0 +CREATE TABLE t2 AS SELECT TRUNCATE(d,0) FROM t1; +SELECT * FROM t2; +TRUNCATE(d,0) +0 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `TRUNCATE(d,0)` decimal(1,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; +# +# MDEV-22503 MDB limits DECIMAL column precision to 16 doing CTAS with floor/ceil over DECIMAL(X,Y) where X > 16 +# +CREATE TABLE t44 (d1 decimal(38,0) DEFAULT NULL); +INSERT INTO t44 VALUES (12345678901234567890123456789012345678); +SELECT FLOOR(d1) FROM t44; +FLOOR(d1) +12345678901234567890123456789012345678 +CREATE TABLE t45 AS SELECT FLOOR(d1) FROM t44; +SELECT * FROM t45; +FLOOR(d1) +12345678901234567890123456789012345678 +SHOW CREATE TABLE t45; +Table Create Table +t45 CREATE TABLE `t45` ( + `FLOOR(d1)` decimal(38,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t44, t45; +CREATE PROCEDURE p1(prec INT, scale INT) +BEGIN +DECLARE maxval VARCHAR(128) DEFAULT ''; +SET @type= CONCAT('DECIMAL(', prec, ',', scale,')'); +SET @stmt= CONCAT('CREATE TABLE t1 (a ', @type, ',b ', @type, 'unsigned)'); +PREPARE stmt FROM @stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +SET maxval= CONCAT(REPEAT('9', prec-scale), '.', REPEAT('9',scale)); +INSERT INTO t1 VALUES (maxval, maxval); +CREATE TABLE t2 AS SELECT a, b, FLOOR(a) AS fa, FLOOR(b) AS fb FROM t1; +SHOW CREATE TABLE t2; +SELECT * FROM t2; +DROP TABLE t1, t2; +END; +$$ +CREATE PROCEDURE p2(prec INT) +BEGIN +DECLARE scale INT DEFAULT 0; +WHILE scale < prec AND scale <= 30 DO +CALL p1(prec, scale); +SET scale= scale + 1; +END WHILE; +END; +$$ +CALL p2(38); +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,0) DEFAULT NULL, + `b` decimal(38,0) unsigned DEFAULT NULL, + `fa` decimal(38,0) DEFAULT NULL, + `fb` decimal(38,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999999999999999 +b 99999999999999999999999999999999999999 +fa 99999999999999999999999999999999999999 +fb 99999999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,1) DEFAULT NULL, + `b` decimal(38,1) unsigned DEFAULT NULL, + `fa` decimal(37,0) DEFAULT NULL, + `fb` decimal(37,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999999999999999.9 +b 9999999999999999999999999999999999999.9 +fa 9999999999999999999999999999999999999 +fb 9999999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,2) DEFAULT NULL, + `b` decimal(38,2) unsigned DEFAULT NULL, + `fa` decimal(36,0) DEFAULT NULL, + `fb` decimal(36,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999999999999.99 +b 999999999999999999999999999999999999.99 +fa 999999999999999999999999999999999999 +fb 999999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,3) DEFAULT NULL, + `b` decimal(38,3) unsigned DEFAULT NULL, + `fa` decimal(35,0) DEFAULT NULL, + `fb` decimal(35,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999999999999.999 +b 99999999999999999999999999999999999.999 +fa 99999999999999999999999999999999999 +fb 99999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,4) DEFAULT NULL, + `b` decimal(38,4) unsigned DEFAULT NULL, + `fa` decimal(34,0) DEFAULT NULL, + `fb` decimal(34,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999999999999.9999 +b 9999999999999999999999999999999999.9999 +fa 9999999999999999999999999999999999 +fb 9999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,5) DEFAULT NULL, + `b` decimal(38,5) unsigned DEFAULT NULL, + `fa` decimal(33,0) DEFAULT NULL, + `fb` decimal(33,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999999999.99999 +b 999999999999999999999999999999999.99999 +fa 999999999999999999999999999999999 +fb 999999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,6) DEFAULT NULL, + `b` decimal(38,6) unsigned DEFAULT NULL, + `fa` decimal(32,0) DEFAULT NULL, + `fb` decimal(32,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999999999.999999 +b 99999999999999999999999999999999.999999 +fa 99999999999999999999999999999999 +fb 99999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,7) DEFAULT NULL, + `b` decimal(38,7) unsigned DEFAULT NULL, + `fa` decimal(31,0) DEFAULT NULL, + `fb` decimal(31,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999999999.9999999 +b 9999999999999999999999999999999.9999999 +fa 9999999999999999999999999999999 +fb 9999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,8) DEFAULT NULL, + `b` decimal(38,8) unsigned DEFAULT NULL, + `fa` decimal(30,0) DEFAULT NULL, + `fb` decimal(30,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999999.99999999 +b 999999999999999999999999999999.99999999 +fa 999999999999999999999999999999 +fb 999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,9) DEFAULT NULL, + `b` decimal(38,9) unsigned DEFAULT NULL, + `fa` decimal(29,0) DEFAULT NULL, + `fb` decimal(29,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999999.999999999 +b 99999999999999999999999999999.999999999 +fa 99999999999999999999999999999 +fb 99999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,10) DEFAULT NULL, + `b` decimal(38,10) unsigned DEFAULT NULL, + `fa` decimal(28,0) DEFAULT NULL, + `fb` decimal(28,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999999.9999999999 +b 9999999999999999999999999999.9999999999 +fa 9999999999999999999999999999 +fb 9999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,11) DEFAULT NULL, + `b` decimal(38,11) unsigned DEFAULT NULL, + `fa` decimal(27,0) DEFAULT NULL, + `fb` decimal(27,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999.99999999999 +b 999999999999999999999999999.99999999999 +fa 999999999999999999999999999 +fb 999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,12) DEFAULT NULL, + `b` decimal(38,12) unsigned DEFAULT NULL, + `fa` decimal(26,0) DEFAULT NULL, + `fb` decimal(26,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999.999999999999 +b 99999999999999999999999999.999999999999 +fa 99999999999999999999999999 +fb 99999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,13) DEFAULT NULL, + `b` decimal(38,13) unsigned DEFAULT NULL, + `fa` decimal(25,0) DEFAULT NULL, + `fb` decimal(25,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999.9999999999999 +b 9999999999999999999999999.9999999999999 +fa 9999999999999999999999999 +fb 9999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,14) DEFAULT NULL, + `b` decimal(38,14) unsigned DEFAULT NULL, + `fa` decimal(24,0) DEFAULT NULL, + `fb` decimal(24,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999.99999999999999 +b 999999999999999999999999.99999999999999 +fa 999999999999999999999999 +fb 999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,15) DEFAULT NULL, + `b` decimal(38,15) unsigned DEFAULT NULL, + `fa` decimal(23,0) DEFAULT NULL, + `fb` decimal(23,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999.999999999999999 +b 99999999999999999999999.999999999999999 +fa 99999999999999999999999 +fb 99999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,16) DEFAULT NULL, + `b` decimal(38,16) unsigned DEFAULT NULL, + `fa` decimal(22,0) DEFAULT NULL, + `fb` decimal(22,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999.9999999999999999 +b 9999999999999999999999.9999999999999999 +fa 9999999999999999999999 +fb 9999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,17) DEFAULT NULL, + `b` decimal(38,17) unsigned DEFAULT NULL, + `fa` decimal(21,0) DEFAULT NULL, + `fb` decimal(21,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999.99999999999999999 +b 999999999999999999999.99999999999999999 +fa 999999999999999999999 +fb 999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,18) DEFAULT NULL, + `b` decimal(38,18) unsigned DEFAULT NULL, + `fa` decimal(20,0) DEFAULT NULL, + `fb` decimal(20,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999.999999999999999999 +b 99999999999999999999.999999999999999999 +fa 99999999999999999999 +fb 99999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,19) DEFAULT NULL, + `b` decimal(38,19) unsigned DEFAULT NULL, + `fa` decimal(19,0) DEFAULT NULL, + `fb` decimal(19,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999.9999999999999999999 +b 9999999999999999999.9999999999999999999 +fa 9999999999999999999 +fb 9999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,20) DEFAULT NULL, + `b` decimal(38,20) unsigned DEFAULT NULL, + `fa` decimal(18,0) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999.99999999999999999999 +b 999999999999999999.99999999999999999999 +fa 999999999999999999 +fb 999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,21) DEFAULT NULL, + `b` decimal(38,21) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999.999999999999999999999 +b 99999999999999999.999999999999999999999 +fa 99999999999999999 +fb 99999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,22) DEFAULT NULL, + `b` decimal(38,22) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999.9999999999999999999999 +b 9999999999999999.9999999999999999999999 +fa 9999999999999999 +fb 9999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,23) DEFAULT NULL, + `b` decimal(38,23) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999.99999999999999999999999 +b 999999999999999.99999999999999999999999 +fa 999999999999999 +fb 999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,24) DEFAULT NULL, + `b` decimal(38,24) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(16) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999.999999999999999999999999 +b 99999999999999.999999999999999999999999 +fa 99999999999999 +fb 99999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,25) DEFAULT NULL, + `b` decimal(38,25) unsigned DEFAULT NULL, + `fa` bigint(16) DEFAULT NULL, + `fb` bigint(15) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999.9999999999999999999999999 +b 9999999999999.9999999999999999999999999 +fa 9999999999999 +fb 9999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,26) DEFAULT NULL, + `b` decimal(38,26) unsigned DEFAULT NULL, + `fa` bigint(15) DEFAULT NULL, + `fb` bigint(14) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999.99999999999999999999999999 +b 999999999999.99999999999999999999999999 +fa 999999999999 +fb 999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,27) DEFAULT NULL, + `b` decimal(38,27) unsigned DEFAULT NULL, + `fa` bigint(14) DEFAULT NULL, + `fb` bigint(13) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999.999999999999999999999999999 +b 99999999999.999999999999999999999999999 +fa 99999999999 +fb 99999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,28) DEFAULT NULL, + `b` decimal(38,28) unsigned DEFAULT NULL, + `fa` bigint(13) DEFAULT NULL, + `fb` bigint(12) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999.9999999999999999999999999999 +b 9999999999.9999999999999999999999999999 +fa 9999999999 +fb 9999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,29) DEFAULT NULL, + `b` decimal(38,29) unsigned DEFAULT NULL, + `fa` bigint(12) DEFAULT NULL, + `fb` bigint(11) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999.99999999999999999999999999999 +b 999999999.99999999999999999999999999999 +fa 999999999 +fb 999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(38,30) DEFAULT NULL, + `b` decimal(38,30) unsigned DEFAULT NULL, + `fa` bigint(11) DEFAULT NULL, + `fb` bigint(10) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999.999999999999999999999999999999 +b 99999999.999999999999999999999999999999 +fa 99999999 +fb 99999999 +CALL p2(30); +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,0) DEFAULT NULL, + `b` decimal(30,0) unsigned DEFAULT NULL, + `fa` decimal(30,0) DEFAULT NULL, + `fb` decimal(31,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999999 +b 999999999999999999999999999999 +fa 999999999999999999999999999999 +fb 999999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,1) DEFAULT NULL, + `b` decimal(30,1) unsigned DEFAULT NULL, + `fa` decimal(29,0) DEFAULT NULL, + `fb` decimal(30,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999999.9 +b 99999999999999999999999999999.9 +fa 99999999999999999999999999999 +fb 99999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,2) DEFAULT NULL, + `b` decimal(30,2) unsigned DEFAULT NULL, + `fa` decimal(28,0) DEFAULT NULL, + `fb` decimal(29,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999999.99 +b 9999999999999999999999999999.99 +fa 9999999999999999999999999999 +fb 9999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,3) DEFAULT NULL, + `b` decimal(30,3) unsigned DEFAULT NULL, + `fa` decimal(27,0) DEFAULT NULL, + `fb` decimal(28,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999999.999 +b 999999999999999999999999999.999 +fa 999999999999999999999999999 +fb 999999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,4) DEFAULT NULL, + `b` decimal(30,4) unsigned DEFAULT NULL, + `fa` decimal(26,0) DEFAULT NULL, + `fb` decimal(27,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999999.9999 +b 99999999999999999999999999.9999 +fa 99999999999999999999999999 +fb 99999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,5) DEFAULT NULL, + `b` decimal(30,5) unsigned DEFAULT NULL, + `fa` decimal(25,0) DEFAULT NULL, + `fb` decimal(26,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999999.99999 +b 9999999999999999999999999.99999 +fa 9999999999999999999999999 +fb 9999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,6) DEFAULT NULL, + `b` decimal(30,6) unsigned DEFAULT NULL, + `fa` decimal(24,0) DEFAULT NULL, + `fb` decimal(25,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999999.999999 +b 999999999999999999999999.999999 +fa 999999999999999999999999 +fb 999999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,7) DEFAULT NULL, + `b` decimal(30,7) unsigned DEFAULT NULL, + `fa` decimal(23,0) DEFAULT NULL, + `fb` decimal(24,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999999.9999999 +b 99999999999999999999999.9999999 +fa 99999999999999999999999 +fb 99999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,8) DEFAULT NULL, + `b` decimal(30,8) unsigned DEFAULT NULL, + `fa` decimal(22,0) DEFAULT NULL, + `fb` decimal(23,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999999.99999999 +b 9999999999999999999999.99999999 +fa 9999999999999999999999 +fb 9999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,9) DEFAULT NULL, + `b` decimal(30,9) unsigned DEFAULT NULL, + `fa` decimal(21,0) DEFAULT NULL, + `fb` decimal(22,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999999.999999999 +b 999999999999999999999.999999999 +fa 999999999999999999999 +fb 999999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,10) DEFAULT NULL, + `b` decimal(30,10) unsigned DEFAULT NULL, + `fa` decimal(20,0) DEFAULT NULL, + `fb` decimal(21,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999999.9999999999 +b 99999999999999999999.9999999999 +fa 99999999999999999999 +fb 99999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,11) DEFAULT NULL, + `b` decimal(30,11) unsigned DEFAULT NULL, + `fa` decimal(19,0) DEFAULT NULL, + `fb` decimal(20,0) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999999.99999999999 +b 9999999999999999999.99999999999 +fa 9999999999999999999 +fb 9999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,12) DEFAULT NULL, + `b` decimal(30,12) unsigned DEFAULT NULL, + `fa` decimal(18,0) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999999.999999999999 +b 999999999999999999.999999999999 +fa 999999999999999999 +fb 999999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,13) DEFAULT NULL, + `b` decimal(30,13) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999999.9999999999999 +b 99999999999999999.9999999999999 +fa 99999999999999999 +fb 99999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,14) DEFAULT NULL, + `b` decimal(30,14) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999999.99999999999999 +b 9999999999999999.99999999999999 +fa 9999999999999999 +fb 9999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,15) DEFAULT NULL, + `b` decimal(30,15) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(17) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999999.999999999999999 +b 999999999999999.999999999999999 +fa 999999999999999 +fb 999999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,16) DEFAULT NULL, + `b` decimal(30,16) unsigned DEFAULT NULL, + `fa` bigint(17) DEFAULT NULL, + `fb` bigint(16) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999999.9999999999999999 +b 99999999999999.9999999999999999 +fa 99999999999999 +fb 99999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,17) DEFAULT NULL, + `b` decimal(30,17) unsigned DEFAULT NULL, + `fa` bigint(16) DEFAULT NULL, + `fb` bigint(15) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999999.99999999999999999 +b 9999999999999.99999999999999999 +fa 9999999999999 +fb 9999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,18) DEFAULT NULL, + `b` decimal(30,18) unsigned DEFAULT NULL, + `fa` bigint(15) DEFAULT NULL, + `fb` bigint(14) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999999.999999999999999999 +b 999999999999.999999999999999999 +fa 999999999999 +fb 999999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,19) DEFAULT NULL, + `b` decimal(30,19) unsigned DEFAULT NULL, + `fa` bigint(14) DEFAULT NULL, + `fb` bigint(13) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999999.9999999999999999999 +b 99999999999.9999999999999999999 +fa 99999999999 +fb 99999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,20) DEFAULT NULL, + `b` decimal(30,20) unsigned DEFAULT NULL, + `fa` bigint(13) DEFAULT NULL, + `fb` bigint(12) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999999.99999999999999999999 +b 9999999999.99999999999999999999 +fa 9999999999 +fb 9999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,21) DEFAULT NULL, + `b` decimal(30,21) unsigned DEFAULT NULL, + `fa` bigint(12) DEFAULT NULL, + `fb` bigint(11) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999999.999999999999999999999 +b 999999999.999999999999999999999 +fa 999999999 +fb 999999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,22) DEFAULT NULL, + `b` decimal(30,22) unsigned DEFAULT NULL, + `fa` bigint(11) DEFAULT NULL, + `fb` bigint(10) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999999.9999999999999999999999 +b 99999999.9999999999999999999999 +fa 99999999 +fb 99999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,23) DEFAULT NULL, + `b` decimal(30,23) unsigned DEFAULT NULL, + `fa` bigint(10) DEFAULT NULL, + `fb` int(9) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999999.99999999999999999999999 +b 9999999.99999999999999999999999 +fa 9999999 +fb 9999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,24) DEFAULT NULL, + `b` decimal(30,24) unsigned DEFAULT NULL, + `fa` int(9) DEFAULT NULL, + `fb` int(8) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999999.999999999999999999999999 +b 999999.999999999999999999999999 +fa 999999 +fb 999999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,25) DEFAULT NULL, + `b` decimal(30,25) unsigned DEFAULT NULL, + `fa` int(8) DEFAULT NULL, + `fb` int(7) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99999.9999999999999999999999999 +b 99999.9999999999999999999999999 +fa 99999 +fb 99999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,26) DEFAULT NULL, + `b` decimal(30,26) unsigned DEFAULT NULL, + `fa` int(7) DEFAULT NULL, + `fb` int(6) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9999.99999999999999999999999999 +b 9999.99999999999999999999999999 +fa 9999 +fb 9999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,27) DEFAULT NULL, + `b` decimal(30,27) unsigned DEFAULT NULL, + `fa` int(6) DEFAULT NULL, + `fb` int(5) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 999.999999999999999999999999999 +b 999.999999999999999999999999999 +fa 999 +fb 999 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,28) DEFAULT NULL, + `b` decimal(30,28) unsigned DEFAULT NULL, + `fa` int(5) DEFAULT NULL, + `fb` int(4) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 99.9999999999999999999999999999 +b 99.9999999999999999999999999999 +fa 99 +fb 99 +Table t2 +Create Table CREATE TABLE `t2` ( + `a` decimal(30,29) DEFAULT NULL, + `b` decimal(30,29) unsigned DEFAULT NULL, + `fa` int(4) DEFAULT NULL, + `fb` int(3) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +a 9.99999999999999999999999999999 +b 9.99999999999999999999999999999 +fa 9 +fb 9 +DROP PROCEDURE p2; +DROP PROCEDURE p1; +# # End of 10.1 tests # # @@ -1466,7 +2202,7 @@ SET @val = 'a'; EXECUTE stmt1 USING @val; CRC32(?) 3904355907 -DEALLOCATE PREPARE stmt; +DEALLOCATE PREPARE stmt1; SET NAMES utf8; CREATE TABLE t1 (a TEXT) CHARACTER SET = utf8; LOAD DATA INFILE '../../std_data/loaddata_utf8.dat' INTO TABLE t1 CHARACTER SET utf8; @@ -1515,6 +2251,36 @@ SELECT ROUND( i, 18446744073709551594 ) AS f FROM t1; f DROP TABLE t1; # +# MDEV-22268 virtual longlong Item_func_div::int_op(): Assertion `0' failed in Item_func_div::int_op +# +SET sql_mode=''; +SET @@SESSION.div_precision_increment=0; +SELECT UTC_TIME / 0; +UTC_TIME / 0 +NULL +SELECT TIMESTAMP'2001-01-01 00:00:00'/0; +TIMESTAMP'2001-01-01 00:00:00'/0 +NULL +SELECT TIME'00:00:00'/0; +TIME'00:00:00'/0 +NULL +CREATE TABLE t1 AS SELECT +UTC_TIME / 0 AS c1, +TIMESTAMP'2001-01-01 00:00:00'/0 AS c3, +TIME'00:00:00'/0 AS c4; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` decimal(7,0) DEFAULT NULL, + `c3` decimal(14,0) DEFAULT NULL, + `c4` decimal(7,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SELECT(-0 * MOD((UTC_TIME / -0)MOD (ATAN('') MOD COT(0)),-0)) MOD (0 DIV 0); +ERROR 22003: DOUBLE value is out of range in 'cot(0)' +SET @@SESSION.div_precision_increment=DEFAULT; +SET sql_mode=DEFAULT; +# # End of 10.3 tests # # diff --git a/mysql-test/main/func_math.test b/mysql-test/main/func_math.test index 37f63bd103c..7f8fe9e7e73 100644 --- a/mysql-test/main/func_math.test +++ b/mysql-test/main/func_math.test @@ -715,6 +715,65 @@ SELECT 9223372036854775808 MOD -9223372036854775808; SELECT -9223372036854775808 MOD 9223372036854775808; SELECT -9223372036854775808 MOD -9223372036854775808; +--echo # +--echo # MDEV-22502 MDB crashes in CREATE TABLE AS SELECT when the precision of returning type = 0 +--echo # + +CREATE TABLE t1 (d decimal(5,5)); +INSERT INTO t1 VALUES (0.55555); +SELECT TRUNCATE(d,0) FROM t1; +CREATE TABLE t2 AS SELECT TRUNCATE(d,0) FROM t1; +SELECT * FROM t2; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + + +--echo # +--echo # MDEV-22503 MDB limits DECIMAL column precision to 16 doing CTAS with floor/ceil over DECIMAL(X,Y) where X > 16 +--echo # + +CREATE TABLE t44 (d1 decimal(38,0) DEFAULT NULL); +INSERT INTO t44 VALUES (12345678901234567890123456789012345678); +SELECT FLOOR(d1) FROM t44; +CREATE TABLE t45 AS SELECT FLOOR(d1) FROM t44; +SELECT * FROM t45; +SHOW CREATE TABLE t45; +DROP TABLE t44, t45; + + +DELIMITER $$; +CREATE PROCEDURE p1(prec INT, scale INT) +BEGIN + DECLARE maxval VARCHAR(128) DEFAULT ''; + SET @type= CONCAT('DECIMAL(', prec, ',', scale,')'); + SET @stmt= CONCAT('CREATE TABLE t1 (a ', @type, ',b ', @type, 'unsigned)'); + PREPARE stmt FROM @stmt; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + SET maxval= CONCAT(REPEAT('9', prec-scale), '.', REPEAT('9',scale)); + INSERT INTO t1 VALUES (maxval, maxval); + CREATE TABLE t2 AS SELECT a, b, FLOOR(a) AS fa, FLOOR(b) AS fb FROM t1; + SHOW CREATE TABLE t2; + SELECT * FROM t2; + DROP TABLE t1, t2; +END; +$$ +CREATE PROCEDURE p2(prec INT) +BEGIN + DECLARE scale INT DEFAULT 0; + WHILE scale < prec AND scale <= 30 DO + CALL p1(prec, scale); + SET scale= scale + 1; + END WHILE; +END; +$$ +DELIMITER ;$$ +--vertical_results +CALL p2(38); +CALL p2(30); +--horizontal_results +DROP PROCEDURE p2; +DROP PROCEDURE p1; --echo # @@ -1013,7 +1072,7 @@ DROP FUNCTION crc32_func; PREPARE stmt1 FROM 'SELECT CRC32(?)'; SET @val = 'a'; EXECUTE stmt1 USING @val; -DEALLOCATE PREPARE stmt; +DEALLOCATE PREPARE stmt1; # Test case for checksum on contents of a file SET NAMES utf8; @@ -1052,6 +1111,29 @@ CREATE TABLE t1 (i INT(23)); SELECT ROUND( i, 18446744073709551594 ) AS f FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-22268 virtual longlong Item_func_div::int_op(): Assertion `0' failed in Item_func_div::int_op +--echo # + +SET sql_mode=''; +SET @@SESSION.div_precision_increment=0; +SELECT UTC_TIME / 0; +SELECT TIMESTAMP'2001-01-01 00:00:00'/0; +SELECT TIME'00:00:00'/0; +CREATE TABLE t1 AS SELECT + UTC_TIME / 0 AS c1, + TIMESTAMP'2001-01-01 00:00:00'/0 AS c3, + TIME'00:00:00'/0 AS c4; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_DATA_OUT_OF_RANGE +SELECT(-0 * MOD((UTC_TIME / -0)MOD (ATAN('') MOD COT(0)),-0)) MOD (0 DIV 0); + +SET @@SESSION.div_precision_increment=DEFAULT; +SET sql_mode=DEFAULT; + --echo # --echo # End of 10.3 tests --echo # diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index 6fc61dc0f5f..992363c6b91 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -3071,7 +3071,7 @@ SELECT ((rpad(1.0,2048,1)) = ('4(') ^ (0.1)); ((rpad(1.0,2048,1)) = ('4(') ^ (0.1)) 0 Warnings: -Warning 1292 Truncated incorrect INTEGER value: '4(' +Warning 1292 Truncated incorrect DECIMAL value: '4(' SELECT pow((rpad(10.0,2048,1)),(b'1111111111111111111111111111111111111111111')); ERROR 22003: DOUBLE value is out of range in 'pow(rpad(10.0,2048,1),0x07ffffffffff)' @@ -3079,7 +3079,7 @@ SELECT ((rpad(1.0,2048,1)) + (0) ^ ('../')); ((rpad(1.0,2048,1)) + (0) ^ ('../')) 1.011111111111111 Warnings: -Warning 1292 Truncated incorrect INTEGER value: '../' +Warning 1292 Truncated incorrect DECIMAL value: '../' SELECT stddev_samp(rpad(1.0,2048,1)); stddev_samp(rpad(1.0,2048,1)) NULL diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index a9b27a15fa7..d44f634db08 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -2795,7 +2795,7 @@ SET sql_mode=DEFAULT; DO TO_DAYS(SEC_TO_TIME(TIME(CEILING(UUID())))); DO TO_DAYS(SEC_TO_TIME(MAKEDATE('',RAND(~(''))))); Warnings: -Warning 1292 Truncated incorrect INTEGER value: '' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect INTEGER value: '' Warning 1292 Truncated incorrect seconds value: '20000101' SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0))); diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 95f4a3f2f79..8bcb98143a2 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5308,5 +5308,23 @@ def COALESCE(gc,gc) 255 (type=geometrycollection) 4294967295 0 Y 128 0 63 COALESCE(gc,p) COALESCE(gc,ls) COALESCE(gc,pl) COALESCE(gc,mp) COALESCE(gc,mls) COALESCE(gc,mpl) COALESCE(gc,g) COALESCE(gc,gc) DROP TABLE t1; # +# MDEV-20809 EXTRACT from INET6 value does not produce any warnings +# +CREATE TABLE t1 (a GEOMETRY); +SELECT EXTRACT(DAY FROM a) FROM t1; +ERROR HY000: Illegal parameter data type geometry for operation 'extract(day)' +DROP TABLE t1; +# +# MDEV-21765 Possibly inconsistent behavior of BIT_xx functions with INET6 field +# +CREATE TABLE t1 (a GEOMETRY); +SELECT BIT_AND(a) FROM t1; +ERROR HY000: Illegal parameter data type geometry for operation 'bit_and(' +SELECT BIT_OR(a) FROM t1; +ERROR HY000: Illegal parameter data type geometry for operation 'bit_or(' +SELECT BIT_XOR(a) FROM t1; +ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor(' +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index c18966bc0fb..17a93291b77 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -3309,6 +3309,29 @@ FROM t1; --disable_metadata DROP TABLE t1; +--echo # +--echo # MDEV-20809 EXTRACT from INET6 value does not produce any warnings +--echo # + +CREATE TABLE t1 (a GEOMETRY); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT EXTRACT(DAY FROM a) FROM t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-21765 Possibly inconsistent behavior of BIT_xx functions with INET6 field +--echo # + +CREATE TABLE t1 (a GEOMETRY); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_AND(a) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_OR(a) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_XOR(a) FROM t1; +DROP TABLE t1; + + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index e804a37d3d0..20f670cbef4 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -2735,7 +2735,20 @@ DROP USER untrusted@localhost; DROP DATABASE secret; set GLOBAL sql_mode=default; # -# End of 10.1 tests +# MDEV-22755 CREATE USER leads to indirect SIGABRT in __stack_chk_fail () from fill_schema_user_privileges + *** stack smashing detected *** (on optimized builds) +# +SET NAMES utf8; +SET SQL_MODE=''; +CREATE USER 觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻@localhost; +SELECT * FROM INFORMATION_SCHEMA.user_privileges WHERE GRANTEE LIKE "'abcdefghijklmnopqrstuvwxyz'%"; +GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE +SELECT GRANTEE FROM INFORMATION_SCHEMA.user_privileges WHERE GRANTEE LIKE '%觻%'; +GRANTEE +'觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻'@'localhost' +DROP USER 觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻@localhost; +SET SQL_MODE=DEFAULT; +# +# Start of 10.2 tests # # # MDEV-10134 Add full support for DEFAULT diff --git a/mysql-test/main/grant.test b/mysql-test/main/grant.test index 7dedf820774..147fc42311c 100644 --- a/mysql-test/main/grant.test +++ b/mysql-test/main/grant.test @@ -2225,7 +2225,19 @@ set GLOBAL sql_mode=default; --source include/wait_until_count_sessions.inc --echo # ---echo # End of 10.1 tests +--echo # MDEV-22755 CREATE USER leads to indirect SIGABRT in __stack_chk_fail () from fill_schema_user_privileges + *** stack smashing detected *** (on optimized builds) +--echo # + +SET NAMES utf8; +SET SQL_MODE=''; +CREATE USER 觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻@localhost; +SELECT * FROM INFORMATION_SCHEMA.user_privileges WHERE GRANTEE LIKE "'abcdefghijklmnopqrstuvwxyz'%"; +SELECT GRANTEE FROM INFORMATION_SCHEMA.user_privileges WHERE GRANTEE LIKE '%觻%'; +DROP USER 觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻_觻觻觻觻觻觻觻觻觻觻@localhost; +SET SQL_MODE=DEFAULT; + +--echo # +--echo # Start of 10.2 tests --echo # --echo # diff --git a/mysql-test/main/grant5.result b/mysql-test/main/grant5.result index 43b58b82231..df09b1fcc64 100644 --- a/mysql-test/main/grant5.result +++ b/mysql-test/main/grant5.result @@ -225,4 +225,21 @@ drop user twg@'%'; insert mysql.tables_priv (host,db,user,table_name,grantor,table_priv) values ('localhost','','otto','t1','root@localhost','select'); flush privileges; delete from mysql.tables_priv where db=''; +create database db; +create table db.t1 (a int); +insert into db.t1 values (1); +create user foo; +grant delete on db.* to foo; +connect con1,localhost,foo,,; +show create table db.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +delete from db.t1 returning *; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'a' in table 't1' +disconnect con1; +connection default; +drop database db; +drop user foo; # End of 10.4 tests diff --git a/mysql-test/main/grant5.test b/mysql-test/main/grant5.test index 307549ec9d8..39fcff92435 100644 --- a/mysql-test/main/grant5.test +++ b/mysql-test/main/grant5.test @@ -182,4 +182,21 @@ insert mysql.tables_priv (host,db,user,table_name,grantor,table_priv) values ('l flush privileges; delete from mysql.tables_priv where db=''; +# +# MDEV-21560 Assertion `grant_table || grant_table_role' failed in check_grant_all_columns +# +create database db; +create table db.t1 (a int); +insert into db.t1 values (1); +create user foo; +grant delete on db.* to foo; +--connect (con1,localhost,foo,,) +show create table db.t1; +--error ER_COLUMNACCESS_DENIED_ERROR +delete from db.t1 returning *; +--disconnect con1 +--connection default +drop database db; +drop user foo; + --echo # End of 10.4 tests diff --git a/mysql-test/main/index_merge_innodb.result b/mysql-test/main/index_merge_innodb.result index b7c006c09e8..775ef3d01e5 100644 --- a/mysql-test/main/index_merge_innodb.result +++ b/mysql-test/main/index_merge_innodb.result @@ -810,4 +810,30 @@ sum(col1) 33632261 drop table t1; set optimizer_switch=@tmp_optimizer_switch; +# +# MDEV-22728: SIGFPE in Unique::get_cost_calc_buff_size from prepare_search_best_index_intersect +# on optimized builds +# +SET @save_sort_buffer_size=@@sort_buffer_size; +SET @save_innodb_file_format= @@innodb_file_format; +SET @save_innodb_large_prefix= @@innodb_large_prefix; +SET sort_buffer_size=2048; +CREATE TABLE t1 ( +a VARCHAR(1024) CHARACTER SET UTF8 PRIMARY KEY, +b INT, +c INT, +INDEX (b) +) ENGINE=InnoDB CHARSET utf8 ROW_FORMAT= DYNAMIC; +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_100; +EXPLAIN SELECT * FROM t1 WHERE a='1' OR b < 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge PRIMARY,b b,PRIMARY 5,3074 NULL 5 Using sort_union(b,PRIMARY); Using where +SELECT * FROM t1 WHERE a='1' OR b < 5; +a b c +2 2 2 +3 3 3 +4 4 4 +1 1 1 +DROP TABLE t1; +SET sort_buffer_size= @save_sort_buffer_size; disconnect disable_purge; diff --git a/mysql-test/main/index_merge_innodb.test b/mysql-test/main/index_merge_innodb.test index 27125c319f5..c0918fec79f 100644 --- a/mysql-test/main/index_merge_innodb.test +++ b/mysql-test/main/index_merge_innodb.test @@ -200,4 +200,27 @@ SELECT sum(col1) FROM t1 FORCE INDEX (key1,key2) WHERE (key1 between 10 and 819 drop table t1; set optimizer_switch=@tmp_optimizer_switch; +--echo # +--echo # MDEV-22728: SIGFPE in Unique::get_cost_calc_buff_size from prepare_search_best_index_intersect +--echo # on optimized builds +--echo # + +SET @save_sort_buffer_size=@@sort_buffer_size; +SET @save_innodb_file_format= @@innodb_file_format; +SET @save_innodb_large_prefix= @@innodb_large_prefix; +SET sort_buffer_size=2048; + +CREATE TABLE t1 ( + a VARCHAR(1024) CHARACTER SET UTF8 PRIMARY KEY, + b INT, + c INT, + INDEX (b) +) ENGINE=InnoDB CHARSET utf8 ROW_FORMAT= DYNAMIC; +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_100; +EXPLAIN SELECT * FROM t1 WHERE a='1' OR b < 5; +SELECT * FROM t1 WHERE a='1' OR b < 5; +DROP TABLE t1; + +SET sort_buffer_size= @save_sort_buffer_size; + disconnect disable_purge; diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index b977af22209..1e1f66e377c 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -2209,3 +2209,13 @@ column_name c1 c2 DROP TABLE tt1, tt2; +# +# MDEV-13242 Wrong results for queries with row constructors and information_schema +# +SELECT SCHEMA_NAME from information_schema.schemata where schema_name='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; +SCHEMA_NAME +SELECT SCHEMA_NAME from information_schema.schemata where schema_name=REPEAT('a',193); +SCHEMA_NAME +# +# End of 10.1 tests +# diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test index dc0ad5cff59..1df0d3f635f 100644 --- a/mysql-test/main/information_schema.test +++ b/mysql-test/main/information_schema.test @@ -1,9 +1,6 @@ # This test uses grants, which can't get tested for embedded server -- source include/not_embedded.inc -#Don't run this test when thread_pool active ---source include/not_threadpool.inc - # check that CSV engine was compiled in, as the result of the test depends # on the presence of the log tables (which are CSV-based). --source include/have_csv.inc @@ -1911,3 +1908,15 @@ SELECT count(*) FROM information_schema.columns WHERE table_schema='test' AND (t SELECT count(*) FROM information_schema.columns WHERE table_schema='test' AND (table_name='tt1' AND column_name='c1') OR (table_name='tt2' AND column_name='c2'); SELECT column_name FROM information_schema.columns WHERE (table_name, column_name) IN (('tt1','c1'),('tt2', 'c2')) ORDER BY column_name; DROP TABLE tt1, tt2; + +--echo # +--echo # MDEV-13242 Wrong results for queries with row constructors and information_schema +--echo # + +SELECT SCHEMA_NAME from information_schema.schemata where schema_name='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; +SELECT SCHEMA_NAME from information_schema.schemata where schema_name=REPEAT('a',193); + + +--echo # +--echo # End of 10.1 tests +--echo # diff --git a/mysql-test/main/information_schema_db.test b/mysql-test/main/information_schema_db.test index b244662a28c..7cf8c0801e6 100644 --- a/mysql-test/main/information_schema_db.test +++ b/mysql-test/main/information_schema_db.test @@ -2,9 +2,6 @@ # in the embedded server by default). So skip the test in embedded-server mode. -- source include/not_embedded.inc -#Don't run this test when thread_pool active ---source include/not_threadpool.inc - -- source include/testdb_only.inc set local sql_mode=""; diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result index ff92b4506ba..b0792605e54 100644 --- a/mysql-test/main/innodb_ext_key.result +++ b/mysql-test/main/innodb_ext_key.result @@ -970,6 +970,10 @@ INSERT INTO t2 VALUES (547118223,998,0,NULL,4,'','',0,0,NULL,NULL,''),(547119246,998,0,NULL,5,'','',0,0,NULL,NULL,''), (547115155,999,0,NULL,1,'','',0,0,NULL,NULL,''),(547116178,999,0,NULL,2,'','',0,0,NULL,NULL,''), (547117201,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547118224,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117213,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117217,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117214,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117218,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117215,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117219,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117216,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117220,999,0,NULL,4,'','',0,0,NULL,NULL,''), (547119271,38928081,0,NULL,10,'','',0,0,NULL,NULL,''),(547119272,38928081,0,NULL,11,'','',0,0,NULL,NULL,''), (547119273,38928081,0,NULL,12,'','',0,0,NULL,NULL,''),(547119274,38928081,0,NULL,13,'','',0,0,NULL,NULL,''), (547119275,38928081,0,NULL,14,'','',0,0,NULL,NULL,''),(547119276,38928081,0,NULL,15,'','',0,0,NULL,NULL,''), diff --git a/mysql-test/main/innodb_ext_key.test b/mysql-test/main/innodb_ext_key.test index f6e9e46ac24..926a3472a6a 100644 --- a/mysql-test/main/innodb_ext_key.test +++ b/mysql-test/main/innodb_ext_key.test @@ -618,6 +618,10 @@ INSERT INTO t2 VALUES (547118223,998,0,NULL,4,'','',0,0,NULL,NULL,''),(547119246,998,0,NULL,5,'','',0,0,NULL,NULL,''), (547115155,999,0,NULL,1,'','',0,0,NULL,NULL,''),(547116178,999,0,NULL,2,'','',0,0,NULL,NULL,''), (547117201,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547118224,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117213,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117217,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117214,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117218,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117215,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117219,999,0,NULL,4,'','',0,0,NULL,NULL,''), +(547117216,999,0,NULL,3,'','',0,0,NULL,NULL,''),(547117220,999,0,NULL,4,'','',0,0,NULL,NULL,''), (547119271,38928081,0,NULL,10,'','',0,0,NULL,NULL,''),(547119272,38928081,0,NULL,11,'','',0,0,NULL,NULL,''), (547119273,38928081,0,NULL,12,'','',0,0,NULL,NULL,''),(547119274,38928081,0,NULL,13,'','',0,0,NULL,NULL,''), (547119275,38928081,0,NULL,14,'','',0,0,NULL,NULL,''),(547119276,38928081,0,NULL,15,'','',0,0,NULL,NULL,''), diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index 12f776d47c7..e882973043e 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -2755,3 +2755,34 @@ WHERE t3.pk IN (2); drop view v4; drop table t1,t2,t3,t4; SET optimizer_switch=@org_optimizer_switch; +# +# MDEV-22866: Crash in join optimizer with constant outer join nest +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c INT, KEY(c)) ENGINE=MyISAM; +CREATE TABLE t4 (d INT, KEY(d)) ENGINE=MyISAM; +INSERT INTO t4 VALUES (5),(6); +CREATE TABLE t5 (e INT) ENGINE=MyISAM; +INSERT INTO t5 VALUES (7),(8); +CREATE TABLE t6 (f INT) ENGINE=MyISAM; +INSERT INTO t6 VALUES (9),(10); +SELECT * +FROM +t1 +LEFT JOIN ( +t2 LEFT JOIN ( +t3 JOIN +t4 ON t3.c = t4.d and t3.c >2 and t3.c<0 +) ON t2.b >= t4.d +) ON t1.a <= t2.b +LEFT JOIN t5 ON t2.b = t5.e +LEFT JOIN t6 ON t3.c = t6.f; +a b c d e f +1 3 NULL NULL NULL NULL +2 3 NULL NULL NULL NULL +1 4 NULL NULL NULL NULL +2 4 NULL NULL NULL NULL +drop table t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/main/join_outer.test b/mysql-test/main/join_outer.test index 2e5fc65ebb6..f835d8af5a8 100644 --- a/mysql-test/main/join_outer.test +++ b/mysql-test/main/join_outer.test @@ -2252,3 +2252,38 @@ drop view v4; drop table t1,t2,t3,t4; SET optimizer_switch=@org_optimizer_switch; + +--echo # +--echo # MDEV-22866: Crash in join optimizer with constant outer join nest +--echo # + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); + +CREATE TABLE t3 (c INT, KEY(c)) ENGINE=MyISAM; + +CREATE TABLE t4 (d INT, KEY(d)) ENGINE=MyISAM; +INSERT INTO t4 VALUES (5),(6); + +CREATE TABLE t5 (e INT) ENGINE=MyISAM; +INSERT INTO t5 VALUES (7),(8); + +CREATE TABLE t6 (f INT) ENGINE=MyISAM; +INSERT INTO t6 VALUES (9),(10); + +SELECT * +FROM + t1 + LEFT JOIN ( + t2 LEFT JOIN ( + t3 JOIN + t4 ON t3.c = t4.d and t3.c >2 and t3.c<0 + ) ON t2.b >= t4.d + ) ON t1.a <= t2.b + LEFT JOIN t5 ON t2.b = t5.e + LEFT JOIN t6 ON t3.c = t6.f; + +drop table t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/main/join_outer_innodb.result b/mysql-test/main/join_outer_innodb.result index 5bfcf7f20e1..0b34a399d77 100644 --- a/mysql-test/main/join_outer_innodb.result +++ b/mysql-test/main/join_outer_innodb.result @@ -481,9 +481,7 @@ drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16; # drop table if exists t1,t2,t3; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' -Note 1051 Unknown table 'test.t3' +Note 1051 Unknown table 'test.t1,test.t2,test.t3' create table t2(a int,unique key (a)) engine=innodb; create table t3(b int) engine=innodb; create table t1(c int,b int)engine=innodb; diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index 6d4a0284e5a..9cbfa5d0fe5 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -2762,3 +2762,34 @@ WHERE t3.pk IN (2); drop view v4; drop table t1,t2,t3,t4; SET optimizer_switch=@org_optimizer_switch; +# +# MDEV-22866: Crash in join optimizer with constant outer join nest +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c INT, KEY(c)) ENGINE=MyISAM; +CREATE TABLE t4 (d INT, KEY(d)) ENGINE=MyISAM; +INSERT INTO t4 VALUES (5),(6); +CREATE TABLE t5 (e INT) ENGINE=MyISAM; +INSERT INTO t5 VALUES (7),(8); +CREATE TABLE t6 (f INT) ENGINE=MyISAM; +INSERT INTO t6 VALUES (9),(10); +SELECT * +FROM +t1 +LEFT JOIN ( +t2 LEFT JOIN ( +t3 JOIN +t4 ON t3.c = t4.d and t3.c >2 and t3.c<0 +) ON t2.b >= t4.d +) ON t1.a <= t2.b +LEFT JOIN t5 ON t2.b = t5.e +LEFT JOIN t6 ON t3.c = t6.f; +a b c d e f +1 3 NULL NULL NULL NULL +2 3 NULL NULL NULL NULL +1 4 NULL NULL NULL NULL +2 4 NULL NULL NULL NULL +drop table t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/main/kill-2.test b/mysql-test/main/kill-2.test index 0c1177722b4..3412e75b8d5 100644 --- a/mysql-test/main/kill-2.test +++ b/mysql-test/main/kill-2.test @@ -8,7 +8,6 @@ # -- source include/not_embedded.inc --- source include/not_threadpool.inc --echo # --echo # MDEV-6896 kill user command cause MariaDB crash! diff --git a/mysql-test/main/kill.test b/mysql-test/main/kill.test index 45d672aebc1..728b6b964e2 100644 --- a/mysql-test/main/kill.test +++ b/mysql-test/main/kill.test @@ -9,7 +9,6 @@ -- source include/not_embedded.inc -- source include/have_debug_sync.inc --- source include/not_threadpool.inc set local sql_mode=""; set global sql_mode=""; diff --git a/mysql-test/main/lock.result b/mysql-test/main/lock.result index 6edb86bfa3f..e76c04520eb 100644 --- a/mysql-test/main/lock.result +++ b/mysql-test/main/lock.result @@ -506,3 +506,17 @@ disconnect con1; connection default; UNLOCK TABLES; DROP TABLE t1, t2; +# +# MDEV-21398 Deadlock (server hang) or assertion failure in +# Diagnostics_area::set_error_status upon ALTER under lock +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +LOCK TABLE t1 WRITE, t1 AS t1a READ; +ALTER TABLE t1 CHANGE COLUMN IF EXISTS x xx INT; +Warnings: +Note 1054 Unknown column 'x' in 't1' +UNLOCK TABLES; +DROP TABLE t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/main/lock.test b/mysql-test/main/lock.test index 8a59f4082b1..32e4fd47664 100644 --- a/mysql-test/main/lock.test +++ b/mysql-test/main/lock.test @@ -619,3 +619,17 @@ UNLOCK TABLES; UNLOCK TABLES; DROP TABLE t1, t2; +--echo # +--echo # MDEV-21398 Deadlock (server hang) or assertion failure in +--echo # Diagnostics_area::set_error_status upon ALTER under lock +--echo # + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +LOCK TABLE t1 WRITE, t1 AS t1a READ; +ALTER TABLE t1 CHANGE COLUMN IF EXISTS x xx INT; +UNLOCK TABLES; +DROP TABLE t1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index 43f44c90b06..90c97f629fb 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -259,6 +259,12 @@ Warning 1286 Unknown storage engine 'NonExistentEngine' alter table mysql.slow_log engine=memory; ERROR HY000: Storage engine MEMORY cannot be used for log tables set default_storage_engine= @save_storage_engine; +ALTER TABLE mysql.general_log ENGINE=Aria; +ERROR HY000: Storage engine Aria cannot be used for log tables +ALTER TABLE mysql.general_log ENGINE=Aria transactional = 0; +ALTER TABLE mysql.slow_log ENGINE=Aria; +ERROR HY000: Storage engine Aria cannot be used for log tables +ALTER TABLE mysql.slow_log ENGINE=Aria transactional = 0; drop table mysql.slow_log; drop table mysql.general_log; drop table mysql.general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index 4622b09079f..ff2a46b1917 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -269,6 +269,14 @@ alter table mysql.slow_log engine=memory; #alter table mysql.slow_log engine=blackhole; set default_storage_engine= @save_storage_engine; +# Make sure only non-transactional Aria table can be used for logging +--error ER_UNSUPORTED_LOG_ENGINE +ALTER TABLE mysql.general_log ENGINE=Aria; +ALTER TABLE mysql.general_log ENGINE=Aria transactional = 0; +--error ER_UNSUPORTED_LOG_ENGINE +ALTER TABLE mysql.slow_log ENGINE=Aria; +ALTER TABLE mysql.slow_log ENGINE=Aria transactional = 0; + drop table mysql.slow_log; drop table mysql.general_log; diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 2b9ec4731de..734de15c078 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -271,6 +271,24 @@ ERROR 42000: Specified key was too long; max key length is 2000 bytes create table t1(a int, unique(a) using hash); #BULK insert > 100 rows (MI_MIN_ROWS_TO_DISABLE_INDEXES) drop table t1; +SET binlog_row_image= NOBLOB; +CREATE TABLE t1 (pk INT PRIMARY KEY, a text ,UNIQUE(a) using hash); +INSERT INTO t1 VALUES (1,'foo'); +create table t2(id int primary key, a blob, b varchar(20) as (LEFT(a,2))); +INSERT INTO t2 VALUES (1, 'foo', default); +DROP TABLE t1, t2; +SET binlog_row_image= FULL; +CREATE TABLE t1 (a int, b VARCHAR(1000), UNIQUE (a,b)) ENGINE=MyISAM; +show index from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 0 a 1 a A NULL NULL NULL YES HASH +t1 0 a 2 b A NULL NULL NULL YES HASH +CREATE TABLE t2 (a varchar(900), b VARCHAR(900), UNIQUE (a,b)) ENGINE=MyISAM; +show index from t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t2 0 a 1 a A NULL NULL NULL YES HASH +t2 0 a 2 b A NULL NULL NULL YES HASH +DROP TABLE t1,t2; create temporary table tmp ( a int, b int, c blob not null, d int, e int default 0, f int, unique key (c)) engine=innodb; create table t2 (x int); lock table t2 write; @@ -341,3 +359,4 @@ create table t1 (a int, b int, unique (b) using hash) engine=innodb partition by insert into t1 values (1,10),(2,20); update t1 set b = 30 limit 1; drop table t1; +# End of 10.5 tests diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 5c6763a5f15..3e0e35e6162 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -342,6 +342,34 @@ while ($count) --enable_query_log drop table t1; +# +# MDEV-21804 Assertion `marked_for_read()' failed upon INSERT into table with long unique blob under binlog_row_image=NOBLOB +# + +--source include/have_binlog_format_row.inc +SET binlog_row_image= NOBLOB; +CREATE TABLE t1 (pk INT PRIMARY KEY, a text ,UNIQUE(a) using hash); +INSERT INTO t1 VALUES (1,'foo'); + +create table t2(id int primary key, a blob, b varchar(20) as (LEFT(a,2))); +INSERT INTO t2 VALUES (1, 'foo', default); + +# Cleanup +DROP TABLE t1, t2; +SET binlog_row_image= FULL; + +# +# MDEV-22719 Long unique keys are not created when individual key_part->length < max_key_length but SUM(key_parts->length) > max_key_length +# + +CREATE TABLE t1 (a int, b VARCHAR(1000), UNIQUE (a,b)) ENGINE=MyISAM; +show index from t1; +CREATE TABLE t2 (a varchar(900), b VARCHAR(900), UNIQUE (a,b)) ENGINE=MyISAM; +show index from t2; + +# Cleanup +DROP TABLE t1,t2; + # # MDEV-22113 SIGSEGV, ASAN use-after-poison, Assertion `next_insert_id == 0' in handler::ha_external_lock # @@ -410,3 +438,5 @@ create table t1 (a int, b int, unique (b) using hash) engine=innodb partition by insert into t1 values (1,10),(2,20); update t1 set b = 30 limit 1; drop table t1; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/long_unique_bugs_replication.result b/mysql-test/main/long_unique_bugs_replication.result new file mode 100644 index 00000000000..af583d00cea --- /dev/null +++ b/mysql-test/main/long_unique_bugs_replication.result @@ -0,0 +1,12 @@ +include/master-slave.inc +[connection master] +create table t1 (i1 int, a1 text, unique key i1 (a1)) engine=myisam; +insert into t1 values (1,1); +insert into t1 values (2,2); +update t1 set a1 = 'd' limit 1; +update t1 set a1 = 'd2' where i1= 2; +connection slave; +connection slave; +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/main/long_unique_bugs_replication.test b/mysql-test/main/long_unique_bugs_replication.test new file mode 100644 index 00000000000..1cacd088bee --- /dev/null +++ b/mysql-test/main/long_unique_bugs_replication.test @@ -0,0 +1,24 @@ +# +# Long unique bugs related to master slave replication +# + +# +# MDEV-22722 Assertion "inited==NONE" failed in handler::ha_index_init on the slave during UPDATE +# + +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +create table t1 (i1 int, a1 text, unique key i1 (a1)) engine=myisam; +insert into t1 values (1,1); +insert into t1 values (2,2); +update t1 set a1 = 'd' limit 1; +update t1 set a1 = 'd2' where i1= 2; + +sync_slave_with_master; +connection slave; + +connection master; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/main/mdev_22370.result b/mysql-test/main/mdev_22370.result new file mode 100644 index 00000000000..c1cb60aa106 --- /dev/null +++ b/mysql-test/main/mdev_22370.result @@ -0,0 +1,5 @@ +connect con1,localhost,root,,; +SET DEBUG_DBUG='+d,mark_busy_mdev_22370'; +FLUSH TABLES WITH READ LOCK; +connection default; +# restart diff --git a/mysql-test/main/mdev_22370.test b/mysql-test/main/mdev_22370.test new file mode 100644 index 00000000000..86bc527ebc0 --- /dev/null +++ b/mysql-test/main/mdev_22370.test @@ -0,0 +1,17 @@ +# +# MDEV-22370 safe_mutex: Trying to lock uninitialized mutex at +# /data/src/10.4-bug/sql/rpl_parallel.cc, line 470 upon shutdown during FTWRL +# +# Purpose of this test case to test crash while FTWRL and shutdown is in race +# condition +# Shutdown can execute first and destroy the mutex making mutex_lock in pool_mark_busy +# to crash + +--source include/have_debug.inc +--connect (con1,localhost,root,,) +SET DEBUG_DBUG='+d,mark_busy_mdev_22370'; +--send + FLUSH TABLES WITH READ LOCK; + +--connection default +--source include/restart_mysqld.inc diff --git a/mysql-test/main/myisampack.result b/mysql-test/main/myisampack.result index 13321695360..61ad21a6c9f 100644 --- a/mysql-test/main/myisampack.result +++ b/mysql-test/main/myisampack.result @@ -1,6 +1,6 @@ DROP TABLE IF EXISTS t1,t2,t3; CREATE TABLE t1(c1 DOUBLE, c2 DOUBLE, c3 DOUBLE, c4 DOUBLE, c5 DOUBLE, -c6 DOUBLE, c7 DOUBLE, c8 DOUBLE, c9 DOUBLE, a INT PRIMARY KEY); +c6 DOUBLE, c7 DOUBLE, c8 DOUBLE, c9 DOUBLE, a INT PRIMARY KEY) checksum=1; INSERT INTO t1 VALUES (-3.31168791059336e-06,-3.19054655887874e-06,-1.06528081684847e-05,-1.227278240089e-06,-1.66718069164799e-06,-2.59038972510885e-06,-2.83145227805303e-06,-4.09678491270648e-07,-2.22610091291797e-06,6), (0.0030743000272545,2.53222044316438e-05,2.78674650061845e-05,1.95914465544536e-05,1.7347572525984e-05,1.87513810069614e-05,1.69882826885005e-05,2.44449336987598e-05,1.89914629921774e-05,9), diff --git a/mysql-test/main/myisampack.test b/mysql-test/main/myisampack.test index 1f97a28e6fd..a63f0bcd484 100644 --- a/mysql-test/main/myisampack.test +++ b/mysql-test/main/myisampack.test @@ -5,7 +5,7 @@ DROP TABLE IF EXISTS t1,t2,t3; # BUG#31277 - myisamchk --unpack corrupts a table # CREATE TABLE t1(c1 DOUBLE, c2 DOUBLE, c3 DOUBLE, c4 DOUBLE, c5 DOUBLE, - c6 DOUBLE, c7 DOUBLE, c8 DOUBLE, c9 DOUBLE, a INT PRIMARY KEY); + c6 DOUBLE, c7 DOUBLE, c8 DOUBLE, c9 DOUBLE, a INT PRIMARY KEY) checksum=1; INSERT INTO t1 VALUES (-3.31168791059336e-06,-3.19054655887874e-06,-1.06528081684847e-05,-1.227278240089e-06,-1.66718069164799e-06,-2.59038972510885e-06,-2.83145227805303e-06,-4.09678491270648e-07,-2.22610091291797e-06,6), (0.0030743000272545,2.53222044316438e-05,2.78674650061845e-05,1.95914465544536e-05,1.7347572525984e-05,1.87513810069614e-05,1.69882826885005e-05,2.44449336987598e-05,1.89914629921774e-05,9), diff --git a/mysql-test/main/mysql_install_db_win.result b/mysql-test/main/mysql_install_db_win.result index 6ee417f1a7d..ca263935788 100644 --- a/mysql-test/main/mysql_install_db_win.result +++ b/mysql-test/main/mysql_install_db_win.result @@ -11,6 +11,8 @@ SELECT @@datadir; @@datadir DATADIR/ # Kill the server +1 +FOUND 1 /is not empty. Only new or empty existing directories are accepted for --datadir/ in install.log connection default; [mysqld] long_query_time=15.000000 diff --git a/mysql-test/main/mysql_install_db_win.test b/mysql-test/main/mysql_install_db_win.test index f9019a8e542..dd93e7cb27d 100644 --- a/mysql-test/main/mysql_install_db_win.test +++ b/mysql-test/main/mysql_install_db_win.test @@ -18,6 +18,30 @@ SELECT @@datadir; # restart in the original datadir again --source include/kill_mysqld.inc rmdir $ddir; + +# MDEV-23052 +# 1. mysql_install_db works on existing, empty directory +mkdir $ddir; +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R > /dev/null; +rmdir $ddir; + +# 2. mysql_install_db rejects existing, non-empty directory, and does not +# remove it. +mkdir $ddir; +write_file $ddir/1; +EOF + +error 1; +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R > $MYSQLTEST_VARDIR/tmp/install.log 2>&1; +list_files $ddir; +let $log=$MYSQLTEST_VARDIR/tmp/install.log; +let SEARCH_FILE=$log; +let SEARCH_PATTERN=is not empty. Only new or empty existing directories are accepted for --datadir; +--source include/search_pattern_in_file.inc +remove_file $log; + +rmdir $ddir; + let $restart_parameters=; connection default; diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 7be0be6ccc3..f6b9770a190 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -643,3 +643,62 @@ count(*) drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; # End of 10.4 tests +# +# Check that mysql_upgrade can be run on mysqldump +# of mysql schema from previous versions +# +call mtr.add_suppression("innodb_table_stats has length mismatch in the column name table_name"); +# +# Upgrade from version 5.5 +# +# Loading dump of 5.5 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 +# +# Upgrade from version 10.0 +# +# Loading dump of 10.0 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 +# +# Upgrade from version 10.1 +# +# Loading dump of 10.1 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 +# +# Upgrade from version 10.2 +# +# Loading dump of 10.2 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 +# +# Upgrade from version 10.3 +# +# Loading dump of 10.3 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 +# +# Upgrade from version 10.4 +# +# Loading dump of 10.4 mysql schema +# Running mysql_upgrade +# Checking that mysql.user is accessible and returns some data +SELECT COUNT(*) > 0 AS `mysql.user has data` FROM mysql.user; +mysql.user has data +1 diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index 0dad53f8881..5c07d3858d3 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -296,3 +296,32 @@ drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; --echo # End of 10.4 tests + +# +# MDEV-22249 Upgrade testing between major versions in MTR +# +--echo # +--echo # Check that mysql_upgrade can be run on mysqldump +--echo # of mysql schema from previous versions +--echo # + +# The warning appears during mysql_upgrade, before the schema becomes consistent +call mtr.add_suppression("innodb_table_stats has length mismatch in the column name table_name"); + +--let $old_version= 5.5 +--source include/load_dump_and_upgrade.inc + +--let $old_version= 10.0 +--source include/load_dump_and_upgrade.inc + +--let $old_version= 10.1 +--source include/load_dump_and_upgrade.inc + +--let $old_version= 10.2 +--source include/load_dump_and_upgrade.inc + +--let $old_version= 10.3 +--source include/load_dump_and_upgrade.inc + +--let $old_version= 10.4 +--source include/load_dump_and_upgrade.inc diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 7cbcdbad2b2..e9ea7e13c99 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1151,8 +1151,6 @@ The following specify which files/extra groups are read (specified before remain characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). - --session-track-user-variables - Track changes to user variables. --show-slave-auth-info Show user and password in SHOW SLAVE HOSTS on this master. @@ -1758,7 +1756,6 @@ session-track-schema TRUE session-track-state-change FALSE session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone session-track-transaction-info OFF -session-track-user-variables FALSE show-slave-auth-info FALSE silent-startup FALSE skip-grant-tables TRUE diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index bacf205d72c..3b7d95f80e9 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -3759,7 +3759,7 @@ DROP TABLE t1; # CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); -mysqldump: Input filename too long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... +mysqldump: Input filename too long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DROP TABLE t1; CREATE TABLE t2 (a INT) ENGINE=MyISAM; CREATE TABLE t3 (a INT) ENGINE=MyISAM; diff --git a/mysql-test/main/mysqlshow.test b/mysql-test/main/mysqlshow.test index 8c60b64a5f1..7201579452e 100644 --- a/mysql-test/main/mysqlshow.test +++ b/mysql-test/main/mysqlshow.test @@ -1,7 +1,5 @@ # Can't run test of external client with embedded server -- source include/not_embedded.inc -# Don't test when thread_pool active ---source include/not_threadpool.inc --disable_warnings DROP TABLE IF EXISTS t1,t2,test1,test2; diff --git a/mysql-test/main/mysqltest_tracking_info.result b/mysql-test/main/mysqltest_tracking_info.result index 3a4419d8651..e044b4a070d 100644 --- a/mysql-test/main/mysqltest_tracking_info.result +++ b/mysql-test/main/mysqltest_tracking_info.result @@ -48,20 +48,4 @@ SET @@session.session_track_system_variables= @save_session_track_system_variabl # # MDEV-16470 - Session user variables tracker # -SET @@session.session_track_user_variables=1; -SET @a=1; -SET @b=NULL; -SELECT @c:=10; -@c:=10 -10 -SET @@session.session_track_user_variables=0; -# -# mdev-22337 Assertion `Alloced_length >= (str_length + length + -net_length_size(length))' failed in Binary_string::q_net_store_data -on long MULTIPOLYGON query with session_track_user_variables=1 -(optimized builds) -# -set @@session.session_track_user_variables=1; -set @a=repeat('X', 1029); -set @@session.session_track_user_variables=0; # End of 10.5 tests diff --git a/mysql-test/main/mysqltest_tracking_info.test b/mysql-test/main/mysqltest_tracking_info.test index c4dfce57fb0..0478ea560d5 100644 --- a/mysql-test/main/mysqltest_tracking_info.test +++ b/mysql-test/main/mysqltest_tracking_info.test @@ -49,24 +49,24 @@ SET @@session.session_track_system_variables= @save_session_track_system_variabl --echo # --echo # MDEV-16470 - Session user variables tracker --echo # -SET @@session.session_track_user_variables=1; ---enable_session_track_info -SET @a=1; -SET @b=NULL; -SELECT @c:=10; ---disable_session_track_info -SET @@session.session_track_user_variables=0; +#SET @@session.session_track_user_variables=1; +#--enable_session_track_info +#SET @a=1; +#SET @b=NULL; +#SELECT @c:=10; +#--disable_session_track_info +#SET @@session.session_track_user_variables=0; ---echo # ---echo # mdev-22337 Assertion `Alloced_length >= (str_length + length + ---echo net_length_size(length))' failed in Binary_string::q_net_store_data ---echo on long MULTIPOLYGON query with session_track_user_variables=1 ---echo (optimized builds) ---echo # -set @@session.session_track_user_variables=1; ---enable_session_track_info -set @a=repeat('X', 1029); ---disable_session_track_info -set @@session.session_track_user_variables=0; +#--echo # +#--echo # mdev-22337 Assertion `Alloced_length >= (str_length + length + +#--echo net_length_size(length))' failed in Binary_string::q_net_store_data +#--echo on long MULTIPOLYGON query with session_track_user_variables=1 +#--echo (optimized builds) +#--echo # +#set @@session.session_track_user_variables=1; +#--enable_session_track_info +#set @a=repeat('X', 1029); +#--disable_session_track_info +#set @@session.session_track_user_variables=0; --echo # End of 10.5 tests diff --git a/mysql-test/main/named_pipe.test b/mysql-test/main/named_pipe.test index 8503907b808..8e0136d06a9 100644 --- a/mysql-test/main/named_pipe.test +++ b/mysql-test/main/named_pipe.test @@ -5,9 +5,6 @@ # Named pipe does not support the non-blocking API. --disable_non_blocking_api -# thread pool causes different results --- source include/not_threadpool.inc - # Only run this test if named pipe is avaliable let $nmp= query_get_value("SHOW VARIABLES LIKE 'named_pipe'", Value, 1); if ($nmp != ON){ diff --git a/mysql-test/main/nested_profiling.result b/mysql-test/main/nested_profiling.result new file mode 100644 index 00000000000..b8bceba480a --- /dev/null +++ b/mysql-test/main/nested_profiling.result @@ -0,0 +1,20 @@ +SET @saved_profiling=@@GLOBAL.profiling; +SET @saved_init_connect=@@GLOBAL.init_connect; +SET GLOBAL init_connect="set @a=2;set @b=3"; +SET GLOBAL profiling=on; +create user mysqltest1@localhost; +connect con1,localhost,mysqltest1,,; +connection con1; +SELECT @a, @b; +@a @b +2 3 +SHOW PROFILES; +Query_ID Duration Query +1 # set @a=2;set @b=3 +2 # set @b=3 +3 # SELECT @a, @b +connection default; +disconnect con1; +DROP USER mysqltest1@localhost; +SET GLOBAL profiling=@saved_profiling; +SET GLOBAL init_connect=@saved_init_connect; diff --git a/mysql-test/main/nested_profiling.test b/mysql-test/main/nested_profiling.test new file mode 100644 index 00000000000..ba89aefc647 --- /dev/null +++ b/mysql-test/main/nested_profiling.test @@ -0,0 +1,42 @@ +# ==== Purpose ==== +# +# Test verifies that "init_connect" and "init_slave" system variables work +# fine when "profiling=on". +# +# ==== Implementation ==== +# +# Steps: +# 0 - Create regular user without super privilege so that "init_connect" +# variable is effective. +# 1 - Enable profiling. +# 2 - Start a new connection which will try to execute the statements +# specified in "init_connect". No assert should be reported. +# 3 - Execute SHOW PROFILES to verify that statements specified in +# "init_connect" are displayed as part of profiling. +# +# ==== References ==== +# +# MDEV-22706: Assertion `!current' failed in PROFILING::start_new_query +# +--source include/not_embedded.inc +--source include/have_profiling.inc + +SET @saved_profiling=@@GLOBAL.profiling; +SET @saved_init_connect=@@GLOBAL.init_connect; +SET GLOBAL init_connect="set @a=2;set @b=3"; +SET GLOBAL profiling=on; + +create user mysqltest1@localhost; +connect (con1,localhost,mysqltest1,,); +connection con1; +SELECT @a, @b; +--replace_column 2 # +SHOW PROFILES; + +#========== Clean up =========== +connection default; +disconnect con1; +DROP USER mysqltest1@localhost; + +SET GLOBAL profiling=@saved_profiling; +SET GLOBAL init_connect=@saved_init_connect; diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 2e4cfb9acb7..b0b6120e271 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -108,6 +108,7 @@ select * from v1 { "selectivity_for_columns": [ { "column_name": "a", + "ranges": ["1 <= a <= 1"], "selectivity_from_histogram": 0.5 } ], @@ -253,6 +254,7 @@ select * from (select * from t1 where t1.a=1)q { "selectivity_for_columns": [ { "column_name": "a", + "ranges": ["1 <= a <= 1"], "selectivity_from_histogram": 0.5 } ], @@ -403,6 +405,7 @@ select * from v2 { "selectivity_for_columns": [ { "column_name": "a", + "ranges": ["1 <= a <= 1"], "selectivity_from_histogram": 0.5 } ], @@ -441,6 +444,7 @@ select * from v2 { }, "rows_for_plan": 1, "cost_for_plan": 2.404394531, + "cost_for_sorting": 1, "estimated_join_cardinality": 1 } ] @@ -765,6 +769,7 @@ explain select * from v1 { }, "rows_for_plan": 10, "cost_for_plan": 4.021972656, + "cost_for_sorting": 10, "estimated_join_cardinality": 10 } ] @@ -1452,6 +1457,7 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a { }, "rows_for_plan": 8, "cost_for_plan": 3.8, + "cost_for_sorting": 8, "estimated_join_cardinality": 8 } ] @@ -1645,6 +1651,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { }, "rows_for_plan": 9, "cost_for_plan": 4.15, + "cost_for_sorting": 9, "estimated_join_cardinality": 9 } ] @@ -1827,6 +1834,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { }, "rows_for_plan": 9, "cost_for_plan": 4.15, + "cost_for_sorting": 9, "estimated_join_cardinality": 9 } ] @@ -2054,10 +2062,12 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 { "selectivity_for_columns": [ { "column_name": "a", + "ranges": ["1 <= a <= 1"], "selectivity_from_histogram": 0.1796875 }, { "column_name": "b", + "ranges": ["2 <= b <= 2"], "selectivity_from_histogram": 0.015625 } ], @@ -3272,10 +3282,12 @@ explain select * from t1 where pk = 2 and a=5 and b=1 { "selectivity_for_columns": [ { "column_name": "a", + "ranges": ["5 <= a <= 5"], "selectivity_from_histogram": 0.1 }, { "column_name": "b", + "ranges": ["1 <= b <= 1"], "selectivity_from_histogram": 0.1 } ], @@ -8258,6 +8270,290 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) ] ] drop table t1; +# +# MDEV-21626: Optimizer misses the details about the picked join order +# +CREATE TABLE t1(a INT, b INT, key(a)); +INSERT INTO t1 SELECT seq, seq from seq_1_to_10; +CREATE TABLE t2(a INT, b INT, key(a)); +INSERT INTO t2 SELECT seq, seq from seq_1_to_100; +SET OPTIMIZER_TRACE=1; +EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a ORDER BY t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 10 Using where; Using temporary; Using filesort +1 SIMPLE t2 ref a a 5 test.t1.a 1 +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) +[ + + [ + + { + "plan_prefix": + [ + ], + "table": "t1", + "best_access_path": + { + "considered_access_paths": + [ + + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.021972656, + "chosen": true + } + ], + "chosen_access_method": + { + "type": "scan", + "records": 10, + "cost": 2.021972656, + "uses_join_buffering": false + } + }, + "rows_for_plan": 10, + "cost_for_plan": 4.021972656, + "rest_of_plan": + [ + + { + "plan_prefix": + [ + "t1" + ], + "table": "t2", + "best_access_path": + { + "considered_access_paths": + [ + + { + "access_type": "ref", + "index": "a", + "used_range_estimates": false, + "cause": "not available", + "rows": 1, + "cost": 20.00585794, + "chosen": true + }, + + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.219726562, + "chosen": false + } + ], + "chosen_access_method": + { + "type": "ref", + "records": 1, + "cost": 20.00585794, + "uses_join_buffering": false + } + }, + "rows_for_plan": 10, + "cost_for_plan": 26.0278306, + "cost_for_sorting": 10, + "estimated_join_cardinality": 10 + } + ] + }, + + { + "plan_prefix": + [ + ], + "table": "t2", + "best_access_path": + { + "considered_access_paths": + [ + + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.219726562, + "chosen": true, + "use_tmp_table": true + } + ], + "chosen_access_method": + { + "type": "scan", + "records": 100, + "cost": 2.219726562, + "uses_join_buffering": false + } + }, + "rows_for_plan": 100, + "cost_for_plan": 22.21972656, + "rest_of_plan": + [ + + { + "plan_prefix": + [ + "t2" + ], + "table": "t1", + "best_access_path": + { + "considered_access_paths": + [ + + { + "access_type": "ref", + "index": "a", + "used_range_estimates": false, + "cause": "not available", + "rows": 1, + "cost": 200.0585794, + "chosen": true + }, + + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.021972656, + "chosen": true + } + ], + "chosen_access_method": + { + "type": "scan", + "records": 10, + "cost": 2.021972656, + "uses_join_buffering": true + } + }, + "rows_for_plan": 1000, + "cost_for_plan": 224.2416992, + "pruned_by_cost": true + } + ] + } + ] +] +DROP TABLE t1,t2; +# +# MDEV-22665: Print ranges in the optimizer trace created for non-indexed columns when +# optimizer_use_condition_selectivity >2 +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +SET optimizer_trace=1; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +EXPLAIN EXTENDED SELECT * from t1 WHERE a between 1 and 5 and b <= 5; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 0.22 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` between 1 and 5 and `test`.`t1`.`b` <= 5 +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) +[ + + [ + + { + "column_name": "a", + "ranges": + [ + "1 <= a <= 5" + ], + "selectivity_from_histogram": 0.046875 + }, + + { + "column_name": "b", + "ranges": + [ + "NULL < b <= 5" + ], + "selectivity_from_histogram": 0.046875 + } + ] +] +EXPLAIN EXTENDED SELECT * from t1 WHERE a != 5; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` <> 5 +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) +[ + + [ + + { + "column_name": "a", + "ranges": + [ + "NULL < a < 5", + "5 < a" + ], + "selectivity_from_histogram": 1 + } + ] +] +EXPLAIN EXTENDED SELECT * from t1 WHERE b >= 10 and b < 25; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 15.62 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` >= 10 and `test`.`t1`.`b` < 25 +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) +[ + + [ + + { + "column_name": "b", + "ranges": + [ + "10 <= b < 25" + ], + "selectivity_from_histogram": 0.15625 + } + ] +] +drop table t1; +# +# MDEV-22910:SIGSEGV in Opt_trace_context::is_started & SIGSEGV in Json_writer::add_table_name +# (on optimized builds) +# +CREATE TABLE t1( a INT, b INT, PRIMARY KEY( a ) ); +SELECT sum(b), row_number() OVER (order by b) FROM t1 WHERE a = 101; +sum(b) row_number() OVER (order by b) +NULL 1 +UPDATE t1 SET b=10 WHERE a=1; +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) +[ + + [ + + { + "index": "PRIMARY", + "ranges": + [ + "(1) <= (a) <= (1)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 0, + "cost": 0.145, + "chosen": true + } + ] +] +DROP TABLE t1; # End of 10.4 tests # # Test many rows to see output of big cost numbers @@ -8357,5 +8653,36 @@ select count(*) from seq_1_to_10000000 { } ] } 0 0 +# +# MDEV-22891: Optimizer trace: const tables are not clearly visible +# +create table t0(a int primary key); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (pk int primary key, a int); +insert into t1 select a,a from t0; +create table t2 (pk int primary key, a int); +insert into t2 select a,a from t0; +create table t3 (pk int primary key, a int); +insert into t3 select a,a from t0; +explain +select * from t1 left join (t2 join t3 on t3.pk=1000) on t2.a=t1.a and t2.pk is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 const PRIMARY NULL NULL NULL 1 Impossible ON condition +1 SIMPLE t2 const PRIMARY NULL NULL NULL 1 Impossible ON condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.mark_join_nest_as_const')) +from information_schema.optimizer_trace; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.mark_join_nest_as_const')) +[ + + { + "members": + [ + "t3", + "t2" + ] + } +] +drop table t0, t1, t2, t3; # End of 10.5 tests set optimizer_trace='enabled=off'; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 2839dbad9e6..d6030543313 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -580,8 +580,49 @@ select * from t1 force index(kp1) where (kp1=2 and kp2 >=4); select JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; drop table t1; ---echo # End of 10.4 tests +--echo # +--echo # MDEV-21626: Optimizer misses the details about the picked join order +--echo # +CREATE TABLE t1(a INT, b INT, key(a)); +INSERT INTO t1 SELECT seq, seq from seq_1_to_10; +CREATE TABLE t2(a INT, b INT, key(a)); +INSERT INTO t2 SELECT seq, seq from seq_1_to_100; + +SET OPTIMIZER_TRACE=1; +EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a ORDER BY t2.b; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +DROP TABLE t1,t2; + +--echo # +--echo # MDEV-22665: Print ranges in the optimizer trace created for non-indexed columns when +--echo # optimizer_use_condition_selectivity >2 +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +SET optimizer_trace=1; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +EXPLAIN EXTENDED SELECT * from t1 WHERE a between 1 and 5 and b <= 5; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +EXPLAIN EXTENDED SELECT * from t1 WHERE a != 5; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +EXPLAIN EXTENDED SELECT * from t1 WHERE b >= 10 and b < 25; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; + +--echo # +--echo # MDEV-22910:SIGSEGV in Opt_trace_context::is_started & SIGSEGV in Json_writer::add_table_name +--echo # (on optimized builds) +--echo # + +CREATE TABLE t1( a INT, b INT, PRIMARY KEY( a ) ); +SELECT sum(b), row_number() OVER (order by b) FROM t1 WHERE a = 101; +UPDATE t1 SET b=10 WHERE a=1; +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +DROP TABLE t1; + +--echo # End of 10.4 tests --echo # --echo # Test many rows to see output of big cost numbers @@ -590,5 +631,28 @@ drop table t1; select count(*) from seq_1_to_10000000; select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +--echo # +--echo # MDEV-22891: Optimizer trace: const tables are not clearly visible +--echo # +create table t0(a int primary key); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 (pk int primary key, a int); +insert into t1 select a,a from t0; + +create table t2 (pk int primary key, a int); +insert into t2 select a,a from t0; + +create table t3 (pk int primary key, a int); +insert into t3 select a,a from t0; + +explain +select * from t1 left join (t2 join t3 on t3.pk=1000) on t2.a=t1.a and t2.pk is null; + +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.mark_join_nest_as_const')) +from information_schema.optimizer_trace; + +drop table t0, t1, t2, t3; + --echo # End of 10.5 tests set optimizer_trace='enabled=off'; diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index 120a318a683..26e42e4d6f9 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3312,6 +3312,71 @@ p 16 set @@sort_buffer_size= @save_sort_buffer_size; drop table t1; # +# MDEV-22715: SIGSEGV in radixsort_for_str_ptr and in native_compare/my_qsort2 (optimized builds) +# +SET @save_sort_buffer_size= @@sort_buffer_size; +SET @save_max_sort_length= @@max_sort_length; +SET max_sort_length=8; +SET sort_buffer_size=1024; +CREATE TABLE t1(a INT, b DECIMAL(65), c BLOB); +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_25; +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_25; +SELECT * FROM t1 ORDER BY a,b; +a b c +1 1 1 +1 1 1 +2 2 2 +2 2 2 +3 3 3 +3 3 3 +4 4 4 +4 4 4 +5 5 5 +5 5 5 +6 6 6 +6 6 6 +7 7 7 +7 7 7 +8 8 8 +8 8 8 +9 9 9 +9 9 9 +10 10 10 +10 10 10 +11 11 11 +11 11 11 +12 12 12 +12 12 12 +13 13 13 +13 13 13 +14 14 14 +14 14 14 +15 15 15 +15 15 15 +16 16 16 +16 16 16 +17 17 17 +17 17 17 +18 18 18 +18 18 18 +19 19 19 +19 19 19 +20 20 20 +20 20 20 +21 21 21 +21 21 21 +22 22 22 +22 22 22 +23 23 23 +23 23 23 +24 24 24 +24 24 24 +25 25 25 +25 25 25 +SET @@sort_buffer_size= @save_sort_buffer_size; +SET @@max_sort_length= @save_max_sort_length; +DROP TABLE t1; +# # MDEV-13994: Bad join results with orderby_uses_equalities=on # CREATE TABLE books ( @@ -3372,6 +3437,7 @@ NULLIF(GROUP_CONCAT(v1), null) C B DROP TABLE t1; +# End of 10.2 tests # # MDEV-16214: Incorrect plan taken by the optimizer , uses INDEX instead of ref access with ORDER BY # @@ -3429,6 +3495,7 @@ LIMIT 1) 908-8-123456 909-9-123456 drop table t1,t2; +# End of 10.3 tests # # MDEV-17761: Odd optimizer choice with ORDER BY LIMIT and condition selectivity # @@ -3466,6 +3533,7 @@ Note 1003 select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` A set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u, optimizer_use_condition_selectivity=@tmp_o; drop table t1,t2,t3,t4; +# End of 10.4 tests # # MDEV-21655: Server crashes in my_qsort2 / Filesort_buffer::sort_buffer # @@ -3751,6 +3819,8 @@ efg 5 5 fgh 6 6 set @save_max_sort_length= @@max_sort_length; set max_sort_length=5; +Warnings: +Warning 1292 Truncated incorrect max_sort_length value: '5' # # should show sortkey in r_sort_mode as the collation is complex and # truncation is not possible @@ -3866,3 +3936,91 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd NULL DROP TABLE t1; +# +# MDEV-22303: Incorrect ordering with REGEXP_REPLACE and OFFSET/LIMIT +# +CREATE TABLE t1 (name VARCHAR(20) CHARACTER SET utf8 NOT NULL); +INSERT INTO t1 (name) VALUES ('Charles Dickens'), ('Roald Dahl'); +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC; +name surname_first +Roald Dahl Dahl, Roald +Charles Dickens Dickens, Charles +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC LIMIT 1; +name surname_first +Roald Dahl Dahl, Roald +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC LIMIT 1 OFFSET 1; +name surname_first +Charles Dickens Dickens, Charles +DROP TABLE t1; +# +# MDEV-22836: Server crashes in err_conv / ErrBuff::set_str +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0),(1); +SELECT * FROM t1 ORDER BY CONVERT(AES_ENCRYPT(1,a), CHAR(4)); +a +1 +0 +DROP TABLE t1; +# +# MDEV-22819:Wrong result or Assertion `ix > 0' failed in read_to_buffer upon select +# with GROUP BY and GROUP_CONCAT +# +CREATE TABLE t1 (a VARCHAR(1000), b CHAR(1)); +INSERT INTO t1 VALUES +(REPEAT('a',1000),'a'),(REPEAT('t',932),'t'),('x',NULL),('x',NULL), +(REPEAT('z',298),'z'),(REPEAT('p',1000),'p'),(REPEAT('k',468),'k'), +(REPEAT('c',1000),'c'),(REPEAT('o',648),'o'),('x',NULL),('x',NULL), +(REPEAT('c',258),'c'),(REPEAT('t',414),'t'),(REPEAT('f',966),'f'), +(REPEAT('y',746),'y'),(REPEAT('f',1000),'f'); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +SET @save_sort_buffer_size= @@sort_buffer_size; +SET sort_buffer_size= 16384; +SELECT LEFT(a,1), GROUP_CONCAT(b) FROM t1 GROUP BY a; +LEFT(a,1) GROUP_CONCAT(b) +a a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a +c c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c +c c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c +f f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f +f f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f +k k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k +o o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o +p p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p +t t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t +t t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t +x NULL +y y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y +z z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z +SELECT SUBSTR(a,1,1), LENGTH(a), GROUP_CONCAT(b), COUNT(*) FROM t1 GROUP BY a; +SUBSTR(a,1,1) LENGTH(a) GROUP_CONCAT(b) COUNT(*) +a 1000 a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a 16 +c 258 c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c 16 +c 1000 c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c 16 +f 966 f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f 16 +f 1000 f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f 16 +k 468 k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k 16 +o 648 o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o 16 +p 1000 p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p 16 +t 414 t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t 16 +t 932 t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t 16 +x 1 NULL 64 +y 746 y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y 16 +z 298 z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z 16 +SET @@sort_buffer_size= @save_sort_buffer_size; +DROP TABLE t1; +CREATE TABLE t1(a VARCHAR(1027), b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_34; +SET @save_tmp_memory_table_size= @@tmp_memory_table_size; +SET tmp_memory_table_size= 1056*2; +SELECT COUNT(DISTINCT a) FROM t1; +COUNT(DISTINCT a) +34 +SET @@tmp_memory_table_size= @save_tmp_memory_table_size; +DROP TABLE t1; +# End of 10.5 tests diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test index f685707bd10..be4a3e4253e 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -15,6 +15,8 @@ call mtr.add_suppression("Out of sort memory; increase server sort buffer size") # Test old ORDER BY bug # +--source include/have_sequence.inc + CREATE TABLE t1 ( id int(6) DEFAULT '0' NOT NULL, idservice int(5), @@ -2162,6 +2164,21 @@ select * from t1 order by b; set @@sort_buffer_size= @save_sort_buffer_size; drop table t1; +--echo # +--echo # MDEV-22715: SIGSEGV in radixsort_for_str_ptr and in native_compare/my_qsort2 (optimized builds) +--echo # + +SET @save_sort_buffer_size= @@sort_buffer_size; +SET @save_max_sort_length= @@max_sort_length; +SET max_sort_length=8; +SET sort_buffer_size=1024; +CREATE TABLE t1(a INT, b DECIMAL(65), c BLOB); +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_25; +INSERT INTO t1 SELECT seq, seq, seq from seq_1_to_25; +SELECT * FROM t1 ORDER BY a,b; +SET @@sort_buffer_size= @save_sort_buffer_size; +SET @@max_sort_length= @save_max_sort_length; +DROP TABLE t1; --echo # --echo # MDEV-13994: Bad join results with orderby_uses_equalities=on @@ -2206,7 +2223,6 @@ set optimizer_switch= @save_optimizer_switch; DROP TABLE books, wings; - --echo # --echo # MDEV-17796: query with DISTINCT, GROUP BY and ORDER BY --echo # @@ -2221,6 +2237,8 @@ ORDER BY id+1 DESC; DROP TABLE t1; +--echo # End of 10.2 tests + --echo # --echo # MDEV-16214: Incorrect plan taken by the optimizer , uses INDEX instead of ref access with ORDER BY --echo # @@ -2258,6 +2276,8 @@ eval $query; drop table t1,t2; +--echo # End of 10.3 tests + --echo # --echo # MDEV-17761: Odd optimizer choice with ORDER BY LIMIT and condition selectivity --echo # @@ -2294,6 +2314,8 @@ set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u, drop table t1,t2,t3,t4; +--echo # End of 10.4 tests + --echo # --echo # MDEV-21655: Server crashes in my_qsort2 / Filesort_buffer::sort_buffer --echo # @@ -2413,3 +2435,70 @@ insert into t1 select repeat('d', 256); SELECT IF( 0, NULL, a ) AS f FROM t1 GROUP BY f WITH ROLLUP; DROP TABLE t1; + +--echo # +--echo # MDEV-22303: Incorrect ordering with REGEXP_REPLACE and OFFSET/LIMIT +--echo # + +CREATE TABLE t1 (name VARCHAR(20) CHARACTER SET utf8 NOT NULL); +INSERT INTO t1 (name) VALUES ('Charles Dickens'), ('Roald Dahl'); + +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC; + +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC LIMIT 1; + +SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1 +ORDER BY surname_first ASC LIMIT 1 OFFSET 1; + +DROP TABLE t1; + +--echo # +--echo # MDEV-22836: Server crashes in err_conv / ErrBuff::set_str +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0),(1); +--disable_warnings +SELECT * FROM t1 ORDER BY CONVERT(AES_ENCRYPT(1,a), CHAR(4)); +--enable_warnings +DROP TABLE t1; + +--echo # +--echo # MDEV-22819:Wrong result or Assertion `ix > 0' failed in read_to_buffer upon select +--echo # with GROUP BY and GROUP_CONCAT +--echo # + +CREATE TABLE t1 (a VARCHAR(1000), b CHAR(1)); + +INSERT INTO t1 VALUES + (REPEAT('a',1000),'a'),(REPEAT('t',932),'t'),('x',NULL),('x',NULL), + (REPEAT('z',298),'z'),(REPEAT('p',1000),'p'),(REPEAT('k',468),'k'), + (REPEAT('c',1000),'c'),(REPEAT('o',648),'o'),('x',NULL),('x',NULL), + (REPEAT('c',258),'c'),(REPEAT('t',414),'t'),(REPEAT('f',966),'f'), + (REPEAT('y',746),'y'),(REPEAT('f',1000),'f'); + +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +SET @save_sort_buffer_size= @@sort_buffer_size; +SET sort_buffer_size= 16384; +SELECT LEFT(a,1), GROUP_CONCAT(b) FROM t1 GROUP BY a; +SELECT SUBSTR(a,1,1), LENGTH(a), GROUP_CONCAT(b), COUNT(*) FROM t1 GROUP BY a; + +SET @@sort_buffer_size= @save_sort_buffer_size; +DROP TABLE t1; + +CREATE TABLE t1(a VARCHAR(1027), b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_34; +SET @save_tmp_memory_table_size= @@tmp_memory_table_size; +SET tmp_memory_table_size= 1056*2; +SELECT COUNT(DISTINCT a) FROM t1; +SET @@tmp_memory_table_size= @save_tmp_memory_table_size; +DROP TABLE t1; + + +--echo # End of 10.5 tests diff --git a/mysql-test/main/partition_alter.result b/mysql-test/main/partition_alter.result index d946f2b8822..997a5cf97fa 100644 --- a/mysql-test/main/partition_alter.result +++ b/mysql-test/main/partition_alter.result @@ -122,7 +122,55 @@ t1 CREATE TABLE `t1` ( PARTITION `p02` ENGINE = MyISAM, PARTITION `p03` ENGINE = MyISAM) drop table t1; -create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +# +# MDEV-19751 Wrong partitioning by KEY() after key dropped +# +create or replace table t1 (pk int, x timestamp(6), primary key (pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP PRIMARY KEY when partitioned by default field list is denied +alter table t1 drop primary key, drop column x, add primary key (pk), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +alter table t1 drop primary key, drop column x, add primary key (pk); +select * from t1 partition (p0); +pk +1 +drop table t1; +create or replace table t1 (pk int not null, x timestamp(6), unique u(pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Same for NOT NULL UNIQUE KEY as this is actually primary key +alter table t1 drop key u, drop column x, add unique (pk), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +alter table t1 drop key u, drop column x, add unique (pk); +select * from t1 partition (p0); +pk +1 +drop table t1; +create or replace table t1 (pk int, x timestamp(6), primary key (pk)) engine innodb +partition by key(pk) partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP PRIMARY KEY when partitioned by explicit field list is allowed +alter table t1 drop primary key, add primary key (pk, x), algorithm=inplace; +select * from t1 partition (p0); +pk x +1 2000-01-01 00:00:00.000000 +drop table t1; +create or replace table t1 (k int, x timestamp(6), unique key u (x, k)) engine innodb +partition by key(k) partitions 2; +insert into t1 (k, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +# Inplace for DROP KEY is allowed +alter table t1 drop key u, algorithm=inplace; +select * from t1 partition (p0); +k x +1 2000-01-01 00:00:00.000000 +drop table t1; +# End of 10.2 tests +# +# MDEV-14817 Server crashes in prep_alter_part_table() +# after table lock and multiple add partition +# +create table t1 (x int) partition by hash (x) (partition p1, partition p2); lock table t1 write; alter table t1 add partition (partition p1); ERROR HY000: Duplicate partition name p1 @@ -134,7 +182,7 @@ drop table t1; # ha_partition::update_row or `part_id == m_last_part' in # ha_partition::delete_row upon UPDATE/DELETE after dropping versioning # -create or replace table t1 (pk int, f int, primary key(pk, f)) engine=innodb +create table t1 (pk int, f int, primary key(pk, f)) engine=innodb partition by key() partitions 2; insert into t1 values (1,10),(2,11); # expected to hit same partition @@ -152,3 +200,4 @@ pk 2 delete from t1; drop table t1; +# End of 10.3 tests diff --git a/mysql-test/main/partition_alter.test b/mysql-test/main/partition_alter.test index 779f12574d5..cca25d0989f 100644 --- a/mysql-test/main/partition_alter.test +++ b/mysql-test/main/partition_alter.test @@ -120,10 +120,52 @@ alter online table t1 delay_key_write=1; show create table t1; drop table t1; -# -# MDEV-14817 Server crashes in prep_alter_part_table() after table lock and multiple add partition -# -create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +--echo # +--echo # MDEV-19751 Wrong partitioning by KEY() after key dropped +--echo # +create or replace table t1 (pk int, x timestamp(6), primary key (pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP PRIMARY KEY when partitioned by default field list is denied +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 drop primary key, drop column x, add primary key (pk), algorithm=inplace; +alter table t1 drop primary key, drop column x, add primary key (pk); +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (pk int not null, x timestamp(6), unique u(pk, x)) engine innodb +partition by key() partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Same for NOT NULL UNIQUE KEY as this is actually primary key +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 drop key u, drop column x, add unique (pk), algorithm=inplace; +alter table t1 drop key u, drop column x, add unique (pk); +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (pk int, x timestamp(6), primary key (pk)) engine innodb +partition by key(pk) partitions 2; +insert into t1 (pk, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP PRIMARY KEY when partitioned by explicit field list is allowed +alter table t1 drop primary key, add primary key (pk, x), algorithm=inplace; +select * from t1 partition (p0); +drop table t1; + +create or replace table t1 (k int, x timestamp(6), unique key u (x, k)) engine innodb +partition by key(k) partitions 2; +insert into t1 (k, x) values (1, '2000-01-01 00:00'), (2, '2000-01-01 00:01'); +--echo # Inplace for DROP KEY is allowed +alter table t1 drop key u, algorithm=inplace; +select * from t1 partition (p0); +drop table t1; + +--echo # End of 10.2 tests + +--echo # +--echo # MDEV-14817 Server crashes in prep_alter_part_table() +--echo # after table lock and multiple add partition +--echo # +create table t1 (x int) partition by hash (x) (partition p1, partition p2); lock table t1 write; --error ER_SAME_NAME_PARTITION alter table t1 add partition (partition p1); @@ -136,7 +178,7 @@ drop table t1; --echo # ha_partition::update_row or `part_id == m_last_part' in --echo # ha_partition::delete_row upon UPDATE/DELETE after dropping versioning --echo # -create or replace table t1 (pk int, f int, primary key(pk, f)) engine=innodb +create table t1 (pk int, f int, primary key(pk, f)) engine=innodb partition by key() partitions 2; insert into t1 values (1,10),(2,11); @@ -149,3 +191,5 @@ select * from t1 partition(p0); select * from t1 partition(p1); delete from t1; drop table t1; + +--echo # End of 10.3 tests diff --git a/mysql-test/main/percona_nonflushing_analyze_debug.result b/mysql-test/main/percona_nonflushing_analyze_debug.result new file mode 100644 index 00000000000..78da085f26f --- /dev/null +++ b/mysql-test/main/percona_nonflushing_analyze_debug.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +connect con1,localhost,root; +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +connection default; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +set @tmp=@@use_stat_tables; +set use_stat_tables='preferably_for_queries'; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +set use_stat_tables=@tmp; +SELECT * FROM t1; +a +1 +2 +3 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +connection con1; +a +1 +2 +3 +disconnect con1; +connection default; +SET DEBUG_SYNC='reset'; +DROP TABLE t1; diff --git a/mysql-test/main/percona_nonflushing_analyze_debug.test b/mysql-test/main/percona_nonflushing_analyze_debug.test new file mode 100644 index 00000000000..4c9c2dcb768 --- /dev/null +++ b/mysql-test/main/percona_nonflushing_analyze_debug.test @@ -0,0 +1,12 @@ +--source include/have_debug_sync.inc +--source include/have_innodb.inc + +#set use_stat_tables='preferably_for_queries'; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; + diff --git a/mysql-test/main/perror-win.result b/mysql-test/main/perror-win.result index 03d43abdb97..a0ea54f9187 100644 --- a/mysql-test/main/perror-win.result +++ b/mysql-test/main/perror-win.result @@ -2,6 +2,6 @@ MariaDB error code 150: Foreign key constraint is incorrectly formed Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system Win32 error code 23: Data error (cyclic redundancy check). -MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192T' for key %d Win32 error code 1062: The service has not been started. Illegal error code: 30000 diff --git a/mysql-test/main/perror.result b/mysql-test/main/perror.result index ad2106524e5..b95b8b8dd99 100644 --- a/mysql-test/main/perror.result +++ b/mysql-test/main/perror.result @@ -1,5 +1,5 @@ Illegal error code: 10000 -MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192T' for key %d MariaDB error code 1408 (ER_STARTUP): %s: ready for connections. Version: '%s' socket: '%s' port: %d %s MariaDB error code 1459 (ER_TABLE_NEEDS_UPGRADE): Upgrade required. Please do "REPAIR %s %`s" or dump/reload to fix it! diff --git a/mysql-test/main/processlist_notembedded.result b/mysql-test/main/processlist_notembedded.result index e663c407a1b..b622fdf32b9 100644 --- a/mysql-test/main/processlist_notembedded.result +++ b/mysql-test/main/processlist_notembedded.result @@ -8,6 +8,9 @@ connection default; SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; FOUND 1 /sleep/ in MDEV-20466.text SET DEBUG_SYNC= 'now SIGNAL go'; +connection con1; +User disconnect con1; +connection default; SET DEBUG_SYNC = 'RESET'; End of 5.5 tests diff --git a/mysql-test/main/processlist_notembedded.test b/mysql-test/main/processlist_notembedded.test index 4979e40a85a..6f269a816fc 100644 --- a/mysql-test/main/processlist_notembedded.test +++ b/mysql-test/main/processlist_notembedded.test @@ -30,7 +30,10 @@ remove_file $MYSQLTEST_VARDIR/tmp/MDEV-20466.text; SET DEBUG_SYNC= 'now SIGNAL go'; +connection con1; +reap; disconnect con1; +connection default; SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/main/profiling.result b/mysql-test/main/profiling.result index 6590d89bc89..f1403c3ec2f 100644 --- a/mysql-test/main/profiling.result +++ b/mysql-test/main/profiling.result @@ -123,8 +123,7 @@ select query_id, count(*), sum(duration) from information_schema.profiling group select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling; drop table if exists t1, t2, t3; Warnings: -Note 1051 Unknown table 'test.t2' -Note 1051 Unknown table 'test.t3' +Note 1051 Unknown table 'test.t2,test.t3' create table t1 (id int ); create table t2 (id int not null); create table t3 (id int not null primary key); diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 1fdd1bef0cc..d97720c2d41 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -2856,12 +2856,10 @@ Level Code Message Note 1051 Unknown table 'test.t2' drop table if exists t1, t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' call proc_1(); Level Code Message -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' drop procedure proc_1; create function func_1() returns int begin show warnings; return 1; end| ERROR 0A000: Not allowed to return a result set from a function @@ -2880,12 +2878,10 @@ Level Code Message Note 1051 Unknown table 'test.t2' drop table if exists t1, t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' execute abc; Level Code Message -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' deallocate prepare abc; set @my_password="password"; set @my_data="clear text to encode"; @@ -5472,6 +5468,23 @@ drop procedure p; drop view v1; drop table t1; # +# MDEV-22591 Debug build crashes on EXECUTE IMMEDIATE '... WHERE ?' USING IGNORE +# +CREATE TABLE t1 (a INT); +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING 0; +a +EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING 0; +a +DROP TABLE t1; +EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING 0; +Database +# # End of 10.2 tests # # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index a3c9f12e582..e702cb76bbb 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -4914,6 +4914,23 @@ drop procedure p; drop view v1; drop table t1; + +--echo # +--echo # MDEV-22591 Debug build crashes on EXECUTE IMMEDIATE '... WHERE ?' USING IGNORE +--echo # + +CREATE TABLE t1 (a INT); +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING IGNORE; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING IGNORE; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING 0; +EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING 0; +DROP TABLE t1; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING DEFAULT; +EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING 0; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index 4ba2568c3d9..4615c63feb2 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -2098,6 +2098,18 @@ drop procedure p1; drop table t1; set GLOBAL query_cache_size=1355776; SET GLOBAL userstat=@save_userstat; +# +# MDEV-5924: MariaDB could crash after changing the query_cache size +# +SET GLOBAL query_cache_size= 50*1024; +SET GLOBAL query_cache_type= 1; +SET query_cache_type= 1; +CREATE TABLE t1 (pk INT); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1 WHERE pk IN (5178922,5178924,6911605,6584899,1754348,7735031,9583206,8377182,6309967,3110885,7197937,5582397,9811721,8310302,7001831,3687942,8454635,8743988,9524703,3313583,1376007,5276565,7238861,5307189,2242691,2052764,8160476,7668014,5891525,9070968,1989181,3014068,5365005,2974655,6877822,7813446,6188705,1028564,6426696,6098205,7231857,2749710,4996963,9879425,2995803,8160614,1934799,1981216,3673522,2135299,4803054,8515609,1825485,5805694,8211425,3712249,8013259,3496368,4339706,2326187,3236816,8158416,5749801,6339492,2517486,1769729,2576400,8177368,5471847,4670669,5694046,5155990,1219314,1304321,7951736,2381942,1467330,3329376,6069503,3821151,8118179,4575775,5291671,4757186,6241302,9809112,5388351,3356292,5753921,8776535,7101943,8558868,6655212,5498901,1629516,8016143,1156005,1280700,9236450,8289703,4549957,5404968,3594833,3034667,3167602,7983322,3939941,8382949,9258422,6927947,9639236,3246566,3144943,5516067,5266540,3760726,6491516,9515090,7776229,1582824,4031951,3336517,5871612,4268432,2600433,6188018,6158355,6442214,7808502,7692871,9180969,3982238,9212692,9944381,3932525,5937118,6315460,2464477,1933151,3393646,4244674,7036026,1470764,3015029,2453765,9876129,2097534,3467391,4287658,8120651,4975540,4454101,7758102,6087905,2167022,7575454,5370086,8289703,7460235,8734512,7346801,6660293,5826843,4305511,8093597,8970031,9104476,1784973,9245925,6893890,4996414,3144393,1145568,2702056,4984878,5602859,7088073,2044113,5248275,6037094,2185287,1791564,3180374,8750991,9187011,6411453,9600372,4819671,3105667,2837051,1252548,3729003,7986618,8305633,5684432,4528808,8670104,4132202,2101516,5218475,6885513,4886413,1288803,9584167,6524475,3943649,6195846,4204986,5435592,8877334,9276275,8848358,3583435,6662216,7178298,1973526,5917205,9156387,8877334,4559432,2792144,9831634,8846710,6979858,5287277,2220718,9358123,4140029,1263122,8049789,9508361,3597030,8504348,4525924,9062866,1880691,9788375,4746612,7711822,9735366,9227523,9701721,2832519,4498870,3725021,4836151,2351181,7339935,9890686,7641098,1797607,1571838,3258377,6244186,5147476,6760543,9151580,2465576,2545776,6846237,4037582,8310440,2503616,1998245,1716445,2364913,4665039,8420440,1187728,1065917,1734710,5826705,8538681,8311950,4662017,7804519,7696853,7385116,8674362,2787612,2393341,1652313,2254364,3852737,4177108,7013641,8654037,9062728,7826629,2569396,1039138,2572692,9001892,3470550,4859359,5218887,6479568,1424621,3535644,7808639,7817291,8825149,6060302,2830047,7787765,5971313,9603256,1800491,3429214,9350021,8716796,1972564,6054946,6445510,9234802,5616729,6064559,2048233,9458511,1597244,3902862,2530120,5723846,3463821,9008346,3055130,2941696,8774337,3095367,2195037,6208480,9869262,3615295,9916641,1078002,1815597,7737228,1412261,6588607,9740173,6696411,7740386,1641326,9269546,3848754,7745193,6819458,5297164,1280975,1224395,5247589,7793533,5314743,8814025,2579010,7882659,6753128,9558349,8710067,7898727,4209106,2634902,7311233,1644897,8363449,6201339,1770828,3572174,5493408,8835449,5644332,5096115,7116088,1534484,3204544,1772064,2091903,6744476,9183166,5546005,1030075,7387725,1300888,5799789,7340209,7356552,7677627,9410995,5775894,9442581,5718353,6544937,9809524,7171569,4565475,1397293,6687759,1509353,3715682,8607208,3506118,3910827,1890167,1559341,4150329,9679336,9756927,1292373,3445419,2105361,6594238,4234237,8359466,7352432,1492462,9482818,1601226,8561614,4186584,5849365,1460189,9139495,3113357,8384460,7229660,8701553,7786254,4606399,2057708,1638992,1083221,8147293,9569198,4776550,2539871,8040039,7104141,8090713,7242568,2361480,6913940,7958053,1414596,3451461,9160644,7901473,8289703,5428588,3063232,2302291,5366378,8216918,8033447,8048965,8636322,7807952,7146026,6589569,2882644,1971328,7786392,5357864,4637985,2137222,9819961,9039932,8900680,1666732,8126968,1652999,7199035,8229003,7845581,8902328,8100051,9506164,8168579,8786560,4753890,6941268,5035552,2919860,9570983,4751968,4566574,7540023,1621963,7924270,7578750,6669494,5857192,6409805,2030792,4401779,5737991,8241088,4739746,2776901,7373718,8786697,9211593,6219741,1758331,3863586,6932754,5006164,8200302,5925033,1962127,2728149,8540191,9044326,6171264,4224899,9248672,5911026,6974502,1950317,4998611,2561569,2891845,3243957,8806335,8058303,8791778,1475708,3335281,7841186,9153228,5532135,5453994,5966369,4194824,3612686,8645385,9952621,1211349,2806289,4358520,7454330,5964035,2415313,8897384,6479431,1467330,6496185,8941055,8369903,5015502,5586105,4288482,3266204,1793212,6083923,6920394,1272048,7913696,1253234,3975372,9038970,7229522,7319061,4729995,9990386,5756942,4622741,8179565,1901840,2060729,6308593,2311767,6058517,9440521,4506286,2667724,2707412,9264328,7481658,7283767,4022613,7292282,7722808,1607543,3303695,9334091,4429382,7483169,2624877,7084777,1376693,3797668,1654510,6480667,4619720,9884094,5862548,9422256,4009429,6273574,8836135,8204696,7987167,1890991,6920944,2501831,7627502,3287765,9907714,8246444,2397872,6005920,6982330,5250473,8604049,6665649,4658172,8910156,2989349,2872344,5909790,5837142,1457168,6535461,2226623,1763137,9385314,1692550,9805267,2558547,7501022,7434143,5598876,5709976,6785263,6020614,1443572,3101684,3374557,4787536,3978530,9441757,1930130,9930648,8580841,9180145,1442749,9766128,9032516,7260009,3941177,6559494,9137985,4546386,3074356,5515518,9012878,2276748,4035247,9025100,6259704,9377487,4794540,5761474,2752593,3987731,8114746,2718948,3247390,3037689,3311660,8790679,5536666,2222091,5232482,8974563,4368682,3214843,8420028,8806335,8848220,7466827,6930969,8109664,5539825,4431991,9777114,1658630,1989456,4565338,4458084,9845504,1885635,9934494,5555755,2949661,1578155,8792465,5856231,1098190,3172134,3951339,2971771,6514724,7918090,8303161,8927734,5148162,3115005,8331726,8686172,9277099,5245941,8956710,9073989,9181930,1564422,7557327,9082504,3478927,5851699,1516220,6011001,3210998,7561996,3128875,3419052,8286682,3075180,4222702,9359085,4364151,5275878,8327606,8856597,5770950,4176971,9744155,7107299,3555694,8808120,1351837,1360076,6263137,8084533,7500198,4953704,5528839,7879226,7829376,8476745,9084976,9013153,9360595,1519927,9272705,2386062,6703552,2987976,2653991,7962310,6720443,7441421,9816116,8835861,1495346,2436462,3964523,5086776,2948287,9331619,3395294,2654541,4939971,5529388,2443054,8942016,4211166,4622741,4996826,3370712,8998596,8414672,6178268,8606521,4673553,8279541,6275634,5673858,3244918,1834274,1526931,7676940,2071578,4389968,8847671,8347793,5627304,3150848,6094223,3139175,7662246,4629882,6958709,6080078,6604812,6250503,8088928,8115158,5547515,6602340,9526214,7144378,6659744,2319869,8054733,1483261,5373657,5053268,2558273,4960433,3183807,8498855,9974731,2374801,8405883,1960617,4945877,2526550,7739700,5407440,6752304,8544998,3976608,6499618,1631164,8728744,3698516,8548431,5066864,5619064,5310623,6882492,6150802,6524063,6251052,3584671,8603775,2213165,7723495,4073150,9552993,9999450,8793975,6491241,4660095,9930786,4196609,8377456,4691268,3305343,4692779,5583221,8125320,4233688,4325836,7907516,4892318,4463714,3417266,1417343,9836441,1187866,2645751,7921936,2998275,2052352,5054229,9570159,9308273,7085052,4329132,6040390,5786056,7763320,5193618,8289703,5839752,2938400,9261032,2333740,8758682,8836135,3190261,2023376,1993301,8853439,8487869,8288879,1314758,9366775,4800720,2819610,1451126,3274719,2042053,9648025,2290206,7490997,1195281,1606033,1245407,3106765,2140518,9124389,8877197,7443206,5344268,1341262,5363906,7709762,3759902,4991333,2916427,3489913,1779754,4042251,5729888,4771057,3584533,4547760,5565505,7738327,7732559,5686904,2558273,2051116,4332153,9457275,9341644,4819946,2643692,7991149,1085830,4004486,4451492,8963714,3540176,4449020,5051483,2061691,2676651,5276153,9197860,7980850,3026428,2856414,8852752,4922805,8302612,1072509,9081542,9056823,8404922,6097930,3939804,4919097,7398712,5407302,6692565,2214401,5561660,7238311,9212554,4992568,6093811,5223144,1899368,7665542,4582092,7409286,9964294,1835372,4815963,3387054,7423294,9401657,1044494,8743713,6644226,8916748,6272750,6561965,4788223,4657897,3687393,6183486,3993774,6385223,8807159,2952682,2643692,7253280,2452804,5163818,3558853,6846511,3127502,1926834,8465347,4805801,2904479,2171691,8575622,3015853,8413299,9511245,3628479,4821868,1020324,9179046,5233032,4244400,3795471,2762893,2857376,7661010,6360778,4951644,1309265,8922927,7212219,2014862,9049407,5376403,5611511,2232940,5183456,2757949,4638946,6997848,7474517,6429168,1501800,5802124,8222274,9924880,8694000,3835708,8349304,5278213,1097091,5408126,6541915,8095245,3619415,6916961,2786102,4845352,7466827,3578079,8144683,4338470,1635971,9640609,3117614,1855010,5728103,6300903,7430709,1900192,3673660,6037643,5595443,7049072,6462951,3585632,8084533,1853363,8477294,2266586,1465270,1276580,2511856,2895828,4337097,3626968,7087249,8985000,9414840,7458724,1141174,7457214,1602325,4407272,7694519,5595306,3399688,8429092,5586380,2441543,4488845,6415573,9871047,2366287,5840713,7647552,8970306,3026016,8186569,5060821,9175888,2428634,4199768,7791061,9595565,2325363,2228820,2966415,5135116,7646453,5928054,6217681,2612930,8201812,4628372,4872955,3597305,5363082,6790893,7307388,2064025,6947860,9389984,2415451,4464401,8022598,7566390,6675811,3299850,6845413,9396438,2775527,1796508,1665359,7119934,1264907,2772644,8598693,4670669,2209182,5293182,1299514,7853683,7307525,3205093,1643661,5012481,3448440,2148208,6146820,6530380,5167251,4132614,4331054,9009719,4979522,3280487,7764144,6472427,9053253,4821456,3984985,4425674,7194503,2939361,6038879,6136795,9609985,1561401,3836807,7960662,8419204,4684951,6060989,9063690,5382308,6334548,5833572,9388198,8814849,5744033,4868148,1200775,6155197,5857192,1321624,9067535,4156234,2739959,4067108,3602661,8168441,4998748,5604919,4829833,5483520,9798538,3330474,2504852,4206909,1574035,1379440,9239746,3629440,8028366,1766845,8773513,1564834,9511657,7040695,7232955,4622467,6376022,7167312,3728591,2885940,4396835,8868270,7126800,9963195,6857360,8126831,5344406,3878555,7389236,9083740,5007949,4776962,9162017,8039764,2822631,7905044,1516357,9784667,6493438,7841873,9634292,3971252,2542480,3446517,4340805,4752929,6867660,3490188,3628890,9403579,5384231,3443496,9004089,6138854,1594360,7386215,9240707,3856857,5428863,2509521,9643905,7018722,9202941,5178375,4411254,7385116,1032135,5022506,3187652,5829727,7550186,7026824,2408035,9947540,9273666,7087936,3519851,2677337,8457244,2005661,4680969,7654968,2781570,4380081,5025390,3519851,9721084,1380264,2092041,1889892,2931121,7856018,3507766,5226303,4501617,8759506,6521591,6303924,5419250,4346023,2481506,6510330,3082870,7123367,4848236,7687789,8214035,6017868,4840545,8739181,4010116,7725280,6304473,6717834,6878509,8717071,7901062,6616348,4601318,7868927,3206878,3577255,2269744,3181472,1819305,4741119,5834259,1561264,7062255,9452194,2613754,3131347,7384979,6041351,2607711,7039733,7047561,2902420,1954162,9234252,9188522,8082885,4378570,3174057,3865371,2107696,6976425,7944458,9164901,7252593,5173294,8744537,1974624,9989013,4207321,5217926,2511032,1816970,1975036,7593170,5195953,3204681,2588897,5102981,1978607,2856002,7484954,7652359,6692153,1021011,7428237,5203643,2542892,8071487,3258789,8846160,9323516,7058685,6720581,9020843,3444595,1471038,4219131,5868041,4378570,3913986,5849914,1166580,6608795,5926269,9542007,7833496,7679412,9654891,2661956,2453765,9437225,8606246,1918182,2806838,9062179,7191619,1914337,6861343,9976791,2286773,4190429,2203964,6232238,7523681,6100128,7373992,6461715,7533432,4364425,3069549,5995483,3859741,9647476,2696838,9232879,3760177,9996704,3229263,1862838,5615081,5493682,2845703,2029144,3163070,6955413,6317382,9031143,8281463,4034286,6611404,5656692,6529281,2557037,7679138,3738891,7174179,1447692,4899871,1031311,2919723,9078796,6147369,9996154,1052597,5393844,9947265,8596496,4228469,3644683,5696243,9690322,3616119,1088714,2409408,9116287,6616210,8487594,6966949,9066986,8876098,1753799,3326492,2843505,4818298,3586044,6671554,9584304,9400833,3439788,9963745,9062454,5329025,4675338,4869110,9144851,4437484,6226333,2525177,6007293,2460083,9634979,2118820,6699844,6908035,2795578,3744247,9154464,7273742,2250106,4507247,1230575,4279830,6382064,2348434,8891067,3391723,4348358,9550247,3103195,8312500,1096817,1399078,1557693,9679061,5311035,8970581,3799728,4678497,3626144,2506088,5866256,6802154,2960510,8350540,3022857,9459060,2306274,6918197,1693374,6662902,2821807,9658737,3177215,7515991,7572296,6487258,7247650,3706619,2758773,1652862,7224166,6737197,6782653,9508499,6613464,6106307,7986755,3156753,1912689,1157928,3418365,2435089,6668395,2821121,4458084,6213150,7384841,4956588,5656692,9468399,7376190,1529541,7625167,8110488,4155548,4326660,9321182,7022293,2455001,2438247,6575973,6285659,7469299,7221694,2205200,8063247,1420089,6965988,1546844,1101211,1029525,1977233,7771560,1325469,1002197,7301620,8807983,6497558,9104614,4806625,6226608,6400192,4939971,1838119,5926544,5520736,1008239,7172256,2969299,1701065,2148345,9481033,6402252,3724060,5954696,3031097,1415832,4303314,2261367,1832077,2679534,9446289,6289642,5956481,6198181,4659408,2550033,5247451,2534515,3963287,5095428,2133926,2739273,8188217,3215667,3772262,5836044,9515914,7171432,1232360,3201110,3740264,8057205,2948013,2683380,3211685,3389938,5149536,5809814,2937438,1515121,2497161,1916946,9803070,3426055,2634490,2554565,6387695,1088165,3881027,9005325,4338607,8863464,7781997,8261825,4775314,5127700,7733795,7307662,2691619,7675155,7405029,3044555,5825195,7004577,1170974,5709426,6961456,8078491,6280166,4126296,6142974,3652511,6972854,8634674,3751251,3765670,8268692,6040664,6930145,7486328,5643508,7432495,6320541,5509338,5313095,5205291,1573486,7694519,9343841,2139007,5612060,4143325,1307479,9871459,7109771,6907073,8700454,8613937,1154495,8917709,7844482,8447906,4566436,7239135,8489517,6052200,3839691,8229141,2835678,4199905,4175323,8708282,8194808,4871032,1574859,5727005,5008087,8324310,1463348,2027908,8441726,9971160,4810195,5793334,3275268,9397537,4217071,9775192,7305740,5373931,9941085,2398422,1982727,9201156,4322540,4933517,4495849,5232894,6585449,7331008,2030380,7920013,2480133,3811264,4413452,9220382,1735946,9804443,7867004,1716995,4794265,9334091,9085937,6289505,6787734,2436599,6362701,1682113,9238510,2713180,9974731,8810867,5440124,1605346,7554306,2156448,8995162,1488616,5659713,9083602,1474746,8179290,3266479,6432189,3670639,3946395,9397125,2223464,2407348,7623107,5608078,1825759,9384216,8912216,1553573,3422897,2014999,9478012,3343109,1127990,4734252,2919174,6914352,5589126,6739257,9217086,7136825,6427658,1636795,4750732,8867584,3355194,6962417,7476028,3676681,3311248,7041381,5358688,6461715,2466674,1160812,5658477,7668701,3436492,1520339,1155868,7340484,5543807,9931472,4916351,4708572,9482269,6733489,3684921,1550277,1217529,7894882,8505722,1027053,1472686,7768676,7660186,6224548,1642013,7472045,9516738,9112304,7475891,9356063,7386627,1142272,2380706,6537246,8979507,5205017,6678558,9957977,7552108,7161132,8668594,6944839,1344284,2669509,6835388,1734024,1395782,1526519,2048233,4932006,8337219,7240371,8092910,5380798,6250778,3054855,9382293,7395965,8190826,7143417,6188568,4846725,3462585,3192459,4239730,2046173,3249038,7091369,8025619,6921768,7681472,3949142,9657363,7432083,9947952,7155502,5621810,9702407,4531005,9706253,6277420,4844802,7171432,7510910,7433593,5931900,8650329,8901092,5858154,4095260,4981582,3058837,1055618,3214157,8112823,8584686,2161529,9165863,8723663,3921676,9294815,7104553,2218933,4856338,6214111,9738388,4507385,9814605,5619476,3073944,6663589,6171264,3944747,7595642,2061828,1291549,3983886,9349472,8080001,1524597,7195190,5899627,8965774,1866134,8026992,2628311,2957077,8510116,9107772,6343338,8253860,4008056,8646896,4668334,3932388,3253845,5886444,5178100,2396499,2014038,2950347,5752685,4460418,2222091,3933761,6116195,6655349,5753921,7576416,4029617,9855392,7905731,3363021,5107925,9814193,8291625,3396118,7727340,8709106,7378662,2883880,9994369,1283721,6381515,9586502,9243728,1684173,5730987,8065444,5034179,1582687,1839355,8079864,3111434,6681854,4377883,6971893,4306335,6193237,1788269,6387695,2837463,4385025,5243469,3174743,4987213,4790969,8780242,4800720,2618560,4176147,4818984,7139160,2503341,3850814,9791671,2962158,9929962,5429962,5096252,3986495,4558197,7627365,9094863,9817352,4991607,7182281,5376953,5630050,8035095,2510208,6003860,2938125,7106887,3171859,1955535,7287338,1773712,7754669,7495941,8222000,4877899,7259323,4678359,1366531,4223800,3587005,3707168,2965866,2295425,1219451,7376739,3728454,9970886,6685424,5303894,2315887,9703781,2909561,2175811,2323165,7140121,5034454,7728713,5091583,6640106,2812194,1678405,8201538,2672393,4156784,8321426,5984634,2550033,2953506,6023086,1902389,1477493,4717636,4315399,2133514,6376846,5195816,4818298,9213790,2461318,1505645,7708389,3072433,4026733,2905441,4950271,9309646,2427673,3788604,5009185,8055969,6708496,2996353,3267303,8261962,7856567,5043243,5857742,4757736,8148254,6347595,3138214,7927566,9555328,1061660,9522094,7344879,3679702,9596115,2885391,5208862,1187316,2430694,6269180,7927566,8208404,1305557,1094345,3691787,5673171,5388214,4610794,3382659,1052047,6508132,9796203,1656845,1468566,2053451,3425094,7553344,4655014,8623550,3527130,1465820,9716827,3031921,7952148,3823211,9178497,9751296,2261642,4323776,9275726,9396713,8665298,9065475,3965347,4339019,9221206,8415771,3620239,6043273,4017669,5966918,7879364,1225357,1557693,1418029,5619750,3420288,4062301,4727935,8520965,4057769,9912384,1385345,3190261,1635009,5948928,9135787,8316482,4085784,7848876,2012527,4822143,2933731,4295349,4014236,6482864,3328826,7162643,2271255,2981796,9557113,9432693,9047897,6868209,5119186,8063522,3421249,8389816,6970932,1526794,9981323,6666061,8019989,2235137,9397674,2172653,4471405,9574966,1193222,2005249,3118026,1768218,3572723,3890502,7165664,9276138,4645675,1415008,1691864,3969055,9891784,3438964,9327087,8777359,2208221,2164550,3255218,9043640,4385986,8827209,9126037,7295166,6357345,1478454,2973831,9655166,1058364,2829772,8735198,6611129,8250564,6625549,2459808,6358993,6145446,6513763,8809906,3443222,1175506,7884445,5938491,3910003,2754791,6642028,6344024,7692321,7374542,4383651,1791976,6447158,1875610,7949401,4899871,5562210,9243316,1815460,1476806,2551406,6766448,3296005,1213958,2557037,9905792,9026611,9817352,3179687,7716079,5693908,2177871,2351318,7162918,6483001,7673095,6473388,7181182,7209884,9192642,2536437,6816848,3608978,9982421,6441802,3296966,8742614,5900588,7242019,3370437,5003005,1180038,9520996,3764846,3674896,3289688,2631469,9101318,2526824,8989807,5007400,7113479,5401260,7174453,3273345,5511123,2270706,1593536,6365859,5335891,1730178,7051544,7387725,6149566,5393157,4172851,1414047,7900924,7161407,4330230,4966888,5813796,5835769,2828125,9380371,6140365,6038192,7937316,2771408,5123031,4912918,4870758,1837982,4010116,2574890,6298431,3201385,2466812,6776748,3491561,2513092,7227188,6759307,5692810,9042953,7330047,3757431,8803588,5969116,6781829,1129501,8984313,9088272,2991958,5577041,1259963,3164169,1823287,5426803,6726211,7632995,2600433,4440368,5447265,5885894,7922348,5123031,7642471,7846130,9620559,1999069,5252807,7059509,5707778,4822280,9482543,3017227,8660079,8191787,6408432,2930847,9877914,8539230,9252243,2676239,4667510,2959274,3407928,5126190,6587783,7850250,7819076,3590988,2506912,4833679,3799865,6584762,2210281,4922119,8892715,4637023,7906829,3403945,1856384,9367874,3473297,7413269,3380325,2544815,4784790,7654968,9615203,6342239,9971298,4251541,2117309,4519607,7946517,3183120,1297866,6738845,1051910,3286804,8972640,3738891,2159606,7285964,5103530,6586410,7077911,4817749,6329193,7722259,1603561,5926681,9375427,3019973,4063812,9994644,6939620,2578460,4693328,6574325,7145065,7464492,9687576,1096542,1156280,6125946,6278930,8918533,8050064,3693298,2677200,1683486,6537109,2888824,4219543,1459091,8626159,3761962,7572845,9624130,3825820,3968780,9332580,1971603,1976409,3816619,2862869,9997940,2307785,6790069,4718322,6846374,8813613,1777969,3496368,4872543,9539810,7721435,7458587,2303665,3877731,4899459,2769210,5956069,4456573,4572067,7691223,1483673,7730087,9200744,7586166,8124221,3849990,6962142,1059600,8411376,1920242,4776962,5097625,6823440,6225646,9569747,6536422,7835830,9529373,6981643,4710769,5347152,2032440,9251419,6622802,7945831,8088516,5485855,2476974,2988937,5269012,3038101,7923171,9959075,7870986,2211242,2853256,9069732,7463119,3007064,6093948,3587417,7560760,3138900,7839126,1839767,7027923,5026901,8167617,6376571,7295303,8993240,9487762,3256179,5992187,1379440,4252777,2920959,7083404,4800170,3793411,8635635,1105880,1255706,5607391,8953414,8598556,2320556,7952972,5181121,5320098,5126464,5088424,8310302,2346237,9359497,9002166,7384567,9643218,4989135,3976333,5771224,3207702,6949234,5828079,1304595,2371093,1488204,6173599,6773727,8357406,6408294,9555328,4717910,9692520,1911865,6779769,5003417,3555969,6274536,2307785,9147460,4669708,8062423,2040130,4858810,8818420,2114013,7345428,1764511,8593612,3003219,2669921,6790618,1456893,4204849,9576339,4165985,6714675,8679168,5553833,9517425,4499008,9095275,5443008,2026672,2348159,7412719,4820083,2114974,7480285,6037643,2184051,8626983,2354614,6275634,6289505,8980880,7612533,9296875,2471069,1254608,5995071,1334533,9300170,7675155,9326675,8334060,1420776,9482681,6162338,3772125,9906066,7634506,9190582,6864776,4980621,4321441,2985504,1883026,7451583,1762176,2202453,6793502,6691879,2246124,2810958,2945541,5521011,6893066,9458099,9021118,3825271,6098617,2557449,1967208,7262207,4133438,1194869,4129455,7893096,7865768,4447372,3305892,5086364,4075759,3208389,6939208,4536224,8330490,7111282,5166290,9741546,2888275,8646896,8943939,6785263,8600479,9068771,9970336,1762588,9280670,1178115,1618530,3697692,9509460,6584213,6604125,3295181,7342956,8532638,7602783,2369445,9894943,3896545,5538314,9294677,8260726,6422164,2759735,1321487,3750839,8825698,9824768,3100723,1905136,5832061,8110076,3261810,3254257,4751968,2966964,2386199,6297744,8689193,9639648,4221878,6668258,6972305,7666915,9481719,7949813,2905578,2983993,4068893,1119064,5430648,8445571,1074844,9077972,5795669,9986267,2391555,9248260,9822845,8139328,2283752,1693374,2869735,4131240,6762603,8740417,8077941,2270980,2107284,3566955,7001831,5853759,8375259,3725296,9212966,6295822,7248474,3069274,3972213,5722198,6054946,5055191,8563949,9722595,9314178,1884674,9386138,3497467,6645874,9457138,1390701,1110000,9389160,2602355,2966140,1065917,1773025,4560668,8858108,9937103,9985168,4180130,1220413,3248764,1978744,8799468,8390914,3350250,1365570,5284805,7485504,8485122,2234451,2189544,2404602,6783477,5243881,6506759,1344696,7390609,4827224,8981018,9410720,7455017,4858947,2450195,3420425,7191207,9621932,8185333,4497222,9738250,4422927,8697296,8542800,1031723,7697265,4978424,7184341,8407806,1947021,6649032,3291748,8159240,5358276,1976959,1654510,5760513,1439041,4238906,4916351,4981994,6522415,5391647,4358245,9611770,1479003,5523620,4626174,8002960,7481796,3053894,8994476,3166503,5167526,6147781,4260742,2627899,4039230,4318557,6865875,3765258,6450592,5683197,2331268,5849777,2020767,6841018,1609466,3505157,6818222,9844543,1439590,1806671,4161727,7229934,9302505,7736267,8379104,4578521,1070449,2215637,9368972,1574035,7941986,9432556,1309539,1029113,2759872,6681716,6356933,2844879,7301071,7437988,8677932,7377288,9637863,6880569,6660156,3174057,5158874,5587478,8644012,8555709,2346786,7618026,9019470,7005401,9906204,1703262,4032501,7838989,8333786,1762863,3143569,9122741,3526306,2465850,5283157,4307983,3519302,7056213,3846557,7551559,6949920,1160125,7774307,5189910,6339355,2794616,7558563,6337158,4785751,8296295,8522476,1073608,4164199,9388610,6213287,8196319,8426071,9106262,8256332,2998275,9091156,4796463,4509582,6045196,5527465,9914581,7866455,6419692,9112030,1833175,4547760,9400970,2865753,2384552,8228454,8048828,3656906,7353118,2841583,6660018,9567001,7639175,4403564,3567642,6511566,7309448,8705261,7249710,5712310,2257522,1211624,2218246,7110458,4687561,3014617,1655746,4319107,5145690,5181259,4268157,7204940,2313140,8344085,1324645,8695922,1282760,1873413,4350143,6906112,2536437,9478836,5441497,9173278,8342300,8581115,2676376,3102645,5790725,3300399,2581344,1209014,7187911,4402877,6129516,9254028,8025482,7049758,7237350,6868759,6244735,7693283,1226455,6558395,6015396,6962966,5222869,9681259,5745407,3885696,6958709,6495498,1543685,9283279,5948654,9869125,5851013,2692443,9506988,8744674,4460968,4648147,3575607,1954162,4647460,8678619,3831451,7477539,7618713,7850387,9041580,9737701,4016433,4211715,7136001,1026779,5677841,1975311,8964263,7656478,5381347,7785430,8208404,4928024,3792312,2912307,4417709,7512557,4328857,9718750,5635406,5338775,7167449,1241424,3586044,4579208,2104400,1230850,8892166,5830688,9494354,6495361,4289169,8081100,6983703,6889770,2306961,5557952,7257400,4796051,2386474,3050186,7518600,3436630,6901718,7799987,3918792,9866241,8053634,5555618,7658538,3985122,6106307,4879959,3976608,9416625,6934402,4309494,6746124,1595596,5348388,2456649,5898254,4907012,1169189,4647735,5388626,6224136,9518524,2193664,2929748,9683593,4296173,3884460,1203933,4047058,8309890,5801712,9778625,5489837,8029602,6043823,1441375,1160125,5433120,4456710,7173080,1354446,1911590,3964248,7478637,7652221,1706008,7592483,2295013,5852111,9839462,9779861,7191894,7055389,4018493,3069549,7088897,2740234,8468368,7775405,2202453,1168365,6172912,1716995,6445648,1971328,6488357,9616577,6997436,4256210,4597885,4251403,6260665,4079055,5777130,4956176,1926696,4624389,3939117,7569137,8367843,3940353,6426834,5414031,2072952,1567993,3523422,5414718,2348022,6912017,1646820,1932601,7998428,9695816,9699523,1423660,1212448,3342422,7540847,6507171,9365539,3629714,2051803,7540298,3961776,9458236,1759292,7292007,5433807,1079238,6490966,9811035,2019119,3625869,5026763,8080276,6429992,5289886,5218612,9552169,2538909,9989013,8544448,8159515,6794601,4868148,7567077,4892868,5590774,5479263,8266906,3542373,2303253,3980590,2714279,2693130,7217575,1203659,2055099,9571945,6062225,1927520,1273422,6836624,1369415,1206130,3703598,5902236,9379959,3092895,3758117,9898788,7712097,9604354,1842376,1853500,4512878,3268402,3922088,6190216,8310577,5100921,7714981,6142974,6286895,6352264,8973876,8173522,9187973,8870880,2830322,8990081,9592819,8423873,4667098,3257827,1758468,2822631,2489883,3597442,8758407,3192733,9264739,3965072,4136734,4235610,1190887,2005386,6793365,8823089,9379272,2474227,2320968,8770904,6902542,9323104,5511398,8132461,2687774,9538986,7251495,8858795,2219345,1334396,3525619,9166824,3521362,6780456,2744628,6460342,3387741,4477172,2120056,1148727,2329895,1354995,9301132,2203689,1208877,8199890,9995468,3802337,5022644,2997863,2789672,5896057,8815811,6691329,1890853,3052383,8181900,4440643,3005828,5410736,9325714,7986343,2078857,7098373,9154190,1204071,8104995,1948257,1367492,1446594,4737823,6863677,6014160,5766830,8911804,3673385,7483993,9615615,1196792,2820159,5404418,2107421,2103164,4727249,9409347,8449142,6057556,8186843,2250930,2623092,2266860,3613098,8221176,3921401,1190063,1504409,3352722,9422119,7835418,6958709,2368209,4004486,4603790,8584686,4846313,5992187,1894561,9653381,9572631,3024642,3194107,7834320,4545974,6243225,5866668,5358825,6606872,5392471,1362960,9954544,4158294,7925231,6069641,9396301,2946640,7708389,5514968,6014709,1372299,3421661,5150497,4008468,5298126,2243103,7428649,8902191,7824295,2916702,9393417,3995971,7999801,1792938,2502792,8146469,2937164,6939071,5904022,8729019,9300720,4910720,6877136,9117935,3636032,9279434,1667831,2534515,8511627,9510559,1428466,3602523,6937561,3283370,7483444,3457229,2033676,2848999,9641845,6750656,3414657,9519485,2771545,7396926,5259674,8880355,3356979,7401870,7537002,7822784,7258224,7619949,1351837,3986770,5388900,2783355,5885345,7711685,7533843,8645797,5894409,7084091,2023925,9585128,3241348,5181808,8486633,7509124,4420455,2102203,7391571,6408020,4552703,5873672,2610733,5396316,5814620,7840362,9709548,5589263,4772842,6615524,1190475,4657211,4590332,7197799,6405685,2400756,4575637,7341857,1358840,9191680,5042007,5779602,2113876,8623138,6945663,8385284,6030639,1211624,8272674,3876358,5544769,8496246,3642486,2145874,6711380,2377685,7096176,7819900,7232131,8041687,5540786,4132888,1181274,3310287,6814514,8714462,1154083,6763565,8845474,6383575,1052734,4477722,8870193,9541183,5229187,8721603,5181121,6255996,2205200,6456222,2373291,1638992,8686996,9980773,8556671,2596588,8093048,3568054,8504623,7560211,8314971,7435653,9206100,4283401,6929321,7892547,6791992,1301025,7579025,2009506,7302032,6144348,1744049,4652954,4263351,2906402,5619476,5228500,9547088,4249618,3318664,9977890,4474014,5451385,3122970,4170928,6637084,5580062,3993637,6038879,2408584,4396011,7067474,1791290,3602249,5070022,4352478,5560974,5258575,3315643,7344192,6619781,4021240,2025161,2780471,2710296,7075027,5007125,6253387,7836242,2111541,1915847,1898132,8355621,7295303,5968704,1875610,7719787,9693756,3544433,4869796,7704544,1145706,3255493,6317245,3472610,1031860,7589187,1587219,2316024,4919235,4710357,8832290,8419067,9547775,1521026,7727890,1486557,8126968,6568695,9818313,4580718,7411621,1897857,3689453,8011749,5526229,1439590,8686996,6624313,9006011,1031448,7397201,7323867,1022659,7661285,8611053,3187515,2266174,7030807,1988632,5002456,1447555,3030685,2144638,9576477,4895065,6220428,6371353,4662017,9210083,5910064,9719985,6841293,2452667,9932708,9657226,7213043,4825027,6706710,9017822,1225082,2321380,5676330,3470275,4499008,9314453,1728942,7214279,5987243,5545181,1679092,4130966,3308502,1485870,3416030,4101303,8604049,4545288,2805877,1714660,7760848,5083892,8944076,8083297,4341766,6709320,7851348,6984664,5069198,3818130,8206207,6047531,6206283,2856552,1208740,7201782,8676147,8264846,4168457,4111053,4267471,6577621,1911727,1806671,5765869,4645263,9599685,4241104,9358261,2449234,8053222,9979949,7151107,1476669,2177322,6751754,1148864,1124420,7578201,5074142,1534347,3101135,8968246,2674316,5595993,3296829,1451263,9923645,3144943,9086761,5283157,1004257,4766937,7540847,3200012,2027496,3750564,3505432,5908416,9821609,3038925,8026718,5832611,6608383,9044326,6085433,6710281,7287475,6673751,9109970,6131713,8546234,6405960,5238250,1616333,1514984,6766036,2796127,5320922,7186264,8038940,6961318,2970397,8315383,1568405,8081375,4109130,7023391,7482070,1615234,2262878,9819137,4189880,1166305,1107666,7260147,2496063,1575958,6237045,1971740,8670928,6546585,3623809,8240676,3325531,5762435,4368408,4905502,4432128,6977523,5828079,7759201,8335571,8038803,2721008,9185089,3098388,5313919,6298019,5243469,1023483,4491729,7177612,1928619,5698440,4224899,1935623,4813766,4405349,8582626,1045181,9804031,9238922,2783630,3260299,8215820,3778030,2175399,7035339,5900039,7653457,9932296,8077117,6630218,7855743,2438110,8619705,4472229,5127288,2822357,5519500,7355453,5281784,1621139,9760635,1564010,5795806,1028564,1467605,5366516,5515106,4708984,8016555,4503128,6819732,4639083,2340744,7748764,2092453,2947463,7022430,6272064,3833236,3221023,2265899,3006378,2264389,9246887,5345092,3754959,8768981,1659179,9620010,1245819,6007843,2458297,6713989,5858016,8057067,8871841,4948623,1234832,6412139,5526779,6626510,4506011,5199249,7400085,1258590,1335357,2441131,9518112,9328323,7513244,3718154,2872482,8686172,9312942,6069915,4521530,3169250,7329635,2481369,9345626,2539459,6019790,7796005,9426788,2333190,2661682,3400787,6518432,2717163,6953353,8526733,1576919,1944000,9968826,4507247,3821975,3500900,5690200,9840835,7295028,8545684,1834411,5398788,4384613,5723571,6194335,7624618,2287048,1958282,6211776,7065826,3871688,7312057,9001205,7084503,8918945,8507644,6545211,6089553,6200378,6205596,5275878,5133193,3368927,6631866,2766326,1216979,2129257,6648345,5746505,3151260,1655197,6860656,8165008,3309600,9723968,1857208,5513595,5124679,9537612,9171768,9135513,3667617,5696105,5065490,1733062,1155456,7295852,8720642,4797424,8729431,8618469,2940185,1174819,8349166,5381072,4946838,9492019,6145721,8015182,2375488,8656646,7076538,8943801,5053405,9153228,6228530,9325851,8660079,5352508,6609756,8235595,3863174,6553588,5775894,5746368,7021057,6976562,6134460,3887207,3048950,2425750,9270370,2942520,1540664,3841339,4136734,4060379,6738983,2458023,8454223,6641342,3450637,7791198,2164138,2475189,2497436,5165878,1277404,9094314,4799072,8011611,2963394,9312530,8679718,6637908,5223281,1418579,9493942,6712203,2990997,8991867,8163360,4156784,2006210,2811096,4720794,8685211,6300903,6822616,2452804,7695617,2647125,7638488,7735992,9739898,5805557,2532318,6160552,5288925,7921936,3402160,8034545,2010192,3913024,7668701,8862503,8278717,8186294,5577865,2893081,5138687,9538436,7876892,3328140,5435317,4574264,1331100,9287811,6335372,2491119,5052169,8125869,5954284,6572814,9105850,7187225,7311096,9235763,4366760,3604034,9326538,5971450,2090805,3220886,7086151,2029556,9172729,6246246,1085006,8185333,1558105,7721298,1673873,8433761,5778503,2401443,1425445,3955734,7078598,6142837,9639099,8200164,1102584,2389770,4702804,7423568,6611816,5854034,6531890,4533752,5199249,7982772,7802185,7578750,3470687,5305953,2196548,8727920,3662261,1259277,1384796,4084274); +pk +DROP VIEW v1; +DROP TABLE t1; End of 5.5 tests # # Bug#12977203: SERVER CRASH ON A DERIVED TABLE WITH QUERY CACHE ENABLED diff --git a/mysql-test/main/query_cache.test b/mysql-test/main/query_cache.test index 3bf905d624c..118ebbf1703 100644 --- a/mysql-test/main/query_cache.test +++ b/mysql-test/main/query_cache.test @@ -1719,6 +1719,23 @@ drop table t1; set GLOBAL query_cache_size=1355776; SET GLOBAL userstat=@save_userstat; +--echo # +--echo # MDEV-5924: MariaDB could crash after changing the query_cache size +--echo # + +SET GLOBAL query_cache_size= 50*1024; +SET GLOBAL query_cache_type= 1; +SET query_cache_type= 1; + +CREATE TABLE t1 (pk INT); +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT * FROM v1 WHERE pk IN (5178922,5178924,6911605,6584899,1754348,7735031,9583206,8377182,6309967,3110885,7197937,5582397,9811721,8310302,7001831,3687942,8454635,8743988,9524703,3313583,1376007,5276565,7238861,5307189,2242691,2052764,8160476,7668014,5891525,9070968,1989181,3014068,5365005,2974655,6877822,7813446,6188705,1028564,6426696,6098205,7231857,2749710,4996963,9879425,2995803,8160614,1934799,1981216,3673522,2135299,4803054,8515609,1825485,5805694,8211425,3712249,8013259,3496368,4339706,2326187,3236816,8158416,5749801,6339492,2517486,1769729,2576400,8177368,5471847,4670669,5694046,5155990,1219314,1304321,7951736,2381942,1467330,3329376,6069503,3821151,8118179,4575775,5291671,4757186,6241302,9809112,5388351,3356292,5753921,8776535,7101943,8558868,6655212,5498901,1629516,8016143,1156005,1280700,9236450,8289703,4549957,5404968,3594833,3034667,3167602,7983322,3939941,8382949,9258422,6927947,9639236,3246566,3144943,5516067,5266540,3760726,6491516,9515090,7776229,1582824,4031951,3336517,5871612,4268432,2600433,6188018,6158355,6442214,7808502,7692871,9180969,3982238,9212692,9944381,3932525,5937118,6315460,2464477,1933151,3393646,4244674,7036026,1470764,3015029,2453765,9876129,2097534,3467391,4287658,8120651,4975540,4454101,7758102,6087905,2167022,7575454,5370086,8289703,7460235,8734512,7346801,6660293,5826843,4305511,8093597,8970031,9104476,1784973,9245925,6893890,4996414,3144393,1145568,2702056,4984878,5602859,7088073,2044113,5248275,6037094,2185287,1791564,3180374,8750991,9187011,6411453,9600372,4819671,3105667,2837051,1252548,3729003,7986618,8305633,5684432,4528808,8670104,4132202,2101516,5218475,6885513,4886413,1288803,9584167,6524475,3943649,6195846,4204986,5435592,8877334,9276275,8848358,3583435,6662216,7178298,1973526,5917205,9156387,8877334,4559432,2792144,9831634,8846710,6979858,5287277,2220718,9358123,4140029,1263122,8049789,9508361,3597030,8504348,4525924,9062866,1880691,9788375,4746612,7711822,9735366,9227523,9701721,2832519,4498870,3725021,4836151,2351181,7339935,9890686,7641098,1797607,1571838,3258377,6244186,5147476,6760543,9151580,2465576,2545776,6846237,4037582,8310440,2503616,1998245,1716445,2364913,4665039,8420440,1187728,1065917,1734710,5826705,8538681,8311950,4662017,7804519,7696853,7385116,8674362,2787612,2393341,1652313,2254364,3852737,4177108,7013641,8654037,9062728,7826629,2569396,1039138,2572692,9001892,3470550,4859359,5218887,6479568,1424621,3535644,7808639,7817291,8825149,6060302,2830047,7787765,5971313,9603256,1800491,3429214,9350021,8716796,1972564,6054946,6445510,9234802,5616729,6064559,2048233,9458511,1597244,3902862,2530120,5723846,3463821,9008346,3055130,2941696,8774337,3095367,2195037,6208480,9869262,3615295,9916641,1078002,1815597,7737228,1412261,6588607,9740173,6696411,7740386,1641326,9269546,3848754,7745193,6819458,5297164,1280975,1224395,5247589,7793533,5314743,8814025,2579010,7882659,6753128,9558349,8710067,7898727,4209106,2634902,7311233,1644897,8363449,6201339,1770828,3572174,5493408,8835449,5644332,5096115,7116088,1534484,3204544,1772064,2091903,6744476,9183166,5546005,1030075,7387725,1300888,5799789,7340209,7356552,7677627,9410995,5775894,9442581,5718353,6544937,9809524,7171569,4565475,1397293,6687759,1509353,3715682,8607208,3506118,3910827,1890167,1559341,4150329,9679336,9756927,1292373,3445419,2105361,6594238,4234237,8359466,7352432,1492462,9482818,1601226,8561614,4186584,5849365,1460189,9139495,3113357,8384460,7229660,8701553,7786254,4606399,2057708,1638992,1083221,8147293,9569198,4776550,2539871,8040039,7104141,8090713,7242568,2361480,6913940,7958053,1414596,3451461,9160644,7901473,8289703,5428588,3063232,2302291,5366378,8216918,8033447,8048965,8636322,7807952,7146026,6589569,2882644,1971328,7786392,5357864,4637985,2137222,9819961,9039932,8900680,1666732,8126968,1652999,7199035,8229003,7845581,8902328,8100051,9506164,8168579,8786560,4753890,6941268,5035552,2919860,9570983,4751968,4566574,7540023,1621963,7924270,7578750,6669494,5857192,6409805,2030792,4401779,5737991,8241088,4739746,2776901,7373718,8786697,9211593,6219741,1758331,3863586,6932754,5006164,8200302,5925033,1962127,2728149,8540191,9044326,6171264,4224899,9248672,5911026,6974502,1950317,4998611,2561569,2891845,3243957,8806335,8058303,8791778,1475708,3335281,7841186,9153228,5532135,5453994,5966369,4194824,3612686,8645385,9952621,1211349,2806289,4358520,7454330,5964035,2415313,8897384,6479431,1467330,6496185,8941055,8369903,5015502,5586105,4288482,3266204,1793212,6083923,6920394,1272048,7913696,1253234,3975372,9038970,7229522,7319061,4729995,9990386,5756942,4622741,8179565,1901840,2060729,6308593,2311767,6058517,9440521,4506286,2667724,2707412,9264328,7481658,7283767,4022613,7292282,7722808,1607543,3303695,9334091,4429382,7483169,2624877,7084777,1376693,3797668,1654510,6480667,4619720,9884094,5862548,9422256,4009429,6273574,8836135,8204696,7987167,1890991,6920944,2501831,7627502,3287765,9907714,8246444,2397872,6005920,6982330,5250473,8604049,6665649,4658172,8910156,2989349,2872344,5909790,5837142,1457168,6535461,2226623,1763137,9385314,1692550,9805267,2558547,7501022,7434143,5598876,5709976,6785263,6020614,1443572,3101684,3374557,4787536,3978530,9441757,1930130,9930648,8580841,9180145,1442749,9766128,9032516,7260009,3941177,6559494,9137985,4546386,3074356,5515518,9012878,2276748,4035247,9025100,6259704,9377487,4794540,5761474,2752593,3987731,8114746,2718948,3247390,3037689,3311660,8790679,5536666,2222091,5232482,8974563,4368682,3214843,8420028,8806335,8848220,7466827,6930969,8109664,5539825,4431991,9777114,1658630,1989456,4565338,4458084,9845504,1885635,9934494,5555755,2949661,1578155,8792465,5856231,1098190,3172134,3951339,2971771,6514724,7918090,8303161,8927734,5148162,3115005,8331726,8686172,9277099,5245941,8956710,9073989,9181930,1564422,7557327,9082504,3478927,5851699,1516220,6011001,3210998,7561996,3128875,3419052,8286682,3075180,4222702,9359085,4364151,5275878,8327606,8856597,5770950,4176971,9744155,7107299,3555694,8808120,1351837,1360076,6263137,8084533,7500198,4953704,5528839,7879226,7829376,8476745,9084976,9013153,9360595,1519927,9272705,2386062,6703552,2987976,2653991,7962310,6720443,7441421,9816116,8835861,1495346,2436462,3964523,5086776,2948287,9331619,3395294,2654541,4939971,5529388,2443054,8942016,4211166,4622741,4996826,3370712,8998596,8414672,6178268,8606521,4673553,8279541,6275634,5673858,3244918,1834274,1526931,7676940,2071578,4389968,8847671,8347793,5627304,3150848,6094223,3139175,7662246,4629882,6958709,6080078,6604812,6250503,8088928,8115158,5547515,6602340,9526214,7144378,6659744,2319869,8054733,1483261,5373657,5053268,2558273,4960433,3183807,8498855,9974731,2374801,8405883,1960617,4945877,2526550,7739700,5407440,6752304,8544998,3976608,6499618,1631164,8728744,3698516,8548431,5066864,5619064,5310623,6882492,6150802,6524063,6251052,3584671,8603775,2213165,7723495,4073150,9552993,9999450,8793975,6491241,4660095,9930786,4196609,8377456,4691268,3305343,4692779,5583221,8125320,4233688,4325836,7907516,4892318,4463714,3417266,1417343,9836441,1187866,2645751,7921936,2998275,2052352,5054229,9570159,9308273,7085052,4329132,6040390,5786056,7763320,5193618,8289703,5839752,2938400,9261032,2333740,8758682,8836135,3190261,2023376,1993301,8853439,8487869,8288879,1314758,9366775,4800720,2819610,1451126,3274719,2042053,9648025,2290206,7490997,1195281,1606033,1245407,3106765,2140518,9124389,8877197,7443206,5344268,1341262,5363906,7709762,3759902,4991333,2916427,3489913,1779754,4042251,5729888,4771057,3584533,4547760,5565505,7738327,7732559,5686904,2558273,2051116,4332153,9457275,9341644,4819946,2643692,7991149,1085830,4004486,4451492,8963714,3540176,4449020,5051483,2061691,2676651,5276153,9197860,7980850,3026428,2856414,8852752,4922805,8302612,1072509,9081542,9056823,8404922,6097930,3939804,4919097,7398712,5407302,6692565,2214401,5561660,7238311,9212554,4992568,6093811,5223144,1899368,7665542,4582092,7409286,9964294,1835372,4815963,3387054,7423294,9401657,1044494,8743713,6644226,8916748,6272750,6561965,4788223,4657897,3687393,6183486,3993774,6385223,8807159,2952682,2643692,7253280,2452804,5163818,3558853,6846511,3127502,1926834,8465347,4805801,2904479,2171691,8575622,3015853,8413299,9511245,3628479,4821868,1020324,9179046,5233032,4244400,3795471,2762893,2857376,7661010,6360778,4951644,1309265,8922927,7212219,2014862,9049407,5376403,5611511,2232940,5183456,2757949,4638946,6997848,7474517,6429168,1501800,5802124,8222274,9924880,8694000,3835708,8349304,5278213,1097091,5408126,6541915,8095245,3619415,6916961,2786102,4845352,7466827,3578079,8144683,4338470,1635971,9640609,3117614,1855010,5728103,6300903,7430709,1900192,3673660,6037643,5595443,7049072,6462951,3585632,8084533,1853363,8477294,2266586,1465270,1276580,2511856,2895828,4337097,3626968,7087249,8985000,9414840,7458724,1141174,7457214,1602325,4407272,7694519,5595306,3399688,8429092,5586380,2441543,4488845,6415573,9871047,2366287,5840713,7647552,8970306,3026016,8186569,5060821,9175888,2428634,4199768,7791061,9595565,2325363,2228820,2966415,5135116,7646453,5928054,6217681,2612930,8201812,4628372,4872955,3597305,5363082,6790893,7307388,2064025,6947860,9389984,2415451,4464401,8022598,7566390,6675811,3299850,6845413,9396438,2775527,1796508,1665359,7119934,1264907,2772644,8598693,4670669,2209182,5293182,1299514,7853683,7307525,3205093,1643661,5012481,3448440,2148208,6146820,6530380,5167251,4132614,4331054,9009719,4979522,3280487,7764144,6472427,9053253,4821456,3984985,4425674,7194503,2939361,6038879,6136795,9609985,1561401,3836807,7960662,8419204,4684951,6060989,9063690,5382308,6334548,5833572,9388198,8814849,5744033,4868148,1200775,6155197,5857192,1321624,9067535,4156234,2739959,4067108,3602661,8168441,4998748,5604919,4829833,5483520,9798538,3330474,2504852,4206909,1574035,1379440,9239746,3629440,8028366,1766845,8773513,1564834,9511657,7040695,7232955,4622467,6376022,7167312,3728591,2885940,4396835,8868270,7126800,9963195,6857360,8126831,5344406,3878555,7389236,9083740,5007949,4776962,9162017,8039764,2822631,7905044,1516357,9784667,6493438,7841873,9634292,3971252,2542480,3446517,4340805,4752929,6867660,3490188,3628890,9403579,5384231,3443496,9004089,6138854,1594360,7386215,9240707,3856857,5428863,2509521,9643905,7018722,9202941,5178375,4411254,7385116,1032135,5022506,3187652,5829727,7550186,7026824,2408035,9947540,9273666,7087936,3519851,2677337,8457244,2005661,4680969,7654968,2781570,4380081,5025390,3519851,9721084,1380264,2092041,1889892,2931121,7856018,3507766,5226303,4501617,8759506,6521591,6303924,5419250,4346023,2481506,6510330,3082870,7123367,4848236,7687789,8214035,6017868,4840545,8739181,4010116,7725280,6304473,6717834,6878509,8717071,7901062,6616348,4601318,7868927,3206878,3577255,2269744,3181472,1819305,4741119,5834259,1561264,7062255,9452194,2613754,3131347,7384979,6041351,2607711,7039733,7047561,2902420,1954162,9234252,9188522,8082885,4378570,3174057,3865371,2107696,6976425,7944458,9164901,7252593,5173294,8744537,1974624,9989013,4207321,5217926,2511032,1816970,1975036,7593170,5195953,3204681,2588897,5102981,1978607,2856002,7484954,7652359,6692153,1021011,7428237,5203643,2542892,8071487,3258789,8846160,9323516,7058685,6720581,9020843,3444595,1471038,4219131,5868041,4378570,3913986,5849914,1166580,6608795,5926269,9542007,7833496,7679412,9654891,2661956,2453765,9437225,8606246,1918182,2806838,9062179,7191619,1914337,6861343,9976791,2286773,4190429,2203964,6232238,7523681,6100128,7373992,6461715,7533432,4364425,3069549,5995483,3859741,9647476,2696838,9232879,3760177,9996704,3229263,1862838,5615081,5493682,2845703,2029144,3163070,6955413,6317382,9031143,8281463,4034286,6611404,5656692,6529281,2557037,7679138,3738891,7174179,1447692,4899871,1031311,2919723,9078796,6147369,9996154,1052597,5393844,9947265,8596496,4228469,3644683,5696243,9690322,3616119,1088714,2409408,9116287,6616210,8487594,6966949,9066986,8876098,1753799,3326492,2843505,4818298,3586044,6671554,9584304,9400833,3439788,9963745,9062454,5329025,4675338,4869110,9144851,4437484,6226333,2525177,6007293,2460083,9634979,2118820,6699844,6908035,2795578,3744247,9154464,7273742,2250106,4507247,1230575,4279830,6382064,2348434,8891067,3391723,4348358,9550247,3103195,8312500,1096817,1399078,1557693,9679061,5311035,8970581,3799728,4678497,3626144,2506088,5866256,6802154,2960510,8350540,3022857,9459060,2306274,6918197,1693374,6662902,2821807,9658737,3177215,7515991,7572296,6487258,7247650,3706619,2758773,1652862,7224166,6737197,6782653,9508499,6613464,6106307,7986755,3156753,1912689,1157928,3418365,2435089,6668395,2821121,4458084,6213150,7384841,4956588,5656692,9468399,7376190,1529541,7625167,8110488,4155548,4326660,9321182,7022293,2455001,2438247,6575973,6285659,7469299,7221694,2205200,8063247,1420089,6965988,1546844,1101211,1029525,1977233,7771560,1325469,1002197,7301620,8807983,6497558,9104614,4806625,6226608,6400192,4939971,1838119,5926544,5520736,1008239,7172256,2969299,1701065,2148345,9481033,6402252,3724060,5954696,3031097,1415832,4303314,2261367,1832077,2679534,9446289,6289642,5956481,6198181,4659408,2550033,5247451,2534515,3963287,5095428,2133926,2739273,8188217,3215667,3772262,5836044,9515914,7171432,1232360,3201110,3740264,8057205,2948013,2683380,3211685,3389938,5149536,5809814,2937438,1515121,2497161,1916946,9803070,3426055,2634490,2554565,6387695,1088165,3881027,9005325,4338607,8863464,7781997,8261825,4775314,5127700,7733795,7307662,2691619,7675155,7405029,3044555,5825195,7004577,1170974,5709426,6961456,8078491,6280166,4126296,6142974,3652511,6972854,8634674,3751251,3765670,8268692,6040664,6930145,7486328,5643508,7432495,6320541,5509338,5313095,5205291,1573486,7694519,9343841,2139007,5612060,4143325,1307479,9871459,7109771,6907073,8700454,8613937,1154495,8917709,7844482,8447906,4566436,7239135,8489517,6052200,3839691,8229141,2835678,4199905,4175323,8708282,8194808,4871032,1574859,5727005,5008087,8324310,1463348,2027908,8441726,9971160,4810195,5793334,3275268,9397537,4217071,9775192,7305740,5373931,9941085,2398422,1982727,9201156,4322540,4933517,4495849,5232894,6585449,7331008,2030380,7920013,2480133,3811264,4413452,9220382,1735946,9804443,7867004,1716995,4794265,9334091,9085937,6289505,6787734,2436599,6362701,1682113,9238510,2713180,9974731,8810867,5440124,1605346,7554306,2156448,8995162,1488616,5659713,9083602,1474746,8179290,3266479,6432189,3670639,3946395,9397125,2223464,2407348,7623107,5608078,1825759,9384216,8912216,1553573,3422897,2014999,9478012,3343109,1127990,4734252,2919174,6914352,5589126,6739257,9217086,7136825,6427658,1636795,4750732,8867584,3355194,6962417,7476028,3676681,3311248,7041381,5358688,6461715,2466674,1160812,5658477,7668701,3436492,1520339,1155868,7340484,5543807,9931472,4916351,4708572,9482269,6733489,3684921,1550277,1217529,7894882,8505722,1027053,1472686,7768676,7660186,6224548,1642013,7472045,9516738,9112304,7475891,9356063,7386627,1142272,2380706,6537246,8979507,5205017,6678558,9957977,7552108,7161132,8668594,6944839,1344284,2669509,6835388,1734024,1395782,1526519,2048233,4932006,8337219,7240371,8092910,5380798,6250778,3054855,9382293,7395965,8190826,7143417,6188568,4846725,3462585,3192459,4239730,2046173,3249038,7091369,8025619,6921768,7681472,3949142,9657363,7432083,9947952,7155502,5621810,9702407,4531005,9706253,6277420,4844802,7171432,7510910,7433593,5931900,8650329,8901092,5858154,4095260,4981582,3058837,1055618,3214157,8112823,8584686,2161529,9165863,8723663,3921676,9294815,7104553,2218933,4856338,6214111,9738388,4507385,9814605,5619476,3073944,6663589,6171264,3944747,7595642,2061828,1291549,3983886,9349472,8080001,1524597,7195190,5899627,8965774,1866134,8026992,2628311,2957077,8510116,9107772,6343338,8253860,4008056,8646896,4668334,3932388,3253845,5886444,5178100,2396499,2014038,2950347,5752685,4460418,2222091,3933761,6116195,6655349,5753921,7576416,4029617,9855392,7905731,3363021,5107925,9814193,8291625,3396118,7727340,8709106,7378662,2883880,9994369,1283721,6381515,9586502,9243728,1684173,5730987,8065444,5034179,1582687,1839355,8079864,3111434,6681854,4377883,6971893,4306335,6193237,1788269,6387695,2837463,4385025,5243469,3174743,4987213,4790969,8780242,4800720,2618560,4176147,4818984,7139160,2503341,3850814,9791671,2962158,9929962,5429962,5096252,3986495,4558197,7627365,9094863,9817352,4991607,7182281,5376953,5630050,8035095,2510208,6003860,2938125,7106887,3171859,1955535,7287338,1773712,7754669,7495941,8222000,4877899,7259323,4678359,1366531,4223800,3587005,3707168,2965866,2295425,1219451,7376739,3728454,9970886,6685424,5303894,2315887,9703781,2909561,2175811,2323165,7140121,5034454,7728713,5091583,6640106,2812194,1678405,8201538,2672393,4156784,8321426,5984634,2550033,2953506,6023086,1902389,1477493,4717636,4315399,2133514,6376846,5195816,4818298,9213790,2461318,1505645,7708389,3072433,4026733,2905441,4950271,9309646,2427673,3788604,5009185,8055969,6708496,2996353,3267303,8261962,7856567,5043243,5857742,4757736,8148254,6347595,3138214,7927566,9555328,1061660,9522094,7344879,3679702,9596115,2885391,5208862,1187316,2430694,6269180,7927566,8208404,1305557,1094345,3691787,5673171,5388214,4610794,3382659,1052047,6508132,9796203,1656845,1468566,2053451,3425094,7553344,4655014,8623550,3527130,1465820,9716827,3031921,7952148,3823211,9178497,9751296,2261642,4323776,9275726,9396713,8665298,9065475,3965347,4339019,9221206,8415771,3620239,6043273,4017669,5966918,7879364,1225357,1557693,1418029,5619750,3420288,4062301,4727935,8520965,4057769,9912384,1385345,3190261,1635009,5948928,9135787,8316482,4085784,7848876,2012527,4822143,2933731,4295349,4014236,6482864,3328826,7162643,2271255,2981796,9557113,9432693,9047897,6868209,5119186,8063522,3421249,8389816,6970932,1526794,9981323,6666061,8019989,2235137,9397674,2172653,4471405,9574966,1193222,2005249,3118026,1768218,3572723,3890502,7165664,9276138,4645675,1415008,1691864,3969055,9891784,3438964,9327087,8777359,2208221,2164550,3255218,9043640,4385986,8827209,9126037,7295166,6357345,1478454,2973831,9655166,1058364,2829772,8735198,6611129,8250564,6625549,2459808,6358993,6145446,6513763,8809906,3443222,1175506,7884445,5938491,3910003,2754791,6642028,6344024,7692321,7374542,4383651,1791976,6447158,1875610,7949401,4899871,5562210,9243316,1815460,1476806,2551406,6766448,3296005,1213958,2557037,9905792,9026611,9817352,3179687,7716079,5693908,2177871,2351318,7162918,6483001,7673095,6473388,7181182,7209884,9192642,2536437,6816848,3608978,9982421,6441802,3296966,8742614,5900588,7242019,3370437,5003005,1180038,9520996,3764846,3674896,3289688,2631469,9101318,2526824,8989807,5007400,7113479,5401260,7174453,3273345,5511123,2270706,1593536,6365859,5335891,1730178,7051544,7387725,6149566,5393157,4172851,1414047,7900924,7161407,4330230,4966888,5813796,5835769,2828125,9380371,6140365,6038192,7937316,2771408,5123031,4912918,4870758,1837982,4010116,2574890,6298431,3201385,2466812,6776748,3491561,2513092,7227188,6759307,5692810,9042953,7330047,3757431,8803588,5969116,6781829,1129501,8984313,9088272,2991958,5577041,1259963,3164169,1823287,5426803,6726211,7632995,2600433,4440368,5447265,5885894,7922348,5123031,7642471,7846130,9620559,1999069,5252807,7059509,5707778,4822280,9482543,3017227,8660079,8191787,6408432,2930847,9877914,8539230,9252243,2676239,4667510,2959274,3407928,5126190,6587783,7850250,7819076,3590988,2506912,4833679,3799865,6584762,2210281,4922119,8892715,4637023,7906829,3403945,1856384,9367874,3473297,7413269,3380325,2544815,4784790,7654968,9615203,6342239,9971298,4251541,2117309,4519607,7946517,3183120,1297866,6738845,1051910,3286804,8972640,3738891,2159606,7285964,5103530,6586410,7077911,4817749,6329193,7722259,1603561,5926681,9375427,3019973,4063812,9994644,6939620,2578460,4693328,6574325,7145065,7464492,9687576,1096542,1156280,6125946,6278930,8918533,8050064,3693298,2677200,1683486,6537109,2888824,4219543,1459091,8626159,3761962,7572845,9624130,3825820,3968780,9332580,1971603,1976409,3816619,2862869,9997940,2307785,6790069,4718322,6846374,8813613,1777969,3496368,4872543,9539810,7721435,7458587,2303665,3877731,4899459,2769210,5956069,4456573,4572067,7691223,1483673,7730087,9200744,7586166,8124221,3849990,6962142,1059600,8411376,1920242,4776962,5097625,6823440,6225646,9569747,6536422,7835830,9529373,6981643,4710769,5347152,2032440,9251419,6622802,7945831,8088516,5485855,2476974,2988937,5269012,3038101,7923171,9959075,7870986,2211242,2853256,9069732,7463119,3007064,6093948,3587417,7560760,3138900,7839126,1839767,7027923,5026901,8167617,6376571,7295303,8993240,9487762,3256179,5992187,1379440,4252777,2920959,7083404,4800170,3793411,8635635,1105880,1255706,5607391,8953414,8598556,2320556,7952972,5181121,5320098,5126464,5088424,8310302,2346237,9359497,9002166,7384567,9643218,4989135,3976333,5771224,3207702,6949234,5828079,1304595,2371093,1488204,6173599,6773727,8357406,6408294,9555328,4717910,9692520,1911865,6779769,5003417,3555969,6274536,2307785,9147460,4669708,8062423,2040130,4858810,8818420,2114013,7345428,1764511,8593612,3003219,2669921,6790618,1456893,4204849,9576339,4165985,6714675,8679168,5553833,9517425,4499008,9095275,5443008,2026672,2348159,7412719,4820083,2114974,7480285,6037643,2184051,8626983,2354614,6275634,6289505,8980880,7612533,9296875,2471069,1254608,5995071,1334533,9300170,7675155,9326675,8334060,1420776,9482681,6162338,3772125,9906066,7634506,9190582,6864776,4980621,4321441,2985504,1883026,7451583,1762176,2202453,6793502,6691879,2246124,2810958,2945541,5521011,6893066,9458099,9021118,3825271,6098617,2557449,1967208,7262207,4133438,1194869,4129455,7893096,7865768,4447372,3305892,5086364,4075759,3208389,6939208,4536224,8330490,7111282,5166290,9741546,2888275,8646896,8943939,6785263,8600479,9068771,9970336,1762588,9280670,1178115,1618530,3697692,9509460,6584213,6604125,3295181,7342956,8532638,7602783,2369445,9894943,3896545,5538314,9294677,8260726,6422164,2759735,1321487,3750839,8825698,9824768,3100723,1905136,5832061,8110076,3261810,3254257,4751968,2966964,2386199,6297744,8689193,9639648,4221878,6668258,6972305,7666915,9481719,7949813,2905578,2983993,4068893,1119064,5430648,8445571,1074844,9077972,5795669,9986267,2391555,9248260,9822845,8139328,2283752,1693374,2869735,4131240,6762603,8740417,8077941,2270980,2107284,3566955,7001831,5853759,8375259,3725296,9212966,6295822,7248474,3069274,3972213,5722198,6054946,5055191,8563949,9722595,9314178,1884674,9386138,3497467,6645874,9457138,1390701,1110000,9389160,2602355,2966140,1065917,1773025,4560668,8858108,9937103,9985168,4180130,1220413,3248764,1978744,8799468,8390914,3350250,1365570,5284805,7485504,8485122,2234451,2189544,2404602,6783477,5243881,6506759,1344696,7390609,4827224,8981018,9410720,7455017,4858947,2450195,3420425,7191207,9621932,8185333,4497222,9738250,4422927,8697296,8542800,1031723,7697265,4978424,7184341,8407806,1947021,6649032,3291748,8159240,5358276,1976959,1654510,5760513,1439041,4238906,4916351,4981994,6522415,5391647,4358245,9611770,1479003,5523620,4626174,8002960,7481796,3053894,8994476,3166503,5167526,6147781,4260742,2627899,4039230,4318557,6865875,3765258,6450592,5683197,2331268,5849777,2020767,6841018,1609466,3505157,6818222,9844543,1439590,1806671,4161727,7229934,9302505,7736267,8379104,4578521,1070449,2215637,9368972,1574035,7941986,9432556,1309539,1029113,2759872,6681716,6356933,2844879,7301071,7437988,8677932,7377288,9637863,6880569,6660156,3174057,5158874,5587478,8644012,8555709,2346786,7618026,9019470,7005401,9906204,1703262,4032501,7838989,8333786,1762863,3143569,9122741,3526306,2465850,5283157,4307983,3519302,7056213,3846557,7551559,6949920,1160125,7774307,5189910,6339355,2794616,7558563,6337158,4785751,8296295,8522476,1073608,4164199,9388610,6213287,8196319,8426071,9106262,8256332,2998275,9091156,4796463,4509582,6045196,5527465,9914581,7866455,6419692,9112030,1833175,4547760,9400970,2865753,2384552,8228454,8048828,3656906,7353118,2841583,6660018,9567001,7639175,4403564,3567642,6511566,7309448,8705261,7249710,5712310,2257522,1211624,2218246,7110458,4687561,3014617,1655746,4319107,5145690,5181259,4268157,7204940,2313140,8344085,1324645,8695922,1282760,1873413,4350143,6906112,2536437,9478836,5441497,9173278,8342300,8581115,2676376,3102645,5790725,3300399,2581344,1209014,7187911,4402877,6129516,9254028,8025482,7049758,7237350,6868759,6244735,7693283,1226455,6558395,6015396,6962966,5222869,9681259,5745407,3885696,6958709,6495498,1543685,9283279,5948654,9869125,5851013,2692443,9506988,8744674,4460968,4648147,3575607,1954162,4647460,8678619,3831451,7477539,7618713,7850387,9041580,9737701,4016433,4211715,7136001,1026779,5677841,1975311,8964263,7656478,5381347,7785430,8208404,4928024,3792312,2912307,4417709,7512557,4328857,9718750,5635406,5338775,7167449,1241424,3586044,4579208,2104400,1230850,8892166,5830688,9494354,6495361,4289169,8081100,6983703,6889770,2306961,5557952,7257400,4796051,2386474,3050186,7518600,3436630,6901718,7799987,3918792,9866241,8053634,5555618,7658538,3985122,6106307,4879959,3976608,9416625,6934402,4309494,6746124,1595596,5348388,2456649,5898254,4907012,1169189,4647735,5388626,6224136,9518524,2193664,2929748,9683593,4296173,3884460,1203933,4047058,8309890,5801712,9778625,5489837,8029602,6043823,1441375,1160125,5433120,4456710,7173080,1354446,1911590,3964248,7478637,7652221,1706008,7592483,2295013,5852111,9839462,9779861,7191894,7055389,4018493,3069549,7088897,2740234,8468368,7775405,2202453,1168365,6172912,1716995,6445648,1971328,6488357,9616577,6997436,4256210,4597885,4251403,6260665,4079055,5777130,4956176,1926696,4624389,3939117,7569137,8367843,3940353,6426834,5414031,2072952,1567993,3523422,5414718,2348022,6912017,1646820,1932601,7998428,9695816,9699523,1423660,1212448,3342422,7540847,6507171,9365539,3629714,2051803,7540298,3961776,9458236,1759292,7292007,5433807,1079238,6490966,9811035,2019119,3625869,5026763,8080276,6429992,5289886,5218612,9552169,2538909,9989013,8544448,8159515,6794601,4868148,7567077,4892868,5590774,5479263,8266906,3542373,2303253,3980590,2714279,2693130,7217575,1203659,2055099,9571945,6062225,1927520,1273422,6836624,1369415,1206130,3703598,5902236,9379959,3092895,3758117,9898788,7712097,9604354,1842376,1853500,4512878,3268402,3922088,6190216,8310577,5100921,7714981,6142974,6286895,6352264,8973876,8173522,9187973,8870880,2830322,8990081,9592819,8423873,4667098,3257827,1758468,2822631,2489883,3597442,8758407,3192733,9264739,3965072,4136734,4235610,1190887,2005386,6793365,8823089,9379272,2474227,2320968,8770904,6902542,9323104,5511398,8132461,2687774,9538986,7251495,8858795,2219345,1334396,3525619,9166824,3521362,6780456,2744628,6460342,3387741,4477172,2120056,1148727,2329895,1354995,9301132,2203689,1208877,8199890,9995468,3802337,5022644,2997863,2789672,5896057,8815811,6691329,1890853,3052383,8181900,4440643,3005828,5410736,9325714,7986343,2078857,7098373,9154190,1204071,8104995,1948257,1367492,1446594,4737823,6863677,6014160,5766830,8911804,3673385,7483993,9615615,1196792,2820159,5404418,2107421,2103164,4727249,9409347,8449142,6057556,8186843,2250930,2623092,2266860,3613098,8221176,3921401,1190063,1504409,3352722,9422119,7835418,6958709,2368209,4004486,4603790,8584686,4846313,5992187,1894561,9653381,9572631,3024642,3194107,7834320,4545974,6243225,5866668,5358825,6606872,5392471,1362960,9954544,4158294,7925231,6069641,9396301,2946640,7708389,5514968,6014709,1372299,3421661,5150497,4008468,5298126,2243103,7428649,8902191,7824295,2916702,9393417,3995971,7999801,1792938,2502792,8146469,2937164,6939071,5904022,8729019,9300720,4910720,6877136,9117935,3636032,9279434,1667831,2534515,8511627,9510559,1428466,3602523,6937561,3283370,7483444,3457229,2033676,2848999,9641845,6750656,3414657,9519485,2771545,7396926,5259674,8880355,3356979,7401870,7537002,7822784,7258224,7619949,1351837,3986770,5388900,2783355,5885345,7711685,7533843,8645797,5894409,7084091,2023925,9585128,3241348,5181808,8486633,7509124,4420455,2102203,7391571,6408020,4552703,5873672,2610733,5396316,5814620,7840362,9709548,5589263,4772842,6615524,1190475,4657211,4590332,7197799,6405685,2400756,4575637,7341857,1358840,9191680,5042007,5779602,2113876,8623138,6945663,8385284,6030639,1211624,8272674,3876358,5544769,8496246,3642486,2145874,6711380,2377685,7096176,7819900,7232131,8041687,5540786,4132888,1181274,3310287,6814514,8714462,1154083,6763565,8845474,6383575,1052734,4477722,8870193,9541183,5229187,8721603,5181121,6255996,2205200,6456222,2373291,1638992,8686996,9980773,8556671,2596588,8093048,3568054,8504623,7560211,8314971,7435653,9206100,4283401,6929321,7892547,6791992,1301025,7579025,2009506,7302032,6144348,1744049,4652954,4263351,2906402,5619476,5228500,9547088,4249618,3318664,9977890,4474014,5451385,3122970,4170928,6637084,5580062,3993637,6038879,2408584,4396011,7067474,1791290,3602249,5070022,4352478,5560974,5258575,3315643,7344192,6619781,4021240,2025161,2780471,2710296,7075027,5007125,6253387,7836242,2111541,1915847,1898132,8355621,7295303,5968704,1875610,7719787,9693756,3544433,4869796,7704544,1145706,3255493,6317245,3472610,1031860,7589187,1587219,2316024,4919235,4710357,8832290,8419067,9547775,1521026,7727890,1486557,8126968,6568695,9818313,4580718,7411621,1897857,3689453,8011749,5526229,1439590,8686996,6624313,9006011,1031448,7397201,7323867,1022659,7661285,8611053,3187515,2266174,7030807,1988632,5002456,1447555,3030685,2144638,9576477,4895065,6220428,6371353,4662017,9210083,5910064,9719985,6841293,2452667,9932708,9657226,7213043,4825027,6706710,9017822,1225082,2321380,5676330,3470275,4499008,9314453,1728942,7214279,5987243,5545181,1679092,4130966,3308502,1485870,3416030,4101303,8604049,4545288,2805877,1714660,7760848,5083892,8944076,8083297,4341766,6709320,7851348,6984664,5069198,3818130,8206207,6047531,6206283,2856552,1208740,7201782,8676147,8264846,4168457,4111053,4267471,6577621,1911727,1806671,5765869,4645263,9599685,4241104,9358261,2449234,8053222,9979949,7151107,1476669,2177322,6751754,1148864,1124420,7578201,5074142,1534347,3101135,8968246,2674316,5595993,3296829,1451263,9923645,3144943,9086761,5283157,1004257,4766937,7540847,3200012,2027496,3750564,3505432,5908416,9821609,3038925,8026718,5832611,6608383,9044326,6085433,6710281,7287475,6673751,9109970,6131713,8546234,6405960,5238250,1616333,1514984,6766036,2796127,5320922,7186264,8038940,6961318,2970397,8315383,1568405,8081375,4109130,7023391,7482070,1615234,2262878,9819137,4189880,1166305,1107666,7260147,2496063,1575958,6237045,1971740,8670928,6546585,3623809,8240676,3325531,5762435,4368408,4905502,4432128,6977523,5828079,7759201,8335571,8038803,2721008,9185089,3098388,5313919,6298019,5243469,1023483,4491729,7177612,1928619,5698440,4224899,1935623,4813766,4405349,8582626,1045181,9804031,9238922,2783630,3260299,8215820,3778030,2175399,7035339,5900039,7653457,9932296,8077117,6630218,7855743,2438110,8619705,4472229,5127288,2822357,5519500,7355453,5281784,1621139,9760635,1564010,5795806,1028564,1467605,5366516,5515106,4708984,8016555,4503128,6819732,4639083,2340744,7748764,2092453,2947463,7022430,6272064,3833236,3221023,2265899,3006378,2264389,9246887,5345092,3754959,8768981,1659179,9620010,1245819,6007843,2458297,6713989,5858016,8057067,8871841,4948623,1234832,6412139,5526779,6626510,4506011,5199249,7400085,1258590,1335357,2441131,9518112,9328323,7513244,3718154,2872482,8686172,9312942,6069915,4521530,3169250,7329635,2481369,9345626,2539459,6019790,7796005,9426788,2333190,2661682,3400787,6518432,2717163,6953353,8526733,1576919,1944000,9968826,4507247,3821975,3500900,5690200,9840835,7295028,8545684,1834411,5398788,4384613,5723571,6194335,7624618,2287048,1958282,6211776,7065826,3871688,7312057,9001205,7084503,8918945,8507644,6545211,6089553,6200378,6205596,5275878,5133193,3368927,6631866,2766326,1216979,2129257,6648345,5746505,3151260,1655197,6860656,8165008,3309600,9723968,1857208,5513595,5124679,9537612,9171768,9135513,3667617,5696105,5065490,1733062,1155456,7295852,8720642,4797424,8729431,8618469,2940185,1174819,8349166,5381072,4946838,9492019,6145721,8015182,2375488,8656646,7076538,8943801,5053405,9153228,6228530,9325851,8660079,5352508,6609756,8235595,3863174,6553588,5775894,5746368,7021057,6976562,6134460,3887207,3048950,2425750,9270370,2942520,1540664,3841339,4136734,4060379,6738983,2458023,8454223,6641342,3450637,7791198,2164138,2475189,2497436,5165878,1277404,9094314,4799072,8011611,2963394,9312530,8679718,6637908,5223281,1418579,9493942,6712203,2990997,8991867,8163360,4156784,2006210,2811096,4720794,8685211,6300903,6822616,2452804,7695617,2647125,7638488,7735992,9739898,5805557,2532318,6160552,5288925,7921936,3402160,8034545,2010192,3913024,7668701,8862503,8278717,8186294,5577865,2893081,5138687,9538436,7876892,3328140,5435317,4574264,1331100,9287811,6335372,2491119,5052169,8125869,5954284,6572814,9105850,7187225,7311096,9235763,4366760,3604034,9326538,5971450,2090805,3220886,7086151,2029556,9172729,6246246,1085006,8185333,1558105,7721298,1673873,8433761,5778503,2401443,1425445,3955734,7078598,6142837,9639099,8200164,1102584,2389770,4702804,7423568,6611816,5854034,6531890,4533752,5199249,7982772,7802185,7578750,3470687,5305953,2196548,8727920,3662261,1259277,1384796,4084274); + +# Cleanup +DROP VIEW v1; +DROP TABLE t1; + --echo End of 5.5 tests --echo # diff --git a/mysql-test/main/repair.result b/mysql-test/main/repair.result index 84773449e92..899ca1e1a32 100644 --- a/mysql-test/main/repair.result +++ b/mysql-test/main/repair.result @@ -233,3 +233,24 @@ i UNLOCK TABLES; DROP TABLE t1; # End of 10.0 tests +create table t1 (a int, b varchar(200)); +insert t1 select seq, repeat(200, seq) from seq_1_to_30; +delete from t1 where a % 13 = 0; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 28 +test.t1 repair status OK +delete from t1 where a % 11 = 0; +repair table t1 extended use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 26 +test.t1 repair status OK +delete from t1 where a % 7 = 0; +set myisam_repair_threads = 2; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 22 +test.t1 repair status OK +set myisam_repair_threads = default; +drop table t1; +# End of 10.2 tests diff --git a/mysql-test/main/repair.test b/mysql-test/main/repair.test index 75978ac482b..435eb99683a 100644 --- a/mysql-test/main/repair.test +++ b/mysql-test/main/repair.test @@ -1,6 +1,7 @@ # # Test of repair table # +--source include/have_sequence.inc --source include/default_charset.inc call mtr.add_suppression("character set is multi-byte"); @@ -246,3 +247,23 @@ UNLOCK TABLES; DROP TABLE t1; --echo # End of 10.0 tests + +# +# MDEV-17153 server crash on repair table ... use_frm +# +# Note, this test case doesn't crash, but shows spurios warnings +# unless the bug is fixed +# +create table t1 (a int, b varchar(200)); +insert t1 select seq, repeat(200, seq) from seq_1_to_30; +delete from t1 where a % 13 = 0; +repair table t1 use_frm; +delete from t1 where a % 11 = 0; +repair table t1 extended use_frm; +delete from t1 where a % 7 = 0; +set myisam_repair_threads = 2; +repair table t1 use_frm; +set myisam_repair_threads = default; +drop table t1; + +--echo # End of 10.2 tests diff --git a/mysql-test/main/row.result b/mysql-test/main/row.result index 40d3e2640f0..12ab4208c11 100644 --- a/mysql-test/main/row.result +++ b/mysql-test/main/row.result @@ -545,3 +545,16 @@ SELECT (1,null) NOT IN ((2,2),(3,3)), (1,null) NOT IN ((2,2)), (1,null) NOT IN ( # # End of 10.1 tests # +# +# Start of 10.5 tests +# +# +# MDEV-20809 EXTRACT from INET6 value does not produce any warnings +# +CREATE TABLE t1 (a GEOMETRY); +SELECT EXTRACT(DAY FROM a) FROM t1; +ERROR HY000: Illegal parameter data type geometry for operation 'extract(day)' +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/row.test b/mysql-test/main/row.test index 80c61c414bf..d78d61b078a 100644 --- a/mysql-test/main/row.test +++ b/mysql-test/main/row.test @@ -314,3 +314,21 @@ SELECT (1,null) NOT IN ((2,2),(3,3)), (1,null) NOT IN ((2,2)), (1,null) NOT IN ( --echo # --echo # End of 10.1 tests --echo # + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-20809 EXTRACT from INET6 value does not produce any warnings +--echo # + +CREATE TABLE t1 (a GEOMETRY); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT EXTRACT(DAY FROM a) FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/selectivity.result b/mysql-test/main/selectivity.result index f84d2eae05a..591294aff10 100644 --- a/mysql-test/main/selectivity.result +++ b/mysql-test/main/selectivity.result @@ -1866,5 +1866,20 @@ id select_type table type possible_keys key key_len ref rows Extra set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +# +# MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * from t1 WHERE a = 5 and b = 5; +a b +5 5 +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; # End of 10.1 tests set @@global.histogram_size=@save_histogram_size; diff --git a/mysql-test/main/selectivity.test b/mysql-test/main/selectivity.test index d0158fb717e..2a0cc823eb4 100644 --- a/mysql-test/main/selectivity.test +++ b/mysql-test/main/selectivity.test @@ -1267,6 +1267,18 @@ set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +--echo # +--echo # MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT * from t1 WHERE a = 5 and b = 5; +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; + --echo # End of 10.1 tests # diff --git a/mysql-test/main/selectivity_innodb.result b/mysql-test/main/selectivity_innodb.result index 0d9a55a0bdb..7a8f837d4e2 100644 --- a/mysql-test/main/selectivity_innodb.result +++ b/mysql-test/main/selectivity_innodb.result @@ -1876,6 +1876,21 @@ id select_type table type possible_keys key key_len ref rows Extra set optimizer_switch= @save_optimizer_switch; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +# +# MDEV-21495: Conditional jump or move depends on uninitialised value in sel_arg_range_seq_next +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 SELECT seq, seq from seq_1_to_100; +set optimizer_use_condition_selectivity=4; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * from t1 WHERE a = 5 and b = 5; +a b +5 5 +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1; # End of 10.1 tests set @@global.histogram_size=@save_histogram_size; set optimizer_switch=@save_optimizer_switch_for_selectivity_test; diff --git a/mysql-test/main/sp-error.result b/mysql-test/main/sp-error.result index b7d9a3a5cc8..703af07569b 100644 --- a/mysql-test/main/sp-error.result +++ b/mysql-test/main/sp-error.result @@ -443,9 +443,7 @@ create procedure nodb.bug3339() begin end| ERROR 42000: Unknown database 'nodb' create procedure bug2653_1(a int, out b int) set b = aa| -call bug2653_1(1, @b)| -ERROR 42S22: Unknown column 'aa' in 'field list' -drop procedure bug2653_1| +ERROR 42000: Undeclared variable: aa create procedure bug2653_2(a int, out b int) begin if aa < 0 then @@ -1205,9 +1203,7 @@ set selectstr = concat(selectstr, c.operatorid, 'in (',conditionstr, ')'); end| -call bug15091(); -ERROR 42S02: Unknown table 'c' in field list -drop procedure bug15091; +ERROR 42000: Undeclared variable: c drop function if exists bug16896; create aggregate function bug16896() returns int return 1; ERROR HY000: Aggregate specific instruction(FETCH GROUP NEXT ROW) missing from the aggregate function diff --git a/mysql-test/main/sp-error.test b/mysql-test/main/sp-error.test index 95a7372a6f2..0a545b99f42 100644 --- a/mysql-test/main/sp-error.test +++ b/mysql-test/main/sp-error.test @@ -607,13 +607,10 @@ create procedure nodb.bug3339() begin end| # # BUG#2653 # +--error ER_SP_UNDECLARED_VAR create procedure bug2653_1(a int, out b int) set b = aa| ---error ER_BAD_FIELD_ERROR -call bug2653_1(1, @b)| - -drop procedure bug2653_1| --error ER_BAD_FIELD_ERROR create procedure bug2653_2(a int, out b int) @@ -1714,6 +1711,7 @@ drop procedure if exists bug15091; --enable_warnings delimiter |; +--error ER_SP_UNDECLARED_VAR create procedure bug15091() begin declare selectstr varchar(6000) default ' '; @@ -1726,15 +1724,6 @@ begin end| delimiter ;| -# The error message used to be: -# ERROR 1109 (42S02): Unknown table 'c' in order clause -# but is now rephrased to something less misleading: -# ERROR 1109 (42S02): Unknown table 'c' in field list ---error ER_UNKNOWN_TABLE -call bug15091(); - -drop procedure bug15091; - # # BUG#16896: Stored function: unused AGGREGATE-clause in CREATE FUNCTION diff --git a/mysql-test/main/sp-security.result b/mysql-test/main/sp-security.result index 7d2098f62be..2c48883a509 100644 --- a/mysql-test/main/sp-security.result +++ b/mysql-test/main/sp-security.result @@ -802,3 +802,21 @@ connection default; DROP DATABASE u1; DROP USER u1@localhost; set @@global.character_set_server=@save_character_set_server; +# +# Start of 10.5 tests +# +# +# MDEV-20366 Server crashes in get_current_user upon SET PASSWORD via SP +# +CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x'); +CALL p1(); +ERROR 28000: Can't find any matching row in the user table +DROP PROCEDURE p1; +CREATE USER foo@localhost; +CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x'); +CALL p1(); +DROP PROCEDURE p1; +DROP USER foo@localhost; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/sp-security.test b/mysql-test/main/sp-security.test index c375815b29a..e7790bf703a 100644 --- a/mysql-test/main/sp-security.test +++ b/mysql-test/main/sp-security.test @@ -1078,3 +1078,30 @@ DROP DATABASE u1; DROP USER u1@localhost; set @@global.character_set_server=@save_character_set_server; + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-20366 Server crashes in get_current_user upon SET PASSWORD via SP +--echo # + +# Testing without the user +CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x'); +--error ER_PASSWORD_NO_MATCH +CALL p1(); +DROP PROCEDURE p1; + +# Testing with the user +CREATE USER foo@localhost; +CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x'); +CALL p1(); +DROP PROCEDURE p1; +DROP USER foo@localhost; + + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/sp-vars.result b/mysql-test/main/sp-vars.result index 236695a6c0f..4952746c4e0 100644 --- a/mysql-test/main/sp-vars.result +++ b/mysql-test/main/sp-vars.result @@ -1310,3 +1310,406 @@ t1 CREATE TABLE "t1" ( "var" char(1) DEFAULT NULL ) DROP TABLE t1; +# +# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable +# +# +# Simple cases (without subqueries) - the most typical problem: +# a typo in an SP variable name +# +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +IF (a < 0) THEN +SET res= a_long_variable_name_with_a_typo; +END IF; +END; +$$ +ERROR 42000: Undeclared variable: a_long_variable_name_with_a_typo +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +IF (a < 0) THEN +SET res= 1 + a_long_variable_name_with_a_typo; +END IF; +END; +$$ +ERROR 42000: Undeclared variable: a_long_variable_name_with_a_typo +# +# Complex cases with subqueries +# +# +# Maybe a table field identifier (there are some tables) - no error +# +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 USING (c1)); +END; +$$ +DROP PROCEDURE p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 ON (c1=c2)); +END; +$$ +DROP PROCEDURE p1; +# +# One unknown identifier, no tables +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=unknown_ident; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=unknown_ident1.unknown_ident2; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident1 +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=unknown_ident1.unknown_ident2.unknown_ident3; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident1 +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident FROM dual); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident FROM dual)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT 1 WHERE unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT 1 WHERE unknown_ident=1); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT 1 LIMIT unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# GROUP, HAVING, ORDER are not tested yet for unknown identifiers +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT 1 GROUP BY unknown_ident); +END; +$$ +DROP PROCEDURE p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(SELECT 1 HAVING unknown_ident); +END; +$$ +DROP PROCEDURE p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT 1 ORDER BY unknown_ident); +END; +$$ +DROP PROCEDURE p1; +# +# HAVING + aggregate_function(unknown_identifier) is a special case +# +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(SELECT 1 HAVING SUM(unknown_ident)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# Known indentifier + unknown identifier, no tables +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=a+unknown_ident; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=a+(SELECT unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=a+(SELECT unknown_ident FROM dual); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (a+(SELECT unknown_ident))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (a+(SELECT unknown_ident FROM dual))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# Unknown indentifier + known identifier, no tables +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=unknown_ident+a; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident)+a; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident FROM dual)+a; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident)+a); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident FROM dual)+a); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# Maybe a table field indentifier + unknown identifier +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT c1 FROM t1)+unknown_ident; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# Unknown indentifier + maybe a table field identifier +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=unknown_ident+(SELECT c1 FROM t1); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident)+(SELECT c1 FROM t1); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident)+(SELECT c1 FROM t1)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +SET a=(SELECT (SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# Maybe a table field identifier + maybe a field table identifier +# +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +-- c2 does not have a table on its level +-- but it can be a field of a table on the uppder level, i.e. t1 +SET a=(SELECT c1+(SELECT c2) FROM t1); +END; +$$ +DROP PROCEDURE p1; +# +# TVC - unknown identifier +# +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(unknown_ident)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(1),(unknown_ident)); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES((SELECT unknown_ident))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(1),((SELECT unknown_ident))); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(1) LIMIT unknown_ident); +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# TVC - ORDER BY - not tested yet for unknown identifiers +# +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(1) ORDER BY unknown_ident); +END; +$$ +DROP PROCEDURE p1; +# +# TVC - maybe a table field identifier - no error +# +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES((SELECT c1 FROM t1))); +END; +$$ +DROP PROCEDURE p1; +CREATE PROCEDURE p1(a INT) +BEGIN +DECLARE res INT DEFAULT 0; +SET res=(VALUES(1),((SELECT c1 FROM t1))); +END; +$$ +DROP PROCEDURE p1; +# +# Functions DEFAULT(x) and VALUE(x) +# +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=DEFAULT(unknown_ident); +SELECT res; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +CREATE PROCEDURE p1() +BEGIN +DECLARE res INT DEFAULT 0; +SET res=VALUE(unknown_ident); +SELECT res; +END; +$$ +ERROR 42000: Undeclared variable: unknown_ident +# +# End of MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable +# diff --git a/mysql-test/main/sp-vars.test b/mysql-test/main/sp-vars.test index ba8cd4f5ca8..9edf245acbe 100644 --- a/mysql-test/main/sp-vars.test +++ b/mysql-test/main/sp-vars.test @@ -1603,3 +1603,594 @@ $$ DELIMITER ;$$ SHOW CREATE TABLE t1; DROP TABLE t1; + + + +--echo # +--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable +--echo # + +--echo # +--echo # Simple cases (without subqueries) - the most typical problem: +--echo # a typo in an SP variable name +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + IF (a < 0) THEN + SET res= a_long_variable_name_with_a_typo; + END IF; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + IF (a < 0) THEN + SET res= 1 + a_long_variable_name_with_a_typo; + END IF; +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Complex cases with subqueries +--echo # + +--echo # +--echo # Maybe a table field identifier (there are some tables) - no error +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 USING (c1)); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 ON (c1=c2)); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +--echo # +--echo # One unknown identifier, no tables +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=unknown_ident; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=unknown_ident1.unknown_ident2; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=unknown_ident1.unknown_ident2.unknown_ident3; +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident FROM dual); +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident)); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident FROM dual)); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT 1 WHERE unknown_ident); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT 1 WHERE unknown_ident=1); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT 1 LIMIT unknown_ident); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # GROUP, HAVING, ORDER are not tested yet for unknown identifiers +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT 1 GROUP BY unknown_ident); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(SELECT 1 HAVING unknown_ident); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT 1 ORDER BY unknown_ident); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +--echo # +--echo # HAVING + aggregate_function(unknown_identifier) is a special case +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(SELECT 1 HAVING SUM(unknown_ident)); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Known indentifier + unknown identifier, no tables +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=a+unknown_ident; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=a+(SELECT unknown_ident); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=a+(SELECT unknown_ident FROM dual); +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (a+(SELECT unknown_ident))); +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (a+(SELECT unknown_ident FROM dual))); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Unknown indentifier + known identifier, no tables +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=unknown_ident+a; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident)+a; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident FROM dual)+a; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident)+a); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident FROM dual)+a); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Maybe a table field indentifier + unknown identifier +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT c1 FROM t1)+unknown_ident; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual); +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident))); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual))); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Unknown indentifier + maybe a table field identifier +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=unknown_ident+(SELECT c1 FROM t1); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident)+(SELECT c1 FROM t1); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident)+(SELECT c1 FROM t1)); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + SET a=(SELECT (SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1)); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # Maybe a table field identifier + maybe a field table identifier +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + -- c2 does not have a table on its level + -- but it can be a field of a table on the uppder level, i.e. t1 + SET a=(SELECT c1+(SELECT c2) FROM t1); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +--echo # +--echo # TVC - unknown identifier +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(unknown_ident)); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(1),(unknown_ident)); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES((SELECT unknown_ident))); +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(1),((SELECT unknown_ident))); +END; +$$ +DELIMITER ;$$ + + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(1) LIMIT unknown_ident); +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # TVC - ORDER BY - not tested yet for unknown identifiers +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(1) ORDER BY unknown_ident); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +--echo # +--echo # TVC - maybe a table field identifier - no error +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES((SELECT c1 FROM t1))); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + +DELIMITER $$; +CREATE PROCEDURE p1(a INT) +BEGIN + DECLARE res INT DEFAULT 0; + SET res=(VALUES(1),((SELECT c1 FROM t1))); +END; +$$ +DELIMITER ;$$ +DROP PROCEDURE p1; + + +--echo # +--echo # Functions DEFAULT(x) and VALUE(x) +--echo # + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=DEFAULT(unknown_ident); + SELECT res; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_SP_UNDECLARED_VAR +CREATE PROCEDURE p1() +BEGIN + DECLARE res INT DEFAULT 0; + SET res=VALUE(unknown_ident); + SELECT res; +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # End of MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable +--echo # diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 376f44e3b01..dd7e12949f4 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -3220,9 +3220,7 @@ Warnings: Note 4092 Unknown VIEW: 'test.tv' DROP TABLE IF EXISTS tt1,tt2,tt3| Warnings: -Note 1051 Unknown table 'test.tt1' -Note 1051 Unknown table 'test.tt2' -Note 1051 Unknown table 'test.tt3' +Note 1051 Unknown table 'test.tt1,test.tt2,test.tt3' CREATE TABLE tt1 (a1 int, a2 int, a3 int, data varchar(10))| CREATE TABLE tt2 (a2 int, data2 varchar(10))| CREATE TABLE tt3 (a3 int, data3 varchar(10))| diff --git a/mysql-test/main/sp2.result b/mysql-test/main/sp2.result new file mode 100644 index 00000000000..55f3d80f25b --- /dev/null +++ b/mysql-test/main/sp2.result @@ -0,0 +1,20 @@ +CREATE DATABASE test1; +CREATE PROCEDURE test1.sp3() BEGIN END; +SHOW PROCEDURE STATUS; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +mtr add_suppression PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci +mtr check_testcase PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci +mtr check_warnings PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci +mysql AddGeometryColumn PROCEDURE mariadb.sys@localhost # # INVOKER latin1 latin1_swedish_ci latin1_swedish_ci +mysql DropGeometryColumn PROCEDURE mariadb.sys@localhost # # INVOKER latin1 latin1_swedish_ci latin1_swedish_ci +test sp2 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +test1 sp1 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +test1 sp3 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +DROP PROCEDURE sp2; +DROP DATABASE test1; +select count(*) from mysql.event; +count(*) +416 +flush tables; +show events; +truncate table mysql.event; diff --git a/mysql-test/main/sp2.test b/mysql-test/main/sp2.test new file mode 100644 index 00000000000..a638bf1e706 --- /dev/null +++ b/mysql-test/main/sp2.test @@ -0,0 +1,37 @@ +--source include/not_embedded.inc + +# +# MDEV-18457 Assertion `(bitmap->map + (bitmap->full_head_size/6*6)) <= +# full_head_end' failed in _ma_check_bitmap +# +# test 1 +# + +CREATE DATABASE test1; +--disable_query_log +--let $a=`select repeat('a',3023)` +--eval CREATE PROCEDURE test1.sp1() SELECT '$a' +--let $a=`select repeat('a',114513)` +--eval CREATE PROCEDURE test.sp2() SELECT '$a' +--enable_query_log + +CREATE PROCEDURE test1.sp3() BEGIN END; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS; + +# Cleanup +DROP PROCEDURE sp2; +DROP DATABASE test1; + +# +# MDEV-18457, test 2 +# +--disable_query_log +INSERT INTO `mysql`.`event` VALUES ('test','ev_28716_248','UPDATE IGNORE `GLOBAL_STATUS` SET `VARIABLE_NAME` = 138 ORDER BY `VARIABLE_NAME` LIMIT 6','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:27:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `GLOBAL_STATUS` SET `VARIABLE_NAME` = 138 ORDER BY `VARIABLE_NAME` LIMIT 6'),('test','ev_28718_1','SELECT `VARIABLE_NAME` FROM `INNODB_SYS_TABLES` ORDER BY `N_COLS` LIMIT 14','root@localhost',NULL,5,'SECOND','2020-05-18 08:19:53','2020-05-18 08:19:53','2020-05-18 08:23:04','2020-05-18 08:19:53','2020-05-18 08:23:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `VARIABLE_NAME` FROM `INNODB_SYS_TABLES` ORDER BY `N_COLS` LIMIT 14'),('test','ev_28714_146','UPDATE `oltp60` SET `k` = \'beside\' ORDER BY `c` LIMIT 5','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:23','2020-05-18 08:21:23','2020-05-18 08:22:30','2020-05-18 08:21:23','2020-05-18 08:23:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `oltp60` SET `k` = \'beside\' ORDER BY `c` LIMIT 5'),('test','ev_28714_213','START TRANSACTION','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:09','2020-05-18 08:22:09','2020-05-18 08:22:43','2020-05-18 08:22:09','2020-05-18 08:25:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28716_2','INSERT IGNORE INTO `oltp154` ( `pad`, _next_field ) VALUES ( \'\', DEFAULT ) ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:19:53','2020-05-18 08:19:53','2020-05-18 08:23:04','2020-05-18 08:19:53','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp154` ( `pad`, ) VALUES ( \'\', DEFAULT ) ;'),('test','ev_28716_233','UPDATE IGNORE `help_category` SET `name` = NULL ORDER BY `url` LIMIT 8 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:43','2020-05-18 08:22:43',NULL,'2020-05-18 08:22:43','2020-05-18 08:25:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_category` SET `name` = NULL ORDER BY `url` LIMIT 8 ;'),('test','ev_28716_189','INSERT IGNORE INTO `oltp21` ( `c` ) VALUES ( \'p\' )','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:20','2020-05-18 08:22:20','2020-05-18 08:22:59','2020-05-18 08:22:20','2020-05-18 08:25:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp21` ( `c` ) VALUES ( \'p\' )'),('test','ev_28718_4','COMMIT ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:19:53','2020-05-18 08:19:53','2020-05-18 08:22:34','2020-05-18 08:19:53','2020-05-18 08:22:56','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT ;'),('test','ev_28718_129','INSERT INTO `innodb_table_stats` SELECT * FROM `time_zone_leap_second`','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:42','2020-05-18 08:21:42','2020-05-18 08:22:59','2020-05-18 08:21:42','2020-05-18 08:24:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `innodb_table_stats` SELECT * FROM `time_zone_leap_second`'),('test','ev_28714_214','REPLACE INTO `oltp45` ( `c`, _next_field ) VALUES ( 163, NULL )','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:10','2020-05-18 08:22:10','2020-05-18 08:22:45','2020-05-18 08:22:10','2020-05-18 08:26:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp45` ( `c`, ) VALUES ( 163, NULL )'),('test','ev_28716_4','START TRANSACTION','root@localhost',NULL,5,'SECOND','2020-05-18 08:19:54','2020-05-18 08:19:54','2020-05-18 08:22:37','2020-05-18 08:19:54','2020-05-18 08:23:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28716_5','REPLACE INTO `PLUGINS` () VALUES ()','root@localhost',NULL,3,'SECOND','2020-05-18 08:19:54','2020-05-18 08:19:54','2020-05-18 08:23:05','2020-05-18 08:19:54','2020-05-18 08:23:49','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `PLUGINS` () VALUES ()'),('test','ev_28714_266','SELECT * FROM `oltp54` ORDER BY `id` LIMIT 177 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:44','2020-05-18 08:22:44',NULL,'2020-05-18 08:22:44','2020-05-18 08:25:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp54` ORDER BY `id` LIMIT 177 ;'),('test','ev_28716_6','REPLACE INTO `TABLE_PRIVILEGES` ( `TABLE_SCHEMA`, _next_field ) VALUES ( 40, \'\' )','root@localhost',NULL,4,'SECOND','2020-05-18 08:19:54','2020-05-18 08:19:54','2020-05-18 08:22:44','2020-05-18 08:19:54','2020-05-18 08:23:35','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `TABLE_PRIVILEGES` ( `TABLE_SCHEMA`, ) VALUES ( 40, \'\' )'),('test','ev_28718_8','REPLACE INTO `column_stats` ( `hist_type`, _next_field ) VALUES ( \'f\', DEFAULT ) ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:19:54','2020-05-18 08:19:54','2020-05-18 08:23:05','2020-05-18 08:19:54','2020-05-18 08:24:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `column_stats` ( `hist_type`, ) VALUES ( \'f\', DEFAULT ) ;'),('test','ev_28716_117','SHOW EXPLAIN FOR 236','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:23','2020-05-18 08:21:23','2020-05-18 08:22:31','2020-05-18 08:21:23','2020-05-18 08:24:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 236'),('test','ev_28714_268','REPLACE INTO `INNODB_SYS_INDEXES` ( `TABLE_ID` ) VALUES ( \'\' )','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:46','2020-05-18 08:22:46',NULL,'2020-05-18 08:22:46','2020-05-18 08:24:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `INNODB_SYS_INDEXES` ( `TABLE_ID` ) VALUES ( \'\' )'),('test','ev_28714_271','SELECT `ROLE_NAME` FROM `INNODB_FT_BEING_DELETED` ORDER BY `DOC_ID` LIMIT 12','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:46','2020-05-18 08:22:46',NULL,'2020-05-18 08:22:46','2020-05-18 08:23:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `ROLE_NAME` FROM `INNODB_FT_BEING_DELETED` ORDER BY `DOC_ID` LIMIT 12'),('test','ev_28714_89','SELECT * FROM `oltp118` ORDER BY `pad` LIMIT 217','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:52','2020-05-18 08:20:52','2020-05-18 08:22:32','2020-05-18 08:20:52','2020-05-18 08:24:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp118` ORDER BY `pad` LIMIT 217'),('test','ev_28716_208','SHOW SLAVE HOSTS','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:29','2020-05-18 08:22:29',NULL,'2020-05-18 08:22:29','2020-05-18 08:23:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW SLAVE HOSTS'),('test','ev_28716_8','INSERT IGNORE INTO `time_zone_transition` ( `Transition_type_id` ) VALUES ( \'w\' )','root@localhost',NULL,6,'SECOND','2020-05-18 08:19:54','2020-05-18 08:19:54','2020-05-18 08:22:33','2020-05-18 08:19:54','2020-05-18 08:23:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_transition` ( `Transition_type_id` ) VALUES ( \'w\' )'),('test','ev_28714_6','UPDATE IGNORE `INNODB_METRICS` SET `TIME_ELAPSED` = NULL ORDER BY `COMMENT` LIMIT 2','root@localhost',NULL,2,'SECOND','2020-05-18 08:19:55','2020-05-18 08:19:55','2020-05-18 08:23:01','2020-05-18 08:19:55','2020-05-18 08:23:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `INNODB_METRICS` SET `TIME_ELAPSED` = NULL ORDER BY `COMMENT` LIMIT 2'),('test','ev_28716_9','SELECT * FROM `gtid_slave_pos` INTO OUTFILE \'load_gtid_slave_pos\' ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:19:55','2020-05-18 08:19:55','2020-05-18 08:22:41','2020-05-18 08:19:55','2020-05-18 08:23:58','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `gtid_slave_pos` INTO OUTFILE \'load_gtid_slave_pos\' ;'),('test','ev_28716_41','INSERT IGNORE INTO `time_zone_leap_second` ( `Transition_time`, _next_field ) VALUES ( NULL, \'\' )','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:11','2020-05-18 08:20:11','2020-05-18 08:22:32','2020-05-18 08:20:11','2020-05-18 08:24:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_leap_second` ( `Transition_time`, ) VALUES ( NULL, \'\' )'),('test','ev_28714_257','INSERT IGNORE INTO `time_zone_transition_type` ( `Is_DST`, _next_field ) VALUES ( \'\', 115 ) ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:37','2020-05-18 08:22:37',NULL,'2020-05-18 08:22:37','2020-05-18 08:25:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_transition_type` ( `Is_DST`, ) VALUES ( \'\', 115 ) ;'),('test','ev_28718_12','DELETE FROM `help_category` ORDER BY `name` LIMIT 8','root@localhost',NULL,6,'SECOND','2020-05-18 08:19:55','2020-05-18 08:19:55','2020-05-18 08:22:34','2020-05-18 08:19:55','2020-05-18 08:22:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `help_category` ORDER BY `name` LIMIT 8'),('test','ev_28714_8','SELECT `SEGMENT_NUMBER` FROM `INNODB_BUFFER_PAGE_LRU` ORDER BY `IS_HASHED` LIMIT 202','root@localhost',NULL,9,'SECOND','2020-05-18 08:19:55','2020-05-18 08:19:55','2020-05-18 08:22:26','2020-05-18 08:19:55','2020-05-18 08:24:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `SEGMENT_NUMBER` FROM `INNODB_BUFFER_PAGE_LRU` ORDER BY `IS_HASHED` LIMIT 202'),('test','ev_28714_9','DELETE FROM `time_zone_name` ORDER BY `Name` LIMIT 9 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:19:55','2020-05-18 08:19:55','2020-05-18 08:22:26','2020-05-18 08:19:55','2020-05-18 08:23:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `time_zone_name` ORDER BY `Name` LIMIT 9 ;'),('test','ev_28714_282','SHOW EXPLAIN FOR 88','root@localhost',NULL,8,'SECOND','2020-05-18 08:23:00','2020-05-18 08:23:00',NULL,'2020-05-18 08:23:00','2020-05-18 08:23:22','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 88'),('test','ev_28714_10','COMMIT ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:19:56','2020-05-18 08:19:56','2020-05-18 08:22:30','2020-05-18 08:19:56','2020-05-18 08:23:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT ;'),('test','ev_28714_187','REPLACE INTO `oltp140` () VALUES (),(),(),() ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:49','2020-05-18 08:21:49','2020-05-18 08:23:06','2020-05-18 08:21:49','2020-05-18 08:23:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp140` () VALUES (),(),(),() ;'),('test','ev_28718_15','DELETE FROM `oltp153` ORDER BY `id` LIMIT 7','root@localhost',NULL,6,'SECOND','2020-05-18 08:19:56','2020-05-18 08:19:56','2020-05-18 08:22:35','2020-05-18 08:19:56','2020-05-18 08:23:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp153` ORDER BY `id` LIMIT 7'),('test','ev_28714_11','UPDATE IGNORE `oltp73` SET `k` = \'\' ORDER BY `k` LIMIT 6','root@localhost',NULL,8,'SECOND','2020-05-18 08:19:57','2020-05-18 08:19:57','2020-05-18 08:23:00','2020-05-18 08:19:57','2020-05-18 08:23:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp73` SET `k` = \'\' ORDER BY `k` LIMIT 6'),('test','ev_28714_230','SELECT * FROM `general_log` ORDER BY `command_type` LIMIT 215','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:18','2020-05-18 08:22:18','2020-05-18 08:22:56','2020-05-18 08:22:18','2020-05-18 08:22:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `general_log` ORDER BY `command_type` LIMIT 215'),('test','ev_28716_11','INSERT INTO `func` SELECT * FROM `time_zone_leap_second` ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:19:57','2020-05-18 08:19:57','2020-05-18 08:22:34','2020-05-18 08:19:57','2020-05-18 08:24:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `func` SELECT * FROM `time_zone_leap_second` ;'),('test','ev_28714_12','CREATE INDEX m ON `oltp79` ( q(251) )','root@localhost',NULL,1,'SECOND','2020-05-18 08:19:57','2020-05-18 08:19:57','2020-05-18 08:22:33','2020-05-18 08:19:57','2020-05-18 08:23:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','CREATE INDEX m ON `oltp79` ( q(251) )'),('test','ev_28718_16','SELECT * FROM test.`oltp125` AS table1 WHERE (NOT table1.`id` <= \'pl\' OR table1.`pad` != table1.`k`) LIMIT 8','root@localhost',NULL,9,'SECOND','2020-05-18 08:19:57','2020-05-18 08:19:57','2020-05-18 08:22:31','2020-05-18 08:19:57','2020-05-18 08:23:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp125` AS table1 WHERE (NOT table1.`id` <= \'pl\' OR table1.`pad` != table1.`k`) LIMIT 8'),('test','ev_28716_179','SELECT * FROM (test.`oltp86` AS table1 STRAIGHT_JOIN INFORMATION_SCHEMA.`VIEWS` AS table2 ON ( table2.`TABLE_CATALOG` = table1.`id` ) ) WHERE table1.`k` != table1.`id` HAVING table1.`c` != \'2010-11-29 21:40:34.028315\' IS NULL LIMIT 1 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:18','2020-05-18 08:22:18','2020-05-18 08:22:57','2020-05-18 08:22:18','2020-05-18 08:25:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp86` AS table1 STRAIGHT_JOIN INFORMATION_SCHEMA.`VIEWS` AS table2 ON ( table2.`TABLE_CATALOG` = table1.`id` ) ) WHERE table1.`k` != table1.`id` HAVING table1.`c` != \'2010-11-29 21:40:34.028315\' IS NULL LIMIT 1 ;'),('test','ev_28718_17','START TRANSACTION','root@localhost',NULL,4,'SECOND','2020-05-18 08:19:58','2020-05-18 08:19:58','2020-05-18 08:22:46','2020-05-18 08:19:58','2020-05-18 08:23:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28714_250','INSERT IGNORE INTO `user_variables` ( `VARIABLE_NAME` ) VALUES ( NULL ) ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:34','2020-05-18 08:22:34',NULL,'2020-05-18 08:22:34','2020-05-18 08:23:31','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `user_variables` ( `VARIABLE_NAME` ) VALUES ( NULL ) ;'),('test','ev_28714_82','SELECT * FROM `TRIGGERS` ORDER BY `SQL_MODE` LIMIT 252 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:50','2020-05-18 08:20:50','2020-05-18 08:22:31','2020-05-18 08:20:50','2020-05-18 08:24:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `TRIGGERS` ORDER BY `SQL_MODE` LIMIT 252 ;'),('test','ev_28716_72','SELECT * FROM `GLOBAL_STATUS` ORDER BY `VARIABLE_VALUE` LIMIT 20','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:27','2020-05-18 08:20:27','2020-05-18 08:22:32','2020-05-18 08:20:27','2020-05-18 08:23:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `GLOBAL_STATUS` ORDER BY `VARIABLE_VALUE` LIMIT 20'),('test','ev_28714_14','UPDATE IGNORE `oltp72` SET `c` = \'j\' ORDER BY `k` LIMIT 8','root@localhost',NULL,4,'SECOND','2020-05-18 08:19:59','2020-05-18 08:19:59','2020-05-18 08:22:33','2020-05-18 08:19:59','2020-05-18 08:22:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp72` SET `c` = \'j\' ORDER BY `k` LIMIT 8'),('test','ev_28718_217','SELECT * FROM `time_zone_transition_type` ORDER BY `Transition_type_id` LIMIT 133','root@localhost',NULL,6,'SECOND','2020-05-18 08:23:00','2020-05-18 08:23:00',NULL,'2020-05-18 08:23:00','2020-05-18 08:26:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `time_zone_transition_type` ORDER BY `Transition_type_id` LIMIT 133'),('test','ev_28718_19','REPLACE INTO `oltp58` () VALUES (),(),(),(),(),(),()','root@localhost',NULL,1,'SECOND','2020-05-18 08:19:59','2020-05-18 08:19:59','2020-05-18 08:23:01','2020-05-18 08:19:59','2020-05-18 08:23:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp58` () VALUES (),(),(),(),(),(),()'),('test','ev_28718_218','UPDATE IGNORE `oltp76` SET `pad` = \'\' ORDER BY `id` LIMIT 4','root@localhost',NULL,3,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:25:08','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp76` SET `pad` = \'\' ORDER BY `id` LIMIT 4'),('test','ev_28716_143','SELECT * FROM `INNODB_SYS_VIRTUAL` ORDER BY `TABLE_ID` LIMIT 178','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:49','2020-05-18 08:21:49','2020-05-18 08:22:24','2020-05-18 08:21:49','2020-05-18 08:22:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `INNODB_SYS_VIRTUAL` ORDER BY `TABLE_ID` LIMIT 178'),('test','ev_28714_62','SELECT `sub_id` FROM `proc` ORDER BY `created` LIMIT 16','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:33','2020-05-18 08:20:33','2020-05-18 08:22:32','2020-05-18 08:20:33','2020-05-18 08:24:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `sub_id` FROM `proc` ORDER BY `created` LIMIT 16'),('test','ev_28714_16','SELECT * FROM (INFORMATION_SCHEMA.`STATISTICS` AS table1 STRAIGHT_JOIN test.`oltp87` AS table2 ON ( table2.`pad` = table1.`NON_UNIQUE` ) ) WHERE ( table2.`c` = table2.`k` AND table1.`TABLE_NAME` = 5) LIMIT 5 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:19:59','2020-05-18 08:19:59','2020-05-18 08:22:49','2020-05-18 08:19:59','2020-05-18 08:23:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`STATISTICS` AS table1 STRAIGHT_JOIN test.`oltp87` AS table2 ON ( table2.`pad` = table1.`NON_UNIQUE` ) ) WHERE ( table2.`c` = table2.`k` AND table1.`TABLE_NAME` = 5) LIMIT 5 ;'),('test','ev_28714_133','UPDATE IGNORE `time_zone_transition_type` SET `Is_DST` = NULL ORDER BY `Transition_type_id` LIMIT 4','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:12','2020-05-18 08:21:12','2020-05-18 08:22:23','2020-05-18 08:21:12','2020-05-18 08:24:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `time_zone_transition_type` SET `Is_DST` = NULL ORDER BY `Transition_type_id` LIMIT 4'),('test','ev_28716_190','SELECT `description` FROM `roles_mapping` ORDER BY `Role` LIMIT 103 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:20','2020-05-18 08:22:20','2020-05-18 08:23:00','2020-05-18 08:22:20','2020-05-18 08:25:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `description` FROM `roles_mapping` ORDER BY `Role` LIMIT 103 ;'),('test','ev_28714_85','UPDATE IGNORE `help_topic` SET `url` = NULL ORDER BY `name` LIMIT 8 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:50','2020-05-18 08:20:50','2020-05-18 08:22:29','2020-05-18 08:20:50','2020-05-18 08:23:39','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_topic` SET `url` = NULL ORDER BY `name` LIMIT 8 ;'),('test','ev_28718_22','SHOW PROFILE ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:00','2020-05-18 08:20:00','2020-05-18 08:22:57','2020-05-18 08:20:00','2020-05-18 08:23:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW PROFILE ;'),('test','ev_28714_18','SHOW BINLOG EVENTS ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:01','2020-05-18 08:20:01','2020-05-18 08:22:40','2020-05-18 08:20:01','2020-05-18 08:24:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW BINLOG EVENTS ;'),('test','ev_28716_19','UPDATE IGNORE `help_relation` SET `help_topic_id` = 127 ORDER BY `help_keyword_id` LIMIT 9 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:01','2020-05-18 08:20:01','2020-05-18 08:22:56','2020-05-18 08:20:01','2020-05-18 08:24:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_relation` SET `help_topic_id` = 127 ORDER BY `help_keyword_id` LIMIT 9 ;'),('test','ev_28716_214','REPLACE INTO `oltp131` ( `c` ) VALUES ( \'provider\' )','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:33','2020-05-18 08:22:33',NULL,'2020-05-18 08:22:33','2020-05-18 08:24:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp131` ( `c` ) VALUES ( \'provider\' )'),('test','ev_28714_210','SHOW COLLATION','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:06','2020-05-18 08:22:06','2020-05-18 08:22:39','2020-05-18 08:22:06','2020-05-18 08:23:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW COLLATION'),('test','ev_28718_153','SELECT * FROM (INFORMATION_SCHEMA.`USER_PRIVILEGES` AS table1 RIGHT OUTER JOIN mysql.`innodb_index_stats` AS table2 ON ( table2.`table_name` = table1.`GRANTEE` ) ) WHERE ( table2.`table_name` != table2.`stat_description` AND table2.`stat_name` < 5) LIMIT 9 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:25:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`USER_PRIVILEGES` AS table1 RIGHT OUTER JOIN mysql.`innodb_index_stats` AS table2 ON ( table2.`table_name` = table1.`GRANTEE` ) ) WHERE ( table2.`table_name` != table2.`stat_description` AND table2.`stat_name` < 5) LIMIT 9 ;'),('test','ev_28714_283','INSERT IGNORE INTO `time_zone_name` ( `Name` ) VALUES ( NULL )','root@localhost',NULL,5,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:25:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_name` ( `Name` ) VALUES ( NULL )'),('test','ev_28718_227','SELECT * FROM (INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` AS table1 INNER JOIN test.`oltp141` AS table2 ON ( table2.`c` = table1.`TABLE_SCHEMA` ) ) WHERE table2.`c` != 5 LIMIT 6 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:23:08','2020-05-18 08:23:08',NULL,'2020-05-18 08:23:08','2020-05-18 08:26:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` AS table1 INNER JOIN test.`oltp141` AS table2 ON ( table2.`c` = table1.`TABLE_SCHEMA` ) ) WHERE table2.`c` != 5 LIMIT 6 ;'),('test','ev_28718_30','UPDATE `INNODB_SYS_TABLES` SET `ZIP_PAGE_SIZE` = \'application\' ORDER BY `SPACE` LIMIT 2','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:03','2020-05-18 08:20:03','2020-05-18 08:22:36','2020-05-18 08:20:03','2020-05-18 08:23:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `INNODB_SYS_TABLES` SET `ZIP_PAGE_SIZE` = \'application\' ORDER BY `SPACE` LIMIT 2'),('test','ev_28716_180','REPLACE INTO `oltp148` () VALUES ()','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:18','2020-05-18 08:22:18','2020-05-18 08:22:56','2020-05-18 08:22:18','2020-05-18 08:23:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp148` () VALUES ()'),('test','ev_28714_20','SELECT * FROM `oltp125` ORDER BY `pad` LIMIT 12','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:02','2020-05-18 08:20:02','2020-05-18 08:22:36','2020-05-18 08:20:02','2020-05-18 08:24:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp125` ORDER BY `pad` LIMIT 12'),('test','ev_28714_150','INSERT IGNORE INTO `help_keyword` () VALUES (),(),(),(),(),(),(),(),() ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:34','2020-05-18 08:21:29','2020-05-18 08:22:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `help_keyword` () VALUES (),(),(),(),(),(),(),(),() ;'),('test','ev_28714_21','UPDATE IGNORE `INNODB_LOCK_WAITS` SET `blocking_trx_id` = \'x\' ORDER BY `blocking_trx_id` LIMIT 2 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:02','2020-05-18 08:20:02','2020-05-18 08:22:45','2020-05-18 08:20:02','2020-05-18 08:23:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `INNODB_LOCK_WAITS` SET `blocking_trx_id` = \'x\' ORDER BY `blocking_trx_id` LIMIT 2 ;'),('test','ev_28716_178','DELETE FROM `INNODB_SYS_INDEXES` ORDER BY `SPACE` LIMIT 0','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:17','2020-05-18 08:22:17','2020-05-18 08:22:56','2020-05-18 08:22:17','2020-05-18 08:24:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `INNODB_SYS_INDEXES` ORDER BY `SPACE` LIMIT 0'),('test','ev_28714_245','DELETE FROM `index_stats` ORDER BY `avg_frequency` LIMIT 1','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:29','2020-05-18 08:22:29',NULL,'2020-05-18 08:22:29','2020-05-18 08:26:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `index_stats` ORDER BY `avg_frequency` LIMIT 1'),('test','ev_28718_28','UPDATE `innodb_table_stats` SET `last_update` = NULL ORDER BY `database_name` LIMIT 2','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:02','2020-05-18 08:20:02','2020-05-18 08:22:41','2020-05-18 08:20:02','2020-05-18 08:23:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `innodb_table_stats` SET `last_update` = NULL ORDER BY `database_name` LIMIT 2'),('test','ev_28716_28','SELECT * FROM mysql.`proxies_priv` AS table1 WHERE ( (NOT table1.`Timestamp` <= 8 AND table1.`Proxied_host` < table1.`Grantor`) OR table1.`Host` <> 8) HAVING table1.`Timestamp` <> 4 IS NULL LIMIT 6','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:04','2020-05-18 08:20:04','2020-05-18 08:22:28','2020-05-18 08:20:04','2020-05-18 08:23:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM mysql.`proxies_priv` AS table1 WHERE ( (NOT table1.`Timestamp` <= 8 AND table1.`Proxied_host` < table1.`Grantor`) OR table1.`Host` <> 8) HAVING table1.`Timestamp` <> 4 IS NULL LIMIT 6'),('test','ev_28714_209','SHOW PROFILE ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:06','2020-05-18 08:22:06','2020-05-18 08:22:39','2020-05-18 08:22:06','2020-05-18 08:25:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW PROFILE ;'),('test','ev_28714_22','SELECT * FROM (test.`oltp44` AS table1 STRAIGHT_JOIN mysql.`help_keyword` AS table2 ON ( table2.`name` = table1.`k` ) ) WHERE (NOT ( (NOT table2.`help_keyword_id` > \'k\' AND table2.`help_keyword_id` != \'1949-05-18 02:36:35.016964\') OR table1.`pad` < \'1906-07-04 17:02:32.006064\') AND table2.`name` != \'n\') HAVING NOT (table2.`help_keyword_id` = \'v\' IS NOT NULL OR table1.`pad` >= 1) LIMIT 7 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:03','2020-05-18 08:20:03','2020-05-18 08:22:41','2020-05-18 08:20:03','2020-05-18 08:22:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp44` AS table1 STRAIGHT_JOIN mysql.`help_keyword` AS table2 ON ( table2.`name` = table1.`k` ) ) WHERE (NOT ( (NOT table2.`help_keyword_id` > \'k\' AND table2.`help_keyword_id` != \'1949-05-18 02:36:35.016964\') OR table1.`pad` < \'1906-07-04 17:02:32.006064\') AND table2.`name` != \'n\') HAVING NOT (table2.`help_keyword_id` = \'v\' IS NOT NULL OR table1.`pad` >= 1) LIMIT 7 ;'),('test','ev_28718_223','SELECT * FROM test.`oltp124` AS table1 WHERE ( ( ( table1.`id` >= \'wr\' AND table1.`k` <> table1.`id`) AND table1.`k` <= \'r\') AND table1.`id` >= table1.`c`) LIMIT 7','root@localhost',NULL,1,'SECOND','2020-05-18 08:23:05','2020-05-18 08:23:05',NULL,'2020-05-18 08:23:05','2020-05-18 08:25:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp124` AS table1 WHERE ( ( ( table1.`id` >= \'wr\' AND table1.`k` <> table1.`id`) AND table1.`k` <= \'r\') AND table1.`id` >= table1.`c`) LIMIT 7'),('test','ev_28714_284','INSERT INTO `help_keyword` SELECT * FROM `servers` ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:24:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `help_keyword` SELECT * FROM `servers` ;'),('test','ev_28718_150','SELECT * FROM `tables_priv` ORDER BY `Table_priv` LIMIT 46 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:56','2020-05-18 08:21:56','2020-05-18 08:22:32','2020-05-18 08:21:56','2020-05-18 08:24:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `tables_priv` ORDER BY `Table_priv` LIMIT 46 ;'),('test','ev_28714_139','UPDATE IGNORE `t5_MyISAM` SET `id` = \'endless\' ORDER BY `col_char` LIMIT 3','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:17','2020-05-18 08:21:17','2020-05-18 08:22:29','2020-05-18 08:21:17','2020-05-18 08:23:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `t5_MyISAM` SET `id` = \'endless\' ORDER BY `col_char` LIMIT 3'),('test','ev_28714_25','SELECT * FROM `event` ORDER BY `status` LIMIT 15','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:03','2020-05-18 08:20:03','2020-05-18 08:22:36','2020-05-18 08:20:03','2020-05-18 08:23:56','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `event` ORDER BY `status` LIMIT 15'),('test','ev_28718_32','COMMIT','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:03','2020-05-18 08:20:03','2020-05-18 08:23:04','2020-05-18 08:20:03','2020-05-18 08:23:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28716_26','SELECT * FROM `procs_priv` ORDER BY `Grantor` LIMIT 74','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:04','2020-05-18 08:20:04','2020-05-18 08:22:45','2020-05-18 08:20:04','2020-05-18 08:23:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `procs_priv` ORDER BY `Grantor` LIMIT 74'),('test','ev_28718_35','SELECT * FROM `help_category` ORDER BY `help_category_id` LIMIT 157','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:04','2020-05-18 08:20:04','2020-05-18 08:22:56','2020-05-18 08:20:04','2020-05-18 08:22:58','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `help_category` ORDER BY `help_category_id` LIMIT 157'),('test','ev_28716_76','SELECT * FROM (INFORMATION_SCHEMA.`COLLATION_CHARACTER_SET_APPLICABILITY` AS table1 STRAIGHT_JOIN mysql.`gtid_slave_pos` AS table2 ON ( table2.`server_id` = table1.`CHARACTER_SET_NAME` ) ) WHERE ( (NOT table2.`domain_id` >= \'ft\' AND table2.`server_id` <> \'tq\') OR table1.`CHARACTER_SET_NAME` = 9) LIMIT 8 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:35','2020-05-18 08:20:35','2020-05-18 08:22:33','2020-05-18 08:20:35','2020-05-18 08:24:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`COLLATION_CHARACTER_SET_APPLICABILITY` AS table1 STRAIGHT_JOIN mysql.`gtid_slave_pos` AS table2 ON ( table2.`server_id` = table1.`CHARACTER_SET_NAME` ) ) WHERE ( (NOT table2.`domain_id` >= \'ft\' AND table2.`server_id` <> \'tq\') OR table1.`CHARACTER_SET_NAME` = 9) LIMIT 8 ;'),('test','ev_28718_36','SELECT * FROM test.`oltp159` AS table1 WHERE table1.`k` = 9 LIMIT 0 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:04','2020-05-18 08:20:04','2020-05-18 08:22:32','2020-05-18 08:20:04','2020-05-18 08:23:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp159` AS table1 WHERE table1.`k` = 9 LIMIT 0 ;'),('test','ev_28714_285','SHOW EXPLAIN FOR 246','root@localhost',NULL,7,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:26:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 246'),('test','ev_28718_222','SELECT `id` FROM `oltp34` ORDER BY `id` LIMIT 168 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:23:04','2020-05-18 08:23:04',NULL,'2020-05-18 08:23:04','2020-05-18 08:25:56','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp34` ORDER BY `id` LIMIT 168 ;'),('test','ev_28716_226','UPDATE `PARAMETERS` SET `PARAMETER_MODE` = 78 ORDER BY `DTD_IDENTIFIER` LIMIT 8','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:38','2020-05-18 08:22:38',NULL,'2020-05-18 08:22:38','2020-05-18 08:24:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `PARAMETERS` SET `PARAMETER_MODE` = 78 ORDER BY `DTD_IDENTIFIER` LIMIT 8'),('test','ev_28714_170','SELECT * FROM `innodb_table_stats` ORDER BY `sum_of_other_index_sizes` LIMIT 32','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:39','2020-05-18 08:21:39','2020-05-18 08:23:05','2020-05-18 08:21:39','2020-05-18 08:25:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `innodb_table_stats` ORDER BY `sum_of_other_index_sizes` LIMIT 32'),('test','y','SET @a=@a','root@localhost','2020-05-18 08:23:06',NULL,NULL,'2020-05-18 08:23:06','2020-05-18 08:23:06',NULL,NULL,NULL,'ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SET @a=@a'),('test','ev_28716_34','DELETE FROM `roles_mapping` ORDER BY `User` LIMIT 5','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:07','2020-05-18 08:20:07','2020-05-18 08:22:31','2020-05-18 08:20:07','2020-05-18 08:23:35','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `roles_mapping` ORDER BY `User` LIMIT 5'),('test','ev_28714_251','SELECT * FROM test.`oltp117` AS table1 WHERE ( ( ( ( table1.`pad` != \'1908-09-13 15:39:21.026567\' OR table1.`c` <> \'2017-05-05 18:24:59.064732\') AND table1.`id` != \'rh\') OR table1.`c` <> \'hz\') AND table1.`c` > \'zk\') HAVING table1.`id` <= \'k\' LIMIT 9 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:25:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp117` AS table1 WHERE ( ( ( ( table1.`pad` != \'1908-09-13 15:39:21.026567\' OR table1.`c` <> \'2017-05-05 18:24:59.064732\') AND table1.`id` != \'rh\') OR table1.`c` <> \'hz\') AND table1.`c` > \'zk\') HAVING table1.`id` <= \'k\' LIMIT 9 ;'),('test','ev_28714_186','UPDATE `oltp83` SET `k` = DEFAULT ORDER BY `c` LIMIT 9 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:49','2020-05-18 08:21:49','2020-05-18 08:23:06','2020-05-18 08:21:49','2020-05-18 08:24:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `oltp83` SET `k` = DEFAULT ORDER BY `c` LIMIT 9 ;'),('test','ev_28714_86','INSERT IGNORE INTO `VIEWS` ( `CHARACTER_SET_CLIENT` ) VALUES ( DEFAULT )','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:51','2020-05-18 08:20:51','2020-05-18 08:22:26','2020-05-18 08:20:51','2020-05-18 08:23:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `VIEWS` ( `CHARACTER_SET_CLIENT` ) VALUES ( DEFAULT )'),('test','ev_28714_291','SELECT `c` FROM `oltp2` ORDER BY `id` LIMIT 85 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:06','2020-05-18 08:23:06',NULL,'2020-05-18 08:23:06','2020-05-18 08:24:06','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `oltp2` ORDER BY `id` LIMIT 85 ;'),('test','ev_28718_224','SELECT * FROM `t3_InnoDB` ORDER BY `col_datetime` LIMIT 243','root@localhost',NULL,7,'SECOND','2020-05-18 08:23:05','2020-05-18 08:23:05',NULL,'2020-05-18 08:23:05','2020-05-18 08:24:47','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `t3_InnoDB` ORDER BY `col_datetime` LIMIT 243'),('test','ev_28718_41','UPDATE IGNORE `oltp49` SET `c` = 171 ORDER BY `pad` LIMIT 2','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:08','2020-05-18 08:20:08','2020-05-18 08:22:40','2020-05-18 08:20:08','2020-05-18 08:24:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp49` SET `c` = 171 ORDER BY `pad` LIMIT 2'),('test','ev_28714_32','INSERT IGNORE INTO `column_stats` () VALUES (),(),(),()','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:08','2020-05-18 08:20:08','2020-05-18 08:22:29','2020-05-18 08:20:08','2020-05-18 08:23:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `column_stats` () VALUES (),(),(),()'),('test','ev_28716_142','SELECT * FROM test.`oltp125` AS table1 WHERE NOT ( (NOT ( table1.`id` <= table1.`c` AND table1.`k` <= \'1947-07-22 07:23:12.006168\') AND table1.`id` <= table1.`pad`) OR table1.`c` != table1.`k`) HAVING (NOT ( table1.`k` <= \'2009-04-07 03:30:34.054734\' AND table1.`c` <= \'wk\') AND table1.`k` >= \'kr\') LIMIT 3','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:49','2020-05-18 08:21:49','2020-05-18 08:23:06','2020-05-18 08:21:49','2020-05-18 08:23:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp125` AS table1 WHERE NOT ( (NOT ( table1.`id` <= table1.`c` AND table1.`k` <= \'1947-07-22 07:23:12.006168\') AND table1.`id` <= table1.`pad`) OR table1.`c` != table1.`k`) HAVING (NOT ( table1.`k` <= \'2009-04-07 03:30:34.054734\' AND table1.`c` <= \'wk\') AND table1.`k` >= \'kr\') LIMIT 3'),('test','ev_28716_195','REPLACE INTO `servers` ( `Db`, _next_field ) VALUES ( DEFAULT, \'\' )','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:03','2020-05-18 08:22:22','2020-05-18 08:26:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `servers` ( `Db`, ) VALUES ( DEFAULT, \'\' )'),('test','ev_28714_35','COMMIT','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:11','2020-05-18 08:20:11','2020-05-18 08:22:45','2020-05-18 08:20:11','2020-05-18 08:23:21','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28718_186','ALTER TABLE IF EXISTS `time_zone_transition_type` DROP CONSTRAINT IF EXISTS `Is_DST`, LOCK=NONE, ADD KEY IF NOT EXISTS h ( `Transition_type_id` )','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:24','2020-05-18 08:22:24','2020-05-18 08:23:05','2020-05-18 08:22:24','2020-05-18 08:24:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','ALTER TABLE IF EXISTS `time_zone_transition_type` DROP CONSTRAINT IF EXISTS `Is_DST`, LOCK=NONE, ADD KEY IF NOT EXISTS h ( `Transition_type_id` )'),('test','ev_28718_219','INSERT IGNORE INTO `oltp154` () VALUES (),(),(),()','root@localhost',NULL,1,'SECOND','2020-05-18 08:23:01','2020-05-18 08:23:01',NULL,'2020-05-18 08:23:01','2020-05-18 08:24:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp154` () VALUES (),(),(),()'),('test','ev_28718_61','UPDATE `t5_InnoDB` SET `col_bit` = DEFAULT ORDER BY `id` LIMIT 1 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:37','2020-05-18 08:20:37','2020-05-18 08:22:33','2020-05-18 08:20:37','2020-05-18 08:23:26','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `t5_InnoDB` SET `col_bit` = DEFAULT ORDER BY `id` LIMIT 1 ;'),('test','ev_28716_250','SELECT * FROM (mysql.`roles_mapping` AS table1 INNER JOIN test.`oltp20` AS table2 ON ( table2.`k` = table1.`Role` ) ) WHERE NOT ( ( ( table2.`k` <> \'gq\' OR table2.`id` = table1.`User`) AND table1.`Role` < \'1928-08-10 21:51:07.051221\') OR table1.`User` <= \'qe\') LIMIT 7','root@localhost',NULL,3,'SECOND','2020-05-18 08:23:06','2020-05-18 08:23:06',NULL,'2020-05-18 08:23:06','2020-05-18 08:27:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`roles_mapping` AS table1 INNER JOIN test.`oltp20` AS table2 ON ( table2.`k` = table1.`Role` ) ) WHERE NOT ( ( ( table2.`k` <> \'gq\' OR table2.`id` = table1.`User`) AND table1.`Role` < \'1928-08-10 21:51:07.051221\') OR table1.`User` <= \'qe\') LIMIT 7'),('test','ev_28716_162','UPDATE IGNORE `ROUTINES` SET `SQL_PATH` = \'f\' ORDER BY `DATABASE_COLLATION` LIMIT 6','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:06','2020-05-18 08:22:06','2020-05-18 08:22:38','2020-05-18 08:22:06','2020-05-18 08:23:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `ROUTINES` SET `SQL_PATH` = \'f\' ORDER BY `DATABASE_COLLATION` LIMIT 6'),('test','ev_28718_43','SELECT * FROM (mysql.`column_stats` AS table1 INNER JOIN mysql.`procs_priv` AS table2 ON ( table2.`Host` = table1.`hist_type` ) ) WHERE (NOT table1.`avg_frequency` != \'aw\' OR table1.`avg_length` > table1.`histogram`) HAVING ( (table1.`avg_length` > \'1969-05-15 02:38:54.019842\' IS NULL AND table2.`Routine_type` >= \'w\') OR table2.`Db` < \'wv\') LIMIT 4','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:10','2020-05-18 08:20:10','2020-05-18 08:22:26','2020-05-18 08:20:10','2020-05-18 08:22:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`column_stats` AS table1 INNER JOIN mysql.`procs_priv` AS table2 ON ( table2.`Host` = table1.`hist_type` ) ) WHERE (NOT table1.`avg_frequency` != \'aw\' OR table1.`avg_length` > table1.`histogram`) HAVING ( (table1.`avg_length` > \'1969-05-15 02:38:54.019842\' IS NULL AND table2.`Routine_type` >= \'w\') OR table2.`Db` < \'wv\') LIMIT 4'),('test','ev_28718_135','SELECT * FROM (test.`t9_InnoDB` AS table1 STRAIGHT_JOIN mysql.`global_priv` AS table2 ON ( table2.`Host` = table1.`col_blob` ) ) WHERE (NOT table2.`User` <> \'uf\' OR table1.`col_int` > table1.`col_int`) HAVING ( (table2.`Host` < 2 IS NULL AND table2.`User` >= \'1972-03-13 15:59:05.038669\') AND table1.`id` >= \'f\') LIMIT 3 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:45','2020-05-18 08:21:45','2020-05-18 08:23:04','2020-05-18 08:21:45','2020-05-18 08:25:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`t9_InnoDB` AS table1 STRAIGHT_JOIN mysql.`global_priv` AS table2 ON ( table2.`Host` = table1.`col_blob` ) ) WHERE (NOT table2.`User` <> \'uf\' OR table1.`col_int` > table1.`col_int`) HAVING ( (table2.`Host` < 2 IS NULL AND table2.`User` >= \'1972-03-13 15:59:05.038669\') AND table1.`id` >= \'f\') LIMIT 3 ;'),('test','ev_28714_178','UPDATE IGNORE `TABLE_STATISTICS` SET `ROWS_CHANGED` = DEFAULT ORDER BY `ROWS_READ` LIMIT 7','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:44','2020-05-18 08:21:44','2020-05-18 08:23:09','2020-05-18 08:21:44','2020-05-18 08:24:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `TABLE_STATISTICS` SET `ROWS_CHANGED` = DEFAULT ORDER BY `ROWS_READ` LIMIT 7'),('test','ev_28716_45','START TRANSACTION','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:12','2020-05-18 08:20:12','2020-05-18 08:22:57','2020-05-18 08:20:12','2020-05-18 08:23:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28716_163','SELECT * FROM `roles_mapping` ORDER BY `Role` LIMIT 89','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:07','2020-05-18 08:22:07','2020-05-18 08:22:39','2020-05-18 08:22:07','2020-05-18 08:25:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `roles_mapping` ORDER BY `Role` LIMIT 89'),('test','ev_28714_37','DELETE FROM `COLLATION_CHARACTER_SET_APPLICABILITY` ORDER BY `COLLATION_NAME` LIMIT 3','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:13','2020-05-18 08:20:13','2020-05-18 08:22:34','2020-05-18 08:20:13','2020-05-18 08:23:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `COLLATION_CHARACTER_SET_APPLICABILITY` ORDER BY `COLLATION_NAME` LIMIT 3'),('test','ev_28714_211','SELECT `INDEX_ID` FROM `INNODB_FT_DEFAULT_STOPWORD` ORDER BY `value` LIMIT 198 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:07','2020-05-18 08:22:07','2020-05-18 08:22:39','2020-05-18 08:22:07','2020-05-18 08:23:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `INDEX_ID` FROM `INNODB_FT_DEFAULT_STOPWORD` ORDER BY `value` LIMIT 198 ;'),('test','ev_28716_230','UPDATE IGNORE `help_relation` SET `help_keyword_id` = 121 ORDER BY `help_topic_id` LIMIT 9','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:41','2020-05-18 08:22:41',NULL,'2020-05-18 08:22:41','2020-05-18 08:23:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_relation` SET `help_keyword_id` = 121 ORDER BY `help_topic_id` LIMIT 9'),('test','ev_28716_47','SHOW STATUS','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:13','2020-05-18 08:20:13','2020-05-18 08:22:59','2020-05-18 08:20:13','2020-05-18 08:23:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW STATUS'),('test','ev_28714_64','UPDATE IGNORE `plugin` SET `dl` = \'specialist\' ORDER BY `name` LIMIT 4','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:38','2020-05-18 08:20:38','2020-05-18 08:22:33','2020-05-18 08:20:38','2020-05-18 08:23:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `plugin` SET `dl` = \'specialist\' ORDER BY `name` LIMIT 4'),('test','ev_28718_134','START TRANSACTION','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:44','2020-05-18 08:21:44','2020-05-18 08:23:04','2020-05-18 08:21:44','2020-05-18 08:23:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28714_42','INSERT IGNORE INTO `oltp71` ( `id` ) VALUES ( 253 ) ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:14','2020-05-18 08:20:14','2020-05-18 08:22:30','2020-05-18 08:20:14','2020-05-18 08:23:19','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp71` ( `id` ) VALUES ( 253 ) ;'),('test','ev_28714_163','SELECT * FROM `SPATIAL_REF_SYS` INTO OUTFILE \'load_SPATIAL_REF_SYS\' ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:37','2020-05-18 08:21:37','2020-05-18 08:22:51','2020-05-18 08:21:37','2020-05-18 08:25:39','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `SPATIAL_REF_SYS` INTO OUTFILE \'load_SPATIAL_REF_SYS\' ;'),('test','ev_28714_43','INSERT IGNORE INTO `time_zone_leap_second` () VALUES ()','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:15','2020-05-18 08:20:15','2020-05-18 08:23:00','2020-05-18 08:20:15','2020-05-18 08:23:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_leap_second` () VALUES ()'),('test','ev_28716_78','SELECT * FROM `oltp35` ORDER BY `c` LIMIT 12','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:38','2020-05-18 08:20:38','2020-05-18 08:22:41','2020-05-18 08:20:38','2020-05-18 08:23:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp35` ORDER BY `c` LIMIT 12'),('test','ev_28716_234','SELECT * FROM mysql.`column_stats` AS table1 WHERE ( (NOT table1.`avg_length` != table1.`hist_type` AND table1.`max_value` <= table1.`avg_length`) AND table1.`max_value` = table1.`db_name`) HAVING table1.`db_name` >= 7 IS NOT NULL LIMIT 3','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:44','2020-05-18 08:22:44',NULL,'2020-05-18 08:22:44','2020-05-18 08:26:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM mysql.`column_stats` AS table1 WHERE ( (NOT table1.`avg_length` != table1.`hist_type` AND table1.`max_value` <= table1.`avg_length`) AND table1.`max_value` = table1.`db_name`) HAVING table1.`db_name` >= 7 IS NOT NULL LIMIT 3'),('test','ev_28714_249','UPDATE IGNORE `ENABLED_ROLES` SET `ROLE_NAME` = \'q\' ORDER BY `ROLE_NAME` LIMIT 0 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:31','2020-05-18 08:22:31',NULL,'2020-05-18 08:22:31','2020-05-18 08:25:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `ENABLED_ROLES` SET `ROLE_NAME` = \'q\' ORDER BY `ROLE_NAME` LIMIT 0 ;'),('test','ev_28714_212','UPDATE IGNORE `FILES` SET `FULLTEXT_KEYS` = \'highly\' ORDER BY `CREATE_TIME` LIMIT 0 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:09','2020-05-18 08:22:09','2020-05-18 08:22:42','2020-05-18 08:22:09','2020-05-18 08:23:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `FILES` SET `FULLTEXT_KEYS` = \'highly\' ORDER BY `CREATE_TIME` LIMIT 0 ;'),('test','ev_28714_76','UPDATE IGNORE `oltp33` SET `id` = NULL ORDER BY `c` LIMIT 6','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:45','2020-05-18 08:20:45','2020-05-18 08:22:21','2020-05-18 08:20:45','2020-05-18 08:24:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp33` SET `id` = NULL ORDER BY `c` LIMIT 6'),('test','ev_28718_51','UPDATE IGNORE `SPATIAL_REF_SYS` SET `AUTH_SRID` = DEFAULT ORDER BY `AUTH_NAME` LIMIT 5','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:15','2020-05-18 08:20:15','2020-05-18 08:22:33','2020-05-18 08:20:15','2020-05-18 08:23:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `SPATIAL_REF_SYS` SET `AUTH_SRID` = DEFAULT ORDER BY `AUTH_NAME` LIMIT 5'),('test','ev_28718_60','UPDATE IGNORE `roles_mapping` SET `Role` = \'courtroom\' ORDER BY `User` LIMIT 8','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:30','2020-05-18 08:20:30','2020-05-18 08:22:42','2020-05-18 08:20:30','2020-05-18 08:23:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `roles_mapping` SET `Role` = \'courtroom\' ORDER BY `User` LIMIT 8'),('test','ev_28718_69','SELECT `VARIABLE_VALUE` FROM `REFERENTIAL_CONSTRAINTS` ORDER BY `CONSTRAINT_NAME` LIMIT 71','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:42','2020-05-18 08:20:42','2020-05-18 08:23:00','2020-05-18 08:20:42','2020-05-18 08:24:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `VARIABLE_VALUE` FROM `REFERENTIAL_CONSTRAINTS` ORDER BY `CONSTRAINT_NAME` LIMIT 71'),('test','ev_28716_140','REPLACE INTO `INNODB_SYS_INDEXES` ( `N_FIELDS` ) VALUES ( \'x\' )','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:48','2020-05-18 08:21:48','2020-05-18 08:23:05','2020-05-18 08:21:48','2020-05-18 08:23:55','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `INNODB_SYS_INDEXES` ( `N_FIELDS` ) VALUES ( \'x\' )'),('test','ev_28714_47','REPLACE INTO `INNODB_FT_DEFAULT_STOPWORD` () VALUES (),()','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:16','2020-05-18 08:20:16','2020-05-18 08:22:33','2020-05-18 08:20:16','2020-05-18 08:22:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `INNODB_FT_DEFAULT_STOPWORD` () VALUES (),()'),('test','ev_28716_53','SHOW CREATE DATABASE e','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:16','2020-05-18 08:20:16','2020-05-18 08:22:49','2020-05-18 08:20:16','2020-05-18 08:24:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW CREATE DATABASE e'),('test','ev_28718_199','INSERT IGNORE INTO `INNODB_CMPMEM_RESET` () VALUES (),()','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:26:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `INNODB_CMPMEM_RESET` () VALUES (),()'),('test','ev_28714_48','INSERT INTO `help_topic` ( `description`, _next_field ) VALUES ( \'x\', DEFAULT ) ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:17','2020-05-18 08:20:17','2020-05-18 08:22:32','2020-05-18 08:20:17','2020-05-18 08:24:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `help_topic` ( `description`, ) VALUES ( \'x\', DEFAULT ) ;'),('test','ev_28714_168','SELECT `query_time` FROM `index_stats` ORDER BY `prefix_arity` LIMIT 177','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:39','2020-05-18 08:21:39','2020-05-18 08:22:57','2020-05-18 08:21:39','2020-05-18 08:23:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `query_time` FROM `index_stats` ORDER BY `prefix_arity` LIMIT 177'),('test','ev_28716_181','SELECT `Table_name` FROM `db` ORDER BY `Grant_priv` LIMIT 88','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:58','2020-05-18 08:22:19','2020-05-18 08:25:08','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Table_name` FROM `db` ORDER BY `Grant_priv` LIMIT 88'),('test','ev_28718_106','INSERT INTO `COLLATION_CHARACTER_SET_APPLICABILITY` ( `CHARACTER_SET_NAME`, _next_field ) VALUES ( NULL, \'\' )','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:20','2020-05-18 08:21:20','2020-05-18 08:22:30','2020-05-18 08:21:20','2020-05-18 08:23:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `COLLATION_CHARACTER_SET_APPLICABILITY` ( `CHARACTER_SET_NAME`, ) VALUES ( NULL, \'\' )'),('test','ev_28718_146','INSERT INTO `APPLICABLE_ROLES` SELECT * FROM `INNODB_SYS_FOREIGN`','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:53','2020-05-18 08:21:53','2020-05-18 08:22:30','2020-05-18 08:21:53','2020-05-18 08:23:06','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `APPLICABLE_ROLES` SELECT * FROM `INNODB_SYS_FOREIGN`'),('test','ev_28714_167','REPLACE INTO `USER_STATISTICS` ( `DENIED_CONNECTIONS` ) VALUES ( \'now\' ) ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:38','2020-05-18 08:21:38','2020-05-18 08:23:00','2020-05-18 08:21:38','2020-05-18 08:25:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `USER_STATISTICS` ( `DENIED_CONNECTIONS` ) VALUES ( \'now\' ) ;'),('test','ev_28714_130','DELETE FROM `oltp89` ORDER BY `c` LIMIT 9 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:10','2020-05-18 08:21:10','2020-05-18 08:22:22','2020-05-18 08:21:10','2020-05-18 08:24:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp89` ORDER BY `c` LIMIT 9 ;'),('test','ev_28714_52','DELETE FROM `time_zone_name` ORDER BY `Time_zone_id` LIMIT 8 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:18','2020-05-18 08:20:18','2020-05-18 08:22:24','2020-05-18 08:20:18','2020-05-18 08:23:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `time_zone_name` ORDER BY `Time_zone_id` LIMIT 8 ;'),('test','ev_28716_218','SHOW TRIGGERS','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:24:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW TRIGGERS'),('test','ev_28714_239','ALTER IGNORE TABLE IF EXISTS ind_constr_t3 ADD INDEX IF NOT EXISTS o USING BTREE ( h DESC ), LOCK=NONE, /* compatibility 10.5.2 */ RENAME INDEX IF EXISTS `id` TO m, LOCK=DEFAULT, DROP CONSTRAINT IF EXISTS z, /* compatibility 10.5.2 */ RENAME KEY IF EXISTS ind5 TO v ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:24','2020-05-18 08:22:24','2020-05-18 08:23:05','2020-05-18 08:22:24','2020-05-18 08:26:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','ALTER IGNORE TABLE IF EXISTS ind_constr_t3 ADD INDEX IF NOT EXISTS o USING BTREE ( h DESC ), LOCK=NONE, /* compatibility 10.5.2 */ RENAME INDEX IF EXISTS `id` TO m, LOCK=DEFAULT, DROP CONSTRAINT IF EXISTS z, /* compatibility 10.5.2 */ RENAME KEY IF EXISTS ind5 TO v ;'),('test','ev_28716_57','REPLACE INTO `gtid_slave_pos` ( `sub_id` ) VALUES ( \'\' )','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:20','2020-05-18 08:20:20','2020-05-18 08:22:29','2020-05-18 08:20:20','2020-05-18 08:22:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `gtid_slave_pos` ( `sub_id` ) VALUES ( \'\' )'),('test','ev_28714_241','SELECT * FROM `oltp90` ORDER BY `id` LIMIT 196 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:25','2020-05-18 08:22:25','2020-05-18 08:23:08','2020-05-18 08:22:25','2020-05-18 08:26:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp90` ORDER BY `id` LIMIT 196 ;'),('test','ev_28718_139','SELECT `k` FROM `oltp9` ORDER BY `c` LIMIT 2','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:48','2020-05-18 08:21:48','2020-05-18 08:23:05','2020-05-18 08:21:48','2020-05-18 08:25:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `k` FROM `oltp9` ORDER BY `c` LIMIT 2'),('test','ev_28714_55','INSERT IGNORE INTO `TABLES` ( `TABLE_CATALOG` ) VALUES ( \'\' )','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:20','2020-05-18 08:20:20','2020-05-18 08:23:03','2020-05-18 08:20:20','2020-05-18 08:23:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `TABLES` ( `TABLE_CATALOG` ) VALUES ( \'\' )'),('test','ev_28718_55','SELECT * FROM `EVENTS` INTO OUTFILE \'load_EVENTS\' ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:20','2020-05-18 08:20:20','2020-05-18 08:23:10','2020-05-18 08:20:20','2020-05-18 08:23:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `EVENTS` INTO OUTFILE \'load_EVENTS\' ;'),('test','ev_28718_192','FLUSH ERROR LOGS, USER_RESOURCES','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:29','2020-05-18 08:22:29',NULL,'2020-05-18 08:22:29','2020-05-18 08:25:49','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','FLUSH ERROR LOGS, USER_RESOURCES'),('test','ev_28716_219','UPDATE IGNORE `time_zone_name` SET `Name` = \'v\' ORDER BY `Name` LIMIT 9','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:26:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `time_zone_name` SET `Name` = \'v\' ORDER BY `Name` LIMIT 9'),('test','ev_28716_59','INSERT IGNORE INTO `innodb_index_stats` ( `last_update`, _next_field ) VALUES ( DEFAULT, \'request\' ) ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:21','2020-05-18 08:20:21','2020-05-18 08:22:34','2020-05-18 08:20:21','2020-05-18 08:23:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `innodb_index_stats` ( `last_update`, ) VALUES ( DEFAULT, \'request\' ) ;'),('test','ev_28716_207','INSERT IGNORE INTO `INNODB_SYS_VIRTUAL` ( `BASE_POS` ) VALUES ( \'suburban\' )','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:28','2020-05-18 08:22:28',NULL,'2020-05-18 08:22:28','2020-05-18 08:25:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `INNODB_SYS_VIRTUAL` ( `BASE_POS` ) VALUES ( \'suburban\' )'),('test','f','SET @a=@a','root@localhost','2020-05-18 08:23:06',NULL,NULL,'2020-05-18 08:23:06','2020-05-18 08:23:06',NULL,NULL,NULL,'ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SET @a=@a'),('test','ev_28718_200','SELECT * FROM (test.`t5_InnoDB` AS table1 RIGHT OUTER JOIN mysql.`index_stats` AS table2 ON ( table2.`table_name` = table1.`id` ) ) WHERE ( table1.`col_dec` >= 0 AND table1.`col_timestamp` = \'x\') LIMIT 6 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:26:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`t5_InnoDB` AS table1 RIGHT OUTER JOIN mysql.`index_stats` AS table2 ON ( table2.`table_name` = table1.`id` ) ) WHERE ( table1.`col_dec` >= 0 AND table1.`col_timestamp` = \'x\') LIMIT 6 ;'),('test','ev_28714_185','FLUSH NO_WRITE_TO_BINLOG RELAY LOGS, USER_RESOURCES, STATUS','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:48','2020-05-18 08:21:48','2020-05-18 08:22:23','2020-05-18 08:21:48','2020-05-18 08:22:56','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','FLUSH NO_WRITE_TO_BINLOG RELAY LOGS, USER_RESOURCES, STATUS'),('test','ev_28716_193','INSERT INTO `plugin` ( `name` ) VALUES ( \'r\' )','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:21','2020-05-18 08:22:21','2020-05-18 08:23:00','2020-05-18 08:22:21','2020-05-18 08:24:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `plugin` ( `name` ) VALUES ( \'r\' )'),('test','ev_28714_296','SELECT * FROM `SPATIAL_REF_SYS` ORDER BY `SRID` LIMIT 65 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:10','2020-05-18 08:23:10',NULL,'2020-05-18 08:23:10','2020-05-18 08:23:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `SPATIAL_REF_SYS` ORDER BY `SRID` LIMIT 65 ;'),('test','ev_28718_58','SELECT * FROM (INFORMATION_SCHEMA.`REFERENTIAL_CONSTRAINTS` AS table1 STRAIGHT_JOIN test.`oltp161` AS table2 ON ( table2.`k` = table1.`UNIQUE_CONSTRAINT_NAME` ) ) WHERE (NOT (NOT ( (NOT table2.`c` != table1.`CONSTRAINT_NAME` OR table2.`c` > table1.`CONSTRAINT_NAME`) OR table2.`id` = table1.`CONSTRAINT_CATALOG`) OR table1.`UNIQUE_CONSTRAINT_CATALOG` = \'1958-06-11 02:29:35.054611\') OR table1.`UPDATE_RULE` != \'jt\') LIMIT 8 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:23','2020-05-18 08:20:23','2020-05-18 08:22:35','2020-05-18 08:20:23','2020-05-18 08:24:19','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`REFERENTIAL_CONSTRAINTS` AS table1 STRAIGHT_JOIN test.`oltp161` AS table2 ON ( table2.`k` = table1.`UNIQUE_CONSTRAINT_NAME` ) ) WHERE (NOT (NOT ( (NOT table2.`c` != table1.`CONSTRAINT_NAME` OR table2.`c` > table1.`CONSTRAINT_NAME`) OR table2.`id` = table1.`CONSTRAINT_CATALOG`) OR table1.`UNIQUE_CONSTRAINT_CATALOG` = \'1958-06-11 02:29:35.054611\') OR table1.`UPDATE_RULE` != \'jt\') LIMIT 8 ;'),('test','ev_28718_65','SELECT * FROM `oltp160` ORDER BY `c` LIMIT 196 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:38','2020-05-18 08:20:38','2020-05-18 08:22:54','2020-05-18 08:20:38','2020-05-18 08:24:53','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp160` ORDER BY `c` LIMIT 196 ;'),('test','ev_28714_203','UPDATE IGNORE `THREAD_POOL_QUEUES` SET `POSITION` = \'p\' ORDER BY `QUEUEING_TIME_MICROSECONDS` LIMIT 2 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:22:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `THREAD_POOL_QUEUES` SET `POSITION` = \'p\' ORDER BY `QUEUEING_TIME_MICROSECONDS` LIMIT 2 ;'),('test','ev_28716_62','UPDATE IGNORE `proc` SET `definer` = \'h\' ORDER BY `sql_mode` LIMIT 1','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:23','2020-05-18 08:20:23','2020-05-18 08:22:48','2020-05-18 08:20:23','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `proc` SET `definer` = \'h\' ORDER BY `sql_mode` LIMIT 1'),('test','ev_28718_110','SHOW DATABASES ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:34','2020-05-18 08:21:29','2020-05-18 08:23:26','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW DATABASES ;'),('test','ev_28714_59','SELECT * FROM test.`oltp109` AS table1 WHERE (NOT (NOT ( (NOT ( ( table1.`k` <> table1.`id` AND table1.`pad` <= table1.`id`) AND table1.`id` <> 3) OR table1.`k` >= table1.`k`) OR table1.`pad` >= \'kn\') AND table1.`pad` <= \'2001-08-19 13:35:40.063449\') OR table1.`c` < 7) LIMIT 8','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:24','2020-05-18 08:20:24','2020-05-18 08:22:27','2020-05-18 08:20:24','2020-05-18 08:23:55','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp109` AS table1 WHERE (NOT (NOT ( (NOT ( ( table1.`k` <> table1.`id` AND table1.`pad` <= table1.`id`) AND table1.`id` <> 3) OR table1.`k` >= table1.`k`) OR table1.`pad` >= \'kn\') AND table1.`pad` <= \'2001-08-19 13:35:40.063449\') OR table1.`c` < 7) LIMIT 8'),('test','ev_28716_64','SELECT `c` FROM `oltp39` ORDER BY `c` LIMIT 71','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:24','2020-05-18 08:20:24','2020-05-18 08:23:07','2020-05-18 08:20:24','2020-05-18 08:24:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `oltp39` ORDER BY `c` LIMIT 71'),('test','ev_28714_240','SELECT * FROM `oltp128` INTO OUTFILE \'load_oltp128\' ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:24','2020-05-18 08:22:24','2020-05-18 08:23:05','2020-05-18 08:22:24','2020-05-18 08:23:47','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp128` INTO OUTFILE \'load_oltp128\' ;'),('test','ev_28716_66','REPLACE INTO `t4_Aria` ( `col_datetime` ) VALUES ( \'y\' )','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:25','2020-05-18 08:20:25','2020-05-18 08:23:11','2020-05-18 08:20:25','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `t4_Aria` ( `col_datetime` ) VALUES ( \'y\' )'),('test','ev_28714_261','UPDATE IGNORE `column_stats` SET `avg_length` = \'flexible\' ORDER BY `max_value` LIMIT 7 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:41','2020-05-18 08:22:41',NULL,'2020-05-18 08:22:41','2020-05-18 08:25:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `column_stats` SET `avg_length` = \'flexible\' ORDER BY `max_value` LIMIT 7 ;'),('test','ev_28716_243','SELECT `id` FROM `oltp130` ORDER BY `pad` LIMIT 206','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:54','2020-05-18 08:22:54',NULL,'2020-05-18 08:22:54','2020-05-18 08:26:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp130` ORDER BY `pad` LIMIT 206'),('test','ev_28716_155','DELETE FROM `event` ORDER BY `last_executed` LIMIT 0 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:24:49','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `event` ORDER BY `last_executed` LIMIT 0 ;'),('test','ev_28716_253','UPDATE IGNORE `oltp7` SET `pad` = DEFAULT ORDER BY `c` LIMIT 9','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:08','2020-05-18 08:23:08',NULL,'2020-05-18 08:23:08','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp7` SET `pad` = DEFAULT ORDER BY `c` LIMIT 9'),('test','ev_28716_68','UPDATE `oltp3` SET `id` = \'y\' ORDER BY `id` LIMIT 1','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:26','2020-05-18 08:20:26','2020-05-18 08:22:38','2020-05-18 08:20:26','2020-05-18 08:23:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `oltp3` SET `id` = \'y\' ORDER BY `id` LIMIT 1'),('test','ev_28716_119','INSERT INTO `oltp84` SELECT * FROM `oltp142`','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:24','2020-05-18 08:21:24','2020-05-18 08:22:31','2020-05-18 08:21:24','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `oltp84` SELECT * FROM `oltp142`'),('test','ev_28714_66','SELECT `THROTTLES` FROM `INNODB_METRICS` ORDER BY `TYPE` LIMIT 88','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:39','2020-05-18 08:20:39','2020-05-18 08:22:35','2020-05-18 08:20:39','2020-05-18 08:24:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `THROTTLES` FROM `INNODB_METRICS` ORDER BY `TYPE` LIMIT 88'),('test','ev_28714_202','SELECT `k` FROM `oltp113` ORDER BY `c` LIMIT 192','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:23:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `k` FROM `oltp113` ORDER BY `c` LIMIT 192'),('test','ev_28718_86','SELECT * FROM INFORMATION_SCHEMA.`ENGINES` AS table1 WHERE NOT (NOT table1.`SAVEPOINTS` <= table1.`ENGINE` OR table1.`XA` < table1.`COMMENT`) LIMIT 2 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:41','2020-05-18 08:20:58','2020-05-18 08:25:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`ENGINES` AS table1 WHERE NOT (NOT table1.`SAVEPOINTS` <= table1.`ENGINE` OR table1.`XA` < table1.`COMMENT`) LIMIT 2 ;'),('test','ev_28718_84','DELETE FROM `CHECK_CONSTRAINTS` ORDER BY `CONSTRAINT_CATALOG` LIMIT 4','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:55','2020-05-18 08:20:55','2020-05-18 08:22:33','2020-05-18 08:20:55','2020-05-18 08:24:53','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `CHECK_CONSTRAINTS` ORDER BY `CONSTRAINT_CATALOG` LIMIT 4'),('test','ev_28718_111','REPLACE INTO `t4_MyISAM` ( `col_int` ) VALUES ( NULL ) ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:37','2020-05-18 08:21:29','2020-05-18 08:24:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `t4_MyISAM` ( `col_int` ) VALUES ( NULL ) ;'),('test','ev_28714_151','SELECT `id` FROM `oltp56` ORDER BY `c` LIMIT 43','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:34','2020-05-18 08:21:29','2020-05-18 08:24:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp56` ORDER BY `c` LIMIT 43'),('test','ev_28718_187','REPLACE INTO `oltp64` () VALUES (),() ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:25','2020-05-18 08:22:25','2020-05-18 08:23:07','2020-05-18 08:22:25','2020-05-18 08:24:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp64` () VALUES (),() ;'),('test','ev_28716_75','SELECT * FROM (mysql.`help_keyword` AS table1 STRAIGHT_JOIN mysql.`event` AS table2 ON ( table2.`sql_mode` = table1.`help_keyword_id` ) ) WHERE NOT ( (NOT table2.`ends` <> table1.`help_keyword_id` OR table1.`help_keyword_id` <= table2.`db_collation`) OR table2.`db_collation` <> 1) HAVING ( table2.`name` != 3 AND table2.`execute_at` < 0) LIMIT 2','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:35','2020-05-18 08:20:35','2020-05-18 08:22:38','2020-05-18 08:20:35','2020-05-18 08:24:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`help_keyword` AS table1 STRAIGHT_JOIN mysql.`event` AS table2 ON ( table2.`sql_mode` = table1.`help_keyword_id` ) ) WHERE NOT ( (NOT table2.`ends` <> table1.`help_keyword_id` OR table1.`help_keyword_id` <= table2.`db_collation`) OR table2.`db_collation` <> 1) HAVING ( table2.`name` != 3 AND table2.`execute_at` < 0) LIMIT 2'),('test','ev_28718_67','UPDATE IGNORE `oltp129` SET `pad` = 47 ORDER BY `k` LIMIT 7','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:40','2020-05-18 08:20:40','2020-05-18 08:22:20','2020-05-18 08:20:40','2020-05-18 08:23:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp129` SET `pad` = 47 ORDER BY `k` LIMIT 7'),('test','ev_28718_68','UPDATE IGNORE `oltp156` SET `c` = NULL ORDER BY `c` LIMIT 7','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:41','2020-05-18 08:20:41','2020-05-18 08:22:34','2020-05-18 08:20:41','2020-05-18 08:22:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp156` SET `c` = NULL ORDER BY `c` LIMIT 7'),('test','ev_28714_68','START TRANSACTION','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:41','2020-05-18 08:20:41','2020-05-18 08:22:38','2020-05-18 08:20:41','2020-05-18 08:24:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION'),('test','ev_28716_81','SELECT * FROM (mysql.`innodb_table_stats` AS table1 INNER JOIN test.`oltp60` AS table2 ON ( table2.`pad` = table1.`n_rows` ) ) WHERE ( table1.`n_rows` != table2.`id` AND table1.`table_name` >= 5) LIMIT 1 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:20:41','2020-05-18 08:20:41','2020-05-18 08:22:46','2020-05-18 08:20:41','2020-05-18 08:24:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`innodb_table_stats` AS table1 INNER JOIN test.`oltp60` AS table2 ON ( table2.`pad` = table1.`n_rows` ) ) WHERE ( table1.`n_rows` != table2.`id` AND table1.`table_name` >= 5) LIMIT 1 ;'),('test','ev_28714_252','SELECT * FROM INFORMATION_SCHEMA.`CHECK_CONSTRAINTS` AS table1 WHERE NOT ( table1.`CONSTRAINT_CATALOG` < table1.`CONSTRAINT_NAME` OR table1.`TABLE_NAME` < 3) LIMIT 1','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:35','2020-05-18 08:22:35',NULL,'2020-05-18 08:22:35','2020-05-18 08:25:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`CHECK_CONSTRAINTS` AS table1 WHERE NOT ( table1.`CONSTRAINT_CATALOG` < table1.`CONSTRAINT_NAME` OR table1.`TABLE_NAME` < 3) LIMIT 1'),('test','ev_28716_83','SHOW ENGINES','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:42','2020-05-18 08:20:42','2020-05-18 08:22:54','2020-05-18 08:20:42','2020-05-18 08:24:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW ENGINES'),('test','ev_28718_70','UPDATE IGNORE `ROUTINES` SET `CHARACTER_OCTET_LENGTH` = \'agriculture\' ORDER BY `NUMERIC_PRECISION` LIMIT 4 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:42','2020-05-18 08:20:42','2020-05-18 08:22:41','2020-05-18 08:20:42','2020-05-18 08:24:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `ROUTINES` SET `CHARACTER_OCTET_LENGTH` = \'agriculture\' ORDER BY `NUMERIC_PRECISION` LIMIT 4 ;'),('test','ev_28714_288','REPLACE INTO `OPTIMIZER_TRACE` ( `TRACE`, _next_field ) VALUES ( \'beneath\', NULL ) ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:03','2020-05-18 08:23:03',NULL,'2020-05-18 08:23:03','2020-05-18 08:25:49','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `OPTIMIZER_TRACE` ( `TRACE`, ) VALUES ( \'beneath\', NULL ) ;'),('test','ev_28714_70','INSERT INTO `slow_log` SELECT * FROM `procs_priv`','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:42','2020-05-18 08:20:42','2020-05-18 08:22:37','2020-05-18 08:20:42','2020-05-18 08:24:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `slow_log` SELECT * FROM `procs_priv`'),('test','ev_28714_287','REPLACE INTO `help_category` ( `help_category_id` ) VALUES ( NULL ) ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:23:02','2020-05-18 08:23:02',NULL,'2020-05-18 08:23:02','2020-05-18 08:26:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `help_category` ( `help_category_id` ) VALUES ( NULL ) ;'),('test','ev_28718_71','SELECT `c` FROM `oltp160` ORDER BY `k` LIMIT 134','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:43','2020-05-18 08:20:43','2020-05-18 08:22:48','2020-05-18 08:20:43','2020-05-18 08:22:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `oltp160` ORDER BY `k` LIMIT 134'),('test','ev_28714_286','SHOW COUNT(*) WARNINGS','root@localhost',NULL,9,'SECOND','2020-05-18 08:23:02','2020-05-18 08:23:02',NULL,'2020-05-18 08:23:02','2020-05-18 08:23:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW COUNT(*) WARNINGS'),('test','ev_28716_101','INSERT INTO `t4_MyISAM` ( `id` ) VALUES ( DEFAULT ) ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:03','2020-05-18 08:21:03','2020-05-18 08:22:48','2020-05-18 08:21:03','2020-05-18 08:25:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `t4_MyISAM` ( `id` ) VALUES ( DEFAULT ) ;'),('test','ev_28716_249','UPDATE `INNODB_SYS_SEMAPHORE_WAITS` SET `THREAD_ID` = \'\' ORDER BY `WAIT_OBJECT` LIMIT 3','root@localhost',NULL,7,'SECOND','2020-05-18 08:23:02','2020-05-18 08:23:02',NULL,'2020-05-18 08:23:02','2020-05-18 08:26:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `INNODB_SYS_SEMAPHORE_WAITS` SET `THREAD_ID` = \'\' ORDER BY `WAIT_OBJECT` LIMIT 3'),('test','ev_28714_115','SHOW BINLOG EVENTS','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:03','2020-05-18 08:21:03','2020-05-18 08:22:48','2020-05-18 08:21:03','2020-05-18 08:25:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW BINLOG EVENTS'),('test','ev_28714_75','SELECT * FROM `KEY_COLUMN_USAGE` ORDER BY `CONSTRAINT_NAME` LIMIT 185 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:44','2020-05-18 08:20:44','2020-05-18 08:22:56','2020-05-18 08:20:44','2020-05-18 08:24:06','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `KEY_COLUMN_USAGE` ORDER BY `CONSTRAINT_NAME` LIMIT 185 ;'),('test','ev_28718_73','SHOW TRIGGERS','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:44','2020-05-18 08:20:44','2020-05-18 08:22:59','2020-05-18 08:20:44','2020-05-18 08:24:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW TRIGGERS'),('test','ev_28716_88','SELECT `db_name` FROM `general_log` ORDER BY `server_id` LIMIT 149','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:44','2020-05-18 08:20:44','2020-05-18 08:23:00','2020-05-18 08:20:44','2020-05-18 08:24:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `db_name` FROM `general_log` ORDER BY `server_id` LIMIT 149'),('test','ev_28714_218','START TRANSACTION ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:11','2020-05-18 08:22:11','2020-05-18 08:22:47','2020-05-18 08:22:11','2020-05-18 08:23:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION ;'),('test','ev_28718_74','UPDATE `index_stats` SET `table_name` = \'\' ORDER BY `avg_frequency` LIMIT 7','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:45','2020-05-18 08:20:45','2020-05-18 08:23:00','2020-05-18 08:20:45','2020-05-18 08:23:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `index_stats` SET `table_name` = \'\' ORDER BY `avg_frequency` LIMIT 7'),('test','ev_28716_90','CREATE UNIQUE INDEX ind3 ON ind_constr_t2 ( `id`(52) ) ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:45','2020-05-18 08:20:45','2020-05-18 08:23:05','2020-05-18 08:20:45','2020-05-18 08:24:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','CREATE UNIQUE INDEX ind3 ON ind_constr_t2 ( `id`(52) ) ;'),('test','ev_28716_91','REPLACE INTO `table_stats` ( `cardinality` ) VALUES ( DEFAULT )','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:45','2020-05-18 08:20:45','2020-05-18 08:22:56','2020-05-18 08:20:45','2020-05-18 08:24:31','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `table_stats` ( `cardinality` ) VALUES ( DEFAULT )'),('test','ev_28718_75','DELETE FROM `INNODB_FT_DEFAULT_STOPWORD` ORDER BY `value` LIMIT 6','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:46','2020-05-18 08:20:46','2020-05-18 08:22:58','2020-05-18 08:20:46','2020-05-18 08:23:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `INNODB_FT_DEFAULT_STOPWORD` ORDER BY `value` LIMIT 6'),('test','ev_28718_95','INSERT IGNORE INTO `oltp19` ( `c`, _next_field ) VALUES ( 86, \'contain\' )','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:02','2020-05-18 08:21:02','2020-05-18 08:23:04','2020-05-18 08:21:02','2020-05-18 08:23:21','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp19` ( `c`, ) VALUES ( 86, \'contain\' )'),('test','ev_28714_289','SELECT `col_int` FROM `oltp109` ORDER BY `c` LIMIT 29','root@localhost',NULL,3,'SECOND','2020-05-18 08:23:03','2020-05-18 08:23:03',NULL,'2020-05-18 08:23:03','2020-05-18 08:26:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `col_int` FROM `oltp109` ORDER BY `c` LIMIT 29'),('test','ev_28714_77','UPDATE IGNORE `proc` SET `specific_name` = \'\' ORDER BY `created` LIMIT 8','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:46','2020-05-18 08:20:46','2020-05-18 08:22:24','2020-05-18 08:20:46','2020-05-18 08:23:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `proc` SET `specific_name` = \'\' ORDER BY `created` LIMIT 8'),('test','ev_28718_76','UPDATE IGNORE `THREAD_POOL_STATS` SET `POLLS_BY_LISTENER` = \'\' ORDER BY `GROUP_ID` LIMIT 5','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:46','2020-05-18 08:20:46','2020-05-18 08:22:24','2020-05-18 08:20:46','2020-05-18 08:24:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `THREAD_POOL_STATS` SET `POLLS_BY_LISTENER` = \'\' ORDER BY `GROUP_ID` LIMIT 5'),('test','ev_28714_290','SELECT * FROM (mysql.`columns_priv` AS table1 RIGHT OUTER JOIN test.`oltp54` AS table2 ON ( table2.`c` = table1.`Host` ) ) WHERE table2.`c` > table1.`Column_priv` HAVING ( table1.`Column_name` >= \'ey\' OR table2.`c` <> \'y\') LIMIT 0','root@localhost',NULL,9,'SECOND','2020-05-18 08:23:03','2020-05-18 08:23:03',NULL,'2020-05-18 08:23:03','2020-05-18 08:24:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`columns_priv` AS table1 RIGHT OUTER JOIN test.`oltp54` AS table2 ON ( table2.`c` = table1.`Host` ) ) WHERE table2.`c` > table1.`Column_priv` HAVING ( table1.`Column_name` >= \'ey\' OR table2.`c` <> \'y\') LIMIT 0'),('test','ev_28714_78','REPLACE INTO `oltp33` () VALUES (),(),(),(),(),(),(),() ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:47','2020-05-18 08:20:47','2020-05-18 08:22:23','2020-05-18 08:20:47','2020-05-18 08:22:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp33` () VALUES (),(),(),(),(),(),(),() ;'),('test','ev_28714_246','UPDATE IGNORE `CHARACTER_SETS` SET `CHARACTER_SET_NAME` = \'\' ORDER BY `CHARACTER_SET_NAME` LIMIT 1','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:30','2020-05-18 08:22:30',NULL,'2020-05-18 08:22:30','2020-05-18 08:22:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `CHARACTER_SETS` SET `CHARACTER_SET_NAME` = \'\' ORDER BY `CHARACTER_SET_NAME` LIMIT 1'),('test','ev_28714_79','DELETE FROM `procs_priv` ORDER BY `Timestamp` LIMIT 8','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:48','2020-05-18 08:20:48','2020-05-18 08:22:28','2020-05-18 08:20:48','2020-05-18 08:23:21','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `procs_priv` ORDER BY `Timestamp` LIMIT 8'),('test','ev_28718_80','SHOW EXPLAIN FOR 253 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:48','2020-05-18 08:20:48','2020-05-18 08:22:24','2020-05-18 08:20:48','2020-05-18 08:22:30','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 253 ;'),('test','ev_28718_183','UPDATE IGNORE `tables_priv` SET `User` = \'round\' ORDER BY `Host` LIMIT 3','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:01','2020-05-18 08:22:22','2020-05-18 08:26:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `tables_priv` SET `User` = \'round\' ORDER BY `Host` LIMIT 3'),('test','ev_28716_199','SELECT * FROM `PROFILING` ORDER BY `BLOCK_OPS_OUT` LIMIT 144','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:03','2020-05-18 08:22:22','2020-05-18 08:26:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `PROFILING` ORDER BY `BLOCK_OPS_OUT` LIMIT 144'),('test','ev_28714_140','UPDATE IGNORE `oltp64` SET `c` = 197 ORDER BY `c` LIMIT 3','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:18','2020-05-18 08:21:18','2020-05-18 08:23:09','2020-05-18 08:21:18','2020-05-18 08:23:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp64` SET `c` = 197 ORDER BY `c` LIMIT 3'),('test','ev_28714_87','UPDATE IGNORE `plugin` SET `name` = \'\' ORDER BY `dl` LIMIT 1','root@localhost',NULL,3,'SECOND','2020-05-18 08:20:51','2020-05-18 08:20:51','2020-05-18 08:22:25','2020-05-18 08:20:51','2020-05-18 08:24:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `plugin` SET `name` = \'\' ORDER BY `dl` LIMIT 1'),('test','ev_28714_244','DELETE FROM `oltp146` ORDER BY `id` LIMIT 0','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:28','2020-05-18 08:22:28',NULL,'2020-05-18 08:22:28','2020-05-18 08:25:26','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp146` ORDER BY `id` LIMIT 0'),('test','ev_28714_93','UPDATE IGNORE `CLIENT_STATISTICS` SET `ROWS_DELETED` = 40 ORDER BY `ROWS_INSERTED` LIMIT 2','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:52','2020-05-18 08:20:52','2020-05-18 08:22:27','2020-05-18 08:20:52','2020-05-18 08:22:47','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `CLIENT_STATISTICS` SET `ROWS_DELETED` = 40 ORDER BY `ROWS_INSERTED` LIMIT 2'),('test','ev_28716_92','SELECT * FROM (test.`oltp147` AS table1 RIGHT OUTER JOIN mysql.`slow_log` AS table2 ON ( table2.`lock_time` = table1.`c` ) ) WHERE ( ( ( ( ( (NOT (NOT ( ( ( (NOT ( ( table1.`c` <= \'l\' OR table2.`db` >= 3) AND table1.`c` <> 1) OR table2.`last_insert_id` = table2.`rows_affected`) AND table1.`id` != \'e\') AND table1.`k` = 2) AND table2.`rows_examined` < \'2010-05-14 12:39:03.016386\') OR table2.`rows_examined` >= table2.`rows_sent`) OR table2.`rows_affected` <> table1.`c`) OR table2.`user_host` <= table2.`user_host`) OR table2.`rows_examined` <> \'1973-12-26 19:08:11.056914\') OR table1.`pad` >= \'1996-04-01 21:55:05.005559\') AND table1.`pad` <> \'1910-01-08 20:21:36.009380\') AND table1.`id` > table1.`pad`) HAVING ( ( ( ( ( table2.`rows_sent` > 5 AND table2.`thread_id` = \'2032-01-24 11:37:50.000518\') OR table1.`c` = \'ng\') OR table1.`id` < 0) OR table2.`lock_time` <> \'g\') OR table2.`start_time` <= \'1960-05-21 02:11:21.058354\') LIMIT 4','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:53','2020-05-18 08:20:53','2020-05-18 08:22:30','2020-05-18 08:20:53','2020-05-18 08:24:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp147` AS table1 RIGHT OUTER JOIN mysql.`slow_log` AS table2 ON ( table2.`lock_time` = table1.`c` ) ) WHERE ( ( ( ( ( (NOT (NOT ( ( ( (NOT ( ( table1.`c` <= \'l\' OR table2.`db` >= 3) AND table1.`c` <> 1) OR table2.`last_insert_id` = table2.`rows_affected`) AND table1.`id` != \'e\') AND table1.`k` = 2) AND table2.`rows_examined` < \'2010-05-14 12:39:03.016386\') OR table2.`rows_examined` >= table2.`rows_sent`) OR table2.`rows_affected` <> table1.`c`) OR table2.`user_host` <= table2.`user_host`) OR table2.`rows_examined` <> \'1973-12-26 19:08:11.056914\') OR table1.`pad` >= \'1996-04-01 21:55:05.005559\') AND table1.`pad` <> \'1910-01-08 20:21:36.009380\') AND table1.`id` > table1.`pad`) HAVING ( ( ( ( ( table2.`rows_sent` > 5 AND table2.`thread_id` = \'2032-01-24 11:37:50.000518\') OR table1.`c` = \'ng\') OR table1.`id` < 0) OR table2.`lock_time` <> \'g\') OR table2.`start_time` <= \'1960-05-21 02:11:21.058354\') LIMIT 4'),('test','ev_28716_211','DELETE FROM `oltp32` ORDER BY `c` LIMIT 6','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:29','2020-05-18 08:22:29',NULL,'2020-05-18 08:22:29','2020-05-18 08:23:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp32` ORDER BY `c` LIMIT 6'),('test','ev_28718_82','SHOW TABLE STATUS ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:53','2020-05-18 08:20:53','2020-05-18 08:22:31','2020-05-18 08:20:53','2020-05-18 08:23:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW TABLE STATUS ;'),('test','ev_28716_94','UPDATE IGNORE `innodb_index_stats` SET `last_update` = \'welfare\' ORDER BY `last_update` LIMIT 6','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:54','2020-05-18 08:20:54','2020-05-18 08:22:33','2020-05-18 08:20:54','2020-05-18 08:23:39','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `innodb_index_stats` SET `last_update` = \'welfare\' ORDER BY `last_update` LIMIT 6'),('test','ev_28718_83','REPLACE INTO `oltp161` () VALUES (),()','root@localhost',NULL,5,'SECOND','2020-05-18 08:20:54','2020-05-18 08:20:54','2020-05-18 08:22:33','2020-05-18 08:20:54','2020-05-18 08:24:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp161` () VALUES (),()'),('test','ev_28714_94','REPLACE INTO `SPATIAL_REF_SYS` ( `AUTH_NAME` ) VALUES ( \'flower\' ) ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:20:54','2020-05-18 08:20:54','2020-05-18 08:22:34','2020-05-18 08:20:54','2020-05-18 08:24:55','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `SPATIAL_REF_SYS` ( `AUTH_NAME` ) VALUES ( \'flower\' ) ;'),('test','ev_28714_253','ALTER TABLE IF EXISTS ind_constr_t1 ADD UNIQUE KEY ind9 ( b(63) ASC ), LOCK=DEFAULT ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:36','2020-05-18 08:22:36',NULL,'2020-05-18 08:22:36','2020-05-18 08:24:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','ALTER TABLE IF EXISTS ind_constr_t1 ADD UNIQUE KEY ind9 ( b(63) ASC ), LOCK=DEFAULT ;'),('test','ev_28714_96','SELECT `k` FROM `oltp38` ORDER BY `k` LIMIT 144','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:56','2020-05-18 08:20:56','2020-05-18 08:22:33','2020-05-18 08:20:56','2020-05-18 08:22:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `k` FROM `oltp38` ORDER BY `k` LIMIT 144'),('test','ev_28714_97','START TRANSACTION ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:20:57','2020-05-18 08:20:57','2020-05-18 08:22:34','2020-05-18 08:20:57','2020-05-18 08:22:56','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION ;'),('test','ev_28716_95','SELECT * FROM INFORMATION_SCHEMA.`INNODB_MUTEXES` AS table1 WHERE ( ( table1.`CREATE_FILE` = \'2031-03-15 18:29:24.029027\' OR table1.`OS_WAITS` <= \'u\') OR table1.`NAME` = 4) LIMIT 6 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:34','2020-05-18 08:20:58','2020-05-18 08:22:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`INNODB_MUTEXES` AS table1 WHERE ( ( table1.`CREATE_FILE` = \'2031-03-15 18:29:24.029027\' OR table1.`OS_WAITS` <= \'u\') OR table1.`NAME` = 4) LIMIT 6 ;'),('test','ev_28714_215','SELECT * FROM mysql.`help_keyword` AS table1 WHERE table1.`name` != table1.`help_keyword_id` LIMIT 9','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:10','2020-05-18 08:22:10','2020-05-18 08:22:45','2020-05-18 08:22:10','2020-05-18 08:26:23','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM mysql.`help_keyword` AS table1 WHERE table1.`name` != table1.`help_keyword_id` LIMIT 9'),('test','ev_28714_104','DELETE FROM `tables_priv` ORDER BY `Host` LIMIT 8 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:37','2020-05-18 08:20:58','2020-05-18 08:25:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `tables_priv` ORDER BY `Host` LIMIT 8 ;'),('test','ev_28718_87','SELECT `c` FROM `oltp86` ORDER BY `c` LIMIT 111 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:46','2020-05-18 08:20:58','2020-05-18 08:23:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `oltp86` ORDER BY `c` LIMIT 111 ;'),('test','ev_28714_107','UPDATE IGNORE `oltp115` SET `id` = 204 ORDER BY `pad` LIMIT 6 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:41','2020-05-18 08:20:58','2020-05-18 08:23:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp115` SET `id` = 204 ORDER BY `pad` LIMIT 6 ;'),('test','ev_28716_96','SELECT `c` FROM `oltp80` ORDER BY `pad` LIMIT 137 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:58','2020-05-18 08:20:58','2020-05-18 08:22:36','2020-05-18 08:20:58','2020-05-18 08:22:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `oltp80` ORDER BY `pad` LIMIT 137 ;'),('test','ev_28718_88','FLUSH NO_WRITE_TO_BINLOG QUERY CACHE','root@localhost',NULL,2,'SECOND','2020-05-18 08:20:59','2020-05-18 08:20:59','2020-05-18 08:22:35','2020-05-18 08:20:59','2020-05-18 08:25:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','FLUSH NO_WRITE_TO_BINLOG QUERY CACHE'),('test','ev_28718_208','DELETE FROM `table_stats` ORDER BY `db_name` LIMIT 5','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:45','2020-05-18 08:22:45',NULL,'2020-05-18 08:22:45','2020-05-18 08:23:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `table_stats` ORDER BY `db_name` LIMIT 5'),('test','ev_28718_154','SELECT * FROM `INNODB_CMP_PER_INDEX` ORDER BY `compress_ops` LIMIT 39','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:25:31','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `INNODB_CMP_PER_INDEX` ORDER BY `compress_ops` LIMIT 39'),('test','ev_28714_110','SELECT * FROM `global_priv` ORDER BY `User` LIMIT 75','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:00','2020-05-18 08:21:00','2020-05-18 08:22:36','2020-05-18 08:21:00','2020-05-18 08:25:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `global_priv` ORDER BY `User` LIMIT 75'),('test','ev_28714_112','SELECT * FROM (INFORMATION_SCHEMA.`THREAD_POOL_QUEUES` AS table1 INNER JOIN INFORMATION_SCHEMA.`CHECK_CONSTRAINTS` AS table2 ON ( table2.`CHECK_CLAUSE` = table1.`PRIORITY` ) ) WHERE table2.`CONSTRAINT_NAME` > table2.`CONSTRAINT_SCHEMA` LIMIT 1 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:00','2020-05-18 08:21:00','2020-05-18 08:22:35','2020-05-18 08:21:00','2020-05-18 08:24:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`THREAD_POOL_QUEUES` AS table1 INNER JOIN INFORMATION_SCHEMA.`CHECK_CONSTRAINTS` AS table2 ON ( table2.`CHECK_CLAUSE` = table1.`PRIORITY` ) ) WHERE table2.`CONSTRAINT_NAME` > table2.`CONSTRAINT_SCHEMA` LIMIT 1 ;'),('test','ev_28714_113','DELETE FROM `gtid_slave_pos` ORDER BY `seq_no` LIMIT 4','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:01','2020-05-18 08:21:01','2020-05-18 08:22:53','2020-05-18 08:21:01','2020-05-18 08:24:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `gtid_slave_pos` ORDER BY `seq_no` LIMIT 4'),('test','ev_28714_254','UPDATE IGNORE `KEY_COLUMN_USAGE` SET `TABLE_NAME` = 32 ORDER BY `REFERENCED_COLUMN_NAME` LIMIT 9','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:36','2020-05-18 08:22:36',NULL,'2020-05-18 08:22:36','2020-05-18 08:24:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `KEY_COLUMN_USAGE` SET `TABLE_NAME` = 32 ORDER BY `REFERENCED_COLUMN_NAME` LIMIT 9'),('test','ev_28716_98','UPDATE IGNORE `FILES` SET `DATA_LENGTH` = 192 ORDER BY `CREATION_TIME` LIMIT 7 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:01','2020-05-18 08:21:01','2020-05-18 08:22:38','2020-05-18 08:21:01','2020-05-18 08:23:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `FILES` SET `DATA_LENGTH` = 192 ORDER BY `CREATION_TIME` LIMIT 7 ;'),('test','ev_28718_180','SELECT * FROM `oltp58` INTO OUTFILE \'load_oltp58\' ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:17','2020-05-18 08:22:17','2020-05-18 08:22:56','2020-05-18 08:22:17','2020-05-18 08:23:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp58` INTO OUTFILE \'load_oltp58\' ;'),('test','ev_28718_96','SELECT * FROM (test.`oltp104` AS table1 RIGHT OUTER JOIN test.`oltp89` AS table2 ON ( table2.`k` = table1.`pad` ) ) WHERE (NOT (NOT ( ( (NOT table2.`pad` = table1.`c` AND table1.`c` <> \'1970-10-01 14:36:52.023873\') OR table1.`id` = table2.`pad`) OR table1.`c` >= table2.`c`) OR table1.`id` <> table2.`k`) AND table1.`c` != table2.`pad`) LIMIT 3 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:02','2020-05-18 08:21:02','2020-05-18 08:22:36','2020-05-18 08:21:02','2020-05-18 08:25:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp104` AS table1 RIGHT OUTER JOIN test.`oltp89` AS table2 ON ( table2.`k` = table1.`pad` ) ) WHERE (NOT (NOT ( ( (NOT table2.`pad` = table1.`c` AND table1.`c` <> \'1970-10-01 14:36:52.023873\') OR table1.`id` = table2.`pad`) OR table1.`c` >= table2.`c`) OR table1.`id` <> table2.`k`) AND table1.`c` != table2.`pad`) LIMIT 3 ;'),('test','ev_28718_209','SELECT * FROM `roles_mapping` ORDER BY `User` LIMIT 17','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:45','2020-05-18 08:22:45',NULL,'2020-05-18 08:22:45','2020-05-18 08:25:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `roles_mapping` ORDER BY `User` LIMIT 17'),('test','ev_28716_251','ALTER IGNORE TABLE IF EXISTS ind_constr_t2 ENABLE KEYS ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:23:06','2020-05-18 08:23:06',NULL,'2020-05-18 08:23:06','2020-05-18 08:24:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','ALTER IGNORE TABLE IF EXISTS ind_constr_t2 ENABLE KEYS ;'),('test','ev_28716_237','SHOW DATABASES ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:49','2020-05-18 08:22:49',NULL,'2020-05-18 08:22:49','2020-05-18 08:23:07','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW DATABASES ;'),('test','ev_28714_274','UPDATE `columns_priv` SET `User` = \'\' ORDER BY `User` LIMIT 6','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:48','2020-05-18 08:22:48',NULL,'2020-05-18 08:22:48','2020-05-18 08:24:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `columns_priv` SET `User` = \'\' ORDER BY `User` LIMIT 6'),('test','ev_28716_176','SHOW FUNCTION CODE a','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:17','2020-05-18 08:22:17','2020-05-18 08:22:56','2020-05-18 08:22:17','2020-05-18 08:24:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW FUNCTION CODE a'),('test','ev_28716_105','INSERT IGNORE INTO `time_zone_transition` () VALUES ()','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:03','2020-05-18 08:21:03','2020-05-18 08:23:01','2020-05-18 08:21:03','2020-05-18 08:23:55','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_transition` () VALUES ()'),('test','ev_28714_159','SELECT * FROM `TABLESPACES` INTO OUTFILE \'load_TABLESPACES\' ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:35','2020-05-18 08:21:35','2020-05-18 08:22:46','2020-05-18 08:21:35','2020-05-18 08:25:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `TABLESPACES` INTO OUTFILE \'load_TABLESPACES\' ;'),('test','ev_28714_116','DELETE FROM `oltp143` ORDER BY `pad` LIMIT 7','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:05','2020-05-18 08:21:05','2020-05-18 08:22:47','2020-05-18 08:21:05','2020-05-18 08:24:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp143` ORDER BY `pad` LIMIT 7'),('test','ev_28716_107','SELECT * FROM `oltp144` ORDER BY `c` LIMIT 88','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:05','2020-05-18 08:21:05','2020-05-18 08:23:09','2020-05-18 08:21:05','2020-05-18 08:24:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp144` ORDER BY `c` LIMIT 88'),('test','ev_28718_100','UPDATE `oltp20` SET `c` = 76 ORDER BY `pad` LIMIT 7','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:05','2020-05-18 08:21:05','2020-05-18 08:22:48','2020-05-18 08:21:05','2020-05-18 08:23:53','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `oltp20` SET `c` = 76 ORDER BY `pad` LIMIT 7'),('test','ev_28714_120','SHOW OPEN TABLES ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:06','2020-05-18 08:21:06','2020-05-18 08:22:57','2020-05-18 08:21:06','2020-05-18 08:23:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW OPEN TABLES ;'),('test','ev_28714_121','SELECT * FROM (INFORMATION_SCHEMA.`GLOBAL_STATUS` AS table1 RIGHT OUTER JOIN test.`oltp145` AS table2 ON ( table2.`c` = table1.`VARIABLE_NAME` ) ) WHERE ( ( ( ( table1.`VARIABLE_VALUE` >= 3 OR table1.`VARIABLE_VALUE` != 4) AND table2.`id` <= table1.`VARIABLE_VALUE`) OR table2.`pad` != table1.`VARIABLE_VALUE`) OR table1.`VARIABLE_NAME` < table1.`VARIABLE_VALUE`) HAVING (table2.`pad` < 1 IS NOT NULL OR table1.`VARIABLE_VALUE` = \'t\') LIMIT 9','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:06','2020-05-18 08:21:06','2020-05-18 08:22:19','2020-05-18 08:21:06','2020-05-18 08:25:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`GLOBAL_STATUS` AS table1 RIGHT OUTER JOIN test.`oltp145` AS table2 ON ( table2.`c` = table1.`VARIABLE_NAME` ) ) WHERE ( ( ( ( table1.`VARIABLE_VALUE` >= 3 OR table1.`VARIABLE_VALUE` != 4) AND table2.`id` <= table1.`VARIABLE_VALUE`) OR table2.`pad` != table1.`VARIABLE_VALUE`) OR table1.`VARIABLE_NAME` < table1.`VARIABLE_VALUE`) HAVING (table2.`pad` < 1 IS NOT NULL OR table1.`VARIABLE_VALUE` = \'t\') LIMIT 9'),('test','ev_28714_224','INSERT IGNORE INTO `INNODB_FT_INDEX_TABLE` ( `DOC_ID`, _next_field ) VALUES ( \'love\', \'r\' )','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:15','2020-05-18 08:22:15','2020-05-18 08:22:54','2020-05-18 08:22:15','2020-05-18 08:24:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `INNODB_FT_INDEX_TABLE` ( `DOC_ID`, ) VALUES ( \'love\', \'r\' )'),('test','ev_28714_123','UPDATE IGNORE `REFERENTIAL_CONSTRAINTS` SET `REFERENCED_TABLE_NAME` = DEFAULT ORDER BY `UNIQUE_CONSTRAINT_NAME` LIMIT 4','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:07','2020-05-18 08:21:07','2020-05-18 08:23:05','2020-05-18 08:21:07','2020-05-18 08:23:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `REFERENTIAL_CONSTRAINTS` SET `REFERENCED_TABLE_NAME` = DEFAULT ORDER BY `UNIQUE_CONSTRAINT_NAME` LIMIT 4'),('test','ev_28714_294','UPDATE IGNORE `oltp136` SET `c` = DEFAULT ORDER BY `pad` LIMIT 2','root@localhost',NULL,6,'SECOND','2020-05-18 08:23:08','2020-05-18 08:23:08',NULL,'2020-05-18 08:23:08','2020-05-18 08:26:39','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp136` SET `c` = DEFAULT ORDER BY `pad` LIMIT 2'),('test','ev_28716_252','REPLACE INTO `servers` ( `Socket`, _next_field ) VALUES ( \'i\', DEFAULT )','root@localhost',NULL,8,'SECOND','2020-05-18 08:23:07','2020-05-18 08:23:07',NULL,'2020-05-18 08:23:07','2020-05-18 08:25:35','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `servers` ( `Socket`, ) VALUES ( \'i\', DEFAULT )'),('test','ev_28718_226','DELETE FROM `INNODB_SYS_VIRTUAL` ORDER BY `TABLE_ID` LIMIT 3','root@localhost',NULL,9,'SECOND','2020-05-18 08:23:08','2020-05-18 08:23:08',NULL,'2020-05-18 08:23:08','2020-05-18 08:24:06','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `INNODB_SYS_VIRTUAL` ORDER BY `TABLE_ID` LIMIT 3'),('test','ev_28716_254','DROP INDEX IF EXISTS ind1 ON `oltp148`','root@localhost',NULL,5,'SECOND','2020-05-18 08:23:08','2020-05-18 08:23:08',NULL,'2020-05-18 08:23:08','2020-05-18 08:23:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DROP INDEX IF EXISTS ind1 ON `oltp148`'),('test','ev_28716_244','SHOW CREATE FUNCTION b','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:55','2020-05-18 08:22:55',NULL,'2020-05-18 08:22:55','2020-05-18 08:25:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW CREATE FUNCTION b'),('test','ev_28714_126','SELECT `User` FROM `time_zone_leap_second` ORDER BY `Transition_time` LIMIT 212','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:08','2020-05-18 08:21:08','2020-05-18 08:22:20','2020-05-18 08:21:08','2020-05-18 08:25:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `User` FROM `time_zone_leap_second` ORDER BY `Transition_time` LIMIT 212'),('test','ev_28714_127','SELECT * FROM `INNODB_SYS_COLUMNS` INTO OUTFILE \'load_INNODB_SYS_COLUMNS\' ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:08','2020-05-18 08:21:08','2020-05-18 08:22:59','2020-05-18 08:21:08','2020-05-18 08:24:47','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `INNODB_SYS_COLUMNS` INTO OUTFILE \'load_INNODB_SYS_COLUMNS\' ;'),('test','ev_28716_112','SHOW CREATE TABLE y','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:08','2020-05-18 08:21:08','2020-05-18 08:22:59','2020-05-18 08:21:08','2020-05-18 08:23:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW CREATE TABLE y'),('test','ev_28714_128','SHOW EXPLAIN FOR 104','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:09','2020-05-18 08:21:09','2020-05-18 08:22:58','2020-05-18 08:21:09','2020-05-18 08:25:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 104'),('test','ev_28716_196','SELECT * FROM `proc` ORDER BY `body` LIMIT 12','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:02','2020-05-18 08:22:22','2020-05-18 08:24:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `proc` ORDER BY `body` LIMIT 12'),('test','ev_28718_125','UPDATE IGNORE `THREAD_POOL_STATS` SET `THREAD_CREATIONS_DUE_TO_STALL` = 122 ORDER BY `POLLS_BY_WORKER` LIMIT 4 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:40','2020-05-18 08:21:40','2020-05-18 08:23:01','2020-05-18 08:21:40','2020-05-18 08:24:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `THREAD_POOL_STATS` SET `THREAD_CREATIONS_DUE_TO_STALL` = 122 ORDER BY `POLLS_BY_WORKER` LIMIT 4 ;'),('test','ev_28716_114','UPDATE IGNORE `global_priv` SET `Host` = NULL ORDER BY `Priv` LIMIT 8','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:11','2020-05-18 08:21:11','2020-05-18 08:22:22','2020-05-18 08:21:11','2020-05-18 08:22:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `global_priv` SET `Host` = NULL ORDER BY `Priv` LIMIT 8'),('test','ev_28714_132','/* compatibility 10.4.3 */ CREATE OR REPLACE TABLE ind_constr_t4 (f VARBINARY(1025), b LONGTEXT, UNIQUE(b)) AS SELECT /* `transaction_registry` */ `isolation_level`, `commit_id` FROM `time_zone`','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:11','2020-05-18 08:21:11','2020-05-18 08:22:59','2020-05-18 08:21:11','2020-05-18 08:23:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','/* compatibility 10.4.3 */ CREATE OR REPLACE TABLE ind_constr_t4 (f VARBINARY(1025), b LONGTEXT, UNIQUE(b)) AS SELECT /* `transaction_registry` */ `isolation_level`, `commit_id` FROM `time_zone`'),('test','ev_28718_229','UPDATE IGNORE `COLUMN_PRIVILEGES` SET `COLUMN_NAME` = \'\' ORDER BY `TABLE_CATALOG` LIMIT 8 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:23:09','2020-05-18 08:23:09',NULL,'2020-05-18 08:23:09','2020-05-18 08:23:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `COLUMN_PRIVILEGES` SET `COLUMN_NAME` = \'\' ORDER BY `TABLE_CATALOG` LIMIT 8 ;'),('test','ev_28714_232','FLUSH PRIVILEGES, PRIVILEGES, LOGS ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:57','2020-05-18 08:22:19','2020-05-18 08:23:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','FLUSH PRIVILEGES, PRIVILEGES, LOGS ;'),('test','ev_28714_138','SELECT * FROM `innodb_table_stats` ORDER BY `clustered_index_size` LIMIT 59 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:15','2020-05-18 08:21:15','2020-05-18 08:22:25','2020-05-18 08:21:15','2020-05-18 08:24:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `innodb_table_stats` ORDER BY `clustered_index_size` LIMIT 59 ;'),('test','ev_28718_126','UPDATE IGNORE `STATISTICS` SET `CARDINALITY` = 47 ORDER BY `COLUMN_NAME` LIMIT 3 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:41','2020-05-18 08:21:41','2020-05-18 08:22:58','2020-05-18 08:21:41','2020-05-18 08:25:52','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `STATISTICS` SET `CARDINALITY` = 47 ORDER BY `COLUMN_NAME` LIMIT 3 ;'),('test','ev_28718_228','REPLACE INTO `db` ( `Select_priv` ) VALUES ( DEFAULT )','root@localhost',NULL,1,'SECOND','2020-05-18 08:23:09','2020-05-18 08:23:09',NULL,'2020-05-18 08:23:09','2020-05-18 08:24:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `db` ( `Select_priv` ) VALUES ( DEFAULT )'),('test','ev_28714_295','SELECT * FROM `time_zone_transition_type` ORDER BY `Transition_type_id` LIMIT 237','root@localhost',NULL,9,'SECOND','2020-05-18 08:23:10','2020-05-18 08:23:10',NULL,'2020-05-18 08:23:10','2020-05-18 08:23:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `time_zone_transition_type` ORDER BY `Transition_type_id` LIMIT 237'),('test','ev_28714_141','SELECT * FROM (mysql.`time_zone_transition` AS table1 RIGHT OUTER JOIN INFORMATION_SCHEMA.`INNODB_SYS_FOREIGN_COLS` AS table2 ON ( table2.`FOR_COL_NAME` = table1.`Transition_time` ) ) WHERE table1.`Transition_time` != 5 HAVING table1.`Transition_type_id` > \'1910-11-02 04:07:10.013374\' IS NOT NULL LIMIT 3 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:18','2020-05-18 08:21:18','2020-05-18 08:22:29','2020-05-18 08:21:18','2020-05-18 08:22:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (mysql.`time_zone_transition` AS table1 RIGHT OUTER JOIN INFORMATION_SCHEMA.`INNODB_SYS_FOREIGN_COLS` AS table2 ON ( table2.`FOR_COL_NAME` = table1.`Transition_time` ) ) WHERE table1.`Transition_time` != 5 HAVING table1.`Transition_type_id` > \'1910-11-02 04:07:10.013374\' IS NOT NULL LIMIT 3 ;'),('test','ev_28718_202','SHOW EXPLAIN FOR 14','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:40','2020-05-18 08:22:40',NULL,'2020-05-18 08:22:40','2020-05-18 08:24:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 14'),('test','ev_28718_188','SELECT `c` FROM `t3_InnoDB` ORDER BY `id` LIMIT 193','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:25','2020-05-18 08:22:25','2020-05-18 08:23:08','2020-05-18 08:22:25','2020-05-18 08:25:40','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `c` FROM `t3_InnoDB` ORDER BY `id` LIMIT 193'),('test','ev_28718_103','UPDATE `INNODB_CMP` SET `page_size` = \'z\' ORDER BY `compress_ops` LIMIT 3','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:18','2020-05-18 08:21:18','2020-05-18 08:23:10','2020-05-18 08:21:18','2020-05-18 08:23:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE `INNODB_CMP` SET `page_size` = \'z\' ORDER BY `compress_ops` LIMIT 3'),('test','ev_28714_143','SELECT `user_host` FROM `transaction_registry` ORDER BY `begin_timestamp` LIMIT 187','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:19','2020-05-18 08:21:19','2020-05-18 08:22:25','2020-05-18 08:21:19','2020-05-18 08:23:53','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `user_host` FROM `transaction_registry` ORDER BY `begin_timestamp` LIMIT 187'),('test','ev_28718_104','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_FT_BEING_DELETED` AS table1 LEFT JOIN INFORMATION_SCHEMA.`TABLE_STATISTICS` AS table2 ON ( table2.`TABLE_NAME` = table1.`DOC_ID` ) ) WHERE table1.`DOC_ID` != table2.`TABLE_NAME` LIMIT 2 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:19','2020-05-18 08:21:19','2020-05-18 08:23:06','2020-05-18 08:21:19','2020-05-18 08:24:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_FT_BEING_DELETED` AS table1 LEFT JOIN INFORMATION_SCHEMA.`TABLE_STATISTICS` AS table2 ON ( table2.`TABLE_NAME` = table1.`DOC_ID` ) ) WHERE table1.`DOC_ID` != table2.`TABLE_NAME` LIMIT 2 ;'),('test','ev_28718_105','REPLACE INTO `INNODB_SYS_FIELDS` ( `POS` ) VALUES ( \'\' ) ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:19','2020-05-18 08:21:19','2020-05-18 08:23:05','2020-05-18 08:21:19','2020-05-18 08:24:35','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `INNODB_SYS_FIELDS` ( `POS` ) VALUES ( \'\' ) ;'),('test','ev_28714_144','SELECT `pad` FROM `t4_InnoDB` ORDER BY `col_varchar` LIMIT 122','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:19','2020-05-18 08:21:19','2020-05-18 08:22:24','2020-05-18 08:21:19','2020-05-18 08:24:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `pad` FROM `t4_InnoDB` ORDER BY `col_varchar` LIMIT 122'),('test','ev_28716_146','SELECT * FROM (INFORMATION_SCHEMA.`OPTIMIZER_TRACE` AS table1 INNER JOIN INFORMATION_SCHEMA.`TRIGGERS` AS table2 ON ( table2.`COLLATION_CONNECTION` = table1.`QUERY` ) ) WHERE ( table1.`INSUFFICIENT_PRIVILEGES` >= table2.`ACTION_REFERENCE_NEW_TABLE` AND table1.`TRACE` <= table1.`QUERY`) HAVING table2.`TRIGGER_CATALOG` >= 7 LIMIT 1','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:51','2020-05-18 08:21:51','2020-05-18 08:22:25','2020-05-18 08:21:51','2020-05-18 08:25:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`OPTIMIZER_TRACE` AS table1 INNER JOIN INFORMATION_SCHEMA.`TRIGGERS` AS table2 ON ( table2.`COLLATION_CONNECTION` = table1.`QUERY` ) ) WHERE ( table1.`INSUFFICIENT_PRIVILEGES` >= table2.`ACTION_REFERENCE_NEW_TABLE` AND table1.`TRACE` <= table1.`QUERY`) HAVING table2.`TRIGGER_CATALOG` >= 7 LIMIT 1'),('test','ev_28718_107','UPDATE IGNORE `column_stats` SET `nulls_ratio` = \'entrepreneur\' ORDER BY `hist_size` LIMIT 9','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:21','2020-05-18 08:21:21','2020-05-18 08:22:32','2020-05-18 08:21:21','2020-05-18 08:24:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `column_stats` SET `nulls_ratio` = \'entrepreneur\' ORDER BY `hist_size` LIMIT 9'),('test','ev_28716_116','SELECT * FROM (INFORMATION_SCHEMA.`user_variables` AS table1 LEFT JOIN test.`oltp110` AS table2 ON ( table2.`c` = table1.`VARIABLE_NAME` ) ) WHERE ( table1.`VARIABLE_TYPE` != table1.`CHARACTER_SET_NAME` AND table1.`CHARACTER_SET_NAME` >= table1.`VARIABLE_NAME`) HAVING table1.`VARIABLE_VALUE` != \'i\' IS NULL LIMIT 4 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:22','2020-05-18 08:21:22','2020-05-18 08:22:32','2020-05-18 08:21:22','2020-05-18 08:24:21','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`user_variables` AS table1 LEFT JOIN test.`oltp110` AS table2 ON ( table2.`c` = table1.`VARIABLE_NAME` ) ) WHERE ( table1.`VARIABLE_TYPE` != table1.`CHARACTER_SET_NAME` AND table1.`CHARACTER_SET_NAME` >= table1.`VARIABLE_NAME`) HAVING table1.`VARIABLE_VALUE` != \'i\' IS NULL LIMIT 4 ;'),('test','ev_28716_157','DELETE FROM `time_zone` ORDER BY `Use_leap_seconds` LIMIT 2','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:25:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `time_zone` ORDER BY `Use_leap_seconds` LIMIT 2'),('test','ev_28714_147','SELECT `id` FROM `oltp157` ORDER BY `c` LIMIT 112','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:23','2020-05-18 08:21:23','2020-05-18 08:22:31','2020-05-18 08:21:23','2020-05-18 08:24:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp157` ORDER BY `c` LIMIT 112'),('test','ev_28718_109','SELECT `Transition_time` FROM `time_zone_transition` ORDER BY `Transition_time` LIMIT 120 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:24','2020-05-18 08:21:24','2020-05-18 08:22:33','2020-05-18 08:21:24','2020-05-18 08:22:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Transition_time` FROM `time_zone_transition` ORDER BY `Transition_time` LIMIT 120 ;'),('test','ev_28716_120','SELECT * FROM `procs_priv` ORDER BY `Timestamp` LIMIT 104 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:24','2020-05-18 08:21:24','2020-05-18 08:22:32','2020-05-18 08:21:24','2020-05-18 08:25:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `procs_priv` ORDER BY `Timestamp` LIMIT 104 ;'),('test','ev_28714_148','SELECT * FROM `innodb_index_stats` ORDER BY `index_name` LIMIT 226 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:26','2020-05-18 08:21:26','2020-05-18 08:22:38','2020-05-18 08:21:26','2020-05-18 08:23:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `innodb_index_stats` ORDER BY `index_name` LIMIT 226 ;'),('test','n','SET @a=@a','root@localhost','2020-05-18 08:22:36',NULL,NULL,'2020-05-18 08:22:36','2020-05-18 08:22:36',NULL,NULL,NULL,'ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SET @a=@a'),('test','ev_28716_156','SHOW FUNCTION STATUS','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:02','2020-05-18 08:22:02','2020-05-18 08:22:34','2020-05-18 08:22:02','2020-05-18 08:23:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW FUNCTION STATUS'),('test','ev_28716_123','SELECT * FROM `servers` ORDER BY `Owner` LIMIT 133 ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:34','2020-05-18 08:21:29','2020-05-18 08:25:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `servers` ORDER BY `Owner` LIMIT 133 ;'),('test','ev_28718_112','UPDATE IGNORE `t9_InnoDB` SET `col_int` = \'t\' ORDER BY `col_blob` LIMIT 9','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:29','2020-05-18 08:21:29','2020-05-18 08:22:34','2020-05-18 08:21:29','2020-05-18 08:24:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `t9_InnoDB` SET `col_int` = \'t\' ORDER BY `col_blob` LIMIT 9'),('test','ev_28714_242','SELECT * FROM `t4_MyISAM` ORDER BY `col_enum` LIMIT 43','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:25','2020-05-18 08:22:25','2020-05-18 08:23:08','2020-05-18 08:22:25','2020-05-18 08:26:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `t4_MyISAM` ORDER BY `col_enum` LIMIT 43'),('test','ev_28716_220','SELECT * FROM `oltp115` ORDER BY `pad` LIMIT 55','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:37','2020-05-18 08:22:37',NULL,'2020-05-18 08:22:37','2020-05-18 08:23:21','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp115` ORDER BY `pad` LIMIT 55'),('test','ev_28714_153','UPDATE IGNORE `SYSTEM_VARIABLES` SET `NUMERIC_MIN_VALUE` = \'y\' ORDER BY `NUMERIC_MAX_VALUE` LIMIT 3 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:30','2020-05-18 08:21:30','2020-05-18 08:22:37','2020-05-18 08:21:30','2020-05-18 08:23:39','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `SYSTEM_VARIABLES` SET `NUMERIC_MIN_VALUE` = \'y\' ORDER BY `NUMERIC_MAX_VALUE` LIMIT 3 ;'),('test','ev_28714_154','DELETE FROM `oltp118` ORDER BY `pad` LIMIT 9','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:30','2020-05-18 08:21:30','2020-05-18 08:22:35','2020-05-18 08:21:30','2020-05-18 08:22:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `oltp118` ORDER BY `pad` LIMIT 9'),('test','ev_28718_116','SELECT `pad` FROM `oltp30` ORDER BY `id` LIMIT 130','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:30','2020-05-18 08:21:30','2020-05-18 08:22:39','2020-05-18 08:21:30','2020-05-18 08:23:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `pad` FROM `oltp30` ORDER BY `id` LIMIT 130'),('test','ev_28714_157','SELECT * FROM `innodb_table_stats` ORDER BY `clustered_index_size` LIMIT 141','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:31','2020-05-18 08:21:31','2020-05-18 08:22:38','2020-05-18 08:21:31','2020-05-18 08:24:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `innodb_table_stats` ORDER BY `clustered_index_size` LIMIT 141'),('test','ev_28716_125','START TRANSACTION ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:31','2020-05-18 08:21:31','2020-05-18 08:22:35','2020-05-18 08:21:31','2020-05-18 08:23:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','START TRANSACTION ;'),('test','ev_28714_158','UPDATE IGNORE `oltp132` SET `id` = DEFAULT ORDER BY `c` LIMIT 6','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:31','2020-05-18 08:21:31','2020-05-18 08:22:36','2020-05-18 08:21:31','2020-05-18 08:24:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp132` SET `id` = DEFAULT ORDER BY `c` LIMIT 6'),('test','ev_28716_126','DELETE FROM `slow_log` ORDER BY `insert_id` LIMIT 3','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:32','2020-05-18 08:21:32','2020-05-18 08:22:37','2020-05-18 08:21:32','2020-05-18 08:25:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `slow_log` ORDER BY `insert_id` LIMIT 3'),('test','ev_28716_127','DELETE FROM `COLUMN_PRIVILEGES` ORDER BY `TABLE_NAME` LIMIT 4 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:35','2020-05-18 08:21:35','2020-05-18 08:22:42','2020-05-18 08:21:35','2020-05-18 08:24:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `COLUMN_PRIVILEGES` ORDER BY `TABLE_NAME` LIMIT 4 ;'),('test','ev_28718_120','ALTER IGNORE TABLE `time_zone_transition_type` ADD INDEX IF NOT EXISTS l USING BTREE ( e, y, `Is_DST` ) KEY_BLOCK_SIZE = 17980, ORDER BY `Is_DST` ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:35','2020-05-18 08:21:35','2020-05-18 08:22:47','2020-05-18 08:21:35','2020-05-18 08:25:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','ALTER IGNORE TABLE `time_zone_transition_type` ADD INDEX IF NOT EXISTS l USING BTREE ( e, y, `Is_DST` ) KEY_BLOCK_SIZE = 17980, ORDER BY `Is_DST` ;'),('test','ev_28714_160','UPDATE IGNORE `APPLICABLE_ROLES` SET `IS_DEFAULT` = DEFAULT ORDER BY `GRANTEE` LIMIT 4','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:35','2020-05-18 08:21:35','2020-05-18 08:22:46','2020-05-18 08:21:35','2020-05-18 08:23:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `APPLICABLE_ROLES` SET `IS_DEFAULT` = DEFAULT ORDER BY `GRANTEE` LIMIT 4'),('test','ev_28716_128','SELECT * FROM `time_zone_transition_type` ORDER BY `Is_DST` LIMIT 175 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:35','2020-05-18 08:21:35','2020-05-18 08:22:47','2020-05-18 08:21:35','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `time_zone_transition_type` ORDER BY `Is_DST` LIMIT 175 ;'),('test','ev_28718_121','UPDATE IGNORE `db` SET `References_priv` = DEFAULT ORDER BY `Host` LIMIT 3 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:36','2020-05-18 08:21:36','2020-05-18 08:22:57','2020-05-18 08:21:36','2020-05-18 08:25:22','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `db` SET `References_priv` = DEFAULT ORDER BY `Host` LIMIT 3 ;'),('test','ev_28716_129','REPLACE INTO `event` ( `body_utf8`, _next_field ) VALUES ( DEFAULT, DEFAULT )','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:36','2020-05-18 08:21:36','2020-05-18 08:22:50','2020-05-18 08:21:36','2020-05-18 08:25:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `event` ( `body_utf8`, ) VALUES ( DEFAULT, DEFAULT )'),('test','ev_28718_175','INSERT IGNORE INTO `oltp77` ( `k`, _next_field ) VALUES ( \'o\', NULL )','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:12','2020-05-18 08:22:12','2020-05-18 08:22:49','2020-05-18 08:22:12','2020-05-18 08:23:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp77` ( `k`, ) VALUES ( \'o\', NULL )'),('test','ev_28716_242','UPDATE IGNORE `oltp104` SET `id` = 16 ORDER BY `k` LIMIT 5 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:52','2020-05-18 08:22:52',NULL,'2020-05-18 08:22:52','2020-05-18 08:26:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp104` SET `id` = 16 ORDER BY `k` LIMIT 5 ;'),('test','ev_28718_122','COMMIT','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:37','2020-05-18 08:21:37','2020-05-18 08:22:50','2020-05-18 08:21:37','2020-05-18 08:23:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28716_167','UPDATE IGNORE `time_zone` SET `Time_zone_id` = 194 ORDER BY `Use_leap_seconds` LIMIT 1','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:13','2020-05-18 08:22:13','2020-05-18 08:22:52','2020-05-18 08:22:13','2020-05-18 08:26:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `time_zone` SET `Time_zone_id` = 194 ORDER BY `Use_leap_seconds` LIMIT 1'),('test','ev_28714_164','DELETE FROM `INNODB_CMP` ORDER BY `compress_time` LIMIT 0 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:38','2020-05-18 08:21:38','2020-05-18 08:22:55','2020-05-18 08:21:38','2020-05-18 08:23:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `INNODB_CMP` ORDER BY `compress_time` LIMIT 0 ;'),('test','ev_28718_124','SELECT * FROM (INFORMATION_SCHEMA.`SYSTEM_VARIABLES` AS table1 RIGHT OUTER JOIN mysql.`servers` AS table2 ON ( table2.`Owner` = table1.`VARIABLE_NAME` ) ) WHERE table2.`Host` < table2.`Wrapper` LIMIT 8','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:38','2020-05-18 08:21:38','2020-05-18 08:22:55','2020-05-18 08:21:38','2020-05-18 08:23:17','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`SYSTEM_VARIABLES` AS table1 RIGHT OUTER JOIN mysql.`servers` AS table2 ON ( table2.`Owner` = table1.`VARIABLE_NAME` ) ) WHERE table2.`Host` < table2.`Wrapper` LIMIT 8'),('test','ev_28714_165','REPLACE INTO `PLUGINS` ( `PLUGIN_TYPE`, _next_field ) VALUES ( DEFAULT, \'revelation\' )','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:38','2020-05-18 08:21:38','2020-05-18 08:23:03','2020-05-18 08:21:38','2020-05-18 08:23:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `PLUGINS` ( `PLUGIN_TYPE`, ) VALUES ( DEFAULT, \'revelation\' )'),('test','ev_28714_166','SELECT `Time_zone_id` FROM `procs_priv` ORDER BY `Host` LIMIT 205 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:38','2020-05-18 08:21:38','2020-05-18 08:23:03','2020-05-18 08:21:38','2020-05-18 08:23:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Time_zone_id` FROM `procs_priv` ORDER BY `Host` LIMIT 205 ;'),('test','ev_28714_169','SELECT * FROM (test.`oltp121` AS table1 STRAIGHT_JOIN test.`oltp82` AS table2 ON ( table2.`pad` = table1.`c` ) ) WHERE ( table2.`pad` <> 5 AND table2.`k` <> \'1924-04-05 09:22:15.045927\') LIMIT 2','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:39','2020-05-18 08:21:39','2020-05-18 08:23:01','2020-05-18 08:21:39','2020-05-18 08:25:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp121` AS table1 STRAIGHT_JOIN test.`oltp82` AS table2 ON ( table2.`pad` = table1.`c` ) ) WHERE ( table2.`pad` <> 5 AND table2.`k` <> \'1924-04-05 09:22:15.045927\') LIMIT 2'),('test','ev_28718_127','REPLACE INTO `ROUTINES` ( `PARAMETER_STYLE` ) VALUES ( DEFAULT )','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:41','2020-05-18 08:21:41','2020-05-18 08:22:59','2020-05-18 08:21:41','2020-05-18 08:24:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `ROUTINES` ( `PARAMETER_STYLE` ) VALUES ( DEFAULT )'),('test','ev_28714_277','CREATE OR REPLACE UNIQUE INDEX q ON `time_zone_transition_type` ( `Is_DST` ) ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:50','2020-05-18 08:22:50',NULL,'2020-05-18 08:22:50','2020-05-18 08:26:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','CREATE OR REPLACE UNIQUE INDEX q ON `time_zone_transition_type` ( `Is_DST` ) ;'),('test','ev_28714_220','SELECT * FROM test.`oltp77` AS table1 WHERE table1.`k` <= \'1988-09-14 14:55:53.056462\' LIMIT 8 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:13','2020-05-18 08:22:13','2020-05-18 08:22:52','2020-05-18 08:22:13','2020-05-18 08:25:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp77` AS table1 WHERE table1.`k` <= \'1988-09-14 14:55:53.056462\' LIMIT 8 ;'),('test','ev_28718_128','SELECT * FROM `t2_Aria` ORDER BY `col_int` LIMIT 223 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:42','2020-05-18 08:21:42','2020-05-18 08:23:01','2020-05-18 08:21:42','2020-05-18 08:24:44','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `t2_Aria` ORDER BY `col_int` LIMIT 223 ;'),('test','ev_28718_130','INSERT INTO `proc` ( `security_type` ) VALUES ( \'\' ) ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:42','2020-05-18 08:21:42','2020-05-18 08:23:03','2020-05-18 08:21:42','2020-05-18 08:24:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `proc` ( `security_type` ) VALUES ( \'\' ) ;'),('test','ev_28714_173','REPLACE INTO `THREAD_POOL_GROUPS` ( `IS_STALLED`, _next_field ) VALUES ( \'champion\', NULL ) ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:43','2020-05-18 08:21:43','2020-05-18 08:23:02','2020-05-18 08:21:43','2020-05-18 08:24:45','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `THREAD_POOL_GROUPS` ( `IS_STALLED`, ) VALUES ( \'champion\', NULL ) ;'),('test','ev_28716_130','DROP INDEX IF EXISTS ind3 ON `COLUMN_PRIVILEGES`','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:43','2020-05-18 08:21:43','2020-05-18 08:23:03','2020-05-18 08:21:43','2020-05-18 08:24:26','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DROP INDEX IF EXISTS ind3 ON `COLUMN_PRIVILEGES`'),('test','ev_28714_174','DELETE FROM `PROFILING` ORDER BY `CONTEXT_VOLUNTARY` LIMIT 5 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:43','2020-05-18 08:21:43','2020-05-18 08:23:04','2020-05-18 08:21:43','2020-05-18 08:24:04','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `PROFILING` ORDER BY `CONTEXT_VOLUNTARY` LIMIT 5 ;'),('test','ev_28714_234','SELECT `k` FROM `oltp44` ORDER BY `k` LIMIT 83','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:58','2020-05-18 08:22:19','2020-05-18 08:23:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `k` FROM `oltp44` ORDER BY `k` LIMIT 83'),('test','ev_28718_131','UPDATE IGNORE `servers` SET `Owner` = NULL ORDER BY `Socket` LIMIT 1','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:43','2020-05-18 08:21:43','2020-05-18 08:23:06','2020-05-18 08:21:43','2020-05-18 08:23:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `servers` SET `Owner` = NULL ORDER BY `Socket` LIMIT 1'),('test','ev_28716_198','REPLACE INTO `VIEWS` ( `IS_UPDATABLE` ) VALUES ( NULL )','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:03','2020-05-18 08:22:22','2020-05-18 08:23:26','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `VIEWS` ( `IS_UPDATABLE` ) VALUES ( NULL )'),('test','ev_28718_133','INSERT IGNORE INTO `oltp19` () VALUES (),(),(),(),() ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:44','2020-05-18 08:21:44','2020-05-18 08:23:03','2020-05-18 08:21:44','2020-05-18 08:23:34','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `oltp19` () VALUES (),(),(),(),() ;'),('test','ev_28718_230','REPLACE INTO `time_zone_leap_second` () VALUES () ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:23:10','2020-05-18 08:23:10',NULL,'2020-05-18 08:23:10','2020-05-18 08:24:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `time_zone_leap_second` () VALUES () ;'),('test','ev_28716_255','SELECT `Transition_type_id` FROM `time_zone` ORDER BY `Time_zone_id` LIMIT 33 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:23:10','2020-05-18 08:23:10',NULL,'2020-05-18 08:23:10','2020-05-18 08:26:42','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Transition_type_id` FROM `time_zone` ORDER BY `Time_zone_id` LIMIT 33 ;'),('test','ev_28714_179','SELECT * FROM INFORMATION_SCHEMA.`INNODB_BUFFER_POOL_STATS` AS table1 WHERE NOT ( ( table1.`PAGES_MADE_NOT_YOUNG_RATE` != table1.`PAGES_WRITTEN_RATE` AND table1.`PENDING_FLUSH_LIST` <> \'y\') OR table1.`POOL_ID` < table1.`PENDING_DECOMPRESS`) HAVING NOT ( (table1.`PAGES_WRITTEN_RATE` < \'1925-08-04 22:30:53.036416\' IS NULL OR table1.`PAGES_READ_RATE` >= \'1997-01-10 12:21:02.002847\') AND table1.`PAGES_MADE_NOT_YOUNG_RATE` >= 2) LIMIT 8','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:45','2020-05-18 08:21:45','2020-05-18 08:23:06','2020-05-18 08:21:45','2020-05-18 08:23:19','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`INNODB_BUFFER_POOL_STATS` AS table1 WHERE NOT ( ( table1.`PAGES_MADE_NOT_YOUNG_RATE` != table1.`PAGES_WRITTEN_RATE` AND table1.`PENDING_FLUSH_LIST` <> \'y\') OR table1.`POOL_ID` < table1.`PENDING_DECOMPRESS`) HAVING NOT ( (table1.`PAGES_WRITTEN_RATE` < \'1925-08-04 22:30:53.036416\' IS NULL OR table1.`PAGES_READ_RATE` >= \'1997-01-10 12:21:02.002847\') AND table1.`PAGES_MADE_NOT_YOUNG_RATE` >= 2) LIMIT 8'),('test','ev_28718_136','REPLACE INTO `oltp141` () VALUES (),(),(),(),()','root@localhost',NULL,1,'SECOND','2020-05-18 08:21:46','2020-05-18 08:21:46','2020-05-18 08:23:04','2020-05-18 08:21:46','2020-05-18 08:23:22','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp141` () VALUES (),(),(),(),()'),('test','ev_28716_200','SHOW EXPLAIN FOR 202','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:22','2020-05-18 08:22:22','2020-05-18 08:23:02','2020-05-18 08:22:22','2020-05-18 08:25:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW EXPLAIN FOR 202'),('test','ev_28716_137','INSERT INTO `INNODB_SYS_FOREIGN_COLS` SELECT * FROM `SPATIAL_REF_SYS` ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:46','2020-05-18 08:21:46','2020-05-18 08:22:22','2020-05-18 08:21:46','2020-05-18 08:24:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `INNODB_SYS_FOREIGN_COLS` SELECT * FROM `SPATIAL_REF_SYS` ;'),('test','ev_28718_137','UPDATE IGNORE `oltp70` SET `id` = \'\' ORDER BY `k` LIMIT 9','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:46','2020-05-18 08:21:46','2020-05-18 08:23:10','2020-05-18 08:21:46','2020-05-18 08:24:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp70` SET `id` = \'\' ORDER BY `k` LIMIT 9'),('test','ev_28714_180','DELETE FROM `PARAMETERS` ORDER BY `SPECIFIC_SCHEMA` LIMIT 7 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:46','2020-05-18 08:21:46','2020-05-18 08:22:22','2020-05-18 08:21:46','2020-05-18 08:22:52','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `PARAMETERS` ORDER BY `SPECIFIC_SCHEMA` LIMIT 7 ;'),('test','ev_28714_292','SELECT * FROM (INFORMATION_SCHEMA.`TABLE_CONSTRAINTS` AS table1 STRAIGHT_JOIN test.`oltp52` AS table2 ON ( table2.`c` = table1.`TABLE_NAME` ) ) WHERE ( ( (NOT ( ( ( ( ( ( (NOT ( (NOT ( ( table2.`c` < table1.`TABLE_NAME` AND table1.`CONSTRAINT_TYPE` >= \'lv\') AND table2.`k` > 8) AND table1.`CONSTRAINT_SCHEMA` = table1.`CONSTRAINT_NAME`) AND table2.`c` < \'v\') OR table1.`CONSTRAINT_CATALOG` >= \'jh\') AND table1.`CONSTRAINT_SCHEMA` != table2.`k`) AND table2.`c` <= \'h\') OR table1.`CONSTRAINT_TYPE` >= \'2022-07-19 11:11:43.033203\') OR table2.`k` >= \'rp\') AND table1.`CONSTRAINT_SCHEMA` >= table2.`id`) AND table2.`c` < \'1931-03-20 21:53:59.016968\') OR table2.`pad` < \'p\') OR table1.`TABLE_NAME` != table1.`CONSTRAINT_TYPE`) AND table2.`id` != 4) LIMIT 0 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:23:07','2020-05-18 08:23:07',NULL,'2020-05-18 08:23:07','2020-05-18 08:25:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`TABLE_CONSTRAINTS` AS table1 STRAIGHT_JOIN test.`oltp52` AS table2 ON ( table2.`c` = table1.`TABLE_NAME` ) ) WHERE ( ( (NOT ( ( ( ( ( ( (NOT ( (NOT ( ( table2.`c` < table1.`TABLE_NAME` AND table1.`CONSTRAINT_TYPE` >= \'lv\') AND table2.`k` > 8) AND table1.`CONSTRAINT_SCHEMA` = table1.`CONSTRAINT_NAME`) AND table2.`c` < \'v\') OR table1.`CONSTRAINT_CATALOG` >= \'jh\') AND table1.`CONSTRAINT_SCHEMA` != table2.`k`) AND table2.`c` <= \'h\') OR table1.`CONSTRAINT_TYPE` >= \'2022-07-19 11:11:43.033203\') OR table2.`k` >= \'rp\') AND table1.`CONSTRAINT_SCHEMA` >= table2.`id`) AND table2.`c` < \'1931-03-20 21:53:59.016968\') OR table2.`pad` < \'p\') OR table1.`TABLE_NAME` != table1.`CONSTRAINT_TYPE`) AND table2.`id` != 4) LIMIT 0 ;'),('test','ev_28716_138','RESET QUERY CACHE','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:47','2020-05-18 08:21:47','2020-05-18 08:22:23','2020-05-18 08:21:47','2020-05-18 08:23:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','RESET QUERY CACHE'),('test','ev_28718_138','SELECT * FROM `table_stats` ORDER BY `cardinality` LIMIT 0 ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:47','2020-05-18 08:21:47','2020-05-18 08:22:23','2020-05-18 08:21:47','2020-05-18 08:23:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `table_stats` ORDER BY `cardinality` LIMIT 0 ;'),('test','ev_28718_140','REPLACE INTO `oltp82` ( `k`, _next_field ) VALUES ( \'o\', \'miss\' )','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:48','2020-05-18 08:21:48','2020-05-18 08:22:23','2020-05-18 08:21:48','2020-05-18 08:23:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp82` ( `k`, ) VALUES ( \'o\', \'miss\' )'),('test','ev_28716_141','SELECT * FROM `servers` ORDER BY `Host` LIMIT 243 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:48','2020-05-18 08:21:48','2020-05-18 08:22:23','2020-05-18 08:21:48','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `servers` ORDER BY `Host` LIMIT 243 ;'),('test','ev_28716_144','SELECT * FROM (test.`oltp83` AS table1 INNER JOIN test.`oltp73` AS table2 ON ( table2.`c` = table1.`pad` ) ) WHERE ( ( ( ( table2.`k` >= table2.`id` AND table2.`pad` <> table2.`id`) AND table2.`pad` <> \'rs\') OR table1.`pad` = table2.`pad`) OR table2.`id` != 1) HAVING table2.`id` > 1 LIMIT 9','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:50','2020-05-18 08:21:50','2020-05-18 08:22:25','2020-05-18 08:21:50','2020-05-18 08:22:52','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`oltp83` AS table1 INNER JOIN test.`oltp73` AS table2 ON ( table2.`c` = table1.`pad` ) ) WHERE ( ( ( ( table2.`k` >= table2.`id` AND table2.`pad` <> table2.`id`) AND table2.`pad` <> \'rs\') OR table1.`pad` = table2.`pad`) OR table2.`id` != 1) HAVING table2.`id` > 1 LIMIT 9'),('test','ev_28714_188','SHOW GRANTS','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:50','2020-05-18 08:21:50','2020-05-18 08:23:09','2020-05-18 08:21:50','2020-05-18 08:25:22','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW GRANTS'),('test','ev_28716_145','SELECT `User` FROM `time_zone_leap_second` ORDER BY `Transition_time` LIMIT 54 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:50','2020-05-18 08:21:50','2020-05-18 08:23:10','2020-05-18 08:21:50','2020-05-18 08:25:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `User` FROM `time_zone_leap_second` ORDER BY `Transition_time` LIMIT 54 ;'),('test','ev_28716_204','DELETE FROM `THREAD_POOL_STATS` ORDER BY `THREAD_CREATIONS_DUE_TO_STALL` LIMIT 5','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:26','2020-05-18 08:22:26','2020-05-18 08:23:09','2020-05-18 08:22:26','2020-05-18 08:26:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `THREAD_POOL_STATS` ORDER BY `THREAD_CREATIONS_DUE_TO_STALL` LIMIT 5'),('test','ev_28718_190','SELECT * FROM `THREAD_POOL_QUEUES` ORDER BY `PRIORITY` LIMIT 0 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:25','2020-05-18 08:22:25','2020-05-18 08:23:08','2020-05-18 08:22:25','2020-05-18 08:23:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `THREAD_POOL_QUEUES` ORDER BY `PRIORITY` LIMIT 0 ;'),('test','ev_28718_142','SELECT * FROM `oltp89` ORDER BY `id` LIMIT 73 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:51','2020-05-18 08:21:51','2020-05-18 08:22:25','2020-05-18 08:21:51','2020-05-18 08:25:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `oltp89` ORDER BY `id` LIMIT 73 ;'),('test','ev_28714_189','SELECT `pad` FROM `oltp60` ORDER BY `id` LIMIT 8','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:51','2020-05-18 08:21:51','2020-05-18 08:23:09','2020-05-18 08:21:51','2020-05-18 08:23:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `pad` FROM `oltp60` ORDER BY `id` LIMIT 8'),('test','ev_28714_190','REPLACE INTO `oltp34` () VALUES ()','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:51','2020-05-18 08:21:51','2020-05-18 08:22:25','2020-05-18 08:21:51','2020-05-18 08:25:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp34` () VALUES ()'),('test','ev_28716_147','UPDATE IGNORE `oltp39` SET `k` = \'horn\' ORDER BY `id` LIMIT 8 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:51','2020-05-18 08:21:51','2020-05-18 08:23:10','2020-05-18 08:21:51','2020-05-18 08:23:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp39` SET `k` = \'horn\' ORDER BY `id` LIMIT 8 ;'),('test','ev_28718_193','SHOW CREATE FUNCTION u','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:30','2020-05-18 08:22:30',NULL,'2020-05-18 08:22:30','2020-05-18 08:23:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW CREATE FUNCTION u'),('test','ev_28718_144','SELECT `TABLE_CATALOG` FROM `VIEWS` ORDER BY `COLLATION_CONNECTION` LIMIT 135 ;','root@localhost',NULL,7,'SECOND','2020-05-18 08:21:52','2020-05-18 08:21:52','2020-05-18 08:22:29','2020-05-18 08:21:52','2020-05-18 08:23:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `TABLE_CATALOG` FROM `VIEWS` ORDER BY `COLLATION_CONNECTION` LIMIT 135 ;'),('test','ev_28714_191','REPLACE INTO `oltp50` () VALUES (),(),() ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:53','2020-05-18 08:21:53','2020-05-18 08:22:30','2020-05-18 08:21:53','2020-05-18 08:24:03','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp50` () VALUES (),(),() ;'),('test','ev_28716_148','SELECT `Correction` FROM `time_zone` ORDER BY `Time_zone_id` LIMIT 138 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:53','2020-05-18 08:21:53','2020-05-18 08:22:30','2020-05-18 08:21:53','2020-05-18 08:23:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Correction` FROM `time_zone` ORDER BY `Time_zone_id` LIMIT 138 ;'),('test','ev_28718_145','SHOW PROFILE ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:53','2020-05-18 08:21:53','2020-05-18 08:22:30','2020-05-18 08:21:53','2020-05-18 08:24:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW PROFILE ;'),('test','ev_28714_248','INSERT IGNORE INTO `ENABLED_ROLES` ( `ROLE_NAME` ) VALUES ( NULL )','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:31','2020-05-18 08:22:31',NULL,'2020-05-18 08:22:31','2020-05-18 08:24:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `ENABLED_ROLES` ( `ROLE_NAME` ) VALUES ( NULL )'),('test','ev_28716_149','SELECT * FROM `servers` ORDER BY `Password` LIMIT 216','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:53','2020-05-18 08:21:53','2020-05-18 08:22:30','2020-05-18 08:21:53','2020-05-18 08:22:51','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `servers` ORDER BY `Password` LIMIT 216'),('test','ev_28714_193','SELECT `id` FROM `oltp149` ORDER BY `pad` LIMIT 199 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:21:54','2020-05-18 08:21:54','2020-05-18 08:22:31','2020-05-18 08:21:54','2020-05-18 08:24:12','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp149` ORDER BY `pad` LIMIT 199 ;'),('test','ev_28716_150','SELECT * FROM `SCHEMATA` ORDER BY `SCHEMA_COMMENT` LIMIT 92','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:54','2020-05-18 08:21:54','2020-05-18 08:22:31','2020-05-18 08:21:54','2020-05-18 08:24:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `SCHEMATA` ORDER BY `SCHEMA_COMMENT` LIMIT 92'),('test','ev_28718_148','SELECT * FROM `columns_priv` INTO OUTFILE \'load_columns_priv\' ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:21:55','2020-05-18 08:21:55','2020-05-18 08:22:31','2020-05-18 08:21:55','2020-05-18 08:25:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `columns_priv` INTO OUTFILE \'load_columns_priv\' ;'),('test','ev_28716_151','DROP INDEX o ON ind_constr_t2','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:55','2020-05-18 08:21:55','2020-05-18 08:22:32','2020-05-18 08:21:55','2020-05-18 08:25:48','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DROP INDEX o ON ind_constr_t2'),('test','ev_28718_151','REPLACE INTO `roles_mapping` ( `Admin_option`, _next_field ) VALUES ( \'\', \'\' ) ;','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:57','2020-05-18 08:21:57','2020-05-18 08:22:32','2020-05-18 08:21:57','2020-05-18 08:24:02','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `roles_mapping` ( `Admin_option`, ) VALUES ( \'\', \'\' ) ;'),('test','ev_28714_194','SELECT `SOURCE_FILE` FROM `SESSION_VARIABLES` ORDER BY `VARIABLE_VALUE` LIMIT 212','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:57','2020-05-18 08:21:57','2020-05-18 08:22:32','2020-05-18 08:21:57','2020-05-18 08:24:46','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `SOURCE_FILE` FROM `SESSION_VARIABLES` ORDER BY `VARIABLE_VALUE` LIMIT 212'),('test','ev_28716_152','REPLACE INTO `oltp38` ( `c`, _next_field ) VALUES ( 117, NULL ) ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:21:57','2020-05-18 08:21:57','2020-05-18 08:22:32','2020-05-18 08:21:57','2020-05-18 08:25:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp38` ( `c`, ) VALUES ( 117, NULL ) ;'),('test','ev_28718_152','UPDATE IGNORE `oltp35` SET `k` = \'\' ORDER BY `id` LIMIT 1 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:21:57','2020-05-18 08:21:57','2020-05-18 08:22:32','2020-05-18 08:21:57','2020-05-18 08:24:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp35` SET `k` = \'\' ORDER BY `id` LIMIT 1 ;'),('test','ev_28718_147','SELECT * FROM test.`oltp26` AS table1 WHERE ( ( (NOT (NOT ( ( ( table1.`k` <> table1.`pad` AND table1.`pad` <= table1.`id`) AND table1.`k` < \'g\') AND table1.`k` <> \'r\') OR table1.`k` < \'1964-07-26 03:46:24.059922\') AND table1.`pad` >= table1.`id`) AND table1.`k` != \'1906-01-29 02:15:53.017843\') OR table1.`k` > \'2035-03-05 08:38:25.012034\') LIMIT 4 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:54','2020-05-18 08:21:54','2020-05-18 08:22:31','2020-05-18 08:21:54','2020-05-18 08:25:18','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM test.`oltp26` AS table1 WHERE ( ( (NOT (NOT ( ( ( table1.`k` <> table1.`pad` AND table1.`pad` <= table1.`id`) AND table1.`k` < \'g\') AND table1.`k` <> \'r\') OR table1.`k` < \'1964-07-26 03:46:24.059922\') AND table1.`pad` >= table1.`id`) AND table1.`k` != \'1906-01-29 02:15:53.017843\') OR table1.`k` > \'2035-03-05 08:38:25.012034\') LIMIT 4 ;'),('test','ev_28714_197','REPLACE INTO `help_topic` ( `description`, _next_field ) VALUES ( 113, \'\' )','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:58','2020-05-18 08:21:58','2020-05-18 08:22:32','2020-05-18 08:21:58','2020-05-18 08:24:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `help_topic` ( `description`, ) VALUES ( 113, \'\' )'),('test','ev_28716_153','SELECT * FROM `roles_mapping` ORDER BY `Role` LIMIT 53','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:58','2020-05-18 08:21:58','2020-05-18 08:22:32','2020-05-18 08:21:58','2020-05-18 08:24:20','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `roles_mapping` ORDER BY `Role` LIMIT 53'),('test','ev_28714_198','SELECT `Grantor` FROM `plugin` ORDER BY `name` LIMIT 85','root@localhost',NULL,5,'SECOND','2020-05-18 08:21:58','2020-05-18 08:21:58','2020-05-18 08:22:32','2020-05-18 08:21:58','2020-05-18 08:25:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `Grantor` FROM `plugin` ORDER BY `name` LIMIT 85'),('test','ev_28714_199','REPLACE INTO `oltp138` () VALUES (),()','root@localhost',NULL,2,'SECOND','2020-05-18 08:21:58','2020-05-18 08:21:58','2020-05-18 08:22:33','2020-05-18 08:21:58','2020-05-18 08:24:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','REPLACE INTO `oltp138` () VALUES (),()'),('test','ev_28714_200','UPDATE IGNORE `oltp124` SET `id` = \'b\' ORDER BY `k` LIMIT 0','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:59','2020-05-18 08:21:59','2020-05-18 08:22:33','2020-05-18 08:21:59','2020-05-18 08:24:52','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp124` SET `id` = \'b\' ORDER BY `k` LIMIT 0'),('test','ev_28714_201','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_SYS_VIRTUAL` AS table1 INNER JOIN test.`t2_MyISAM` AS table2 ON ( table2.`col_varchar` = table1.`TABLE_ID` ) ) WHERE NOT ( (NOT (NOT ( (NOT ( (NOT (NOT ( ( ( ( ( ( table2.`id` < table1.`BASE_POS` OR table1.`POS` != 8) AND table2.`col_int` <> table2.`col_datetime`) OR table2.`col_varchar` > \'f\') AND table2.`id` >= \'1941-06-08 00:24:32.050817\') OR table2.`col_varchar` != table1.`BASE_POS`) AND table2.`col_int` != table2.`col_varchar`) OR table2.`col_varchar` < \'sz\') OR table1.`TABLE_ID` < table2.`id`) OR table1.`TABLE_ID` != \'2034-08-06 20:33:09.065403\') AND table2.`col_int` >= \'z\') OR table2.`col_datetime` <= 8) AND table2.`id` > 1) AND table2.`id` > table1.`TABLE_ID`) AND table1.`BASE_POS` < table2.`id`) HAVING table2.`col_datetime` < \'1974-01-20 11:30:56.045603\' LIMIT 4 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:21:59','2020-05-18 08:21:59','2020-05-18 08:22:33','2020-05-18 08:21:59','2020-05-18 08:24:01','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_SYS_VIRTUAL` AS table1 INNER JOIN test.`t2_MyISAM` AS table2 ON ( table2.`col_varchar` = table1.`TABLE_ID` ) ) WHERE NOT ( (NOT (NOT ( (NOT ( (NOT (NOT ( ( ( ( ( ( table2.`id` < table1.`BASE_POS` OR table1.`POS` != 8) AND table2.`col_int` <> table2.`col_datetime`) OR table2.`col_varchar` > \'f\') AND table2.`id` >= \'1941-06-08 00:24:32.050817\') OR table2.`col_varchar` != table1.`BASE_POS`) AND table2.`col_int` != table2.`col_varchar`) OR table2.`col_varchar` < \'sz\') OR table1.`TABLE_ID` < table2.`id`) OR table1.`TABLE_ID` != \'2034-08-06 20:33:09.065403\') AND table2.`col_int` >= \'z\') OR table2.`col_datetime` <= 8) AND table2.`id` > 1) AND table2.`id` > table1.`TABLE_ID`) AND table1.`BASE_POS` < table2.`id`) HAVING table2.`col_datetime` < \'1974-01-20 11:30:56.045603\' LIMIT 4 ;'),('test','ev_28714_204','SHOW SLAVE HOSTS','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:23:54','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW SLAVE HOSTS'),('test','ev_28718_156','UPDATE IGNORE `oltp81` SET `pad` = \'c\' ORDER BY `pad` LIMIT 0','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:24:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp81` SET `pad` = \'c\' ORDER BY `pad` LIMIT 0'),('test','ev_28718_159','UPDATE IGNORE `db` SET `Event_priv` = \'\' ORDER BY `Insert_priv` LIMIT 3 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:25:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `db` SET `Event_priv` = \'\' ORDER BY `Insert_priv` LIMIT 3 ;'),('test','ev_28718_160','INSERT IGNORE INTO `global_priv` ( `Priv` ) VALUES ( \'\' )','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:25:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `global_priv` ( `Priv` ) VALUES ( \'\' )'),('test','ev_28714_205','UPDATE IGNORE `EVENTS` SET `EXECUTE_AT` = \'g\' ORDER BY `CHARACTER_SET_CLIENT` LIMIT 9','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:26:11','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `EVENTS` SET `EXECUTE_AT` = \'g\' ORDER BY `CHARACTER_SET_CLIENT` LIMIT 9'),('test','ev_28716_158','UPDATE IGNORE `oltp84` SET `id` = 92 ORDER BY `id` LIMIT 4 ;','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:03','2020-05-18 08:22:03','2020-05-18 08:22:35','2020-05-18 08:22:03','2020-05-18 08:22:43','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp84` SET `id` = 92 ORDER BY `id` LIMIT 4 ;'),('test','ev_28714_206','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_SYS_TABLESTATS` AS table1 RIGHT OUTER JOIN test.`oltp49` AS table2 ON ( table2.`id` = table1.`REF_COUNT` ) ) WHERE table1.`NUM_ROWS` = \'1912-04-26 14:32:34.022333\' LIMIT 6','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:36','2020-05-18 08:22:04','2020-05-18 08:23:58','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`INNODB_SYS_TABLESTATS` AS table1 RIGHT OUTER JOIN test.`oltp49` AS table2 ON ( table2.`id` = table1.`REF_COUNT` ) ) WHERE table1.`NUM_ROWS` = \'1912-04-26 14:32:34.022333\' LIMIT 6'),('test','ev_28716_159','SHOW TABLE STATUS','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:36','2020-05-18 08:22:04','2020-05-18 08:25:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW TABLE STATUS'),('test','ev_28718_163','UPDATE IGNORE `oltp22` SET `pad` = \'pot\' ORDER BY `k` LIMIT 7','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:36','2020-05-18 08:22:04','2020-05-18 08:25:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `oltp22` SET `pad` = \'pot\' ORDER BY `k` LIMIT 7'),('test','ev_28714_207','INSERT IGNORE INTO `INNODB_BUFFER_POOL_STATS` ( `NOT_YOUNG_MAKE_PER_THOUSAND_GETS` ) VALUES ( \'r\' ) ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:36','2020-05-18 08:22:04','2020-05-18 08:24:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `INNODB_BUFFER_POOL_STATS` ( `NOT_YOUNG_MAKE_PER_THOUSAND_GETS` ) VALUES ( \'r\' ) ;'),('test','ev_28716_160','UPDATE IGNORE `VIEWS` SET `DEFINER` = \'y\' ORDER BY `IS_UPDATABLE` LIMIT 4 ;','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:36','2020-05-18 08:22:04','2020-05-18 08:23:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `VIEWS` SET `DEFINER` = \'y\' ORDER BY `IS_UPDATABLE` LIMIT 4 ;'),('test','ev_28718_164','UPDATE IGNORE `ROUTINES` SET `ROUTINE_TYPE` = \'\' ORDER BY `DATA_TYPE` LIMIT 9 ;','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:04','2020-05-18 08:22:04','2020-05-18 08:22:37','2020-05-18 08:22:04','2020-05-18 08:23:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `ROUTINES` SET `ROUTINE_TYPE` = \'\' ORDER BY `DATA_TYPE` LIMIT 9 ;'),('test','ev_28714_208','FLUSH DES_KEY_FILE','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:05','2020-05-18 08:22:05','2020-05-18 08:22:38','2020-05-18 08:22:05','2020-05-18 08:25:33','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','FLUSH DES_KEY_FILE'),('test','ev_28718_165','SELECT `id` FROM `oltp122` ORDER BY `pad` LIMIT 190 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:05','2020-05-18 08:22:05','2020-05-18 08:22:38','2020-05-18 08:22:05','2020-05-18 08:24:16','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp122` ORDER BY `pad` LIMIT 190 ;'),('test','ev_28716_161','DELETE FROM `index_stats` ORDER BY `index_name` LIMIT 6','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:05','2020-05-18 08:22:05','2020-05-18 08:22:38','2020-05-18 08:22:05','2020-05-18 08:24:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `index_stats` ORDER BY `index_name` LIMIT 6'),('test','ev_28718_170','COMMIT','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:10','2020-05-18 08:22:10','2020-05-18 08:22:44','2020-05-18 08:22:10','2020-05-18 08:26:24','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28716_165','INSERT INTO `t2_MyISAM` SELECT * FROM `oltp81`','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:10','2020-05-18 08:22:10','2020-05-18 08:22:45','2020-05-18 08:22:10','2020-05-18 08:25:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `t2_MyISAM` SELECT * FROM `oltp81`'),('test','ev_28714_216','INSERT IGNORE INTO `time_zone_leap_second` () VALUES ()','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:10','2020-05-18 08:22:10','2020-05-18 08:22:44','2020-05-18 08:22:10','2020-05-18 08:26:05','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `time_zone_leap_second` () VALUES ()'),('test','ev_28714_217','INSERT IGNORE INTO `columns_priv` ( `Timestamp` ) VALUES ( NULL )','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:11','2020-05-18 08:22:11','2020-05-18 08:22:47','2020-05-18 08:22:11','2020-05-18 08:24:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `columns_priv` ( `Timestamp` ) VALUES ( NULL )'),('test','ev_28718_173','UPDATE IGNORE `help_topic` SET `name` = \'g\' ORDER BY `help_category_id` LIMIT 3','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:11','2020-05-18 08:22:11','2020-05-18 08:22:47','2020-05-18 08:22:11','2020-05-18 08:24:10','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_topic` SET `name` = \'g\' ORDER BY `help_category_id` LIMIT 3'),('test','ev_28718_176','COMMIT ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:12','2020-05-18 08:22:12','2020-05-18 08:22:50','2020-05-18 08:22:12','2020-05-18 08:26:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT ;'),('test','ev_28714_219','UPDATE IGNORE `time_zone_name` SET `Time_zone_id` = 160 ORDER BY `Time_zone_id` LIMIT 6','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:12','2020-05-18 08:22:12','2020-05-18 08:22:49','2020-05-18 08:22:12','2020-05-18 08:23:38','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `time_zone_name` SET `Time_zone_id` = 160 ORDER BY `Time_zone_id` LIMIT 6'),('test','ev_28716_168','INSERT INTO `general_log` SELECT * FROM `plugin`','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:13','2020-05-18 08:22:13','2020-05-18 08:22:52','2020-05-18 08:22:13','2020-05-18 08:23:25','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT INTO `general_log` SELECT * FROM `plugin`'),('test','ev_28718_177','DELETE FROM `THREAD_POOL_GROUPS` ORDER BY `QUEUE_LENGTH` LIMIT 8','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:13','2020-05-18 08:22:13','2020-05-18 08:22:52','2020-05-18 08:22:13','2020-05-18 08:25:50','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `THREAD_POOL_GROUPS` ORDER BY `QUEUE_LENGTH` LIMIT 8'),('test','ev_28714_221','SELECT `TABLESPACE_NAME` FROM `GLOBAL_STATUS` ORDER BY `VARIABLE_NAME` LIMIT 68','root@localhost',NULL,7,'SECOND','2020-05-18 08:22:13','2020-05-18 08:22:13','2020-05-18 08:22:52','2020-05-18 08:22:13','2020-05-18 08:24:15','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `TABLESPACE_NAME` FROM `GLOBAL_STATUS` ORDER BY `VARIABLE_NAME` LIMIT 68'),('test','ev_28714_222','SELECT `value` FROM `INNODB_CMP_PER_INDEX_RESET` ORDER BY `uncompress_ops` LIMIT 55','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:14','2020-05-18 08:22:14','2020-05-18 08:22:53','2020-05-18 08:22:14','2020-05-18 08:26:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `value` FROM `INNODB_CMP_PER_INDEX_RESET` ORDER BY `uncompress_ops` LIMIT 55'),('test','ev_28714_223','UPDATE IGNORE `ALL_PLUGINS` SET `PLUGIN_TYPE_VERSION` = NULL ORDER BY `PLUGIN_TYPE` LIMIT 9','root@localhost',NULL,1,'SECOND','2020-05-18 08:22:14','2020-05-18 08:22:14','2020-05-18 08:22:53','2020-05-18 08:22:14','2020-05-18 08:23:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `ALL_PLUGINS` SET `PLUGIN_TYPE_VERSION` = NULL ORDER BY `PLUGIN_TYPE` LIMIT 9'),('test','ev_28716_171','SELECT * FROM `KEY_COLUMN_USAGE` ORDER BY `TABLE_CATALOG` LIMIT 205','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:14','2020-05-18 08:22:14','2020-05-18 08:22:53','2020-05-18 08:22:14','2020-05-18 08:24:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `KEY_COLUMN_USAGE` ORDER BY `TABLE_CATALOG` LIMIT 205'),('test','ev_28718_178','UPDATE IGNORE `help_topic` SET `help_category_id` = \'\' ORDER BY `name` LIMIT 1 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:14','2020-05-18 08:22:14','2020-05-18 08:22:53','2020-05-18 08:22:14','2020-05-18 08:26:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','UPDATE IGNORE `help_topic` SET `help_category_id` = \'\' ORDER BY `name` LIMIT 1 ;'),('test','ev_28718_179','SELECT `k` FROM `oltp19` ORDER BY `c` LIMIT 152','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:15','2020-05-18 08:22:15','2020-05-18 08:22:54','2020-05-18 08:22:15','2020-05-18 08:26:00','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `k` FROM `oltp19` ORDER BY `c` LIMIT 152'),('test','ev_28716_173','INSERT IGNORE INTO `ROUTINES` () VALUES (),(),() ;','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:15','2020-05-18 08:22:15','2020-05-18 08:22:54','2020-05-18 08:22:15','2020-05-18 08:23:59','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `ROUTINES` () VALUES (),(),() ;'),('test','ev_28714_225','COMMIT','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:15','2020-05-18 08:22:15','2020-05-18 08:22:54','2020-05-18 08:22:15','2020-05-18 08:23:29','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28716_174','SELECT * FROM `INNODB_FT_INDEX_CACHE` ORDER BY `POSITION` LIMIT 248 ;','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:16','2020-05-18 08:22:16','2020-05-18 08:22:55','2020-05-18 08:22:16','2020-05-18 08:23:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `INNODB_FT_INDEX_CACHE` ORDER BY `POSITION` LIMIT 248 ;'),('test','ev_28714_226','SELECT * FROM `func` ORDER BY `type` LIMIT 48','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:16','2020-05-18 08:22:16','2020-05-18 08:22:55','2020-05-18 08:22:16','2020-05-18 08:24:57','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `func` ORDER BY `type` LIMIT 48'),('test','ev_28716_175','DELETE FROM `CHECK_CONSTRAINTS` ORDER BY `CONSTRAINT_NAME` LIMIT 7','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:16','2020-05-18 08:22:16','2020-05-18 08:22:55','2020-05-18 08:22:16','2020-05-18 08:25:32','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','DELETE FROM `CHECK_CONSTRAINTS` ORDER BY `CONSTRAINT_NAME` LIMIT 7'),('test','ev_28714_227','SELECT `id` FROM `oltp100` ORDER BY `c` LIMIT 232 ;','root@localhost',NULL,3,'SECOND','2020-05-18 08:22:16','2020-05-18 08:22:16','2020-05-18 08:22:55','2020-05-18 08:22:16','2020-05-18 08:23:08','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT `id` FROM `oltp100` ORDER BY `c` LIMIT 232 ;'),('test','ev_28714_228','SHOW TABLES','root@localhost',NULL,2,'SECOND','2020-05-18 08:22:17','2020-05-18 08:22:17','2020-05-18 08:22:56','2020-05-18 08:22:17','2020-05-18 08:23:09','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SHOW TABLES'),('test','ev_28714_229','SELECT * FROM `db` ORDER BY `Select_priv` LIMIT 87 ;','root@localhost',NULL,6,'SECOND','2020-05-18 08:22:17','2020-05-18 08:22:17','2020-05-18 08:22:56','2020-05-18 08:22:17','2020-05-18 08:23:28','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `db` ORDER BY `Select_priv` LIMIT 87 ;'),('test','ev_28716_182','COMMIT','root@localhost',NULL,5,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:58','2020-05-18 08:22:19','2020-05-18 08:24:36','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','COMMIT'),('test','ev_28714_233','INSERT IGNORE INTO `APPLICABLE_ROLES` ( `IS_GRANTABLE` ) VALUES ( \'pasta\' )','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:59','2020-05-18 08:22:19','2020-05-18 08:23:27','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','INSERT IGNORE INTO `APPLICABLE_ROLES` ( `IS_GRANTABLE` ) VALUES ( \'pasta\' )'),('test','ev_28716_185','SELECT * FROM INFORMATION_SCHEMA.`PROFILING` AS table1 WHERE (NOT ( table1.`SEQ` > \'b\' OR table1.`DURATION` = table1.`SOURCE_FUNCTION`) AND table1.`SOURCE_FILE` <> table1.`SOURCE_FUNCTION`) LIMIT 2','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:59','2020-05-18 08:22:19','2020-05-18 08:25:37','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`PROFILING` AS table1 WHERE (NOT ( table1.`SEQ` > \'b\' OR table1.`DURATION` = table1.`SOURCE_FUNCTION`) AND table1.`SOURCE_FILE` <> table1.`SOURCE_FUNCTION`) LIMIT 2'),('test','ev_28714_231','SELECT * FROM INFORMATION_SCHEMA.`PARAMETERS` AS table1 WHERE ( ( ( ( table1.`SPECIFIC_CATALOG` = table1.`PARAMETER_NAME` OR table1.`DATA_TYPE` >= table1.`NUMERIC_SCALE`) OR table1.`COLLATION_NAME` >= \'2039-09-23 05:43:03.009381\') AND table1.`SPECIFIC_CATALOG` < table1.`ORDINAL_POSITION`) AND table1.`CHARACTER_MAXIMUM_LENGTH` >= \'b\') HAVING NOT table1.`SPECIFIC_NAME` < \'hv\' LIMIT 1','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:19','2020-05-18 08:22:19','2020-05-18 08:22:58','2020-05-18 08:22:19','2020-05-18 08:25:14','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM INFORMATION_SCHEMA.`PARAMETERS` AS table1 WHERE ( ( ( ( table1.`SPECIFIC_CATALOG` = table1.`PARAMETER_NAME` OR table1.`DATA_TYPE` >= table1.`NUMERIC_SCALE`) OR table1.`COLLATION_NAME` >= \'2039-09-23 05:43:03.009381\') AND table1.`SPECIFIC_CATALOG` < table1.`ORDINAL_POSITION`) AND table1.`CHARACTER_MAXIMUM_LENGTH` >= \'b\') HAVING NOT table1.`SPECIFIC_NAME` < \'hv\' LIMIT 1'),('test','ev_28714_236','SELECT * FROM `INNODB_CMP` ORDER BY `uncompress_time` LIMIT 209','root@localhost',NULL,4,'SECOND','2020-05-18 08:22:20','2020-05-18 08:22:20','2020-05-18 08:23:00','2020-05-18 08:22:20','2020-05-18 08:25:52','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM `INNODB_CMP` ORDER BY `uncompress_time` LIMIT 209'),('test','ev_28714_238','SELECT * FROM (test.`t5_InnoDB` AS table1 STRAIGHT_JOIN test.`oltp30` AS table2 ON ( table2.`k` = table1.`col_timestamp` ) ) WHERE ( ( ( ( (NOT ( ( table1.`col_bit` <> table1.`col_blob` AND table2.`k` = table2.`pad`) OR table2.`id` > 0) AND table1.`col_timestamp` != table1.`col_bit`) AND table1.`col_char` >= table1.`col_timestamp`) OR table1.`col_char` != table1.`col_blob`) AND table2.`k` > table2.`id`) OR table1.`col_int` <> \'2019-03-13 11:33:09.052418\') LIMIT 7','root@localhost',NULL,9,'SECOND','2020-05-18 08:22:24','2020-05-18 08:22:24','2020-05-18 08:23:05','2020-05-18 08:22:24','2020-05-18 08:25:13','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (test.`t5_InnoDB` AS table1 STRAIGHT_JOIN test.`oltp30` AS table2 ON ( table2.`k` = table1.`col_timestamp` ) ) WHERE ( ( ( ( (NOT ( ( table1.`col_bit` <> table1.`col_blob` AND table2.`k` = table2.`pad`) OR table2.`id` > 0) AND table1.`col_timestamp` != table1.`col_bit`) AND table1.`col_char` >= table1.`col_timestamp`) OR table1.`col_char` != table1.`col_blob`) AND table2.`k` > table2.`id`) OR table1.`col_int` <> \'2019-03-13 11:33:09.052418\') LIMIT 7'),('test','ev_28716_205','SELECT * FROM (INFORMATION_SCHEMA.`SYSTEM_VARIABLES` AS table1 RIGHT JOIN mysql.`slow_log` AS table2 ON ( table2.`lock_time` = table1.`VARIABLE_COMMENT` ) ) WHERE NOT (NOT ( ( ( ( table1.`VARIABLE_NAME` != table2.`lock_time` AND table2.`rows_examined` <> 2) OR table1.`GLOBAL_VALUE` != \'2032-10-01 07:09:48.018373\') AND table2.`last_insert_id` < table2.`query_time`) OR table2.`query_time` = \'n\') AND table2.`sql_text` = \'1997-04-25 15:23:24.051074\') HAVING ( ( (NOT table2.`rows_sent` <> 8 AND table1.`NUMERIC_MIN_VALUE` >= \'1961-10-22 13:14:51.023261\') OR table2.`thread_id` <= \'f\') OR table2.`rows_affected` <= \'2007-12-07 08:50:48.063969\') LIMIT 2','root@localhost',NULL,8,'SECOND','2020-05-18 08:22:26','2020-05-18 08:22:26','2020-05-18 08:23:10','2020-05-18 08:22:26','2020-05-18 08:25:41','ENABLED','DROP','STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION','',1,'SYSTEM','latin1','latin1_swedish_ci','latin1_swedish_ci','SELECT * FROM (INFORMATION_SCHEMA.`SYSTEM_VARIABLES` AS table1 RIGHT JOIN mysql.`slow_log` AS table2 ON ( table2.`lock_time` = table1.`VARIABLE_COMMENT` ) ) WHERE NOT (NOT ( ( ( ( table1.`VARIABLE_NAME` != table2.`lock_time` AND table2.`rows_examined` <> 2) OR table1.`GLOBAL_VALUE` != \'2032-10-01 07:09:48.018373\') AND table2.`last_insert_id` < table2.`query_time`) OR table2.`query_time` = \'n\') AND table2.`sql_text` = \'1997-04-25 15:23:24.051074\') HAVING ( ( (NOT table2.`rows_sent` <> 8 AND table1.`NUMERIC_MIN_VALUE` >= \'1961-10-22 13:14:51.023261\') OR table2.`thread_id` <= \'f\') OR table2.`rows_affected` <= \'2007-12-07 08:50:48.063969\') LIMIT 2'); +--enable_query_log +select count(*) from mysql.event; +flush tables; +--disable_result_log +show events; +--enable_result_log +truncate table mysql.event; diff --git a/mysql-test/main/stack-crash.result b/mysql-test/main/stack-crash.result index 62870db79f3..8c0001e748a 100644 --- a/mysql-test/main/stack-crash.result +++ b/mysql-test/main/stack-crash.result @@ -1,7 +1,6 @@ drop table if exists t1,t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' CREATE TABLE t1 ( `sspo_id` int(11) NOT NULL AUTO_INCREMENT, `sspo_uid` int(11) NOT NULL DEFAULT '0', diff --git a/mysql-test/main/status_bug17954.test b/mysql-test/main/status_bug17954.test index 36430cceeff..75c9ab27dfd 100644 --- a/mysql-test/main/status_bug17954.test +++ b/mysql-test/main/status_bug17954.test @@ -4,9 +4,6 @@ # embedded server causes different stat -- source include/not_embedded.inc -# thread pool causes different results --- source include/not_threadpool.inc - # Save the initial number of concurrent sessions --source include/count_sessions.inc diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 82b75f5daad..51194717676 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -2535,6 +2535,69 @@ c1 1 drop table t1; # +# MDEV-22498: SIGSEGV in Bitmap<64u>::merge on SELECT +# +set @save_sql_select_limit= @@sql_select_limit; +SET sql_select_limit=0; +CREATE TABLE t1(b INT, c INT); +CREATE TABLE t2(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +EXPLAIN EXTENDED SELECT sum(a), t2.a, t2.b FROM t2 HAVING t2.a IN (SELECT t2.b FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Zero limit +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1276 Field or reference 'test.t2.b' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t2.b' of SELECT #2 was resolved in SELECT #1 +Note 1003 /* select#1 */ select sum(`test`.`t2`.`a`) AS `sum(a)`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` having (`test`.`t2`.`a`,(/* select#2 */ select `test`.`t2`.`b` from `test`.`t1` where (`test`.`t2`.`a`) = `test`.`t2`.`b`)) +SELECT sum(a), t2.a, t2.b FROM t2 HAVING t2.a IN (SELECT t2.b FROM t1); +sum(a) a b +SET @@sql_select_limit= @save_sql_select_limit; +EXPLAIN EXTENDED SELECT sum(a), t2.a, t2.b FROM t2 HAVING t2.a IN (SELECT t2.b FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1276 Field or reference 'test.t2.b' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t2.b' of SELECT #2 was resolved in SELECT #1 +Note 1003 /* select#1 */ select sum(`test`.`t2`.`a`) AS `sum(a)`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` having <`test`.`t2`.`a`,`test`.`t2`.`b`>((`test`.`t2`.`a`,(/* select#2 */ select `test`.`t2`.`b` from `test`.`t1` where (`test`.`t2`.`a`) = `test`.`t2`.`b`))) +SELECT sum(a), t2.a, t2.b FROM t2 HAVING t2.a IN (SELECT t2.b FROM t1); +sum(a) a b +6 1 1 +DROP TABLE t1,t2; +# +# MDEV-17606: Query returns wrong results (while using CHARACTER SET utf8) +# +CREATE TABLE t1(l1 varchar(10), i2 int); +INSERT INTO t1 VALUES ('e',2),('o',6),('x',4); +CREATE TABLE t2 (v1 varchar(10) CHARACTER SET utf8, KEY v1 (v1(3))); +INSERT INTO t2 VALUES ('k'),('rid'),('f'),('x'); +EXPLAIN EXTENDED SELECT * FROM t1 where ( t1.l1 < ANY (SELECT MAX(t2.v1) FROM t2)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`l1` AS `l1`,`test`.`t1`.`i2` AS `i2` from `test`.`t1` where ((`test`.`t1`.`l1`,(/* select#2 */ select max(`test`.`t2`.`v1`) from `test`.`t2`) > convert((`test`.`t1`.`l1`) using utf8))) +SELECT * FROM t1 where ( t1.l1 < ANY (SELECT MAX(t2.v1) FROM t2)); +l1 i2 +e 2 +o 6 +DROP TABLE t1, t2; +# +# MDEV-22852: SIGSEGV in sortlength (optimized builds) +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='subquery_cache=off'; +CREATE TABLE t1 (a INT,b INT); +INSERT INTO t1 VALUES (0,0),(0,0); +SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) FROM t1 AS t1o; +(SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) +0 +SET @@optimizer_switch= @save_optimizer_switch; +DROP TABLE t1; +# End of 10.2 tests +# # MDEV-19134: EXISTS() slower if ORDER BY is defined # create table t0 (a int); @@ -2582,3 +2645,4 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100 drop table t0, t1, t2; +# End of 10.4 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index bc8db41c505..36490c340e1 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2078,6 +2078,57 @@ select (select c1 from t1 group by c1,c2 order by c1 limit 1) as x; (select c1 from t1 group by c1,c2 order by c1 limit 1); drop table t1; +--echo # +--echo # MDEV-22498: SIGSEGV in Bitmap<64u>::merge on SELECT +--echo # + +set @save_sql_select_limit= @@sql_select_limit; +SET sql_select_limit=0; + +CREATE TABLE t1(b INT, c INT); +CREATE TABLE t2(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); + +let $query= +SELECT sum(a), t2.a, t2.b FROM t2 HAVING t2.a IN (SELECT t2.b FROM t1); + +eval EXPLAIN EXTENDED $query; +eval $query; + +SET @@sql_select_limit= @save_sql_select_limit; + +eval EXPLAIN EXTENDED $query; +eval $query; +DROP TABLE t1,t2; + +--echo # +--echo # MDEV-17606: Query returns wrong results (while using CHARACTER SET utf8) +--echo # + +CREATE TABLE t1(l1 varchar(10), i2 int); +INSERT INTO t1 VALUES ('e',2),('o',6),('x',4); +CREATE TABLE t2 (v1 varchar(10) CHARACTER SET utf8, KEY v1 (v1(3))); +INSERT INTO t2 VALUES ('k'),('rid'),('f'),('x'); + +EXPLAIN EXTENDED SELECT * FROM t1 where ( t1.l1 < ANY (SELECT MAX(t2.v1) FROM t2)); +SELECT * FROM t1 where ( t1.l1 < ANY (SELECT MAX(t2.v1) FROM t2)); +DROP TABLE t1, t2; + +--echo # +--echo # MDEV-22852: SIGSEGV in sortlength (optimized builds) +--echo # + +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='subquery_cache=off'; +CREATE TABLE t1 (a INT,b INT); +INSERT INTO t1 VALUES (0,0),(0,0); +SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) FROM t1 AS t1o; +SET @@optimizer_switch= @save_optimizer_switch; +DROP TABLE t1; + +--echo # End of 10.2 tests + --echo # --echo # MDEV-19134: EXISTS() slower if ORDER BY is defined --echo # @@ -2118,3 +2169,4 @@ select * from t1 where t1.a in (select t2.a from t2 order by t2.b); drop table t0, t1, t2; +--echo # End of 10.4 tests diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result index 4cf28638484..4d3d958c8c5 100644 --- a/mysql-test/main/subselect_innodb.result +++ b/mysql-test/main/subselect_innodb.result @@ -435,8 +435,7 @@ drop table t1; # drop table if exists `t1`,`t2`; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' create table `t1`(`a` char(1) character set utf8)engine=innodb; create table `t2`(`b` char(1) character set utf8)engine=memory; select distinct (select 1 from `t2` where `a`) `d2` from `t1`; diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 689363c6d22..86c89f9bd5f 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -1616,7 +1616,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index @@ -1628,13 +1628,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; create table t2 (a int, b int not null); create table t3 (a int); @@ -1889,7 +1889,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where 2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !(`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and (`test`.`t1`.`id`) = `test`.`t1`.`id`))) +Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !((`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and (`test`.`t1`.`id`) = `test`.`t1`.`id`)))) explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index f6f468ba1ab..5dc8040698f 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -1619,7 +1619,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index @@ -1631,13 +1631,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index 2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` +Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; create table t2 (a int, b int not null); create table t3 (a int); @@ -1892,7 +1892,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where 2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !(`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and (`test`.`t1`.`id`) = `test`.`t1`.`id`))) +Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !((`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and (`test`.`t1`.`id`) = `test`.`t1`.`id`)))) explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where diff --git a/mysql-test/main/subselect_partial_match.result b/mysql-test/main/subselect_partial_match.result index 5f444457794..52c30492675 100644 --- a/mysql-test/main/subselect_partial_match.result +++ b/mysql-test/main/subselect_partial_match.result @@ -775,7 +775,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using where 3 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Warnings: -Note 1003 /* select#1 */ select `table1`.`a1` AS `a1`,`table1`.`a2` AS `a2` from (/* select#2 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where !(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( (/* select#3 */ select `test`.`t2`.`b2` from `test`.`t2` ), (`test`.`t1`.`a1` in on distinct_key where `test`.`t1`.`a1` = ``.`b2`)))) `table1` +Note 1003 /* select#1 */ select `table1`.`a1` AS `a1`,`table1`.`a2` AS `a2` from (/* select#2 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where !((`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( (/* select#3 */ select `test`.`t2`.`b2` from `test`.`t2` ), (`test`.`t1`.`a1` in on distinct_key where `test`.`t1`.`a1` = ``.`b2`))))) `table1` set optimizer_switch=@tmp_optimizer_switch; DROP TABLE t1, t2; # diff --git a/mysql-test/main/sum_distinct-big.test b/mysql-test/main/sum_distinct-big.test index c51d6c31249..42eeae743b1 100644 --- a/mysql-test/main/sum_distinct-big.test +++ b/mysql-test/main/sum_distinct-big.test @@ -3,6 +3,8 @@ # --source include/big_test.inc +# Test will take more than one hour with valgrind +--source include/not_valgrind.inc --source include/have_innodb.inc --source include/have_sequence.inc diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index 38e1a54082c..c5b71af43b4 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -2599,3 +2599,38 @@ a 2 1 drop view v1; +# +# MDEV-22560 Crash on a table value constructor with an SP variable +# +BEGIN NOT ATOMIC +DECLARE a INT DEFAULT 0; +VALUES (a) UNION SELECT 1; +END; +$$ +a +0 +1 +# +# MDEV-21995 Server crashes in Item_field::real_type_handler with table value constructor +# +VALUES (IGNORE); +ERROR HY000: 'ignore' is not allowed in this context +VALUES (DEFAULT); +ERROR HY000: 'default' is not allowed in this context +EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE; +ERROR HY000: 'ignore' is not allowed in this context +EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT; +ERROR HY000: 'default' is not allowed in this context +# +# MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT)) +# +VALUES (DEFAULT) UNION VALUES (DEFAULT); +ERROR HY000: 'default' is not allowed in this context +VALUES (IGNORE) UNION VALUES (IGNORE); +ERROR HY000: 'ignore' is not allowed in this context +CREATE TABLE t1 (a INT DEFAULT 10); +INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT)); +ERROR HY000: 'default' is not allowed in this context +INSERT INTO t1 (VALUES (IGNORE) UNION VALUES (IGNORE)); +ERROR HY000: 'ignore' is not allowed in this context +DROP TABLE t1; diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test index 4464eb7b77b..f40a8d44c9a 100644 --- a/mysql-test/main/table_value_constr.test +++ b/mysql-test/main/table_value_constr.test @@ -1326,3 +1326,46 @@ create view v1 as with t(a) as (values (2), (1)) select a from t; show create view v1; select * from v1; drop view v1; + + +--echo # +--echo # MDEV-22560 Crash on a table value constructor with an SP variable +--echo # + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE a INT DEFAULT 0; + VALUES (a) UNION SELECT 1; +END; +$$ +DELIMITER ;$$ + + +--echo # +--echo # MDEV-21995 Server crashes in Item_field::real_type_handler with table value constructor +--echo # + +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +VALUES (IGNORE); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +VALUES (DEFAULT); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT; + + +--echo # +--echo # MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT)) +--echo # + +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +VALUES (DEFAULT) UNION VALUES (DEFAULT); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +VALUES (IGNORE) UNION VALUES (IGNORE); +CREATE TABLE t1 (a INT DEFAULT 10); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT)); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +INSERT INTO t1 (VALUES (IGNORE) UNION VALUES (IGNORE)); +DROP TABLE t1; diff --git a/mysql-test/main/temp_table.result b/mysql-test/main/temp_table.result index 69f3b8e5155..293b6d5cd77 100644 --- a/mysql-test/main/temp_table.result +++ b/mysql-test/main/temp_table.result @@ -584,3 +584,21 @@ ALTER TABLE t1 CHANGE no_such_col1 col1 BIGINT NULL; ERROR 42S22: Unknown column 'no_such_col1' in 't1' TRUNCATE TABLE t1; DROP TEMPORARY TABLE t1; +# +# MDEV-21695 Server crashes in TABLE::evaluate_update_default_function upon UPDATE on temporary table +# +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); +CREATE TEMPORARY TABLE t1 (a DATETIME ON UPDATE CURRENT_TIMESTAMP); +ALTER TABLE t1 ADD b INT; +INSERT INTO t1 (b) VALUES (1),(2); +ALTER TABLE t1 CHANGE COLUMN x xx INT; +ERROR 42S22: Unknown column 'x' in 't1' +UPDATE t1 SET b = 3; +SELECT * FROM t1; +a b +2001-01-01 10:20:30 3 +2001-01-01 10:20:30 3 +DROP TEMPORARY TABLE t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/main/temp_table.test b/mysql-test/main/temp_table.test index bd3bba34f89..dc5fe7f3cd0 100644 --- a/mysql-test/main/temp_table.test +++ b/mysql-test/main/temp_table.test @@ -639,3 +639,22 @@ ALTER TABLE t1 CHANGE no_such_col1 col1 BIGINT NULL; # was not dropped during the first TRUNCATE due to extra table handles. TRUNCATE TABLE t1; DROP TEMPORARY TABLE t1; + +--echo # +--echo # MDEV-21695 Server crashes in TABLE::evaluate_update_default_function upon UPDATE on temporary table +--echo # + +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); +CREATE TEMPORARY TABLE t1 (a DATETIME ON UPDATE CURRENT_TIMESTAMP); +ALTER TABLE t1 ADD b INT; +INSERT INTO t1 (b) VALUES (1),(2); +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 CHANGE COLUMN x xx INT; +UPDATE t1 SET b = 3; +SELECT * FROM t1; +DROP TEMPORARY TABLE t1; + + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/main/type_date.result b/mysql-test/main/type_date.result index fbf348c1a2f..aa5d6ccadc1 100644 --- a/mysql-test/main/type_date.result +++ b/mysql-test/main/type_date.result @@ -924,6 +924,24 @@ DROP TABLE t1; # End of 10.1 tests # # +# Start of 10.2 tests +# +# +# MDEV-21619 Server crash or assertion failures in my_datetime_to_str +# +CREATE TABLE t1 (f DATE, KEY(f)); +INSERT INTO t1 VALUES ('2020-01-01'),('2020-01-02'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '2012-12-12'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range f f 4 NULL 1 100.00 Using where; Using index +Warnings: +Warning 1292 Truncated incorrect datetime value: '1995.0000000' +Note 1003 select `test`.`t1`.`f` AS `f` from `test`.`t1` where '0000-00-00' between `test`.`t1`.`f` and ('2012-12-12') +DROP TABLE t1; +# +# End of 10.2 tests +# +# # Start of 10.3 tests # # diff --git a/mysql-test/main/type_date.test b/mysql-test/main/type_date.test index bd874ec51fb..c041295f845 100644 --- a/mysql-test/main/type_date.test +++ b/mysql-test/main/type_date.test @@ -634,6 +634,24 @@ DROP TABLE t1; --echo # End of 10.1 tests --echo # +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-21619 Server crash or assertion failures in my_datetime_to_str +--echo # + +CREATE TABLE t1 (f DATE, KEY(f)); +INSERT INTO t1 VALUES ('2020-01-01'),('2020-01-02'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '2012-12-12'; +DROP TABLE t1; + + +--echo # +--echo # End of 10.2 tests +--echo # + --echo # --echo # Start of 10.3 tests --echo # diff --git a/mysql-test/main/type_datetime.result b/mysql-test/main/type_datetime.result index b23fa762c73..5b27d02d28f 100644 --- a/mysql-test/main/type_datetime.result +++ b/mysql-test/main/type_datetime.result @@ -1330,6 +1330,18 @@ a 2000-10-00 00:00:00 DROP TABLE t1; # +# MDEV-21619 Server crash or assertion failures in my_datetime_to_str +# +CREATE TABLE t1 (f DATETIME, KEY(f)); +INSERT INTO t1 VALUES ('2020-01-01 00:00:00'),('2020-01-02 00:00:00'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '2012-12-12'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range f f 6 NULL 1 100.00 Using where; Using index +Warnings: +Warning 1292 Truncated incorrect datetime value: '1995.0000000' +Note 1003 select `test`.`t1`.`f` AS `f` from `test`.`t1` where '0000-00-00 00:00:00.000000' between `test`.`t1`.`f` and ('2012-12-12') +DROP TABLE t1; +# # End of 10.2 tests # # diff --git a/mysql-test/main/type_datetime.test b/mysql-test/main/type_datetime.test index e4b18a245f0..c8ad240d817 100644 --- a/mysql-test/main/type_datetime.test +++ b/mysql-test/main/type_datetime.test @@ -837,6 +837,15 @@ ALTER TABLE t1 MODIFY a DATETIME; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-21619 Server crash or assertion failures in my_datetime_to_str +--echo # + +CREATE TABLE t1 (f DATETIME, KEY(f)); +INSERT INTO t1 VALUES ('2020-01-01 00:00:00'),('2020-01-02 00:00:00'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '2012-12-12'; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests diff --git a/mysql-test/main/type_datetime_hires.result b/mysql-test/main/type_datetime_hires.result index ebb9c6032b9..5211515ea77 100644 --- a/mysql-test/main/type_datetime_hires.result +++ b/mysql-test/main/type_datetime_hires.result @@ -889,5 +889,16 @@ Warning 1411 Incorrect date value: '0000-02-28' for function round(datetime) Warning 1411 Incorrect date value: '0000-12-31' for function round(datetime) DROP TABLE t1; # +# MDEV-20984 Possibly wrong result or Assertion `args[0]->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATETIME' failed in Item_func_round::date_op +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1979-01-03 10:33:32'),('2012-12-12 12:12:12'); +SELECT ROUND(a) AS f FROM t1 GROUP BY a WITH ROLLUP; +f +1979-01-03 10:33:32 +2012-12-12 12:12:12 +NULL +DROP TABLE t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_datetime_hires.test b/mysql-test/main/type_datetime_hires.test index ed9a85bcda3..7b3b37560a3 100644 --- a/mysql-test/main/type_datetime_hires.test +++ b/mysql-test/main/type_datetime_hires.test @@ -146,6 +146,16 @@ SELECT a, ROUND(a,-6) FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-20984 Possibly wrong result or Assertion `args[0]->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATETIME' failed in Item_func_round::date_op +--echo # + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1979-01-03 10:33:32'),('2012-12-12 12:12:12'); +SELECT ROUND(a) AS f FROM t1 GROUP BY a WITH ROLLUP; +DROP TABLE t1; + + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index 360746bb856..8ef8e981f57 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -1368,6 +1368,18 @@ CAST(f1() AS TIME) 00:00:00 DROP FUNCTION f1; # +# MDEV-21619 Server crash or assertion failures in my_datetime_to_str +# +CREATE TABLE t1 (f TIME, KEY(f)); +INSERT INTO t1 VALUES ('10:10:10'),('20:20:20'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '23:59:59'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range f f 4 NULL 1 100.00 Using where; Using index +Warnings: +Warning 1292 Truncated incorrect time value: '1995.0000000' +Note 1003 select `test`.`t1`.`f` AS `f` from `test`.`t1` where '00:00:00.000000' between `test`.`t1`.`f` and ('23:59:59') +DROP TABLE t1; +# # End of 10.2 tests # # diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index 13101f0e29d..521953a5078 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -819,6 +819,15 @@ SELECT CAST(f1() AS TIME); DROP FUNCTION f1; +--echo # +--echo # MDEV-21619 Server crash or assertion failures in my_datetime_to_str +--echo # + +CREATE TABLE t1 (f TIME, KEY(f)); +INSERT INTO t1 VALUES ('10:10:10'),('20:20:20'); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1995.0000000 BETWEEN f AND '23:59:59'; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index d8c74f15c57..e6fa9756b1d 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -884,8 +884,9 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Warning 1292 Truncated incorrect datetime value: ' garbage ' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and (octet_length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand() +Warning 1292 Incorrect datetime value: ' garbage ' +Warning 1292 Incorrect datetime value: ' garbage ' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(`test`.`t1`.`a`) = 30 + rand() and `test`.`t1`.`a` = ' garbage ' DROP TABLE t1; CREATE TABLE t1 (a TIMESTAMP);; INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'); @@ -1297,5 +1298,27 @@ SELECT (SELECT MIN(b) FROM t1) - a FROM t1; -20030101000000.0000 DROP TABLE t1; # +# MDEV-22734 Assertion `mon > 0 && mon < 13' failed in sec_since_epoch +# +SET time_zone="-02:00"; +CREATE TABLE t1(c TIMESTAMP KEY); +SELECT * FROM t1 WHERE c='2010-00-01 00:00:00'; +c +Warnings: +Warning 1292 Incorrect datetime value: '2010-00-01 00:00:00' +DROP TABLE t1; +# +# MDEV-22854 Garbage returned with SELECT CASE..DEFAULT(timestamp_field_with_now_as_default) +# +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.456789'); +CREATE TABLE t1 (a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP); +INSERT INTO t1 VALUES ('2019-02-23 11:31:04'),('2023-02-09 00:00:00'); +SELECT CASE WHEN a THEN DEFAULT(a) END FROM t1; +CASE WHEN a THEN DEFAULT(a) END +2001-01-01 10:20:30.456 +2001-01-01 10:20:30.456 +DROP TABLE t1; +SET timestamp=DEFAULT; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index 7b2311eaac3..9c5b57b8885 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -854,6 +854,26 @@ SELECT * FROM t1 WHERE (SELECT MIN(b) FROM t1) - a; SELECT (SELECT MIN(b) FROM t1) - a FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-22734 Assertion `mon > 0 && mon < 13' failed in sec_since_epoch +--echo # +SET time_zone="-02:00"; +CREATE TABLE t1(c TIMESTAMP KEY); +SELECT * FROM t1 WHERE c='2010-00-01 00:00:00'; +DROP TABLE t1; + + +--echo # +--echo # MDEV-22854 Garbage returned with SELECT CASE..DEFAULT(timestamp_field_with_now_as_default) +--echo # + +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.456789'); +CREATE TABLE t1 (a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP); +INSERT INTO t1 VALUES ('2019-02-23 11:31:04'),('2023-02-09 00:00:00'); +SELECT CASE WHEN a THEN DEFAULT(a) END FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; + --echo # --echo # End of 10.4 tests diff --git a/mysql-test/main/udf.result b/mysql-test/main/udf.result index 4077a85c813..8ad21e68c71 100644 --- a/mysql-test/main/udf.result +++ b/mysql-test/main/udf.result @@ -30,9 +30,9 @@ lookup("127.0.0.1") 127.0.0.1 select lookup(127,0,0,1); ERROR HY000: Can't initialize function 'lookup'; Wrong arguments to lookup; Use the source -select lookup("localhost"); -lookup("localhost") -127.0.0.1 +select lookup("localhost") rlike '^127\.\\d+\.\\d+.\\d+$'; +lookup("localhost") rlike '^127\.\\d+\.\\d+.\\d+$' +1 select reverse_lookup(); ERROR HY000: Can't initialize function 'reverse_lookup'; Wrong number of arguments to reverse_lookup; Use the source select reverse_lookup("127.0.0.1"); diff --git a/mysql-test/main/udf.test b/mysql-test/main/udf.test index bb8493135aa..640d5567574 100644 --- a/mysql-test/main/udf.test +++ b/mysql-test/main/udf.test @@ -47,7 +47,7 @@ select lookup(); select lookup("127.0.0.1"); --error ER_CANT_INITIALIZE_UDF select lookup(127,0,0,1); -select lookup("localhost"); +select lookup("localhost") rlike '^127\.\\d+\.\\d+.\\d+$'; --error ER_CANT_INITIALIZE_UDF select reverse_lookup(); diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 55d95b2bb3b..c1ed5d72d68 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -198,7 +198,7 @@ c d drop view v100; ERROR 42S02: Unknown VIEW: 'test.v100' drop view t1; -ERROR HY000: 'test.t1' is not of type 'VIEW' +ERROR 42S02: Unknown VIEW: 'test.t1' drop table v1; ERROR 42S02: 'test.v1' is a view drop view v1,v2; @@ -2848,7 +2848,11 @@ Tables_in_test t1 CREATE VIEW v1 AS SELECT id FROM t1; DROP VIEW t1,v1; -ERROR HY000: 'test.t1' is not of type 'VIEW' +ERROR 42S02: Unknown VIEW: 'test.t1' +show warnings; +Level Code Message +Warning 1347 'test.t1' is not of type 'VIEW' +Error 4092 Unknown VIEW: 'test.t1' SHOW TABLES; Tables_in_test t1 diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index 1632e6105ff..0545810fa69 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -130,7 +130,7 @@ select * from v2; drop view v100; # try to drop table with DROP VIEW --- error ER_WRONG_OBJECT +-- error ER_UNKNOWN_VIEW drop view t1; # try to drop VIEW with DROP TABLE @@ -2730,8 +2730,9 @@ DROP VIEW v2,v1; SHOW TABLES; CREATE VIEW v1 AS SELECT id FROM t1; ---error ER_WRONG_OBJECT +--error ER_UNKNOWN_VIEW DROP VIEW t1,v1; +show warnings; SHOW TABLES; DROP TABLE t1; diff --git a/mysql-test/main/warnings_debug.result b/mysql-test/main/warnings_debug.result index 3a9d8225795..4d815767c14 100644 --- a/mysql-test/main/warnings_debug.result +++ b/mysql-test/main/warnings_debug.result @@ -5,8 +5,12 @@ SET SESSION debug_dbug="+d,warn_during_ha_commit_trans"; INSERT INTO t1 VALUES (1); Warnings: Warning 1196 Some non-transactional changed tables couldn't be rolled back +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Warning 1196 Some non-transactional changed tables couldn't be rolled back SHOW WARNINGS; Level Code Message Warning 1196 Some non-transactional changed tables couldn't be rolled back -drop table t1; +Warning 1196 Some non-transactional changed tables couldn't be rolled back +Warning 1196 Some non-transactional changed tables couldn't be rolled back SET debug_dbug= @saved_dbug; +drop table t1; diff --git a/mysql-test/main/warnings_debug.test b/mysql-test/main/warnings_debug.test index 6605daf875d..4d084b1f52c 100644 --- a/mysql-test/main/warnings_debug.test +++ b/mysql-test/main/warnings_debug.test @@ -17,5 +17,5 @@ INSERT INTO t1 VALUES (1); # packet. Show the warnings manually also. SHOW WARNINGS; -drop table t1; SET debug_dbug= @saved_dbug; +drop table t1; diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index fd0efd917e6..82e9399e653 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -3723,6 +3723,82 @@ MAX(1) OVER () COUNT(a) abs(a) 1 0 NULL drop table t1; # +# MDEV-22461: JOIN::make_aggr_tables_info(): Assertion `select_options & (1ULL << 17)' failed. +# +CREATE TEMPORARY TABLE t0 (a INT PRIMARY KEY ) ; +INSERT INTO t0 VALUES (1),(2),(3); +SELECT a FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); +a +1 +SELECT a, ROW_NUMBER() OVER v2 +FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); +a ROW_NUMBER() OVER v2 +1 1 +drop table t0; +# +# MDEV-16230:Server crashes when Analyze format=json is run with a window function with +# empty PARTITION BY and ORDER BY clauses +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +ANALYZE FORMAT=JSON SELECT row_number() OVER() FROM t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "`row_number() OVER()`", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 3, + "r_buffer_size": "REPLACED", + "r_sort_mode": "sort_key,rowid" + } + }, + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 3, + "r_rows": 3, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } +} +SELECT row_number() OVER() FROM t1; +row_number() OVER() +1 +2 +3 +DROP TABLE t1; +# +# MDEV-22984: Throw an error when arguments to window functions are window functions +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT NTILE(MAX(a) OVER (PARTITION BY a)) OVER (PARTITION BY a ORDER BY b) FROM t1; +ERROR HY000: Window functions can not be used as arguments to group functions. +SELECT FIRST_VALUE(MAX(a) OVER (PARTITION BY a)) OVER (ORDER BY a) AS x FROM t1 GROUP BY a; +ERROR HY000: Window functions can not be used as arguments to group functions. +DROP TABLE t1; +# # End of 10.2 tests # # diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 89a018ea374..6e628d3c0ba 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2425,6 +2425,52 @@ SELECT MAX(1) OVER (), COUNT(a), abs(a) FROM t1 WHERE FALSE; drop table t1; +--echo # +--echo # MDEV-22461: JOIN::make_aggr_tables_info(): Assertion `select_options & (1ULL << 17)' failed. +--echo # + +CREATE TEMPORARY TABLE t0 (a INT PRIMARY KEY ) ; +INSERT INTO t0 VALUES (1),(2),(3); + +SELECT a FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); + +SELECT a, ROW_NUMBER() OVER v2 +FROM t0 +WHERE a < 8 +GROUP BY 1.5 +WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); + +drop table t0; + +--echo # +--echo # MDEV-16230:Server crashes when Analyze format=json is run with a window function with +--echo # empty PARTITION BY and ORDER BY clauses +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); + +--source include/analyze-format.inc +ANALYZE FORMAT=JSON SELECT row_number() OVER() FROM t1; +SELECT row_number() OVER() FROM t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-22984: Throw an error when arguments to window functions are window functions +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); + +--error ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG +SELECT NTILE(MAX(a) OVER (PARTITION BY a)) OVER (PARTITION BY a ORDER BY b) FROM t1; +--error ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG +SELECT FIRST_VALUE(MAX(a) OVER (PARTITION BY a)) OVER (ORDER BY a) AS x FROM t1 GROUP BY a; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/win_percentile.result b/mysql-test/main/win_percentile.result index a2ca775fcfb..09c2c4fc5de 100644 --- a/mysql-test/main/win_percentile.result +++ b/mysql-test/main/win_percentile.result @@ -99,7 +99,14 @@ Tatiana select score, percentile_cont(0.5) within group(order by name) over (partition by score) from t1; ERROR HY000: Numeric datatype is required for percentile_cont function select score, percentile_disc(0.5) within group(order by name) over (partition by score) from t1; -ERROR HY000: Numeric datatype is required for percentile_disc function +score percentile_disc(0.5) within group(order by name) over (partition by score) +3.0000 Chun +3.0000 Chun +4.0000 Tata +4.0000 Tata +4.0000 Tata +7.0000 Chun +7.0000 Chun #parameter value should be in the range of [0,1] select percentile_disc(1.5) within group(order by score) over (partition by name) from t1; ERROR HY000: Argument to the percentile_disc function does not belong to the range [0,1] @@ -452,7 +459,7 @@ Lord of the Ladybirds 30000000000.00 Lord of the Ladybirds 30000000000.00 DROP TABLE t2, t1; # -# MDEV-20272 PERCENTILE_DISC() crashes on a temporal type input +# MDEV-20280 PERCENTILE_DISC() rejects temporal and string input # CREATE OR REPLACE TABLE t1 (name CHAR(30), star_rating TIME); INSERT INTO t1 VALUES ('Lord of the Ladybirds', 5); @@ -463,5 +470,28 @@ INSERT INTO t1 VALUES ('Lady of the Flies', 5); SELECT name, PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY star_rating) OVER (PARTITION BY name) AS pc FROM t1; -ERROR HY000: Numeric datatype is required for percentile_disc function +name pc +Lady of the Flies 00:00:02 +Lady of the Flies 00:00:02 +Lady of the Flies 00:00:02 +Lord of the Ladybirds 00:00:03 +Lord of the Ladybirds 00:00:03 +SELECT name, PERCENTILE_DISC(0) +WITHIN GROUP (ORDER BY star_rating) +OVER (PARTITION BY name) AS pc FROM t1; +name pc +Lady of the Flies 00:00:01 +Lady of the Flies 00:00:01 +Lady of the Flies 00:00:01 +Lord of the Ladybirds 00:00:03 +Lord of the Ladybirds 00:00:03 +SELECT name, PERCENTILE_DISC(1) +WITHIN GROUP (ORDER BY star_rating) +OVER (PARTITION BY name) AS pc FROM t1; +name pc +Lady of the Flies 00:00:05 +Lady of the Flies 00:00:05 +Lady of the Flies 00:00:05 +Lord of the Ladybirds 00:00:05 +Lord of the Ladybirds 00:00:05 DROP TABLE t1; diff --git a/mysql-test/main/win_percentile.test b/mysql-test/main/win_percentile.test index 8705be123ff..e981dc62c41 100644 --- a/mysql-test/main/win_percentile.test +++ b/mysql-test/main/win_percentile.test @@ -61,7 +61,7 @@ select name from t1 a where (select percentile_disc(0.5) within group (order by --echo #disallowed fields in order by --error ER_WRONG_TYPE_FOR_PERCENTILE_FUNC select score, percentile_cont(0.5) within group(order by name) over (partition by score) from t1; ---error ER_WRONG_TYPE_FOR_PERCENTILE_FUNC + select score, percentile_disc(0.5) within group(order by name) over (partition by score) from t1; --echo #parameter value should be in the range of [0,1] @@ -212,7 +212,7 @@ DROP TABLE t2, t1; --echo # ---echo # MDEV-20272 PERCENTILE_DISC() crashes on a temporal type input +--echo # MDEV-20280 PERCENTILE_DISC() rejects temporal and string input --echo # CREATE OR REPLACE TABLE t1 (name CHAR(30), star_rating TIME); @@ -221,8 +221,13 @@ INSERT INTO t1 VALUES ('Lord of the Ladybirds', 3); INSERT INTO t1 VALUES ('Lady of the Flies', 1); INSERT INTO t1 VALUES ('Lady of the Flies', 2); INSERT INTO t1 VALUES ('Lady of the Flies', 5); ---error ER_WRONG_TYPE_FOR_PERCENTILE_FUNC SELECT name, PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY star_rating) OVER (PARTITION BY name) AS pc FROM t1; +SELECT name, PERCENTILE_DISC(0) + WITHIN GROUP (ORDER BY star_rating) + OVER (PARTITION BY name) AS pc FROM t1; +SELECT name, PERCENTILE_DISC(1) + WITHIN GROUP (ORDER BY star_rating) + OVER (PARTITION BY name) AS pc FROM t1; DROP TABLE t1; diff --git a/mysql-test/main/xa.result b/mysql-test/main/xa.result index e2a103a7a77..2fe8316b65b 100644 --- a/mysql-test/main/xa.result +++ b/mysql-test/main/xa.result @@ -403,6 +403,22 @@ XA ROLLBACK 'xid1'; # XA START 'gtrid', 'bqual', 0x80000000; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '0x80000000' at line 1 +XA BEGIN 'xid'; +CREATE TEMPORARY SEQUENCE s; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state +XA END 'xid'; +XA ROLLBACK 'xid'; +XA BEGIN 'xid'; +CREATE SEQUENCE s; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state +XA END 'xid'; +XA ROLLBACK 'xid'; +# +# End of 10.3 tests +# +# +# Start of 10.5 tests +# # MDEV-7974 related # Check XA state when lock_wait_timeout happens # More tests added to flush_read_lock.test @@ -461,3 +477,6 @@ formatID gtrid_length bqual_length data drop table asd; disconnect con_tmp; connection default; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/xa.test b/mysql-test/main/xa.test index 7aaa72b1645..07183feda76 100644 --- a/mysql-test/main/xa.test +++ b/mysql-test/main/xa.test @@ -544,6 +544,37 @@ XA START 'gtrid', 'bqual', 0x80000000; --source include/wait_until_count_sessions.inc +# +# MDEV-22002 Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' +# failed upon CREATE TEMPORARY SEQUENCE under XA +# + +XA BEGIN 'xid'; + +--error ER_XAER_RMFAIL +CREATE TEMPORARY SEQUENCE s; + +XA END 'xid'; + +XA ROLLBACK 'xid'; + +XA BEGIN 'xid'; + +--error ER_XAER_RMFAIL +CREATE SEQUENCE s; + +XA END 'xid'; + +XA ROLLBACK 'xid'; + +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + --echo # MDEV-7974 related --echo # Check XA state when lock_wait_timeout happens --echo # More tests added to flush_read_lock.test @@ -590,3 +621,7 @@ drop table asd; disconnect con_tmp; --source include/wait_until_disconnected.inc connection default; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/xa_binlog.result b/mysql-test/main/xa_binlog.result index c45749d500f..a272570aac1 100644 --- a/mysql-test/main/xa_binlog.result +++ b/mysql-test/main/xa_binlog.result @@ -18,7 +18,33 @@ a 1 2 3 -SHOW BINLOG EVENTS LIMIT 3,12; +DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=Aria; +INSERT INTO t1 VALUES (1),(2); +XA BEGIN 'x'; +DELETE FROM t1; +XA END 'x'; +XA PREPARE 'x'; +Warnings: +Warning 1030 Got error 131 "Command not supported by the engine" from storage engine Aria +XA COMMIT 'x'; +SELECT * from t1; +a +XA BEGIN 'x'; +INSERT INTO t1 VALUES (3),(4); +XA END 'x'; +XA PREPARE 'x'; +Warnings: +Warning 1030 Got error 131 "Command not supported by the engine" from storage engine Aria +XA ROLLBACK 'x'; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +SELECT * from t1; +a +3 +4 +DROP TABLE t1; +SHOW BINLOG EVENTS LIMIT 3,100; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Gtid 1 # XA START X'786174657374',X'',1 GTID #-#-# master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (1) @@ -32,4 +58,28 @@ master-bin.000001 # Xid 1 # COMMIT /* xid=XX */ master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (3) master-bin.000001 # Xid 1 # COMMIT /* xid=XX */ -DROP TABLE t1; +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */ +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1 (a INT) ENGINE=Aria +master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (1),(2) +master-bin.000001 # Query 1 # COMMIT +master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000001 # Query 1 # use `test`; DELETE FROM t1 +master-bin.000001 # Query 1 # COMMIT +master-bin.000001 # Gtid 1 # XA START X'78',X'',1 GTID #-#-# +master-bin.000001 # Query 1 # XA END X'78',X'',1 +master-bin.000001 # XA_prepare 1 # XA PREPARE X'78',X'',1 +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # XA COMMIT X'78',X'',1 +master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (3),(4) +master-bin.000001 # Query 1 # COMMIT +master-bin.000001 # Gtid 1 # XA START X'78',X'',1 GTID #-#-# +master-bin.000001 # Query 1 # XA END X'78',X'',1 +master-bin.000001 # XA_prepare 1 # XA PREPARE X'78',X'',1 +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # XA ROLLBACK X'78',X'',1 +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */ diff --git a/mysql-test/main/xa_binlog.test b/mysql-test/main/xa_binlog.test index 91bca2ac8cb..1343fa2aaee 100644 --- a/mysql-test/main/xa_binlog.test +++ b/mysql-test/main/xa_binlog.test @@ -24,9 +24,38 @@ INSERT INTO t1 VALUES (3); COMMIT; SELECT * FROM t1 ORDER BY a; +DROP TABLE t1; + +# +# MDEV-22607 Assertion `ha_info->ht() != binlog_hton' failed in +# MYSQL_BIN_LOG::unlog_xa_prepare +# + +CREATE TABLE t1 (a INT) ENGINE=Aria; +INSERT INTO t1 VALUES (1),(2); +XA BEGIN 'x'; +DELETE FROM t1; +XA END 'x'; +XA PREPARE 'x'; + +# Cleanup +XA COMMIT 'x'; + +SELECT * from t1; + +XA BEGIN 'x'; +INSERT INTO t1 VALUES (3),(4); +XA END 'x'; +XA PREPARE 'x'; +XA ROLLBACK 'x'; + +SELECT * from t1; +DROP TABLE t1; + +# +# Time to check the log +# --replace_column 2 # 5 # --replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ -SHOW BINLOG EVENTS LIMIT 3,12; - -DROP TABLE t1; +SHOW BINLOG EVENTS LIMIT 3,100; diff --git a/mysql-test/mtr.out-of-source b/mysql-test/mtr.out-of-source index 51713517ae1..30e2e65c569 100644 --- a/mysql-test/mtr.out-of-source +++ b/mysql-test/mtr.out-of-source @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Call mtr in out-of-source build $ENV{MTR_BINDIR} = '@CMAKE_BINARY_DIR@'; chdir('@CMAKE_SOURCE_DIR@/mysql-test'); diff --git a/mysql-test/mysql-stress-test.pl b/mysql-test/mysql-stress-test.pl index ef7d97453a3..3ccf965024d 100755 --- a/mysql-test/mysql-stress-test.pl +++ b/mysql-test/mysql-stress-test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f84a2a645d7..de07d018bdf 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- cperl -*- # Copyright (c) 2004, 2014, Oracle and/or its affiliates. @@ -201,6 +201,7 @@ my @DEFAULT_SUITES= qw( plugins- roles- rpl- + stress- sys_vars- sql_sequence- unit- @@ -266,8 +267,12 @@ our %gprof_dirs; our $glob_debugger= 0; our $opt_gdb; +my $opt_rr; +my $opt_rr_dir; +my @rr_record_args; our $opt_client_gdb; my $opt_boot_gdb; +my $opt_boot_rr; our $opt_dbx; our $opt_client_dbx; my $opt_boot_dbx; @@ -377,32 +382,6 @@ my $opt_stop_keep_alive= $ENV{MTR_STOP_KEEP_ALIVE}; select(STDOUT); $| = 1; # Automatically flush STDOUT -my $set_titlebar; - - - BEGIN { - if (IS_WINDOWS) { - my $have_win32_console= 0; - eval { - require Win32::Console; - Win32::Console->import(); - $have_win32_console = 1; - }; - eval 'sub HAVE_WIN32_CONSOLE { $have_win32_console }'; - } else { - eval 'sub HAVE_WIN32_CONSOLE { 0 }'; - } -} - -if (-t STDOUT) { - if (IS_WINDOWS and HAVE_WIN32_CONSOLE) { - $set_titlebar = sub {Win32::Console::Title $_[0];}; - } elsif (defined $ENV{TERM} and $ENV{TERM} =~ /xterm/) { - $set_titlebar = sub { syswrite STDOUT, "\e];$_[0]\a"; }; - } -} - - main(); sub main { @@ -475,7 +454,7 @@ sub main { } ####################################################################### - my $num_tests= @$tests; + my $num_tests= $mtr_report::tests_total= @$tests; if ( $opt_parallel eq "auto" ) { # Try to find a suitable value for number of workers if (IS_WINDOWS) @@ -582,6 +561,7 @@ sub main { # Create minimalistic "test" for the reporting my $tinfo = My::Test->new ( + suite => { name => 'valgrind', }, name => 'valgrind_report', ); # Set dummy worker id to align report with normal tests @@ -784,8 +764,14 @@ sub run_test_server ($$$) { if ( $result->is_failed() ) { my $worker_logdir= $result->{savedir}; my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log"; - $result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20); - rename $log_file_name,$log_file_name.".failed"; + + if (-e $log_file_name) { + $result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20); + } else { + $result->{'logfile-failed'} = ""; + } + + rename $log_file_name, $log_file_name.".failed"; } delete($result->{result}); $result->{retries}= $retries+1; @@ -909,8 +895,6 @@ sub run_test_server ($$$) { delete $next->{reserved}; } - titlebar_stat(scalar(@$tests)) if $set_titlebar; - if ($next) { # We don't need this any more delete $next->{criteria}; @@ -1179,10 +1163,14 @@ sub command_line_setup { 'debug-common' => \$opt_debug_common, 'debug-server' => \$opt_debug_server, 'gdb=s' => \$opt_gdb, + 'rr' => \$opt_rr, + 'rr-arg=s' => \@rr_record_args, + 'rr-dir=s' => \$opt_rr_dir, 'client-gdb' => \$opt_client_gdb, 'manual-gdb' => \$opt_manual_gdb, 'manual-lldb' => \$opt_manual_lldb, 'boot-gdb' => \$opt_boot_gdb, + 'boot-rr' => \$opt_boot_rr, 'manual-debug' => \$opt_manual_debug, 'ddd' => \$opt_ddd, 'client-ddd' => \$opt_client_ddd, @@ -1658,9 +1646,9 @@ sub command_line_setup { $ENV{LSAN_OPTIONS}= "suppressions=${glob_mysql_test_dir}/lsan.supp:print_suppressions=0" if -f "$glob_mysql_test_dir/lsan.supp" and not IS_WINDOWS; - if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd || - $opt_manual_gdb || $opt_manual_lldb || $opt_manual_ddd || - $opt_manual_debug || $opt_dbx || $opt_client_dbx || $opt_manual_dbx || + if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd || $opt_rr || + $opt_manual_gdb || $opt_manual_lldb || $opt_manual_ddd || + $opt_manual_debug || $opt_dbx || $opt_client_dbx || $opt_manual_dbx || $opt_debugger || $opt_client_debugger ) { $ENV{ASAN_OPTIONS}= 'disable_coredump=0:'. $ENV{ASAN_OPTIONS}; @@ -3308,6 +3296,13 @@ sub mysql_install_db { ddd_arguments(\$args, \$exe_mysqld_bootstrap, $mysqld->name(), $bootstrap_sql_file); } + if ($opt_boot_rr) { + $args= ["record", @rr_record_args, $exe_mysqld_bootstrap, @$args]; + $exe_mysqld_bootstrap= "rr"; + my $rr_dir= $opt_rr_dir ? $opt_rr_dir : "$opt_vardir/rr.boot"; + $ENV{'_RR_TRACE_DIR'}= $rr_dir; + mkpath($rr_dir); + } my $path_sql= my_find_file($install_basedir, ["mysql", "sql/share", "share/mariadb", @@ -5306,6 +5301,14 @@ sub mysqld_start ($$) { # Indicate the exe should not be started $exe= undef; } + elsif ( $opt_rr ) + { + $args= ["record", @rr_record_args, "$exe", @$args]; + $exe= "rr"; + my $rr_dir= $opt_rr_dir ? $opt_rr_dir : "$opt_vardir/rr". $mysqld->after('mysqld'); + $ENV{'_RR_TRACE_DIR'}= $rr_dir; + mkpath($rr_dir); + } else { # Default to not wait until pid file has been created @@ -6490,6 +6493,15 @@ Options for strace stracer= Specify name and path to the trace program to use. Default is "strace". Example: $0 --stracer=ktrace. +Options for rr (Record and Replay) + rr Run the "mysqld" executables using rr. Default run + option is "rr record mysqld mysqld_options" + boot-rr Start bootstrap server in rr + rr-arg=ARG Option to give rr record, can be specified more then once + rr-dir=DIR The directory where rr recordings are stored. Defaults + to 'vardir'/rr.0 (rr.boot for bootstrap instance and + rr.1, ..., rr.N for slave instances). + Misc options user=USER User for connecting to mysqld(default: $opt_user) comment=STR Write STR to the output @@ -6579,23 +6591,3 @@ sub list_options ($) { exit(1); } - -sub time_format($) { - sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60; -} - -our $num_tests; - -sub titlebar_stat { - my ($left) = @_; - - # 2.5 -> best by test - $num_tests = $left + 2.5 unless $num_tests; - - my $done = $num_tests - $left; - my $spent = time - $^T; - - &$set_titlebar(sprintf "mtr: spent %s on %d tests. %s (%d tests) left", - time_format($spent), $done, - time_format($spent/$done * $left), $left); -} diff --git a/mysql-test/std_data/checkDBI_DBD-MariaDB.pl b/mysql-test/std_data/checkDBI_DBD-MariaDB.pl index ed0f5b415d7..b078342c2a0 100755 --- a/mysql-test/std_data/checkDBI_DBD-MariaDB.pl +++ b/mysql-test/std_data/checkDBI_DBD-MariaDB.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2011, Oracle and/or its affiliates # diff --git a/mysql-test/std_data/mysql_database_10.0.dump b/mysql-test/std_data/mysql_database_10.0.dump new file mode 100644 index 00000000000..f3c9334ab6a --- /dev/null +++ b/mysql-test/std_data/mysql_database_10.0.dump @@ -0,0 +1,902 @@ +-- MySQL dump 10.15 Distrib 10.0.38-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 10.0.38-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `column_stats` +-- + +DROP TABLE IF EXISTS `column_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, + `nulls_ratio` decimal(12,4) DEFAULT NULL, + `avg_length` decimal(12,4) DEFAULT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + `hist_size` tinyint(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `column_stats` +-- + +LOCK TABLES `column_stats` WRITE; +/*!40000 ALTER TABLE `column_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `column_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT '0', + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gtid_slave_pos` +-- + +DROP TABLE IF EXISTS `gtid_slave_pos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gtid_slave_pos` ( + `domain_id` int(10) unsigned NOT NULL, + `sub_id` bigint(20) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `seq_no` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`domain_id`,`sub_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Replication slave GTID position'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gtid_slave_pos` +-- + +LOCK TABLES `gtid_slave_pos` WRITE; +/*!40000 ALTER TABLE `gtid_slave_pos` DISABLE KEYS */; +/*!40000 ALTER TABLE `gtid_slave_pos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control flow functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry constructors',34,''),(25,'GeometryCollection properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (0,'JOIN'),(1,'HOST'),(2,'REPEAT'),(3,'SERIALIZABLE'),(4,'REPLACE'),(5,'AT'),(6,'SCHEDULE'),(7,'RETURNS'),(8,'STARTS'),(9,'MASTER_SSL_CA'),(10,'NCHAR'),(11,'COLUMNS'),(12,'COMPLETION'),(13,'WORK'),(14,'DATETIME'),(15,'MODE'),(16,'OPEN'),(17,'INTEGER'),(18,'ESCAPE'),(19,'VALUE'),(20,'MASTER_SSL_VERIFY_SERVER_CERT'),(21,'SQL_BIG_RESULT'),(22,'DROP'),(23,'GEOMETRYCOLLECTIONFROMWKB'),(24,'EVENTS'),(25,'MONTH'),(26,'PROFILES'),(27,'DUPLICATE'),(28,'REPLICATION'),(29,'UNLOCK'),(30,'INNODB'),(31,'YEAR_MONTH'),(32,'SUBJECT'),(33,'PREPARE'),(34,'LOCK'),(35,'NDB'),(36,'CHECK'),(37,'FULL'),(38,'INT4'),(39,'BY'),(40,'NO'),(41,'MINUTE'),(42,'PARTITION'),(43,'DATA'),(44,'DAY'),(45,'SHARE'),(46,'REAL'),(47,'SEPARATOR'),(48,'MESSAGE_TEXT'),(49,'MASTER_HEARTBEAT_PERIOD'),(50,'DELETE'),(51,'ON'),(52,'COLUMN_NAME'),(53,'CONNECTION'),(54,'CLOSE'),(55,'X509'),(56,'USE'),(57,'SUBCLASS_ORIGIN'),(58,'WHERE'),(59,'PRIVILEGES'),(60,'SPATIAL'),(61,'EVENT'),(62,'SUPER'),(63,'SQL_BUFFER_RESULT'),(64,'IGNORE'),(65,'SHA2'),(66,'QUICK'),(67,'SIGNED'),(68,'OFFLINE'),(69,'SECURITY'),(70,'AUTOEXTEND_SIZE'),(71,'NDBCLUSTER'),(72,'POLYGONFROMWKB'),(73,'FALSE'),(74,'LEVEL'),(75,'FORCE'),(76,'BINARY'),(77,'TO'),(78,'CHANGE'),(79,'CURRENT_USER'),(80,'HOUR_MINUTE'),(81,'UPDATE'),(82,'PRESERVE'),(83,'TABLE_NAME'),(84,'INTO'),(85,'FEDERATED'),(86,'VARYING'),(87,'MAX_SIZE'),(88,'HOUR_SECOND'),(89,'VARIABLE'),(90,'ROLLBACK'),(91,'PROCEDURE'),(92,'TIMESTAMP'),(93,'IMPORT'),(94,'AGAINST'),(95,'CHECKSUM'),(96,'COUNT'),(97,'LONGBINARY'),(98,'THEN'),(99,'INSERT'),(100,'ENGINES'),(101,'HANDLER'),(102,'PORT'),(103,'DAY_SECOND'),(104,'EXISTS'),(105,'MUTEX'),(106,'HELP_DATE'),(107,'RELEASE'),(108,'BOOLEAN'),(109,'MOD'),(110,'DEFAULT'),(111,'TYPE'),(112,'NO_WRITE_TO_BINLOG'),(113,'OPTIMIZE'),(114,'SQLSTATE'),(115,'RESET'),(116,'CLASS_ORIGIN'),(117,'INSTALL'),(118,'ITERATE'),(119,'DO'),(120,'BIGINT'),(121,'SET'),(122,'ISSUER'),(123,'DATE'),(124,'STATUS'),(125,'FULLTEXT'),(126,'COMMENT'),(127,'MASTER_CONNECT_RETRY'),(128,'INNER'),(129,'RELAYLOG'),(130,'STOP'),(131,'MASTER_LOG_FILE'),(132,'MRG_MYISAM'),(133,'PRECISION'),(134,'REQUIRE'),(135,'TRAILING'),(136,'PARTITIONS'),(137,'LONG'),(138,'OPTION'),(139,'REORGANIZE'),(140,'ELSE'),(141,'DEALLOCATE'),(142,'IO_THREAD'),(143,'CASE'),(144,'CIPHER'),(145,'CONTINUE'),(146,'FROM'),(147,'READ'),(148,'LEFT'),(149,'ELSEIF'),(150,'MINUTE_SECOND'),(151,'COMPACT'),(152,'DEC'),(153,'FOR'),(154,'WARNINGS'),(155,'MIN_ROWS'),(156,'STRING'),(157,'CONDITION'),(158,'ENCLOSED'),(159,'FUNCTION'),(160,'AGGREGATE'),(161,'FIELDS'),(162,'INT3'),(163,'ARCHIVE'),(164,'AVG_ROW_LENGTH'),(165,'ADD'),(166,'KILL'),(167,'FLOAT4'),(168,'TABLESPACE'),(169,'VIEW'),(170,'REPEATABLE'),(171,'INFILE'),(172,'HELP_VERSION'),(173,'ORDER'),(174,'USING'),(175,'CONSTRAINT_CATALOG'),(176,'MIDDLEINT'),(177,'GRANT'),(178,'UNSIGNED'),(179,'DECIMAL'),(180,'GEOMETRYFROMTEXT'),(181,'INDEXES'),(182,'FOREIGN'),(183,'CACHE'),(184,'HOSTS'),(185,'MYSQL_ERRNO'),(186,'COMMIT'),(187,'SCHEMAS'),(188,'LEADING'),(189,'SNAPSHOT'),(190,'CONSTRAINT_NAME'),(191,'DECLARE'),(192,'LOAD'),(193,'SQL_CACHE'),(194,'CONVERT'),(195,'DYNAMIC'),(196,'COLLATE'),(197,'POLYGONFROMTEXT'),(198,'BYTE'),(199,'GLOBAL'),(200,'LINESTRINGFROMWKB'),(201,'WHEN'),(202,'HAVING'),(203,'AS'),(204,'STARTING'),(205,'RELOAD'),(206,'AUTOCOMMIT'),(207,'REVOKE'),(208,'GRANTS'),(209,'OUTER'),(210,'CURSOR_NAME'),(211,'FLOOR'),(212,'EXPLAIN'),(213,'WITH'),(214,'AFTER'),(215,'STD'),(216,'CSV'),(217,'DISABLE'),(218,'UNINSTALL'),(219,'OUTFILE'),(220,'LOW_PRIORITY'),(221,'FILE'),(222,'NODEGROUP'),(223,'SCHEMA'),(224,'SONAME'),(225,'POW'),(226,'DUAL'),(227,'MULTIPOINTFROMWKB'),(228,'INDEX'),(229,'MULTIPOINTFROMTEXT'),(230,'DEFINER'),(231,'MASTER_BIND'),(232,'REMOVE'),(233,'EXTENDED'),(234,'MULTILINESTRINGFROMWKB'),(235,'CROSS'),(236,'CONTRIBUTORS'),(237,'NATIONAL'),(238,'GROUP'),(239,'SHA'),(240,'ONLINE'),(241,'UNDO'),(242,'IGNORE_SERVER_IDS'),(243,'ZEROFILL'),(244,'CLIENT'),(245,'MASTER_PASSWORD'),(246,'OWNER'),(247,'RELAY_LOG_FILE'),(248,'TRUE'),(249,'CHARACTER'),(250,'MASTER_USER'),(251,'SCHEMA_NAME'),(252,'TABLE'),(253,'ENGINE'),(254,'INSERT_METHOD'),(255,'CASCADE'),(256,'RELAY_LOG_POS'),(257,'SQL_CALC_FOUND_ROWS'),(258,'UNION'),(259,'MYISAM'),(260,'LEAVE'),(261,'MODIFY'),(262,'MATCH'),(263,'MASTER_LOG_POS'),(264,'DISTINCTROW'),(265,'DESC'),(266,'TIME'),(267,'NUMERIC'),(268,'EXPANSION'),(269,'CODE'),(270,'CURSOR'),(271,'GEOMETRYCOLLECTIONFROMTEXT'),(272,'CHAIN'),(273,'LOGFILE'),(274,'FLUSH'),(275,'CREATE'),(276,'DESCRIBE'),(277,'EXTENT_SIZE'),(278,'MAX_UPDATES_PER_HOUR'),(279,'INT2'),(280,'PROCESSLIST'),(281,'ENDS'),(282,'LOGS'),(283,'DISCARD'),(284,'HEAP'),(285,'SOUNDS'),(286,'BETWEEN'),(287,'MULTILINESTRINGFROMTEXT'),(288,'REPAIR'),(289,'PACK_KEYS'),(290,'FAST'),(291,'VALUES'),(292,'CALL'),(293,'LOOP'),(294,'VARCHARACTER'),(295,'BEFORE'),(296,'TRUNCATE'),(297,'SHOW'),(298,'ALL'),(299,'REDUNDANT'),(300,'USER_RESOURCES'),(301,'PARTIAL'),(302,'BINLOG'),(303,'END'),(304,'SECOND'),(305,'AND'),(306,'FLOAT8'),(307,'PREV'),(308,'HOUR'),(309,'SELECT'),(310,'DATABASES'),(311,'OR'),(312,'IDENTIFIED'),(313,'WRAPPER'),(314,'MASTER_SSL_CIPHER'),(315,'SQL_SLAVE_SKIP_COUNTER'),(316,'BOTH'),(317,'BOOL'),(318,'YEAR'),(319,'MASTER_PORT'),(320,'CONCURRENT'),(321,'HELP'),(322,'UNIQUE'),(323,'TRIGGERS'),(324,'PROCESS'),(325,'OPTIONS'),(326,'RESIGNAL'),(327,'CONSISTENT'),(328,'MASTER_SSL'),(329,'DATE_ADD'),(330,'MAX_CONNECTIONS_PER_HOUR'),(331,'LIKE'),(332,'PLUGIN'),(333,'FETCH'),(334,'IN'),(335,'COLUMN'),(336,'DUMPFILE'),(337,'USAGE'),(338,'EXECUTE'),(339,'MEMORY'),(340,'CEIL'),(341,'QUERY'),(342,'MASTER_HOST'),(343,'LINES'),(344,'SQL_THREAD'),(345,'SERVER'),(346,'MAX_QUERIES_PER_HOUR'),(347,'MASTER_SSL_CERT'),(348,'MULTIPOLYGONFROMWKB'),(349,'TRANSACTION'),(350,'DAY_MINUTE'),(351,'STDDEV'),(352,'DATE_SUB'),(353,'REBUILD'),(354,'GEOMETRYFROMWKB'),(355,'INT1'),(356,'RENAME'),(357,'PARSER'),(358,'RIGHT'),(359,'ALTER'),(360,'MAX_ROWS'),(361,'SOCKET'),(362,'STRAIGHT_JOIN'),(363,'NATURAL'),(364,'VARIABLES'),(365,'ESCAPED'),(366,'SHA1'),(367,'KEY_BLOCK_SIZE'),(368,'PASSWORD'),(369,'OFFSET'),(370,'CHAR'),(371,'NEXT'),(372,'ERRORS'),(373,'SQL_LOG_BIN'),(374,'TEMPORARY'),(375,'COMMITTED'),(376,'SQL_SMALL_RESULT'),(377,'UPGRADE'),(378,'BEGIN'),(379,'DELAY_KEY_WRITE'),(380,'PROFILE'),(381,'MEDIUM'),(382,'INTERVAL'),(383,'SSL'),(384,'DAY_HOUR'),(385,'NAME'),(386,'REFERENCES'),(387,'AES_ENCRYPT'),(388,'STORAGE'),(389,'ISOLATION'),(390,'CEILING'),(391,'EVERY'),(392,'INT8'),(393,'AUTHORS'),(394,'RESTRICT'),(395,'UNCOMMITTED'),(396,'LINESTRINGFROMTEXT'),(397,'IS'),(398,'NOT'),(399,'ANALYSE'),(400,'DATAFILE'),(401,'DES_KEY_FILE'),(402,'SIGNAL'),(403,'COMPRESSED'),(404,'START'),(405,'PLUGINS'),(406,'SAVEPOINT'),(407,'IF'),(408,'ROWS'),(409,'PRIMARY'),(410,'PURGE'),(411,'LAST'),(412,'USER'),(413,'EXIT'),(414,'KEYS'),(415,'LIMIT'),(416,'KEY'),(417,'MERGE'),(418,'UNTIL'),(419,'SQL_NO_CACHE'),(420,'DELAYED'),(421,'CONSTRAINT_SCHEMA'),(422,'ANALYZE'),(423,'CONSTRAINT'),(424,'SERIAL'),(425,'ACTION'),(426,'WRITE'),(427,'INITIAL_SIZE'),(428,'SESSION'),(429,'DATABASE'),(430,'NULL'),(431,'POWER'),(432,'USE_FRM'),(433,'TERMINATED'),(434,'SLAVE'),(435,'NVARCHAR'),(436,'ASC'),(437,'RETURN'),(438,'OPTIONALLY'),(439,'ENABLE'),(440,'DIRECTORY'),(441,'MAX_USER_CONNECTIONS'),(442,'WHILE'),(443,'LOCAL'),(444,'DISTINCT'),(445,'AES_DECRYPT'),(446,'MASTER_SSL_KEY'),(447,'NONE'),(448,'TABLES'),(449,'<>'),(450,'RLIKE'),(451,'TRIGGER'),(452,'COLLATION'),(453,'SHUTDOWN'),(454,'HIGH_PRIORITY'),(455,'BTREE'),(456,'FIRST'),(457,'COALESCE'),(458,'WAIT'),(459,'CATALOG_NAME'),(460,'MASTER'),(461,'FIXED'),(462,'MULTIPOLYGONFROMTEXT'),(463,'ROW_FORMAT'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (1,0),(356,0),(473,1),(232,2),(447,3),(3,4),(130,4),(421,4),(89,5),(89,6),(406,6),(97,7),(89,8),(185,9),(430,10),(21,11),(347,11),(421,11),(463,11),(468,11),(89,12),(406,12),(146,13),(230,14),(88,15),(356,15),(18,16),(106,16),(134,16),(347,16),(97,17),(500,17),(380,18),(3,19),(104,19),(243,19),(374,19),(459,19),(185,20),(356,21),(9,22),(30,22),(34,22),(87,22),(186,22),(237,22),(263,22),(276,22),(300,22),(331,22),(405,22),(415,22),(416,22),(463,22),(478,22),(108,23),(122,24),(170,24),(424,24),(376,25),(82,26),(104,27),(199,28),(36,29),(347,30),(468,30),(376,31),(199,32),(35,33),(237,33),(36,34),(356,34),(468,35),(417,36),(463,36),(468,36),(21,37),(294,37),(347,37),(451,37),(468,37),(500,38),(48,39),(77,39),(83,39),(130,39),(199,39),(356,39),(361,39),(421,39),(463,39),(468,39),(468,40),(472,40),(376,41),(463,42),(468,42),(212,43),(421,43),(468,43),(473,43),(376,44),(356,45),(97,46),(314,46),(361,47),(374,48),(459,48),(185,49),(48,50),(468,50),(472,50),(1,51),(89,51),(406,51),(472,51),(374,52),(459,52),(176,53),(468,53),(51,54),(106,54),(199,55),(1,56),(55,56),(194,56),(374,57),(459,57),(48,58),(83,58),(106,58),(193,59),(199,59),(249,59),(210,60),(463,60),(89,61),(300,61),(358,61),(406,61),(199,62),(356,63),(1,64),(83,64),(104,64),(130,64),(356,64),(421,64),(463,64),(66,65),(48,66),(417,66),(466,66),(230,67),(87,68),(210,68),(463,68),(199,69),(194,70),(468,71),(91,72),(482,72),(385,73),(447,74),(1,75),(39,76),(230,76),(269,76),(185,77),(269,77),(460,77),(185,78),(463,78),(89,79),(406,79),(376,80),(83,81),(104,81),(356,81),(472,81),(89,82),(406,82),(374,83),(459,83),(3,84),(104,84),(304,84),(356,84),(468,85),(257,86),(194,87),(376,88),(129,89),(146,90),(460,90),(17,91),(189,91),(302,91),(328,91),(347,91),(356,91),(416,91),(439,91),(488,91),(99,92),(188,92),(421,93),(463,93),(88,94),(401,95),(468,95),(69,96),(330,96),(433,96),(285,97),(28,98),(57,98),(85,98),(104,99),(195,99),(301,99),(486,99),(282,100),(347,100),(106,101),(313,101),(473,102),(376,103),(9,104),(30,104),(89,104),(155,104),(186,104),(276,104),(300,104),(347,105),(365,105),(109,106),(146,107),(460,107),(24,108),(88,108),(113,109),(174,109),(3,110),(104,110),(155,110),(200,110),(212,110),(243,110),(463,110),(468,110),(463,111),(115,112),(326,112),(466,112),(470,112),(115,113),(463,113),(374,114),(459,114),(38,115),(119,115),(151,115),(264,115),(374,116),(459,116),(419,117),(124,118),(89,119),(125,119),(406,119),(496,119),(221,120),(3,121),(83,121),(104,121),(129,121),(130,121),(146,121),(155,121),(182,121),(212,121),(333,121),(347,121),(356,121),(374,121),(421,121),(459,121),(463,121),(468,121),(472,121),(477,121),(494,121),(199,122),(132,123),(230,123),(262,123),(376,123),(58,124),(137,124),(215,124),(223,124),(328,124),(336,124),(347,124),(365,124),(210,125),(463,125),(468,125),(89,126),(194,126),(210,126),(406,126),(468,126),(185,127),(1,128),(424,129),(52,130),(185,131),(468,132),(314,133),(199,134),(455,135),(255,136),(285,137),(199,138),(249,138),(463,139),(57,140),(85,140),(237,141),(52,142),(324,142),(57,143),(85,143),(199,144),(313,145),(48,146),(122,146),(347,146),(356,146),(424,146),(455,146),(36,147),(106,147),(447,147),(1,148),(28,149),(376,150),(468,151),(209,152),(180,153),(313,153),(347,153),(356,153),(420,153),(330,154),(347,154),(468,155),(97,156),(180,157),(421,158),(34,159),(68,159),(97,159),(211,159),(233,159),(302,159),(336,159),(347,159),(393,159),(405,159),(416,159),(97,160),(347,161),(421,161),(252,162),(468,163),(463,164),(468,164),(60,165),(194,165),(463,165),(478,165),(176,166),(168,167),(194,168),(415,168),(463,168),(478,168),(30,169),(159,169),(454,169),(447,170),(130,171),(421,171),(190,172),(48,173),(83,173),(356,173),(361,173),(463,173),(1,174),(48,174),(86,174),(374,175),(459,175),(252,176),(199,177),(249,177),(24,178),(128,178),(168,178),(209,178),(230,178),(314,178),(500,178),(97,179),(156,179),(230,179),(411,180),(347,181),(463,182),(468,182),(472,182),(473,182),(101,183),(151,183),(304,183),(145,184),(347,184),(374,185),(459,185),(146,186),(160,187),(347,187),(455,188),(146,189),(374,190),(459,190),(180,191),(200,191),(313,191),(420,191),(304,192),(421,192),(356,193),(230,194),(377,194),(468,195),(155,196),(212,196),(468,196),(395,197),(465,198),(129,199),(137,199),(182,199),(349,199),(447,199),(452,200),(57,201),(85,201),(356,202),(1,203),(36,203),(356,203),(421,204),(199,205),(146,206),(249,207),(192,208),(347,208),(1,209),(374,210),(459,210),(221,211),(255,212),(88,213),(199,213),(210,213),(463,213),(468,213),(463,214),(260,215),(421,216),(468,216),(89,217),(406,217),(463,217),(291,218),(356,219),(3,220),(36,220),(48,220),(83,220),(104,220),(130,220),(421,220),(199,221),(194,222),(155,223),(186,223),(212,223),(309,223),(347,223),(97,224),(277,225),(279,226),(464,227),(1,228),(60,228),(87,228),(101,228),(210,228),(304,228),(308,228),(347,228),(463,228),(468,228),(425,229),(89,230),(406,230),(185,231),(463,232),(255,233),(466,233),(272,234),(1,235),(7,236),(347,236),(257,237),(430,237),(194,238),(226,238),(356,238),(427,239),(87,240),(210,240),(463,240),(313,241),(185,242),(24,243),(128,243),(168,243),(209,243),(314,243),(500,243),(199,244),(185,245),(473,246),(185,247),(385,248),(130,249),(155,249),(212,249),(257,249),(333,249),(347,249),(356,249),(421,249),(430,249),(468,249),(185,250),(374,251),(459,251),(60,252),(110,252),(115,252),(215,252),(276,252),(278,252),(321,252),(347,252),(401,252),(417,252),(463,252),(466,252),(468,252),(470,252),(194,253),(347,253),(365,253),(415,253),(463,253),(468,253),(478,253),(468,254),(30,255),(276,255),(468,255),(472,255),(185,256),(356,257),(305,258),(468,259),(310,260),(463,261),(88,262),(185,263),(356,264),(329,265),(356,265),(361,265),(230,266),(315,266),(375,266),(209,267),(88,268),(68,269),(488,269),(420,270),(246,271),(146,272),(194,273),(226,273),(151,274),(326,274),(17,275),(22,275),(60,275),(77,275),(89,275),(97,275),(155,275),(194,275),(210,275),(211,275),(278,275),(302,275),(309,275),(347,275),(358,275),(393,275),(454,275),(468,275),(473,275),(329,276),(194,277),(199,278),(234,279),(347,280),(451,280),(89,281),(39,282),(269,282),(347,282),(463,283),(468,284),(378,285),(147,286),(107,287),(463,288),(466,288),(468,289),(417,290),(3,291),(104,291),(339,292),(344,293),(257,294),(269,295),(321,296),(463,296),(7,297),(10,297),(17,297),(21,297),(25,297),(33,297),(39,297),(58,297),(68,297),(69,297),(82,297),(122,297),(134,297),(137,297),(145,297),(160,297),(170,297),(192,297),(193,297),(215,297),(223,297),(278,297),(282,297),(294,297),(308,297),(309,297),(328,297),(330,297),(333,297),(336,297),(347,297),(349,297),(358,297),(365,297),(393,297),(424,297),(451,297),(487,297),(488,297),(492,297),(38,298),(199,298),(249,298),(305,298),(356,298),(468,299),(326,300),(468,301),(122,302),(350,302),(28,303),(57,303),(85,303),(232,303),(327,303),(344,303),(496,303),(376,304),(147,305),(316,305),(314,306),(106,307),(376,308),(3,309),(104,309),(255,309),(301,309),(356,309),(160,310),(347,310),(141,311),(77,312),(130,312),(199,312),(473,313),(185,314),(182,315),(455,316),(24,317),(111,317),(376,318),(185,319),(130,320),(421,320),(118,321),(390,321),(463,322),(25,323),(347,323),(199,324),(373,325),(473,325),(374,326),(146,327),(185,328),(376,329),(199,330),(347,331),(378,331),(291,332),(347,332),(419,332),(383,333),(88,334),(122,334),(356,334),(424,334),(463,335),(356,336),(199,337),(86,338),(199,338),(356,339),(397,340),(88,341),(151,341),(176,341),(185,342),(130,343),(421,343),(52,344),(324,344),(9,345),(373,345),(473,345),(199,346),(185,347),(123,348),(146,349),(447,349),(376,350),(407,351),(376,352),(463,353),(144,354),(24,355),(110,356),(222,356),(406,356),(463,356),(210,357),(463,357),(468,357),(1,358),(60,359),(159,359),(199,359),(212,359),(226,359),(233,359),(373,359),(406,359),(439,359),(463,359),(478,359),(463,360),(468,360),(473,361),(1,362),(356,362),(1,363),(347,364),(349,364),(421,365),(427,366),(468,367),(77,368),(199,368),(473,368),(477,368),(356,369),(230,370),(465,370),(106,371),(69,372),(347,372),(494,373),(276,374),(447,375),(356,376),(212,377),(417,377),(146,378),(327,378),(468,379),(487,380),(417,381),(89,382),(376,382),(199,383),(376,384),(212,385),(199,386),(468,386),(472,386),(443,387),(282,388),(447,389),(448,390),(89,391),(128,392),(10,393),(347,393),(30,394),(276,394),(472,394),(447,395),(56,396),(84,397),(206,397),(368,397),(456,397),(84,398),(89,398),(155,398),(206,398),(312,398),(189,399),(194,400),(478,400),(326,401),(459,402),(468,403),(146,404),(324,404),(33,405),(460,406),(9,407),(28,407),(30,407),(89,407),(155,407),(186,407),(276,407),(300,407),(479,407),(130,408),(463,409),(269,410),(106,411),(77,412),(222,412),(331,412),(473,412),(313,413),(308,414),(347,414),(463,414),(48,415),(83,415),(106,415),(122,415),(356,415),(424,415),(60,416),(104,416),(463,416),(468,416),(472,416),(468,417),(232,418),(356,419),(3,420),(104,420),(486,420),(374,421),(459,421),(463,422),(470,422),(463,423),(468,423),(243,424),(468,424),(468,425),(472,425),(36,426),(194,427),(478,427),(129,428),(137,428),(349,428),(447,428),(155,429),(186,429),(212,429),(309,429),(347,429),(473,429),(84,430),(368,430),(472,430),(483,431),(466,432),(421,433),(38,434),(52,434),(89,434),(145,434),(223,434),(324,434),(406,434),(257,435),(356,436),(361,436),(491,437),(421,438),(89,439),(406,439),(463,439),(212,440),(468,440),(199,441),(496,442),(36,443),(115,443),(130,443),(326,443),(421,443),(466,443),(470,443),(0,444),(96,444),(288,444),(305,444),(356,444),(361,444),(384,444),(433,444),(497,445),(185,446),(199,447),(36,448),(134,448),(294,448),(347,448),(495,449),(27,450),(22,451),(263,451),(347,451),(347,452),(492,452),(199,453),(104,454),(356,454),(210,455),(106,456),(463,456),(468,456),(463,457),(194,458),(478,458),(374,459),(459,459),(39,460),(58,460),(185,460),(264,460),(269,460),(209,461),(468,461),(201,462),(468,463); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (0,'MIN',16,'Syntax:\nMIN([DISTINCT] expr)\n\nReturns the minimum value of expr. MIN() may take a string argument; in\nsuch cases, it returns the minimum string value.\nThe DISTINCT keyword can be used to find the minimum of the distinct values\nof expr, however, this produces the same result as omitting DISTINCT.\n\nMIN() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/min/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/min/'),(1,'JOIN',27,'MySQL supports the following JOIN syntaxes for the table_references\npart of SELECT statements and multiple-table DELETE and UPDATE\nstatements:\n\ntable_references:\n table_reference [, table_reference] ...\n\ntable_reference:\n table_factor\n | join_table\n\ntable_factor:\n tbl_name [[AS] alias] [index_hint_list]\n | table_subquery [AS] alias\n | ( table_references )\n | { OJ table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n\njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor [join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON conditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor\n\njoin_condition:\n ON conditional_expr\n | USING (column_list)\n\nindex_hint_list:\n index_hint [, index_hint] ...\n\nindex_hint:\n USE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n\nindex_list:\n index_name [, index_name] ...\n\nA table reference is also known as a join expression.\n\nThe syntax of table_factor is extended in comparison with the SQL\nStandard. The latter accepts only table_reference, not a list of them\ninside a pair of parentheses.\n\nThis is a conservative extension if we consider each comma in a list of\ntable_reference items as equivalent to an inner join. For example:\n\nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nis equivalent to:\n\nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nIn MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents\n(they can replace each other). In standard SQL, they are not\nequivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used\notherwise.\n\nIn general, parentheses can be ignored in join expressions containing\nonly inner join operations.\n\nIndex hints can be specified to affect how the MySQL optimizer makes\nuse of indexes. For more information, see\nhttps://mariadb.com/kb/en/how-to-force-query-plans/.\n\nURL: https://mariadb.com/kb/en/join-syntax/\n\n','SELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id\n WHERE right_tbl.id IS NULL;\n','https://mariadb.com/kb/en/join-syntax/'),(2,'HEX',37,'Syntax:\nHEX(str), HEX(N)\n\nFor a string argument str, HEX() returns a hexadecimal string\nrepresentation of str where each character in str is converted to two\nhexadecimal digits. The inverse of this operation is performed by the\nUNHEX() function.\n\nFor a numeric argument N, HEX() returns a hexadecimal string\nrepresentation of the value of N treated as a longlong (BIGINT) number.\nThis is equivalent to CONV(N,10,16). The inverse of this operation is\nperformed by CONV(HEX(N),16,10).\n\nURL: https://mariadb.com/kb/en/hex/\n\n','MariaDB> SELECT 0x616263, HEX(\'abc\'), UNHEX(HEX(\'abc\'));\n -> \'abc\', 616263, \'abc\'\nMariaDB> SELECT HEX(255), CONV(HEX(255),16,10);\n -> \'FF\', 255\n','https://mariadb.com/kb/en/hex/'),(3,'REPLACE',27,'Syntax:\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n\nREPLACE works exactly like INSERT, except that if an old row in the\ntable has the same value as a new row for a PRIMARY KEY or a UNIQUE\nindex, the old row is deleted before the new row is inserted. See [HELP\nINSERT].\n\nREPLACE is a MySQL extension to the SQL standard. It either inserts, or\ndeletes and inserts. For another MySQL extension to standard SQL---that\neither inserts or updates---see\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nNote that unless the table has a PRIMARY KEY or UNIQUE index, using a\nREPLACE statement makes no sense. It becomes equivalent to INSERT,\nbecause there is no index to be used to determine whether a new row\nduplicates another.\n\nValues for all columns are taken from the values specified in the\nREPLACE statement. Any missing columns are set to their default values,\njust as happens for INSERT. You cannot refer to values from the current\nrow and use them in the new row. If you use an assignment such as SET\ncol_name = col_name + 1, the reference to the column name on the right\nhand side is treated as DEFAULT(col_name), so the assignment is\nequivalent to SET col_name = DEFAULT(col_name) + 1.\n\nTo use REPLACE, you must have both the INSERT and DELETE privileges for\nthe table.\n\nURL: https://mariadb.com/kb/en/replace/\n\n','','https://mariadb.com/kb/en/replace/'),(4,'CONTAINS',30,'Contains(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 completely contains g2. This\ntests the opposite relationship as Within().\n\nURL: https://mariadb.com/kb/en/contains/\n\n','','https://mariadb.com/kb/en/contains/'),(5,'SRID',36,'SRID(g)\n\nReturns an integer indicating the Spatial Reference System ID for the\ngeometry value g.\n\nIn MySQL, the SRID value is just an integer associated with the\ngeometry value. All calculations are done assuming Euclidean (planar)\ngeometry.\n\nURL: https://mariadb.com/kb/en/srid/\n\n','MariaDB> SELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n','https://mariadb.com/kb/en/srid/'),(6,'CURRENT_TIMESTAMP',31,'Syntax:\nCURRENT_TIMESTAMP, CURRENT_TIMESTAMP()\n\nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/current_timestamp/\n\n','','https://mariadb.com/kb/en/current_timestamp/'),(7,'SHOW CONTRIBUTORS',26,'Syntax:\nSHOW CONTRIBUTORS\n\nThe SHOW CONTRIBUTORS statement displays information about the people\nwho contribute to MySQL source or to causes that we support. For each\ncontributor, it displays Name, Location, and Comment values.\n\nURL: https://mariadb.com/kb/en/show-contributors/\n\n','','https://mariadb.com/kb/en/show-contributors/'),(8,'VARIANCE',16,'Syntax:\nVARIANCE(expr)\n\nReturns the population standard variance of expr. This is an extension\nto standard SQL. The standard SQL function VAR_POP() can be used\ninstead.\n\nVARIANCE() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/variance/\n\n','','https://mariadb.com/kb/en/variance/'),(9,'DROP SERVER',39,'Syntax:\nDROP SERVER [ IF EXISTS ] server_name\n\nDrops the server definition for the server named server_name. The\ncorresponding row within the mysql.servers table will be deleted. This\nstatement requires the SUPER privilege.\n\nDropping a server for a table does not affect any FEDERATED tables that\nused this connection information when they were created. See [HELP\nCREATE SERVER].\n\nURL: https://mariadb.com/kb/en/drop-server/\n\n','','https://mariadb.com/kb/en/drop-server/'),(10,'SHOW AUTHORS',26,'Syntax:\nSHOW AUTHORS\n\nThe SHOW AUTHORS statement displays information about the people who\nwork on MySQL. For each author, it displays Name, Location, and Comment\nvalues.\n\nURL: https://mariadb.com/kb/en/show-authors/\n\n','','https://mariadb.com/kb/en/show-authors/'),(11,'VAR_SAMP',16,'Syntax:\nVAR_SAMP(expr)\n\nReturns the sample variance of expr. That is, the denominator is the\nnumber of rows minus one.\n\nVAR_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_samp/\n\n','','https://mariadb.com/kb/en/var_samp/'),(12,'CONCAT',37,'Syntax:\nCONCAT(str1,str2,...)\n\nReturns the string that results from concatenating the arguments. May\nhave one or more arguments. If all arguments are nonbinary strings, the\nresult is a nonbinary string. If the arguments include any binary\nstrings, the result is a binary string. A numeric argument is converted\nto its equivalent string form. This is a nonbinary string as of MySQL\n5.5.3. Before 5.5.3, it is a binary string; to to avoid that and\nproduce a nonbinary string, you can use an explicit type cast, as in\nthis example:\n\nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n\nCONCAT() returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/concat/\n\n','MariaDB> SELECT CONCAT(\'My\', \'S\', \'QL\');\n -> \'MySQL\'\nMariaDB> SELECT CONCAT(\'My\', NULL, \'QL\');\n -> NULL\nMariaDB> SELECT CONCAT(14.3);\n -> \'14.3\'\n','https://mariadb.com/kb/en/concat/'),(13,'GEOMETRY HIERARCHY',34,'Geometry is the base class. It is an abstract class. The instantiable\nsubclasses of Geometry are restricted to zero-, one-, and\ntwo-dimensional geometric objects that exist in two-dimensional\ncoordinate space. All instantiable geometry classes are defined so that\nvalid instances of a geometry class are topologically closed (that is,\nall defined geometries include their boundary).\n\nThe base Geometry class has subclasses for Point, Curve, Surface, and\nGeometryCollection:\n\no Point represents zero-dimensional objects.\n\no Curve represents one-dimensional objects, and has subclass\n LineString, with sub-subclasses Line and LinearRing.\n\no Surface is designed for two-dimensional objects and has subclass\n Polygon.\n\no GeometryCollection has specialized zero-, one-, and two-dimensional\n collection classes named MultiPoint, MultiLineString, and\n MultiPolygon for modeling geometries corresponding to collections of\n Points, LineStrings, and Polygons, respectively. MultiCurve and\n MultiSurface are introduced as abstract superclasses that generalize\n the collection interfaces to handle Curves and Surfaces.\n\nGeometry, Curve, Surface, MultiCurve, and MultiSurface are defined as\nnoninstantiable classes. They define a common set of methods for their\nsubclasses and are included for extensibility.\n\nPoint, LineString, Polygon, GeometryCollection, MultiPoint,\nMultiLineString, and MultiPolygon are instantiable classes.\n\nURL: https://mariadb.com/kb/en/geometry-hierarchy/\n\n','','https://mariadb.com/kb/en/geometry-hierarchy/'),(14,'CHAR FUNCTION',37,'Syntax:\nCHAR(N,... [USING charset_name])\n\nCHAR() interprets each argument N as an integer and returns a string\nconsisting of the characters given by the code values of those\nintegers. NULL values are skipped.\nBy default, CHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n\nMariaDB> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n\nIf USING is given and the result string is illegal for the given\ncharacter set, a warning is issued. Also, if strict SQL mode is\nenabled, the result from CHAR() becomes NULL.\n\nURL: https://mariadb.com/kb/en/char-function/\n\n','MariaDB> SELECT CHAR(77,121,83,81,\'76\');\n -> \'MySQL\'\nMariaDB> SELECT CHAR(77,77.3,\'77.3\');\n -> \'MMM\'\n','https://mariadb.com/kb/en/char-function/'),(15,'DATETIME',22,'DATETIME\n\nA date and time combination. The supported range is \'1000-01-01\n00:00:00\' to \'9999-12-31 23:59:59\'. MySQL displays DATETIME values in\n\'YYYY-MM-DD HH:MM:SS\' format, but permits assignment of values to\nDATETIME columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/datetime/\n\n','','https://mariadb.com/kb/en/datetime/'),(16,'SHOW CREATE TRIGGER',26,'Syntax:\nSHOW CREATE TRIGGER trigger_name\n\nThis statement shows a CREATE TRIGGER statement that creates the given\ntrigger.\n\nURL: https://mariadb.com/kb/en/show-create-trigger/\n\n','','https://mariadb.com/kb/en/show-create-trigger/'),(17,'SHOW CREATE PROCEDURE',26,'Syntax:\nSHOW CREATE PROCEDURE proc_name\n\nThis statement is a MySQL extension. It returns the exact string that\ncan be used to re-create the named stored procedure. A similar\nstatement, SHOW CREATE FUNCTION, displays information about stored\nfunctions (see [HELP SHOW CREATE FUNCTION]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table. If you do not have privileges\nfor the routine itself, the value displayed for the Create Procedure or\nCreate Function field will be NULL.\n\nURL: https://mariadb.com/kb/en/show-create-procedure/\n\n','MariaDB> SHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row ***************************\n Procedure: simpleproc\n sql_mode:\n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nMariaDB> SHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row ***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-procedure/'),(18,'OPEN',23,'Syntax:\nOPEN cursor_name\n\nThis statement opens a previously declared cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/open/\n\n','','https://mariadb.com/kb/en/open/'),(19,'INTEGER',22,'INTEGER[(M)] [UNSIGNED] [ZEROFILL]\n\nThis type is a synonym for INT.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-int\n\n','','https://mariadb.com/kb/en/sql_language-data_types-int'),(20,'LOWER',37,'Syntax:\nLOWER(str)\n\nReturns the string str with all characters changed to lowercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT LOWER(\'QUADRATICALLY\');\n -> \'quadratically\'\n\nLOWER() (and UPPER()) are ineffective when applied to binary strings\n(BINARY, VARBINARY, BLOB). To perform lettercase conversion, convert\nthe string to a nonbinary string:\n\nMariaDB> SET @str = BINARY \'New York\';\nMariaDB> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+-------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+-------------+-----------------------------------+\n| New York | new york |\n+-------------+-----------------------------------+\n\nURL: https://mariadb.com/kb/en/lower/\n\n','','https://mariadb.com/kb/en/lower/'),(21,'SHOW COLUMNS',26,'Syntax:\nSHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW COLUMNS displays information about the columns in a given table.\nIt also works for views. The LIKE clause, if present, indicates which\ncolumn names to match. The WHERE clause can be given to select rows\nusing more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nSHOW COLUMNS displays information only for those columns for which you\nhave some privilege.\n\nMariaDB> SHOW COLUMNS FROM City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nIf the data types differ from what you expect them to be based on a\nCREATE TABLE statement, note that MySQL sometimes changes data types\nwhen you create or alter a table. The conditions under which this\noccurs are described in\nhttps://mariadb.com/kb/en/silent-column-changes/.\n\nThe FULL keyword causes the output to include the column collation and\ncomments, as well as the privileges you have for each column.\n\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. In other words, these two statements are equivalent:\n\nMariaDB> SHOW COLUMNS FROM mytable FROM mydb;\nMariaDB> SHOW COLUMNS FROM mydb.mytable;\n\nSHOW COLUMNS displays the following values for each table column:\n\nField indicates the column name.\n\nType indicates the column data type.\n\nCollation indicates the collation for nonbinary string columns, or NULL\nfor other columns. This value is displayed only if you use the FULL\nkeyword.\n\nThe Null field contains YES if NULL values can be stored in the column,\nNO if not.\n\nThe Key field indicates whether the column is indexed:\n\no If Key is empty, the column either is not indexed or is indexed only\n as a secondary column in a multiple-column, nonunique index.\n\no If Key is PRI, the column is a PRIMARY KEY or is one of the columns\n in a multiple-column PRIMARY KEY.\n\no If Key is UNI, the column is the first column of a UNIQUE index. (A\n UNIQUE index permits multiple NULL values, but you can tell whether\n the column permits NULL by checking the Null field.)\n\no If Key is MUL, the column is the first column of a nonunique index in\n which multiple occurrences of a given value are permitted within the\n column.\n\nIf more than one of the Key values applies to a given column of a\ntable, Key displays the one with the highest priority, in the order\nPRI, UNI, MUL.\n\nA UNIQUE index may be displayed as PRI if it cannot contain NULL values\nand there is no PRIMARY KEY in the table. A UNIQUE index may display as\nMUL if several columns form a composite UNIQUE index; although the\ncombination of the columns is unique, each column can still hold\nmultiple occurrences of a given value.\n\nThe Default field indicates the default value that is assigned to the\ncolumn. This is NULL if the column has an explicit default of NULL, or\nif the column definition has no DEFAULT clause.\n\nThe Extra field contains any additional information that is available\nabout a given column. The value is nonempty in these cases:\nauto_increment for columns that have the AUTO_INCREMENT attribute; on\nupdate CURRENT_TIMESTAMP for TIMESTAMP columns that have the ON UPDATE\nCURRENT_TIMESTAMP attribute.\n\nPrivileges indicates the privileges you have for the column. This value\nis displayed only if you use the FULL keyword.\n\nComment indicates any comment the column has. This value is displayed\nonly if you use the FULL keyword.\n\nSHOW FIELDS is a synonym for SHOW COLUMNS. You can also list a table\'s\ncolumns with the mysqlshow db_name tbl_name command.\n\nThe DESCRIBE statement provides information similar to SHOW COLUMNS.\nSee [HELP DESCRIBE].\n\nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX statements\nalso provide information about tables. See [HELP SHOW].\n\nURL: https://mariadb.com/kb/en/show-columns/\n\n','','https://mariadb.com/kb/en/show-columns/'),(22,'CREATE TRIGGER',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name trigger_time trigger_event\n ON tbl_name FOR EACH ROW trigger_body\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section. If\nbinary logging is enabled, CREATE TRIGGER might require the SUPER\nprivilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time. See later in\nthis section for more information.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\ntrigger_event indicates the kind of statement that activates the\ntrigger. The trigger_event can be one of the following:\n\no INSERT: The trigger is activated whenever a new row is inserted into\n the table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger is activated whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger is activated whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. However,\n DROP TABLE and TRUNCATE TABLE statements on the table do not activate\n this trigger, because they do not use DELETE. Dropping a partition\n does not activate DELETE triggers, either. See [HELP TRUNCATE TABLE].\n\nURL: https://mariadb.com/kb/en/create-trigger/\n\n','','https://mariadb.com/kb/en/create-trigger/'),(23,'MONTH',31,'Syntax:\nMONTH(date)\n\nReturns the month for date, in the range 1 to 12 for January to\nDecember, or 0 for dates such as \'0000-00-00\' or \'2008-00-00\' that have\na zero month part.\n\nURL: https://mariadb.com/kb/en/month/\n\n','MariaDB> SELECT MONTH(\'2008-02-03\');\n -> 2\n','https://mariadb.com/kb/en/month/'),(24,'TINYINT',22,'TINYINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA very small integer. The signed range is -128 to 127. The unsigned\nrange is 0 to 255.\n\nURL: https://mariadb.com/kb/en/tinyint/\n\n','','https://mariadb.com/kb/en/tinyint/'),(25,'SHOW TRIGGERS',26,'Syntax:\nSHOW TRIGGERS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TRIGGERS lists the triggers currently defined for tables in a\ndatabase (the default database unless a FROM clause is given). This\nstatement returns results only for databases and tables for which you\nhave the TRIGGER privilege. The LIKE clause, if present, indicates\nwhich table names to match and causes the statement to display triggers\nfor those tables. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nFor the trigger ins_sum as defined in\nhttps://mariadb.com/kb/en/triggers/, the output of\nthis statement is as shown here:\n\nMariaDB> SHOW TRIGGERS LIKE \'acc%\'\\G\n*************************** 1. row ***************************\n Trigger: ins_sum\n Event: INSERT\n Table: account\n Statement: SET @sum = @sum + NEW.amount\n Timing: BEFORE\n Created: NULL\n sql_mode:\n Definer: myname@localhost\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\ncharacter_set_client is the session value of the character_set_client\nsystem variable when the trigger was created. collation_connection is\nthe session value of the collation_connection system variable when the\ntrigger was created. Database Collation is the collation of the\ndatabase with which the trigger is associated.\n\nURL: https://mariadb.com/kb/en/show-triggers/\n\n','','https://mariadb.com/kb/en/show-triggers/'),(26,'MASTER_POS_WAIT',14,'Syntax:\nMASTER_POS_WAIT(log_name,log_pos[,timeout])\n\nThis function is useful for control of master/slave synchronization. It\nblocks until the slave has read and applied all updates up to the\nspecified position in the master log. The return value is the number of\nlog events the slave had to wait for to advance to the specified\nposition. The function returns NULL if the slave SQL thread is not\nstarted, the slave\'s master information is not initialized, the\narguments are incorrect, or an error occurs. It returns -1 if the\ntimeout has been exceeded. If the slave SQL thread stops while\nMASTER_POS_WAIT() is waiting, the function returns NULL. If the slave\nis past the specified position, the function returns immediately.\n\nIf a timeout value is specified, MASTER_POS_WAIT() stops waiting when\ntimeout seconds have elapsed. timeout must be greater than 0; a zero or\nnegative timeout means no timeout.\n\nURL: https://mariadb.com/kb/en/master_pos_wait/\n\n','','https://mariadb.com/kb/en/master_pos_wait/'),(27,'REGEXP',37,'Syntax:\nexpr REGEXP pat, expr RLIKE pat\n\nPerforms a pattern match of a string expression expr against a pattern\npat. The pattern can be an extended regular expression. The syntax for\nregular expressions is discussed in\nhttps://mariadb.com/kb/en/regexp/. Returns 1 if expr\nmatches pat; otherwise it returns 0. If either expr or pat is NULL, the\nresult is NULL. RLIKE is a synonym for REGEXP, provided for mSQL\ncompatibility.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\n*Note*: Because MySQL uses the C escape syntax in strings (for example,\n\"\\n\" to represent the newline character), you must double any \"\\\" that\nyou use in your REGEXP strings.\n\nREGEXP is not case sensitive, except when used with binary strings.\n\nURL: https://mariadb.com/kb/en/regexp/\n\n','MariaDB> SELECT \'Monty!\' REGEXP \'.*\';\n -> 1\nMariaDB> SELECT \'new*\\n*line\' REGEXP \'new\\\\*.\\\\*line\';\n -> 1\nMariaDB> SELECT \'a\' REGEXP \'A\', \'a\' REGEXP BINARY \'A\';\n -> 1 0\nMariaDB> SELECT \'a\' REGEXP \'^[a-d]\';\n -> 1\n','https://mariadb.com/kb/en/regexp/'),(28,'IF STATEMENT',23,'Syntax:\nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF\n\nThe IF statement for stored programs implements a basic conditional\nconstruct.\n\n*Note*: There is also an IF() function, which differs from the IF\nstatement described here. See\nhttps://mariadb.com/kb/en/if-function/. The\nIF statement can have THEN, ELSE, and ELSEIF clauses, and it is\nterminated with END IF.\n\nIf the search_condition evaluates to true, the corresponding THEN or\nELSEIF clause statement_list executes. If no search_condition matches,\nthe ELSE clause statement_list executes.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nURL: https://mariadb.com/kb/en/if-statement/\n\n','','https://mariadb.com/kb/en/if-statement/'),(29,'^',19,'Syntax:\n^\n\nBitwise XOR:\n\nURL: https://mariadb.com/kb/en/bitwise-xor/\n\n','MariaDB> SELECT 1 ^ 1;\n -> 0\nMariaDB> SELECT 1 ^ 0;\n -> 1\nMariaDB> SELECT 11 ^ 3;\n -> 8\n','https://mariadb.com/kb/en/bitwise-xor/'),(30,'DROP VIEW',39,'Syntax:\nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n\nDROP VIEW removes one or more views. You must have the DROP privilege\nfor each view. If any of the views named in the argument list do not\nexist, MySQL returns an error indicating by name which nonexisting\nviews it was unable to drop, but it also drops all of the views in the\nlist that do exist.\n\nThe IF EXISTS clause prevents an error from occurring for views that\ndon\'t exist. When this clause is given, a NOTE is generated for each\nnonexistent view. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE, if given, are parsed and ignored.\n\nURL: https://mariadb.com/kb/en/drop-view/\n\n','','https://mariadb.com/kb/en/drop-view/'),(31,'WITHIN',30,'Within(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially within g2. This\ntests the opposite relationship as Contains().\n\nURL: https://mariadb.com/kb/en/within/\n\n','','https://mariadb.com/kb/en/within/'),(32,'WEEK',31,'Syntax:\nWEEK(date[,mode])\n\nThis function returns the week number for date. The two-argument form\nof WEEK() enables you to specify whether the week starts on Sunday or\nMonday and whether the return value should be in the range from 0 to 53\nor from 1 to 53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/week/\n\n','MariaDB> SELECT WEEK(\'2008-02-20\');\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',0);\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',1);\n -> 8\nMariaDB> SELECT WEEK(\'2008-12-31\',1);\n -> 53\n','https://mariadb.com/kb/en/week/'),(33,'SHOW PLUGINS',26,'Syntax:\nSHOW PLUGINS\n\nSHOW PLUGINS displays information about server plugins. Plugin\ninformation is also available in the INFORMATION_SCHEMA.PLUGINS table.\nSee https://mariadb.com/kb/en/information_schemaplugins-table/.\n\nExample of SHOW PLUGINS output:\n\nMariaDB> SHOW PLUGINS\\G\n*************************** 1. row ***************************\n Name: binlog\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 2. row ***************************\n Name: CSV\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 3. row ***************************\n Name: MEMORY\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 4. row ***************************\n Name: MyISAM\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n...\n\nURL: https://mariadb.com/kb/en/show-plugins/\n\n','','https://mariadb.com/kb/en/show-plugins/'),(34,'DROP FUNCTION UDF',21,'Syntax:\nDROP FUNCTION function_name\n\nThis statement drops the user-defined function (UDF) named\nfunction_name.\n\nTo drop a function, you must have the DELETE privilege for the mysql\ndatabase. This is because DROP FUNCTION removes a row from the\nmysql.func system table that records the function\'s name, type, and\nshared library name.\n\nURL: https://mariadb.com/kb/en/drop-function-udf/\n\n','','https://mariadb.com/kb/en/drop-function-udf/'),(35,'PREPARE',8,'Syntax:\nPREPARE stmt_name FROM preparable_stmt\n\nThe PREPARE statement prepares a statement and assigns it a name,\nstmt_name, by which to refer to the statement later. Statement names\nare not case sensitive. preparable_stmt is either a string literal or a\nuser variable that contains the text of the statement. The text must\nrepresent a single SQL statement, not multiple statements. Within the\nstatement, \"?\" characters can be used as parameter markers to indicate\nwhere data values are to be bound to the query later when you execute\nit. The \"?\" characters should not be enclosed within quotation marks,\neven if you intend to bind them to string values. Parameter markers can\nbe used only where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n\nIf a prepared statement with the given name already exists, it is\ndeallocated implicitly before the new statement is prepared. This means\nthat if the new statement contains an error and cannot be prepared, an\nerror is returned and no statement with the given name exists.\n\nA prepared statement is executed with EXECUTE and released with\nDEALLOCATE PREPARE.\n\nThe scope of a prepared statement is the session within which it is\ncreated. Other sessions cannot see it.\n\nURL: https://mariadb.com/kb/en/prepare-statement/\n\n','','https://mariadb.com/kb/en/prepare-statement/'),(36,'LOCK',8,'Syntax:\nLOCK TABLES\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n\nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n\nUNLOCK TABLES\n\nMySQL enables client sessions to acquire table locks explicitly for the\npurpose of cooperating with other sessions for access to tables, or to\nprevent other sessions from modifying tables during periods when a\nsession requires exclusive access to them. A session can acquire or\nrelease locks only for itself. One session cannot acquire locks for\nanother session or release locks held by another session.\n\nLocks may be used to emulate transactions or to get more speed when\nupdating tables. This is explained in more detail later in this\nsection.\n\nLOCK TABLES explicitly acquires table locks for the current client\nsession. Table locks can be acquired for base tables or views. You must\nhave the LOCK TABLES privilege, and the SELECT privilege for each\nobject to be locked.\n\nFor view locking, LOCK TABLES adds all base tables used in the view to\nthe set of tables to be locked and locks them automatically. If you\nlock a table explicitly with LOCK TABLES, any tables used in triggers\nare also locked implicitly, as described in\nhttps://mariadb.com/kb/en/triggers-and-implicit-locks/.\n\nUNLOCK TABLES explicitly releases any table locks held by the current\nsession. LOCK TABLES implicitly releases any table locks held by the\ncurrent session before acquiring new locks.\n\nAnother use for UNLOCK TABLES is to release the global read lock\nacquired with the FLUSH TABLES WITH READ LOCK statement, which enables\nyou to lock all tables in all databases. See [HELP FLUSH]. (This is a\nvery convenient way to get backups if you have a file system such as\nVeritas that can take snapshots in time.)\n\nURL: https://mariadb.com/kb/en/transactions-lock/\n\n','','https://mariadb.com/kb/en/transactions-lock/'),(37,'UPDATEXML',37,'Syntax:\nUpdateXML(xml_target, xpath_expr, new_xml)\n\nThis function replaces a single portion of a given fragment of XML\nmarkup xml_target with a new XML fragment new_xml, and then returns the\nchanged XML. The portion of xml_target that is replaced matches an\nXPath expression xpath_expr supplied by the user. In MySQL 5.5, the\nXPath expression can contain at most 127 characters. (This limitation\nis lifted in MySQL 5.6.)\n\nIf no expression matching xpath_expr is found, or if multiple matches\nare found, the function returns the original xml_target XML fragment.\nAll three arguments should be strings.\n\nURL: https://mariadb.com/kb/en/updatexml/\n\n','MariaDB> SELECT\n -> UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n -> UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n -> UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n -> \\G\n\n*************************** 1. row ***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n','https://mariadb.com/kb/en/updatexml/'),(38,'RESET SLAVE',8,'Syntax:\nRESET SLAVE [ALL]\n\nRESET SLAVE makes the slave forget its replication position in the\nmaster\'s binary log. This statement is meant to be used for a clean\nstart: It deletes the master.info and relay-log.info files, all the\nrelay log files, and starts a new relay log file. To use RESET SLAVE,\nthe slave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\n*Note*: All relay log files are deleted, even if they have not been\ncompletely executed by the slave SQL thread. (This is a condition\nlikely to exist on a replication slave if you have issued a STOP SLAVE\nstatement or if the slave is highly loaded.)\n\nIn MySQL 5.5 (unlike the case in MySQL 5.1 and earlier), RESET SLAVE\ndoes not change any replication connection parameters such as master\nhost, master port, master user, or master password, which are retained\nin memory. This means that START SLAVE can be issued without requiring\na CHANGE MASTER TO statement following RESET SLAVE.\n\nIn MySQL 5.5.16 and later, you can use RESET SLAVE ALL to reset these\nconnection parameters (Bug #11809016). Connection parameters are also\nreset if the slave mysqld is shut down.\n\nIf the slave SQL thread was in the middle of replicating temporary\ntables when it was stopped, and RESET SLAVE is issued, these replicated\ntemporary tables are deleted on the slave.\n\nURL: https://mariadb.com/kb/en/reset-slave-connection_name/\n\n','','https://mariadb.com/kb/en/reset-slave-connection_name/'),(39,'SHOW BINARY LOGS',26,'Syntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [HELP PURGE BINARY LOGS], that shows\nhow to determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/show-binary-logs/\n\n','','https://mariadb.com/kb/en/show-binary-logs/'),(40,'POLYGON',24,'Polygon(ls1,ls2,...)\n\nConstructs a Polygon value from a number of LineString or WKB\nLineString arguments. If any argument does not represent a LinearRing\n(that is, not a closed and simple LineString), the return value is\nNULL.\n\nURL: https://mariadb.com/kb/en/polygon/\n\n','','https://mariadb.com/kb/en/polygon/'),(41,'MINUTE',31,'Syntax:\nMINUTE(time)\n\nReturns the minute for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/minute/\n\n','MariaDB> SELECT MINUTE(\'2008-02-03 10:05:03\');\n -> 5\n','https://mariadb.com/kb/en/minute/'),(42,'DAY',31,'Syntax:\nDAY(date)\n\nDAY() is a synonym for DAYOFMONTH().\n\nURL: https://mariadb.com/kb/en/day/\n\n','','https://mariadb.com/kb/en/day/'),(43,'MID',37,'Syntax:\nMID(str,pos,len)\n\nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n\nURL: https://mariadb.com/kb/en/mid/\n\n','','https://mariadb.com/kb/en/mid/'),(44,'UUID',14,'Syntax:\nUUID()\n\nReturns a Universal Unique Identifier (UUID) generated according to\n\"DCE 1.1: Remote Procedure Call\" (Appendix A) CAE (Common Applications\nEnvironment) Specifications published by The Open Group in October 1997\n(Document Number C706,\nhttp://www.opengroup.org/public/pubs/catalog/c706.htm).\n\nA UUID is designed as a number that is globally unique in space and\ntime. Two calls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate computers\nthat are not connected to each other.\n\nA UUID is a 128-bit number represented by a utf8 string of five\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format:\n\no The first three numbers are generated from a timestamp.\n\no The fourth number preserves temporal uniqueness in case the timestamp\n value loses monotonicity (for example, due to daylight saving time).\n\no The fifth number is an IEEE 802 node number that provides spatial\n uniqueness. A random number is substituted if the latter is not\n available (for example, because the host computer has no Ethernet\n card, or we do not know how to find the hardware address of an\n interface on your operating system). In this case, spatial uniqueness\n cannot be guaranteed. Nevertheless, a collision should have very low\n probability.\n\n Currently, the MAC address of an interface is taken into account only\n on FreeBSD and Linux. On other operating systems, MySQL uses a\n randomly generated 48-bit number.\n\nURL: https://mariadb.com/kb/en/uuid/\n\n','MariaDB> SELECT UUID();\n -> \'6ccd780c-baba-1026-9564-0040f4311e29\'\n','https://mariadb.com/kb/en/uuid/'),(45,'LINESTRING',24,'LineString(pt1,pt2,...)\n\nConstructs a LineString value from a number of Point or WKB Point\narguments. If the number of arguments is less than two, the return\nvalue is NULL.\n\nURL: https://mariadb.com/kb/en/linestring/\n\n','','https://mariadb.com/kb/en/linestring/'),(46,'SLEEP',14,'Syntax:\nSLEEP(duration)\n\nSleeps (pauses) for the number of seconds given by the duration\nargument, then returns 0. If SLEEP() is interrupted, it returns 1. The\nduration may have a fractional part given in microseconds.\n\nURL: https://mariadb.com/kb/en/sleep/\n\n','','https://mariadb.com/kb/en/sleep/'),(47,'CONNECTION_ID',17,'Syntax:\nCONNECTION_ID()\n\nReturns the connection ID (thread ID) for the connection. Every\nconnection has an ID that is unique among the set of currently\nconnected clients.\n\nURL: https://mariadb.com/kb/en/connection_id/\n\n','MariaDB> SELECT CONNECTION_ID();\n -> 23786\n','https://mariadb.com/kb/en/connection_id/'),(48,'DELETE',27,'Syntax:\nSingle-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n\nOr:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n\nFor the single-table syntax, the DELETE statement deletes rows from\ntbl_name and returns a count of the number of deleted rows. This count\ncan be obtained by calling the ROW_COUNT() function (see\nhttps://mariadb.com/kb/en/information-functions-row_count/). The\nWHERE clause, if given, specifies the conditions that identify which\nrows to delete. With no WHERE clause, all rows are deleted. If the\nORDER BY clause is specified, the rows are deleted in the order that is\nspecified. The LIMIT clause places a limit on the number of rows that\ncan be deleted.\n\nFor the multiple-table syntax, DELETE deletes from each tbl_name the\nrows that satisfy the conditions. In this case, ORDER BY and LIMIT\ncannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe deleted. It is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nCurrently, you cannot delete from a table and select from the same\ntable in a subquery.\n\nYou need the DELETE privilege on a table to delete rows from it. You\nneed only the SELECT privilege for any columns that are only read, such\nas those named in the WHERE clause.\n\nAs stated, a DELETE statement with no WHERE clause deletes all rows. A\nfaster way to do this, when you do not need to know the number of\ndeleted rows, is to use TRUNCATE TABLE. However, within a transaction\nor if you have a lock on the table, TRUNCATE TABLE cannot be used\nwhereas DELETE can. See [HELP TRUNCATE TABLE], and [HELP LOCK].\n\nURL: https://mariadb.com/kb/en/delete/\n\n','','https://mariadb.com/kb/en/delete/'),(49,'ROUND',4,'Syntax:\nROUND(X), ROUND(X,D)\n\nRounds the argument X to D decimal places. The rounding algorithm\ndepends on the data type of X. D defaults to 0 if not specified. D can\nbe negative to cause D digits left of the decimal point of the value X\nto become zero.\n\nURL: https://mariadb.com/kb/en/round/\n\n','MariaDB> SELECT ROUND(-1.23);\n -> -1\nMariaDB> SELECT ROUND(-1.58);\n -> -2\nMariaDB> SELECT ROUND(1.58);\n -> 2\nMariaDB> SELECT ROUND(1.298, 1);\n -> 1.3\nMariaDB> SELECT ROUND(1.298, 0);\n -> 1\nMariaDB> SELECT ROUND(23.298, -1);\n -> 20\n','https://mariadb.com/kb/en/round/'),(50,'NULLIF',7,'Syntax:\nNULLIF(expr1,expr2)\n\nReturns NULL if expr1 = expr2 is true, otherwise returns expr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.\n\nURL: https://mariadb.com/kb/en/nullif/\n\n','MariaDB> SELECT NULLIF(1,1);\n -> NULL\nMariaDB> SELECT NULLIF(1,2);\n -> 1\n','https://mariadb.com/kb/en/nullif/'),(51,'CLOSE',23,'Syntax:\nCLOSE cursor_name\n\nThis statement closes a previously opened cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nAn error occurs if the cursor is not open.\n\nIf not closed explicitly, a cursor is closed at the end of the BEGIN\n... END block in which it was declared.\n\nURL: https://mariadb.com/kb/en/close/\n\n','','https://mariadb.com/kb/en/close/'),(52,'STOP SLAVE',8,'Syntax:\nSTOP SLAVE [thread_types]\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nStops the slave threads. STOP SLAVE requires the SUPER privilege.\nRecommended best practice is to execute STOP SLAVE on the slave before\nstopping the slave server (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-shutdown.html, for more\ninformation).\n\nWhen using the row-based logging format: You should execute STOP SLAVE\non the slave prior to shutting down the slave server if you are\nreplicating any tables that use a nontransactional storage engine (see\nthe Note later in this section). In MySQL 5.5.9 and later, you can also\nuse STOP SLAVE SQL_THREAD for this purpose.\n\nLike START SLAVE, this statement may be used with the IO_THREAD and\nSQL_THREAD options to name the thread or threads to be stopped.\n\n*Note*: In MySQL 5.5, STOP SLAVE waits until the current replication\nevent group affecting one or more non-transactional tables has finished\nexecuting (if there is any such replication group), or until the user\nissues a KILL QUERY or KILL CONNECTION statement. (Bug #319, Bug\n#38205)\n\nURL: https://mariadb.com/kb/en/stop-slave/\n\n','','https://mariadb.com/kb/en/stop-slave/'),(53,'TIMEDIFF',31,'Syntax:\nTIMEDIFF(expr1,expr2)\n\nTIMEDIFF() returns expr1 - expr2 expressed as a time value. expr1 and\nexpr2 are time or date-and-time expressions, but both must be of the\nsame type.\n\nThe result returned by TIMEDIFF() is limited to the range allowed for\nTIME values. Alternatively, you can use either of the functions\nTIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.\n\nURL: https://mariadb.com/kb/en/timediff/\n\n','MariaDB> SELECT TIMEDIFF(\'2000:01:01 00:00:00\',\n -> \'2000:01:01 00:00:00.000001\');\n -> \'-00:00:00.000001\'\nMariaDB> SELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\',\n -> \'2008-12-30 01:01:01.000002\');\n -> \'46:58:57.999999\'\n','https://mariadb.com/kb/en/timediff/'),(54,'REPLACE FUNCTION',37,'Syntax:\nREPLACE(str,from_str,to_str)\n\nReturns the string str with all occurrences of the string from_str\nreplaced by the string to_str. REPLACE() performs a case-sensitive\nmatch when searching for from_str.\n\nURL: https://mariadb.com/kb/en/replace-function/\n\n','MariaDB> SELECT REPLACE(\'www.mariadb.org\', \'w\', \'Ww\');\n -> \'WwWwWw.mariadb.org\'\n','https://mariadb.com/kb/en/replace-function/'),(55,'USE',28,'Syntax:\nUSE db_name\n\nThe USE db_name statement tells MySQL to use the db_name database as\nthe default (current) database for subsequent statements. The database\nremains the default until the end of the session or another USE\nstatement is issued:\n\nUSE db1;\nSELECT COUNT(*) FROM mytable; # selects from db1.mytable\nUSE db2;\nSELECT COUNT(*) FROM mytable; # selects from db2.mytable\n\nURL: https://mariadb.com/kb/en/use/\n\n','','https://mariadb.com/kb/en/use/'),(56,'LINEFROMTEXT',3,'LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])\n\nConstructs a LINESTRING value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromtext/\n\n','','https://mariadb.com/kb/en/linefromtext/'),(57,'CASE OPERATOR',7,'Syntax:\nCASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN\nresult ...] [ELSE result] END\n\nCASE WHEN [condition] THEN result [WHEN [condition] THEN result ...]\n[ELSE result] END\n\nThe first version returns the result where value=compare_value. The\nsecond version returns the result for the first condition that is true.\nIf there was no matching result value, the result after ELSE is\nreturned, or NULL if there is no ELSE part.\n\nURL: https://mariadb.com/kb/en/case-operator/\n\n','MariaDB> SELECT CASE 1 WHEN 1 THEN \'one\'\n -> WHEN 2 THEN \'two\' ELSE \'more\' END;\n -> \'one\'\nMariaDB> SELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n -> \'true\'\nMariaDB> SELECT CASE BINARY \'B\'\n -> WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END;\n -> NULL\n','https://mariadb.com/kb/en/case-operator/'),(58,'SHOW MASTER STATUS',26,'Syntax:\nSHOW MASTER STATUS\n\nThis statement provides status information about the binary log files\nof the master. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nExample:\n\nMariaDB> SHOW MASTER STATUS;\n+---------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+---------------+----------+--------------+------------------+\n| mysql-bin.003 | 73 | test | manual,mysql |\n+---------------+----------+--------------+------------------+\n\nURL: https://mariadb.com/kb/en/show-master-status/\n\n','','https://mariadb.com/kb/en/show-master-status/'),(59,'ADDTIME',31,'Syntax:\nADDTIME(expr1,expr2)\n\nADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time\nor datetime expression, and expr2 is a time expression.\n\nURL: https://mariadb.com/kb/en/addtime/\n\n','MariaDB> SELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1 1:1:1.000002\');\n -> \'2008-01-02 01:01:01.000001\'\nMariaDB> SELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'03:00:01.999997\'\n','https://mariadb.com/kb/en/addtime/'),(60,'SPATIAL',34,'For MyISAM tables, MySQL can create spatial indexes using syntax\nsimilar to that for creating regular indexes, but extended with the\nSPATIAL keyword. Currently, columns in spatial indexes must be declared\nNOT NULL. The following examples demonstrate how to create spatial\nindexes:\n\no With CREATE TABLE:\n\nCREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;\n\no With ALTER TABLE:\n\nALTER TABLE geom ADD SPATIAL INDEX(g);\n\no With CREATE INDEX:\n\nCREATE SPATIAL INDEX sp_index ON geom (g);\n\nFor MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage\nengines that support nonspatial indexing of spatial columns, the engine\ncreates a B-tree index. A B-tree index on spatial values will be useful\nfor exact-value lookups, but not for range scans.\n\nFor more information on indexing spatial columns, see [HELP CREATE\nINDEX].\n\nTo drop spatial indexes, use ALTER TABLE or DROP INDEX:\n\no With ALTER TABLE:\n\nALTER TABLE geom DROP INDEX g;\n\no With DROP INDEX:\n\nDROP INDEX sp_index ON geom;\n\nExample: Suppose that a table geom contains more than 32,000\ngeometries, which are stored in the column g of type GEOMETRY. The\ntable also has an AUTO_INCREMENT column fid for storing object ID\nvalues.\n\nURL: https://mariadb.com/kb/en/spatial/\n\n','','https://mariadb.com/kb/en/spatial/'),(61,'TO_SECONDS',31,'Syntax:\nTO_SECONDS(expr)\n\nGiven a date or datetime expr, returns a the number of seconds since\nthe year 0. If expr is not a valid date or datetime value, returns\nNULL.\n\nURL: https://mariadb.com/kb/en/to_seconds/\n\n','MariaDB> SELECT TO_SECONDS(950501);\n -> 62966505600\nMariaDB> SELECT TO_SECONDS(\'2009-11-29\');\n -> 63426672000\nMariaDB> SELECT TO_SECONDS(\'2009-11-29 13:43:32\');\n -> 63426721412\nMariaDB> SELECT TO_SECONDS( NOW() );\n -> 63426721458\n','https://mariadb.com/kb/en/to_seconds/'),(62,'TIMESTAMPDIFF',31,'Syntax:\nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n\nReturns datetime_expr2 - datetime_expr1, where datetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One expression may be\na date and the other a datetime; a date value is treated as a datetime\nhaving the time part \'00:00:00\' where necessary. The unit for the\nresult (an integer) is given by the unit argument. The legal values for\nunit are the same as those listed in the description of the\nTIMESTAMPADD() function.\n\nURL: https://mariadb.com/kb/en/timestampdiff/\n\n','MariaDB> SELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n -> 3\nMariaDB> SELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n -> -1\nMariaDB> SELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01 12:05:55\');\n -> 128885\n','https://mariadb.com/kb/en/timestampdiff/'),(63,'UPPER',37,'Syntax:\nUPPER(str)\n\nReturns the string str with all characters changed to uppercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT UPPER(\'Hej\');\n -> \'HEJ\'\n\nSee the description of LOWER() for information that also applies to\nUPPER(), such as information about how to perform lettercase conversion\nof binary strings (BINARY, VARBINARY, BLOB) for which these functions\nare ineffective.\n\nURL: https://mariadb.com/kb/en/upper/\n\n','','https://mariadb.com/kb/en/upper/'),(64,'FROM_UNIXTIME',31,'Syntax:\nFROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)\n\nReturns a representation of the unix_timestamp argument as a value in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the function is used in a string or numeric context. The value\nis expressed in the current time zone. unix_timestamp is an internal\ntimestamp value such as is produced by the UNIX_TIMESTAMP() function.\n\nIf format is given, the result is formatted according to the format\nstring, which is used the same way as listed in the entry for the\nDATE_FORMAT() function.\n\nURL: https://mariadb.com/kb/en/from_unixtime/\n\n','MariaDB> SELECT FROM_UNIXTIME(1196440219);\n -> \'2007-11-30 10:30:19\'\nMariaDB> SELECT FROM_UNIXTIME(1196440219) + 0;\n -> 20071130103019.000000\nMariaDB> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),\n -> \'%Y %D %M %h:%i:%s %x\');\n -> \'2007 30th November 10:30:59 2007\'\n','https://mariadb.com/kb/en/from_unixtime/'),(65,'MEDIUMBLOB',22,'MEDIUMBLOB\n\nA BLOB column with a maximum length of 16,777,215 (224 - 1) bytes. Each\nMEDIUMBLOB value is stored using a 3-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumblob/\n\n','','https://mariadb.com/kb/en/mediumblob/'),(66,'SHA2',12,'Syntax:\nSHA2(str, hash_length)\n\nCalculates the SHA-2 family of hash functions (SHA-224, SHA-256,\nSHA-384, and SHA-512). The first argument is the cleartext string to be\nhashed. The second argument indicates the desired bit length of the\nresult, which must have a value of 224, 256, 384, 512, or 0 (which is\nequivalent to 256). If either argument is NULL or the hash length is\nnot one of the permitted values, the return value is NULL. Otherwise,\nthe function result is a hash value containing the desired number of\nbits. See the notes at the beginning of this section about storing hash\nvalues efficiently.\n\nAs of MySQL 5.5.6, the return value is a nonbinary string in the\nconnection character set. Before 5.5.6, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha2/\n\n','MariaDB> SELECT SHA2(\'abc\', 224);\n -> \'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\'\n','https://mariadb.com/kb/en/sha2/'),(67,'IFNULL',7,'Syntax:\nIFNULL(expr1,expr2)\n\nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it returns\nexpr2. IFNULL() returns a numeric or string value, depending on the\ncontext in which it is used.\n\nURL: https://mariadb.com/kb/en/ifnull/\n\n','MariaDB> SELECT IFNULL(1,0);\n -> 1\nMariaDB> SELECT IFNULL(NULL,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,\'yes\');\n -> \'yes\'\n','https://mariadb.com/kb/en/ifnull/'),(68,'SHOW FUNCTION CODE',26,'Syntax:\nSHOW FUNCTION CODE func_name\n\nThis statement is similar to SHOW PROCEDURE CODE but for stored\nfunctions. See [HELP SHOW PROCEDURE CODE].\n\nURL: https://mariadb.com/kb/en/show-function-code/\n\n','','https://mariadb.com/kb/en/show-function-code/'),(69,'SHOW ERRORS',26,'Syntax:\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW COUNT(*) ERRORS\n\nThis statement is similar to SHOW WARNINGS, except that it displays\ninformation only for errors, rather than for errors, warnings, and\nnotes.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nThe SHOW COUNT(*) ERRORS statement displays the number of errors. You\ncan also retrieve this number from the error_count variable:\n\nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n\nSHOW ERRORS and error_count apply only to errors, not warnings or\nnotes. In other respects, they are similar to SHOW WARNINGS and\nwarning_count. In particular, SHOW ERRORS cannot display information\nfor more than max_error_count messages, and error_count can exceed the\nvalue of max_error_count if the number of errors exceeds\nmax_error_count.\n\nURL: https://mariadb.com/kb/en/show-errors/\n\n','','https://mariadb.com/kb/en/show-errors/'),(70,'LEAST',18,'Syntax:\nLEAST(value1,value2,...)\n\nWith two or more arguments, returns the smallest (minimum-valued)\nargument. The arguments are compared using the following rules:\n\no If any argument is NULL, the result is NULL. No comparison is needed.\n\no If the return value is used in an INTEGER context or all arguments\n are integer-valued, they are compared as integers.\n\no If the return value is used in a REAL context or all arguments are\n real-valued, they are compared as reals.\n\no If the arguments comprise a mix of numbers and strings, they are\n compared as numbers.\n\no If any argument is a nonbinary (character) string, the arguments are\n compared as nonbinary strings.\n\no In all other cases, the arguments are compared as binary strings.\n\nURL: https://mariadb.com/kb/en/least/\n\n','MariaDB> SELECT LEAST(2,0);\n -> 0\nMariaDB> SELECT LEAST(34.0,3.0,5.0,767.0);\n -> 3.0\nMariaDB> SELECT LEAST(\'B\',\'A\',\'C\');\n -> \'A\'\n','https://mariadb.com/kb/en/least/'),(71,'=',18,'=\n\nEqual:\n\nURL: https://mariadb.com/kb/en/equal/\n\n','MariaDB> SELECT 1 = 0;\n -> 0\nMariaDB> SELECT \'0\' = 0;\n -> 1\nMariaDB> SELECT \'0.0\' = 0;\n -> 1\nMariaDB> SELECT \'0.01\' = 0;\n -> 0\nMariaDB> SELECT \'.01\' = 0.01;\n -> 1\n','https://mariadb.com/kb/en/equal/'),(72,'REVERSE',37,'Syntax:\nREVERSE(str)\n\nReturns the string str with the order of the characters reversed.\n\nURL: https://mariadb.com/kb/en/reverse/\n\n','MariaDB> SELECT REVERSE(\'abc\');\n -> \'cba\'\n','https://mariadb.com/kb/en/reverse/'),(73,'ISNULL',18,'Syntax:\nISNULL(expr)\n\nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n\nURL: https://mariadb.com/kb/en/isnull/\n\n','MariaDB> SELECT ISNULL(1+1);\n -> 0\nMariaDB> SELECT ISNULL(1/0);\n -> 1\n','https://mariadb.com/kb/en/isnull/'),(74,'BINARY',22,'BINARY(M)\n\nThe BINARY type is similar to the CHAR type, but stores binary byte\nstrings rather than nonbinary character strings. M represents the\ncolumn length in bytes.\n\nURL: https://mariadb.com/kb/en/binary/\n\n','','https://mariadb.com/kb/en/binary/'),(75,'BLOB DATA TYPE',22,'A BLOB is a binary large object that can hold a variable amount of\ndata. The four BLOB types are TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB.\nThese differ only in the maximum length of the values they can hold.\nThe four TEXT types are TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. These\ncorrespond to the four BLOB types and have the same maximum lengths and\nstorage requirements. See\nhttps://mariadb.com/kb/en/data-type-storage-requirements/.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-blob/\n\n','','https://mariadb.com/kb/en/sql_language-data_types-blob/'),(76,'BOUNDARY',36,'Boundary(g)\n\nReturns a geometry that is the closure of the combinatorial boundary of\nthe geometry value g.\n\nURL: https://mariadb.com/kb/en/boundary/\n\n','','https://mariadb.com/kb/en/boundary/'),(77,'CREATE USER',10,'Syntax:\nCREATE USER user_specification\n [, user_specification] ...\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nThe CREATE USER statement creates new MySQL accounts. To use it, you\nmust have the global CREATE USER privilege or the INSERT privilege for\nthe mysql database. For each account, CREATE USER creates a new row in\nthe mysql.user table and assigns the account no privileges. An error\noccurs if the account already exists.\n\nEach account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nThe user specification may indicate how the user should authenticate\nwhen connecting to the server:\n\no To enable the user to connect with no password (which is insecure),\n include no IDENTIFIED BY clause:\n\nCREATE USER \'jeffrey\'@\'localhost\';\n\n In this case, the account uses built-in authentication and clients\n must provide no password.\n\no To assign a password, use IDENTIFIED BY with the literal plaintext\n password value:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To avoid specifying the plaintext password if you know its hash value\n (the value that PASSWORD() would return for the password), specify\n the hash value preceded by the keyword PASSWORD:\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED BY PASSWORD \'*90E462C37378CED12064BB3388827D2BA3A9B689\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To authenticate the account using a specific authentication plugin,\n use IDENTIFIED WITH, where auth_plugin is the plugin name. It can be\n an unquoted name or a quoted string literal. \'auth_string\' is an\n optional quoted string literal to pass to the plugin. The plugin\n interprets the meaning of the string, so its format is plugin\n specific. Consult the documentation for a given plugin for\n information about the authentication string values it accepts.\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED WITH my_auth_plugin;\n\n For connections that use this account, the server invokes the named\n plugin and clients must provide credentials as required for the\n authentication method that the plugin implements. If the server\n cannot find the plugin, either at account-creation time or connect\n time, an error occurs. IDENTIFIED WITH can be used as of MySQL 5.5.7.\n\nThe IDENTIFIED BY and IDENTIFIED WITH clauses are mutually exclusive,\nso at most one of them can be specified for a given user.\n\nFor additional information about setting passwords, see\nhttps://mariadb.com/kb/en/create-user/.\n\nURL: https://mariadb.com/kb/en/create-user/\n\n','','https://mariadb.com/kb/en/create-user/'),(78,'POINT',24,'Point(x,y)\n\nConstructs a Point using its coordinates.\n\nURL: https://mariadb.com/kb/en/point/\n\n','','https://mariadb.com/kb/en/point/'),(79,'CURRENT_USER',17,'Syntax:\nCURRENT_USER, CURRENT_USER()\n\nReturns the user name and host name combination for the MySQL account\nthat the server used to authenticate the current client. This account\ndetermines your access privileges. The return value is a string in the\nutf8 character set.\n\nThe value of CURRENT_USER() can differ from the value of USER().\n\nURL: https://mariadb.com/kb/en/current_user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\nMariaDB> SELECT * FROM mysql.user;\nERROR 1044: Access denied for user \'\'@\'localhost\' to\ndatabase \'mysql\'\nMariaDB> SELECT CURRENT_USER();\n -> \'@localhost\'\n','https://mariadb.com/kb/en/current_user/'),(80,'LCASE',37,'Syntax:\nLCASE(str)\n\nLCASE() is a synonym for LOWER().\n\nURL: https://mariadb.com/kb/en/lcase/\n\n','','https://mariadb.com/kb/en/lcase/'),(81,'<=',18,'Syntax:\n<=\n\nLess than or equal:\n\nURL: https://mariadb.com/kb/en/less-than-or-equal/\n\n','MariaDB> SELECT 0.1 <= 2;\n -> 1\n','https://mariadb.com/kb/en/less-than-or-equal/'),(82,'SHOW PROFILES',26,'Syntax:\nSHOW PROFILES\n\nThe SHOW PROFILES statement, together with SHOW PROFILE, displays\nprofiling information that indicates resource usage for statements\nexecuted during the course of the current session. For more\ninformation, see [HELP SHOW PROFILE].\n\nURL: https://mariadb.com/kb/en/show-profiles/\n\n','','https://mariadb.com/kb/en/show-profiles/'),(83,'UPDATE',27,'Syntax:\nSingle-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_reference\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n\nFor the single-table syntax, the UPDATE statement updates columns of\nexisting rows in the named table with new values. The SET clause\nindicates which columns to modify and the values they should be given.\nEach value can be given as an expression, or the keyword DEFAULT to set\na column explicitly to its default value. The WHERE clause, if given,\nspecifies the conditions that identify which rows to update. With no\nWHERE clause, all rows are updated. If the ORDER BY clause is\nspecified, the rows are updated in the order that is specified. The\nLIMIT clause places a limit on the number of rows that can be updated.\n\nFor the multiple-table syntax, UPDATE updates rows in each table named\nin table_references that satisfy the conditions. In this case, ORDER BY\nand LIMIT cannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe updated. For expression syntax, see\nhttp://dev.mysql.com/doc/refman/5.5/en/expressions.html.\n\ntable_references and where_condition are is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nYou need the UPDATE privilege only for columns referenced in an UPDATE\nthat are actually updated. You need only the SELECT privilege for any\ncolumns that are read but not modified.\n\nThe UPDATE statement supports the following modifiers:\n\no With the LOW_PRIORITY keyword, execution of the UPDATE is delayed\n until no other clients are reading from the table. This affects only\n storage engines that use only table-level locking (such as MyISAM,\n MEMORY, and MERGE).\n\no With the IGNORE keyword, the update statement does not abort even if\n errors occur during the update. Rows for which duplicate-key\n conflicts occur are not updated. Rows for which columns are updated\n to values that would cause data conversion errors are updated to the\n closest valid values instead.\n\nURL: https://mariadb.com/kb/en/update/\n\n','','https://mariadb.com/kb/en/update/'),(84,'IS NOT NULL',18,'Syntax:\nIS NOT NULL\n\nTests whether a value is not NULL.\n\nURL: https://mariadb.com/kb/en/is-not-null/\n\n','MariaDB> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not-null/'),(85,'CASE STATEMENT',23,'Syntax:\nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nOr:\n\nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nThe CASE statement for stored programs implements a complex conditional\nconstruct.\n\n*Note*: There is also a CASE expression, which differs from the CASE\nstatement described here. See\nhttps://mariadb.com/kb/en/case-operator/. The\nCASE statement cannot have an ELSE NULL clause, and it is terminated\nwith END CASE instead of END.\n\nFor the first syntax, case_value is an expression. This value is\ncompared to the when_value expression in each WHEN clause until one of\nthem is equal. When an equal when_value is found, the corresponding\nTHEN clause statement_list executes. If no when_value is equal, the\nELSE clause statement_list executes, if there is one.\n\nThis syntax cannot be used to test for equality with NULL because NULL\n= NULL is false. See\nhttps://mariadb.com/kb/en/null-values/.\n\nFor the second syntax, each WHEN clause search_condition expression is\nevaluated until one is true, at which point its corresponding THEN\nclause statement_list executes. If no search_condition is equal, the\nELSE clause statement_list executes, if there is one.\n\nIf no when_value or search_condition matches the value tested and the\nCASE statement contains no ELSE clause, a Case not found for CASE\nstatement error results.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nTo handle situations where no value is matched by any WHEN clause, use\nan ELSE containing an empty BEGIN ... END block, as shown in this\nexample. (The indentation used here in the ELSE clause is for purposes\nof clarity only, and is not otherwise significant.)\n\nDELIMITER |\n\nCREATE PROCEDURE p()\n BEGIN\n DECLARE v INT DEFAULT 1;\n\n CASE v\n WHEN 2 THEN SELECT v;\n WHEN 3 THEN SELECT 0;\n ELSE\n BEGIN\n END;\n END CASE;\n END;\n |\n\nURL: https://mariadb.com/kb/en/case-statement/\n\n','','https://mariadb.com/kb/en/case-statement/'),(86,'EXECUTE STATEMENT',8,'Syntax:\nEXECUTE stmt_name\n [USING @var_name [, @var_name] ...]\n\nAfter preparing a statement with PREPARE, you execute it with an\nEXECUTE statement that refers to the prepared statement name. If the\nprepared statement contains any parameter markers, you must supply a\nUSING clause that lists user variables containing the values to be\nbound to the parameters. Parameter values can be supplied only by user\nvariables, and the USING clause must name exactly as many variables as\nthe number of parameter markers in the statement.\n\nYou can execute a given prepared statement multiple times, passing\ndifferent variables to it or setting the variables to different values\nbefore each execution.\n\nURL: https://mariadb.com/kb/en/execute-statement/\n\n','','https://mariadb.com/kb/en/execute-statement/'),(87,'DROP INDEX',39,'Syntax:\nDROP [ONLINE|OFFLINE] INDEX index_name ON tbl_name\n\nDROP INDEX drops the index named index_name from the table tbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop the index.\nSee [HELP ALTER TABLE].\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: https://mariadb.com/kb/en/drop-index/\n\n','','https://mariadb.com/kb/en/drop-index/'),(88,'MATCH AGAINST',37,'Syntax:\nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n\nMySQL has support for full-text indexing and searching:\n\no A full-text index in MySQL is an index of type FULLTEXT.\n\no Full-text indexes can be used only with MyISAM tables, and can be\n created only for CHAR, VARCHAR, or TEXT columns.\n\no A FULLTEXT index definition can be given in the CREATE TABLE\n statement when a table is created, or added later using ALTER TABLE\n or CREATE INDEX.\n\no For large data sets, it is much faster to load your data into a table\n that has no FULLTEXT index and then create the index after that, than\n to load data into a table that has an existing FULLTEXT index.\n\nFull-text searching is performed using MATCH() ... AGAINST syntax.\nMATCH() takes a comma-separated list that names the columns to be\nsearched. AGAINST takes a string to search for, and an optional\nmodifier that indicates what type of search to perform. The search\nstring must be a literal string, not a variable or a column name. There\nare three types of full-text searches:\n\no A natural language search interprets the search string as a phrase in\n natural human language (a phrase in free text). There are no special\n operators. The stopword list applies. In addition, words that are\n present in 50% or more of the rows are considered common and do not\n match.\n\n Full-text searches are natural language searches if the IN NATURAL\n LANGUAGE MODE modifier is given or if no modifier is given. For more\n information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-natural-language-mode\n .\n\no A boolean search interprets the search string using the rules of a\n special query language. The string contains the words to search for.\n It can also contain operators that specify requirements such that a\n word must be present or absent in matching rows, or that it should be\n weighted higher or lower than usual. Common words such as \"some\" or\n \"then\" are stopwords and do not match if present in the search\n string. The IN BOOLEAN MODE modifier specifies a boolean search. For\n more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-boolean-mode.\n\no A query expansion search is a modification of a natural language\n search. The search string is used to perform a natural language\n search. Then words from the most relevant rows returned by the search\n are added to the search string and the search is done again. The\n query returns the rows from the second search. The IN NATURAL\n LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier\n specifies a query expansion search. For more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#with-query-expansion.\n\nURL: https://mariadb.com/kb/en/match-against/\n\n','MariaDB> SELECT id, body, MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE) AS score\n -> FROM articles WHERE MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |\n| 6 | When configured properly, MySQL ... | 1.3114095926285 |\n+----+-------------------------------------+-----------------+\n2 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/match-against/'),(89,'CREATE EVENT',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n EVENT\n [IF NOT EXISTS]\n event_name\n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO event_body;\n\nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval\n [STARTS timestamp [+ INTERVAL interval] ...]\n [ENDS timestamp [+ INTERVAL interval] ...]\n\ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n\nThis statement creates and schedules a new event. The event will not\nrun unless the Event Scheduler is enabled. For information about\nchecking Event Scheduler status and enabling it if necessary, see\nhttps://mariadb.com/kb/en/events/.\n\nCREATE EVENT requires the EVENT privilege for the schema in which the\nevent is to be created. It might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section.\n\nThe minimum requirements for a valid CREATE EVENT statement are as\nfollows:\n\no The keywords CREATE EVENT plus an event name, which uniquely\n identifies the event in a database schema.\n\no An ON SCHEDULE clause, which determines when and how often the event\n executes.\n\no A DO clause, which contains the SQL statement to be executed by an\n event.\n\nThis is an example of a minimal CREATE EVENT statement:\n\nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n\nThe previous statement creates an event named myevent. This event\nexecutes once---one hour following its creation---by running an SQL\nstatement that increments the value of the myschema.mytable table\'s\nmycol column by 1.\n\nThe event_name must be a valid MySQL identifier with a maximum length\nof 64 characters. Event names are not case sensitive, so you cannot\nhave two events named myevent and MyEvent in the same schema. In\ngeneral, the rules governing event names are the same as those for\nnames of stored routines. See\nhttps://mariadb.com/kb/en/identifier-names/.\n\nAn event is associated with a schema. If no schema is indicated as part\nof event_name, the default (current) schema is assumed. To create an\nevent in a specific schema, qualify the event name with a schema using\nschema_name.event_name syntax.\n\nURL: https://mariadb.com/kb/en/create-event/\n\n','','https://mariadb.com/kb/en/create-event/'),(90,'ABS',4,'Syntax:\nABS(X)\n\nReturns the absolute value of X.\n\nURL: https://mariadb.com/kb/en/abs/\n\n','MariaDB> SELECT ABS(2);\n -> 2\nMariaDB> SELECT ABS(-32);\n -> 32\n','https://mariadb.com/kb/en/abs/'),(91,'POLYFROMWKB',32,'PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])\n\nConstructs a POLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromwkb/\n\n','','https://mariadb.com/kb/en/polyfromwkb/'),(92,'NOT LIKE',37,'Syntax:\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n\nThis is the same as NOT (expr LIKE pat [ESCAPE \'escape_char\']).\n\nURL: https://mariadb.com/kb/en/not-like/\n\n','','https://mariadb.com/kb/en/not-like/'),(93,'SPACE',37,'Syntax:\nSPACE(N)\n\nReturns a string consisting of N space characters.\n\nURL: https://mariadb.com/kb/en/space/\n\n','MariaDB> SELECT SPACE(6);\n -> \' \'\n','https://mariadb.com/kb/en/space/'),(94,'MBR DEFINITION',6,'Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding\ngeometry, formed by the minimum and maximum (X,Y) coordinates:\n\nURL: https://mariadb.com/kb/en/mbr-definition/\n\n','((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n','https://mariadb.com/kb/en/mbr-definition/'),(95,'GEOMETRYCOLLECTION',24,'GeometryCollection(g1,g2,...)\n\nConstructs a GeometryCollection.\n\nURL: https://mariadb.com/kb/en/geometrycollection/\n\n','','https://mariadb.com/kb/en/geometrycollection/'),(96,'MAX',16,'Syntax:\nMAX([DISTINCT] expr)\n\nReturns the maximum value of expr. MAX() may take a string argument; in\nsuch cases, it returns the maximum string value. See\nhttps://mariadb.com/kb/en/max/. The DISTINCT\nkeyword can be used to find the maximum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMAX() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/max/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/max/'),(97,'CREATE FUNCTION UDF',21,'Syntax:\nCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n\nA user-defined function (UDF) is a way to extend MySQL with a new\nfunction that works like a native (built-in) MySQL function such as\nABS() or CONCAT().\n\nfunction_name is the name that should be used in SQL statements to\ninvoke the function. The RETURNS clause indicates the type of the\nfunction\'s return value. DECIMAL is a legal value after RETURNS, but\ncurrently DECIMAL functions return string values and should be written\nlike STRING functions.\n\nshared_library_name is the basename of the shared object file that\ncontains the code that implements the function. The file must be\nlocated in the plugin directory. This directory is given by the value\nof the plugin_dir system variable. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/udf-compiling.html.\n\nTo create a function, you must have the INSERT privilege for the mysql\ndatabase. This is necessary because CREATE FUNCTION adds a row to the\nmysql.func system table that records the function\'s name, type, and\nshared library name. If you do not have this table, you should run the\nmysql_upgrade command to create it. See\nhttps://mariadb.com/kb/en/mysql_upgrade/.\n\nURL: https://mariadb.com/kb/en/create-function-udf/\n\n','','https://mariadb.com/kb/en/create-function-udf/'),(98,'*',4,'Syntax:\n*\n\nMultiplication:\n\nURL: https://mariadb.com/kb/en/multiplication-operator/\n\n','MariaDB> SELECT 3*5;\n -> 15\nMariaDB> SELECT 18014398509481984*18014398509481984.0;\n -> 324518553658426726783156020576256.0\nMariaDB> SELECT 18014398509481984*18014398509481984;\n -> 0\n','https://mariadb.com/kb/en/multiplication-operator/'),(99,'TIMESTAMP',22,'TIMESTAMP\n\nA timestamp. The range is \'1970-01-01 00:00:01\' UTC to \'2038-01-19\n03:14:07\' UTC. TIMESTAMP values are stored as the number of seconds\nsince the epoch (\'1970-01-01 00:00:00\' UTC). A TIMESTAMP cannot\nrepresent the value \'1970-01-01 00:00:00\' because that is equivalent to\n0 seconds from the epoch and the value 0 is reserved for representing\n\'0000-00-00 00:00:00\', the \"zero\" TIMESTAMP value.\n\nUnless specified otherwise, the first TIMESTAMP column in a table is\ndefined to be automatically set to the date and time of the most recent\nmodification if not explicitly assigned a value. This makes TIMESTAMP\nuseful for recording the timestamp of an INSERT or UPDATE operation.\nYou can also set any TIMESTAMP column to the current date and time by\nassigning it a NULL value, unless it has been defined with the NULL\nattribute to permit NULL values. The automatic initialization and\nupdating to the current date and time can be specified using DEFAULT\nCURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, as described\nin\nhttps://mariadb.com/kb/en/timestamp/.\n\n*Note*: The TIMESTAMP format that was used prior to MySQL 4.1 is not\nsupported in MySQL 5.5; see MySQL 3.23, 4.0, 4.1 Reference Manual for\ninformation regarding the old format.\n\nURL: https://mariadb.com/kb/en/timestamp/\n\n','','https://mariadb.com/kb/en/timestamp/'),(100,'DES_DECRYPT',12,'Syntax:\nDES_DECRYPT(crypt_str[,key_str])\n\nDecrypts a string encrypted with DES_ENCRYPT(). If an error occurs,\nthis function returns NULL.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nIf no key_str argument is given, DES_DECRYPT() examines the first byte\nof the encrypted string to determine the DES key number that was used\nto encrypt the original string, and then reads the key from the DES key\nfile to decrypt the message. For this to work, the user must have the\nSUPER privilege. The key file can be specified with the --des-key-file\nserver option.\n\nIf you pass this function a key_str argument, that string is used as\nthe key for decrypting the message.\n\nIf the crypt_str argument does not appear to be an encrypted string,\nMySQL returns the given crypt_str.\n\nURL: https://mariadb.com/kb/en/des_decrypt/\n\n','','https://mariadb.com/kb/en/des_decrypt/'),(101,'CACHE INDEX',26,'Syntax:\nCACHE INDEX\n tbl_index_list [, tbl_index_list] ...\n [PARTITION (partition_list | ALL)]\n IN key_cache_name\n\ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe CACHE INDEX statement assigns table indexes to a specific key\ncache. It is used only for MyISAM tables. After the indexes have been\nassigned, they can be preloaded into the cache if desired with LOAD\nINDEX INTO CACHE.\n\nThe following statement assigns indexes from the tables t1, t2, and t3\nto the key cache named hot_cache:\n\nMariaDB> CACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n\nURL: https://mariadb.com/kb/en/cache-index/\n\n','','https://mariadb.com/kb/en/cache-index/'),(102,'ENDPOINT',13,'EndPoint(ls)\n\nReturns the Point that is the endpoint of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/endpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/endpoint/'),(103,'COMPRESS',12,'Syntax:\nCOMPRESS(string_to_compress)\n\nCompresses a string and returns the result as a binary string. This\nfunction requires MySQL to have been compiled with a compression\nlibrary such as zlib. Otherwise, the return value is always NULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n\nURL: https://mariadb.com/kb/en/compress/\n\n','MariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n -> 21\nMariaDB> SELECT LENGTH(COMPRESS(\'\'));\n -> 0\nMariaDB> SELECT LENGTH(COMPRESS(\'a\'));\n -> 13\nMariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n -> 15\n','https://mariadb.com/kb/en/compress/'),(104,'INSERT',27,'Syntax:\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nINSERT inserts new rows into an existing table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based on\nexplicitly specified values. The INSERT ... SELECT form inserts rows\nselected from another table or tables. INSERT ... SELECT is discussed\nfurther in [HELP INSERT SELECT].\n\nURL: https://mariadb.com/kb/en/insert/\n\n','','https://mariadb.com/kb/en/insert/'),(105,'COUNT',16,'Syntax:\nCOUNT(expr)\n\nReturns a count of the number of non-NULL values of expr in the rows\nretrieved by a SELECT statement. The result is a BIGINT value.\n\nCOUNT() returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count/\n\n','MariaDB> SELECT student.student_name,COUNT(*)\n -> FROM student,course\n -> WHERE student.student_id=course.student_id\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/count/'),(106,'HANDLER',27,'Syntax:\nHANDLER tbl_name OPEN [ [AS] alias]\n\nHANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ { FIRST | NEXT }\n [ WHERE where_condition ] [LIMIT ... ]\n\nHANDLER tbl_name CLOSE\n\nThe HANDLER statement provides direct access to table storage engine\ninterfaces. It is available for MyISAM and InnoDB tables.\n\nURL: https://mariadb.com/kb/en/handler-commands/\n\n','','https://mariadb.com/kb/en/handler-commands/'),(107,'MLINEFROMTEXT',3,'MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])\n\nConstructs a MULTILINESTRING value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromtext/\n\n','','https://mariadb.com/kb/en/mlinefromtext/'),(108,'GEOMCOLLFROMWKB',32,'GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkb[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromwkb/\n\n','','https://mariadb.com/kb/en/geomcollfromwkb/'),(109,'HELP_DATE',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25\n','',''),(110,'RENAME TABLE',39,'Syntax:\nRENAME TABLE tbl_name TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n\nThis statement renames one or more tables.\n\nThe rename operation is done atomically, which means that no other\nsession can access any of the tables while the rename is running. For\nexample, if you have an existing table old_table, you can create\nanother table new_table that has the same structure but is empty, and\nthen replace the existing table with the empty one as follows (assuming\nthat backup_table does not already exist):\n\nURL: https://mariadb.com/kb/en/rename-table/\n\n','CREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO old_table;\n','https://mariadb.com/kb/en/rename-table/'),(111,'BOOLEAN',22,'BOOL, BOOLEAN\n\nThese types are synonyms for TINYINT(1). A value of zero is considered\nfalse. Nonzero values are considered true:\n\nMariaDB> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n\nMariaDB> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nMariaDB> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nHowever, the values TRUE and FALSE are merely aliases for 1 and 0,\nrespectively, as shown here:\n\nMariaDB> SELECT IF(0 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n\nMariaDB> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n\nThe last two statements display the results shown because 2 is equal to\nneither 1 nor 0.\n\nURL: https://mariadb.com/kb/en/boolean/\n\n','','https://mariadb.com/kb/en/boolean/'),(112,'DEFAULT',14,'Syntax:\nDEFAULT(col_name)\n\nReturns the default value for a table column. An error results if the\ncolumn has no default value.\n\nURL: https://mariadb.com/kb/en/default/\n\n','MariaDB> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\n','https://mariadb.com/kb/en/default/'),(113,'MOD',4,'Syntax:\nMOD(N,M), N % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M.\n\nURL: https://mariadb.com/kb/en/mod/\n\n','MariaDB> SELECT MOD(234, 10);\n -> 4\nMariaDB> SELECT 253 % 7;\n -> 1\nMariaDB> SELECT MOD(29,9);\n -> 2\nMariaDB> SELECT 29 MOD 9;\n -> 2\n','https://mariadb.com/kb/en/mod/'),(114,'TINYTEXT',22,'TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 255 (28 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TINYTEXT value is stored using a 1-byte length prefix\nthat indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinytext/\n\n','','https://mariadb.com/kb/en/tinytext/'),(115,'OPTIMIZE TABLE',20,'Syntax:\nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nOPTIMIZE TABLE should be used if you have deleted a large part of a\ntable or if you have made many changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT columns).\nDeleted rows are maintained in a linked list and subsequent INSERT\noperations reuse old row positions. You can use OPTIMIZE TABLE to\nreclaim the unused space and to defragment the data file. After\nextensive changes to a table, this statement may also improve\nperformance of statements that use the table, sometimes significantly.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nOPTIMIZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... OPTIMIZE PARTITION to optimize one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/optimize-table/\n\n','','https://mariadb.com/kb/en/optimize-table/'),(116,'DECODE',12,'Syntax:\nDECODE(crypt_str,pass_str)\n\nDecrypts the encrypted string crypt_str using pass_str as the password.\ncrypt_str should be a string returned from ENCODE().\n\nURL: https://mariadb.com/kb/en/decode/\n\n','','https://mariadb.com/kb/en/decode/'),(117,'<=>',18,'Syntax:\n<=>\n\nNULL-safe equal. This operator performs an equality comparison like the\n= operator, but returns 1 rather than NULL if both operands are NULL,\nand 0 rather than NULL if one operand is NULL.\n\nURL: https://mariadb.com/kb/en/null-safe-equal/\n\n','MariaDB> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\n -> 1, 1, 0\nMariaDB> SELECT 1 = 1, NULL = NULL, 1 = NULL;\n -> 1, NULL, NULL\n','https://mariadb.com/kb/en/null-safe-equal/'),(118,'HELP STATEMENT',28,'Syntax:\nHELP \'search_string\'\n\nThe HELP statement returns online information from the MySQL Reference\nmanual. Its proper operation requires that the help tables in the mysql\ndatabase be initialized with help topic information.\n\nThe HELP statement searches the help tables for the given search string\nand displays the result of the search. The search string is not case\nsensitive.\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(119,'RESET',26,'Syntax:\nRESET reset_option [, reset_option] ...\n\nThe RESET statement is used to clear the state of various server\noperations. You must have the RELOAD privilege to execute RESET.\n\nRESET acts as a stronger version of the FLUSH statement. See [HELP\nFLUSH].\n\nThe RESET statement causes an implicit commit. See\nhttps://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/.\n\nURL: https://mariadb.com/kb/en/reset/\n\n','','https://mariadb.com/kb/en/reset/'),(120,'GET_LOCK',14,'Syntax:\nGET_LOCK(str,timeout)\n\nTries to obtain a lock with a name given by the string str, using a\ntimeout of timeout seconds. Returns 1 if the lock was obtained\nsuccessfully, 0 if the attempt timed out (for example, because another\nclient has previously locked the name), or NULL if an error occurred\n(such as running out of memory or the thread was killed with mysqladmin\nkill). If you have a lock obtained with GET_LOCK(), it is released when\nyou execute RELEASE_LOCK(), execute a new GET_LOCK(), or your\nconnection terminates (either normally or abnormally). Locks obtained\nwith GET_LOCK() do not interact with transactions. That is, committing\na transaction does not release any such locks obtained during the\ntransaction.\n\nThis function can be used to implement application locks or to simulate\nrecord locks. Names are locked on a server-wide basis. If a name has\nbeen locked by one client, GET_LOCK() blocks any request by another\nclient for a lock with the same name. This enables clients that agree\non a given lock name to use the name to perform cooperative advisory\nlocking. But be aware that it also enables a client that is not among\nthe set of cooperating clients to lock a name, either inadvertently or\ndeliberately, and thus prevent any of the cooperating clients from\nlocking that name. One way to reduce the likelihood of this is to use\nlock names that are database-specific or application-specific. For\nexample, use lock names of the form db_name.str or app_name.str.\n\nURL: https://mariadb.com/kb/en/get_lock/\n\n','MariaDB> SELECT GET_LOCK(\'lock1\',10);\n -> 1\nMariaDB> SELECT IS_FREE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT GET_LOCK(\'lock2\',10);\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock1\');\n -> NULL\n','https://mariadb.com/kb/en/get_lock/'),(121,'UCASE',37,'Syntax:\nUCASE(str)\n\nUCASE() is a synonym for UPPER().\n\nURL: https://mariadb.com/kb/en/ucase/\n\n','','https://mariadb.com/kb/en/ucase/'),(122,'SHOW BINLOG EVENTS',26,'Syntax:\nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the binary log. If you do not specify \'log_name\',\nthe first binary log is displayed.\n\nURL: https://mariadb.com/kb/en/show-binlog-events/\n\n','','https://mariadb.com/kb/en/show-binlog-events/'),(123,'MPOLYFROMWKB',32,'MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])\n\nConstructs a MULTIPOLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromwkb/\n\n','','https://mariadb.com/kb/en/mpolyfromwkb/'),(124,'ITERATE',23,'Syntax:\nITERATE label\n\nITERATE can appear only within LOOP, REPEAT, and WHILE statements.\nITERATE means \"start the loop again.\"\n\nURL: https://mariadb.com/kb/en/iterate/\n\n','','https://mariadb.com/kb/en/iterate/'),(125,'DO',27,'Syntax:\nDO expr [, expr] ...\n\nDO executes the expressions but does not return any results. In most\nrespects, DO is shorthand for SELECT expr, ..., but has the advantage\nthat it is slightly faster when you do not care about the result.\n\nDO is useful primarily with functions that have side effects, such as\nRELEASE_LOCK().\n\nURL: https://mariadb.com/kb/en/do/\n\n','','https://mariadb.com/kb/en/do/'),(126,'CURTIME',31,'Syntax:\nCURTIME()\n\nReturns the current time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context. The value is expressed in the current time zone.\n\nURL: https://mariadb.com/kb/en/curtime/\n\n','MariaDB> SELECT CURTIME();\n -> \'23:50:26\'\nMariaDB> SELECT CURTIME() + 0;\n -> 235026.000000\n','https://mariadb.com/kb/en/curtime/'),(127,'CHAR_LENGTH',37,'Syntax:\nCHAR_LENGTH(str)\n\nReturns the length of the string str, measured in characters. A\nmulti-byte character counts as a single character. This means that for\na string containing five 2-byte characters, LENGTH() returns 10,\nwhereas CHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/char_length/\n\n','','https://mariadb.com/kb/en/char_length/'),(128,'BIGINT',22,'BIGINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to 18446744073709551615.\n\nSERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.\n\nURL: https://mariadb.com/kb/en/bigint/\n\n','','https://mariadb.com/kb/en/bigint/'),(129,'SET',26,'Syntax:\nSET variable_assignment [, variable_assignment] ...\n\nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n\nThe SET statement assigns values to different types of variables that\naffect the operation of the server or your client. Older versions of\nMySQL employed SET OPTION, but this syntax is deprecated in favor of\nSET without OPTION.\n\nURL: https://mariadb.com/kb/en/set/\n\n','','https://mariadb.com/kb/en/set/'),(130,'LOAD XML',27,'Syntax:\nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD XML statement reads data from an XML file into a table. The\nfile_name must be given as a literal string. The tagname in the\noptional ROWS IDENTIFIED BY clause must also be given as a literal\nstring, and must be surrounded by angle brackets (< and >).\n\nLOAD XML acts as the complement of running the mysql client in XML\noutput mode (that is, starting the client with the --xml option). To\nwrite data from a table to an XML file, use a command such as the\nfollowing one from the system shell:\n\nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n\nTo read the file back into a table, use LOAD XML INFILE. By default,\nthe element is considered to be the equivalent of a database\ntable row; this can be changed using the ROWS IDENTIFIED BY clause.\n\nThis statement supports three different XML formats:\n\no Column names as attributes and column values as attribute values:\n\n\n\no Column names as tags and column values as the content of these tags:\n\n\n value1\n value2\n\n\no Column names are the name attributes of tags, and values are\n the contents of these tags:\n\n\n value1\n value2\n\n\n This is the format used by other MySQL tools, such as mysqldump.\n\nAll 3 formats can be used in the same XML file; the import routine\nautomatically detects the format for each row and interprets it\ncorrectly. Tags are matched based on the tag or attribute name and the\ncolumn name.\n\nThe following clauses work essentially the same way for LOAD XML as\nthey do for LOAD DATA:\n\no LOW_PRIORITY or CONCURRENT\n\no LOCAL\n\no REPLACE or IGNORE\n\no CHARACTER SET\n\no (column_or_user_var,...)\n\no SET\n\nSee [HELP LOAD DATA], for more information about these clauses.\n\nThe IGNORE number LINES or IGNORE number ROWS clause causes the first\nnumber rows in the XML file to be skipped. It is analogous to the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n\nURL: https://mariadb.com/kb/en/load-xml/\n\n','','https://mariadb.com/kb/en/load-xml/'),(131,'CONV',4,'Syntax:\nCONV(N,from_base,to_base)\n\nConverts numbers between different number bases. Returns a string\nrepresentation of the number N, converted from base from_base to base\nto_base. Returns NULL if any argument is NULL. The argument N is\ninterpreted as an integer, but may be specified as an integer or a\nstring. The minimum base is 2 and the maximum base is 36. If to_base is\na negative number, N is regarded as a signed number. Otherwise, N is\ntreated as unsigned. CONV() works with 64-bit precision.\n\nURL: https://mariadb.com/kb/en/conv/\n\n','MariaDB> SELECT CONV(\'a\',16,2);\n -> \'1010\'\nMariaDB> SELECT CONV(\'6E\',18,8);\n -> \'172\'\nMariaDB> SELECT CONV(-17,10,-18);\n -> \'-H\'\nMariaDB> SELECT CONV(10+\'10\'+\'10\'+0xa,10,10);\n -> \'40\'\n','https://mariadb.com/kb/en/conv/'),(132,'DATE',22,'DATE\n\nA date. The supported range is \'1000-01-01\' to \'9999-12-31\'. MySQL\ndisplays DATE values in \'YYYY-MM-DD\' format, but permits assignment of\nvalues to DATE columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/date/\n\n','','https://mariadb.com/kb/en/date/'),(133,'ASSIGN-VALUE',15,'Syntax:\n:=\n\nAssignment operator. Causes the user variable on the left hand side of\nthe operator to take on the value to its right. The value on the right\nhand side may be a literal value, another variable storing a value, or\nany legal expression that yields a scalar value, including the result\nof a query (provided that this value is a scalar value). You can\nperform multiple assignments in the same SET statement. You can perform\nmultiple assignments in the same statement-\n\nUnlike =, the := operator is never interpreted as a comparison\noperator. This means you can use := in any valid SQL statement (not\njust in SET statements) to assign a value to a variable.\n\nURL: https://mariadb.com/kb/en/assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n\nMariaDB> SELECT @var1:=COUNT(*) FROM t1;\n -> 4\nMariaDB> SELECT @var1;\n -> 4\n','https://mariadb.com/kb/en/assignment-operator/'),(134,'SHOW OPEN TABLES',26,'Syntax:\nSHOW OPEN TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW OPEN TABLES lists the non-TEMPORARY tables that are currently open\nin the table cache. See\nhttp://dev.mysql.com/doc/refman/5.5/en/table-cache.html. The FROM\nclause, if present, restricts the tables shown to those present in the\ndb_name database. The LIKE clause, if present, indicates which table\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-open-tables/\n\n','','https://mariadb.com/kb/en/show-open-tables/'),(135,'EXTRACT',31,'Syntax:\nEXTRACT(unit FROM date)\n\nThe EXTRACT() function uses the same kinds of unit specifiers as\nDATE_ADD() or DATE_SUB(), but extracts parts from the date rather than\nperforming date arithmetic.\n\nURL: https://mariadb.com/kb/en/extract/\n\n','MariaDB> SELECT EXTRACT(YEAR FROM \'2009-07-02\');\n -> 2009\nMariaDB> SELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n -> 200907\nMariaDB> SELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n -> 20102\nMariaDB> SELECT EXTRACT(MICROSECOND\n -> FROM \'2003-01-02 10:30:00.000123\');\n -> 123\n','https://mariadb.com/kb/en/extract/'),(136,'ENCRYPT',12,'Syntax:\nENCRYPT(str[,salt])\n\nEncrypts str using the Unix crypt() system call and returns a binary\nstring. The salt argument must be a string with at least two characters\nor the result will be NULL. If no salt argument is given, a random\nvalue is used.\n\nURL: https://mariadb.com/kb/en/encrypt/\n\n','MariaDB> SELECT ENCRYPT(\'hello\');\n -> \'VxuFAJXVARROc\'\n','https://mariadb.com/kb/en/encrypt/'),(137,'SHOW STATUS',26,'Syntax:\nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW STATUS provides server status information. This information also\ncan be obtained using the mysqladmin extended-status command. The LIKE\nclause, if present, indicates which variable names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\nThis statement does not require any privilege. It requires only the\nability to connect to the server.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern:\n\nMariaDB> SHOW STATUS LIKE \'Key%\';\n+--------------------+----------+\n| Variable_name | Value |\n+--------------------+----------+\n| Key_blocks_used | 14955 |\n| Key_read_requests | 96854827 |\n| Key_reads | 162040 |\n| Key_write_requests | 7589728 |\n| Key_writes | 3813196 |\n+--------------------+----------+\n\nWith the GLOBAL modifier, SHOW STATUS displays the status values for\nall connections to MySQL. With SESSION, it displays the status values\nfor the current connection. If no modifier is present, the default is\nSESSION. LOCAL is a synonym for SESSION.\n\nSome status variables have only a global value. For these, you get the\nsame value for both GLOBAL and SESSION. The scope for each status\nvariable is listed at\nhttps://mariadb.com/kb/en/server-status-variables/.\n\nEach invocation of the SHOW STATUS statement uses an internal temporary\ntable and increments the global Created_tmp_tables value.\n\nURL: https://mariadb.com/kb/en/show-status/\n\n','','https://mariadb.com/kb/en/show-status/'),(138,'EXTRACTVALUE',37,'Syntax:\nExtractValue(xml_frag, xpath_expr)\n\nExtractValue() takes two string arguments, a fragment of XML markup\nxml_frag and an XPath expression xpath_expr (also known as a locator);\nit returns the text (CDATA) of the first text node which is a child of\nthe elements or elements matched by the XPath expression. In MySQL 5.5,\nthe XPath expression can contain at most 127 characters. (This\nlimitation is lifted in MySQL 5.6.)\n\nUsing this function is the equivalent of performing a match using the\nxpath_expr after appending /text(). In other words,\nExtractValue(\'Sakila\', \'/a/b\') and\nExtractValue(\'Sakila\', \'/a/b/text()\') produce the same\nresult.\n\nIf multiple matches are found, the content of the first child text node\nof each matching element is returned (in the order matched) as a\nsingle, space-delimited string.\n\nIf no matching text node is found for the expression (including the\nimplicit /text())---for whatever reason, as long as xpath_expr is\nvalid, and xml_frag consists of elements which are properly nested and\nclosed---an empty string is returned. No distinction is made between a\nmatch on an empty element and no match at all. This is by design.\n\nIf you need to determine whether no matching element was found in\nxml_frag or such an element was found but contained no child text\nnodes, you should test the result of an expression that uses the XPath\ncount() function. For example, both of these statements return an empty\nstring, as shown here:\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nHowever, you can determine whether there was actually a matching\nelement using the following:\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 1 |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n1 row in set (0.01 sec)\n\n*Important*: ExtractValue() returns only CDATA, and does not return any\ntags that might be contained within a matching tag, nor any of their\ncontent (see the result returned as val1 in the following example).\n\nURL: https://mariadb.com/kb/en/extractvalue/\n\n','MariaDB> SELECT\n -> ExtractValue(\'cccddd\', \'/a\') AS val1,\n -> ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n -> ExtractValue(\'cccddd\', \'//b\') AS val3,\n -> ExtractValue(\'cccddd\', \'/b\') AS val4,\n -> ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n\n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n','https://mariadb.com/kb/en/extractvalue/'),(139,'OLD_PASSWORD',12,'Syntax:\nOLD_PASSWORD(str)\n\nOLD_PASSWORD() was added when the implementation of PASSWORD() was\nchanged in MySQL 4.1 to improve security. OLD_PASSWORD() returns the\nvalue of the pre-4.1 implementation of PASSWORD() as a string, and is\nintended to permit you to reset passwords for any pre-4.1 clients that\nneed to connect to your version 5.5 MySQL server without locking them\nout. See http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/old_password/\n\n','','https://mariadb.com/kb/en/old_password/'),(140,'FORMAT',37,'Syntax:\nFORMAT(X,D[,locale])\n\nFormats the number X to a format like \'#,###,###.##\', rounded to D\ndecimal places, and returns the result as a string. If D is 0, the\nresult has no decimal point or fractional part.\n\nThe optional third parameter enables a locale to be specified to be\nused for the result number\'s decimal point, thousands separator, and\ngrouping between separators. Permissible locale values are the same as\nthe legal values for the lc_time_names system variable (see\nhttps://mariadb.com/kb/en/server-locale/). If no\nlocale is specified, the default is \'en_US\'.\n\nURL: https://mariadb.com/kb/en/format/\n\n','MariaDB> SELECT FORMAT(12332.123456, 4);\n -> \'12,332.1235\'\nMariaDB> SELECT FORMAT(12332.1,4);\n -> \'12,332.1000\'\nMariaDB> SELECT FORMAT(12332.2,0);\n -> \'12,332\'\nMariaDB> SELECT FORMAT(12332.2,2,\'de_DE\');\n -> \'12.332,20\'\n','https://mariadb.com/kb/en/format/'),(141,'||',15,'Syntax:\nOR, ||\n\nLogical OR. When both operands are non-NULL, the result is 1 if any\noperand is nonzero, and 0 otherwise. With a NULL operand, the result is\n1 if the other operand is nonzero, and NULL otherwise. If both operands\nare NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/or/\n\n','MariaDB> SELECT 1 || 1;\n -> 1\nMariaDB> SELECT 1 || 0;\n -> 1\nMariaDB> SELECT 0 || 0;\n -> 0\nMariaDB> SELECT 0 || NULL;\n -> NULL\nMariaDB> SELECT 1 || NULL;\n -> 1\n','https://mariadb.com/kb/en/or/'),(142,'BIT_LENGTH',37,'Syntax:\nBIT_LENGTH(str)\n\nReturns the length of the string str in bits.\n\nURL: https://mariadb.com/kb/en/bit_length/\n\n','MariaDB> SELECT BIT_LENGTH(\'text\');\n -> 32\n','https://mariadb.com/kb/en/bit_length/'),(143,'EXTERIORRING',2,'ExteriorRing(poly)\n\nReturns the exterior ring of the Polygon value poly as a LineString.\n\nURL: https://mariadb.com/kb/en/exteriorring/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n','https://mariadb.com/kb/en/exteriorring/'),(144,'GEOMFROMWKB',32,'GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkb[,srid])\n\nConstructs a geometry value of any type using its WKB representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromwkb/\n\n','','https://mariadb.com/kb/en/geomfromwkb/'),(145,'SHOW SLAVE HOSTS',26,'Syntax:\nSHOW SLAVE HOSTS\n\nDisplays a list of replication slaves currently registered with the\nmaster. (Before MySQL 5.5.3, only slaves started with the\n--report-host=host_name option are visible in this list.)\n\nThe list is displayed on any server (not just the master server). The\noutput looks like this:\n\nMariaDB> SHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\n\no Server_id: The unique server ID of the slave server, as configured in\n the server\'s option file, or on the command line with\n --server-id=value.\n\no Host: The host name of the slave server, as configured in the\n server\'s option file, or on the command line with\n --report-host=host_name. Note that this can differ from the machine\n name as configured in the operating system.\n\no Port: The port the slave server is listening on.\n\n In MySQL 5.5.23 and later, a zero in this column means that the slave\n port (--report-port) was not set. Prior to MySQL 5.5.23, 3306 was\n used as the default in such cases (Bug #13333431).\n\no Master_id: The unique server ID of the master server that the slave\n server is replicating from.\n\nSome MySQL versions report another variable, Rpl_recovery_rank. This\nvariable was never used, and was removed in MySQL 5.5.3. (Bug #13963)\n\nURL: https://mariadb.com/kb/en/show-slave-hosts/\n\n','','https://mariadb.com/kb/en/show-slave-hosts/'),(146,'START TRANSACTION',8,'Syntax:\nSTART TRANSACTION [WITH CONSISTENT SNAPSHOT]\nBEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n\nThese statements provide control over use of transactions:\n\no START TRANSACTION or BEGIN start a new transaction.\n\no COMMIT commits the current transaction, making its changes permanent.\n\no ROLLBACK rolls back the current transaction, canceling its changes.\n\no SET autocommit disables or enables the default autocommit mode for\n the current session.\n\nBy default, MySQL runs with autocommit mode enabled. This means that as\nsoon as you execute a statement that updates (modifies) a table, MySQL\nstores the update on disk to make it permanent. The change cannot be\nrolled back.\n\nTo disable autocommit mode implicitly for a single series of\nstatements, use the START TRANSACTION statement:\n\nSTART TRANSACTION;\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\nUPDATE table2 SET summary=@A WHERE type=1;\nCOMMIT;\n\nWith START TRANSACTION, autocommit remains disabled until you end the\ntransaction with COMMIT or ROLLBACK. The autocommit mode then reverts\nto its previous state.\n\nYou can also begin a transaction like this:\n\nSTART TRANSACTION WITH CONSISTENT SNAPSHOT;\n\nThe WITH CONSISTENT SNAPSHOT option starts a consistent read for\nstorage engines that are capable of it. This applies only to InnoDB.\nThe effect is the same as issuing a START TRANSACTION followed by a\nSELECT from any InnoDB table. See\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html. The\nWITH CONSISTENT SNAPSHOT option does not change the current transaction\nisolation level, so it provides a consistent snapshot only if the\ncurrent isolation level is one that permits consistent read (REPEATABLE\nREAD or SERIALIZABLE).\n\n*Important*: Many APIs used for writing MySQL client applications (such\nas JDBC) provide their own methods for starting transactions that can\n(and sometimes should) be used instead of sending a START TRANSACTION\nstatement from the client. See\nhttp://dev.mysql.com/doc/refman/5.5/en/connectors-apis.html, or the\ndocumentation for your API, for more information.\n\nTo disable autocommit mode explicitly, use the following statement:\n\nSET autocommit=0;\n\nAfter disabling autocommit mode by setting the autocommit variable to\nzero, changes to transaction-safe tables (such as those for InnoDB) are not made permanent immediately. You must use COMMIT to\nstore your changes to disk or ROLLBACK to ignore the changes.\n\nautocommit is a session variable and must be set for each session. To\ndisable autocommit mode for each new connection, see the description of\nthe autocommit system variable at\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nBEGIN and BEGIN WORK are supported as aliases of START TRANSACTION for\ninitiating a transaction. START TRANSACTION is standard SQL syntax and\nis the recommended way to start an ad-hoc transaction.\n\nThe BEGIN statement differs from the use of the BEGIN keyword that\nstarts a BEGIN ... END compound statement. The latter does not begin a\ntransaction. See [HELP BEGIN END].\n\n*Note*: Within all stored programs (stored procedures and functions,\ntriggers, and events), the parser treats BEGIN [WORK] as the beginning\nof a BEGIN ... END block. Begin a transaction in this context with\nSTART TRANSACTION instead.\n\nThe optional WORK keyword is supported for COMMIT and ROLLBACK, as are\nthe CHAIN and RELEASE clauses. CHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of the\ncompletion_type system variable determines the default completion\nbehavior. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nThe AND CHAIN clause causes a new transaction to begin as soon as the\ncurrent one ends, and the new transaction has the same isolation level\nas the just-terminated transaction. The RELEASE clause causes the\nserver to disconnect the current client session after terminating the\ncurrent transaction. Including the NO keyword suppresses CHAIN or\nRELEASE completion, which can be useful if the completion_type system\nvariable is set to cause chaining or release completion by default.\n\nURL: https://mariadb.com/kb/en/start-transaction/\n\n','','https://mariadb.com/kb/en/start-transaction/'),(147,'BETWEEN AND',18,'Syntax:\nexpr BETWEEN min AND max\n\nIf expr is greater than or equal to min and expr is less than or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is equivalent\nto the expression (min <= expr AND expr <= max) if all the arguments\nare of the same type. Otherwise type conversion takes place according\nto the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the three arguments.\n\nURL: https://mariadb.com/kb/en/between-and/\n\n','MariaDB> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;\n -> 1, 0\nMariaDB> SELECT 1 BETWEEN 2 AND 3;\n -> 0\nMariaDB> SELECT \'b\' BETWEEN \'a\' AND \'c\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'3\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'x-3\';\n -> 0\n','https://mariadb.com/kb/en/between-and/'),(148,'MULTIPOLYGON',24,'MultiPolygon(poly1,poly2,...)\n\nConstructs a MultiPolygon value from a set of Polygon or WKB Polygon\narguments.\n\nURL: https://mariadb.com/kb/en/multipolygon/\n\n','','https://mariadb.com/kb/en/multipolygon/'),(149,'TIME_FORMAT',31,'Syntax:\nTIME_FORMAT(time,format)\n\nThis is used like the DATE_FORMAT() function, but the format string may\ncontain format specifiers only for hours, minutes, seconds, and\nmicroseconds. Other specifiers produce a NULL value or 0.\n\nURL: https://mariadb.com/kb/en/time_format/\n\n','MariaDB> SELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n -> \'100 100 04 04 4\'\n','https://mariadb.com/kb/en/time_format/'),(150,'LEFT',37,'Syntax:\nLEFT(str,len)\n\nReturns the leftmost len characters from the string str, or NULL if any\nargument is NULL.\n\nURL: https://mariadb.com/kb/en/left/\n\n','MariaDB> SELECT LEFT(\'foobarbar\', 5);\n -> \'fooba\'\n','https://mariadb.com/kb/en/left/'),(151,'FLUSH QUERY CACHE',26,'You can defragment the query cache to better utilize its memory with\nthe FLUSH QUERY CACHE statement. The statement does not remove any\nqueries from the cache.\n\nThe RESET QUERY CACHE statement removes all query results from the\nquery cache. The FLUSH TABLES statement also does this.\n\nURL: https://mariadb.com/kb/en/flush-query-cache/\n\n','','https://mariadb.com/kb/en/flush-query-cache/'),(152,'SET DATA TYPE',22,'SET(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA set. A string object that can have zero or more values, each of which\nmust be chosen from the list of values \'value1\', \'value2\', ... A SET\ncolumn can have a maximum of 64 members. SET values are represented\ninternally as integers.\n\nURL: https://mariadb.com/kb/en/set-data-type/\n\n','','https://mariadb.com/kb/en/set-data-type/'),(153,'RAND',4,'Syntax:\nRAND(), RAND(N)\n\nReturns a random floating-point value v in the range 0 <= v < 1.0. If a\nconstant integer argument N is specified, it is used as the seed value,\nwhich produces a repeatable sequence of column values. In the following\nexample, note that the sequences of values produced by RAND(3) is the\nsame both places where it occurs.\n\nURL: https://mariadb.com/kb/en/rand/\n\n','MariaDB> CREATE TABLE t (i INT);\nQuery OK, 0 rows affected (0.42 sec)\n\nMariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.61914388706828 |\n| 2 | 0.93845168309142 |\n| 3 | 0.83482678498591 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.35877890638893 |\n| 2 | 0.28941420772058 |\n| 3 | 0.37073435016976 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.01 sec)\n','https://mariadb.com/kb/en/rand/'),(154,'RPAD',37,'Syntax:\nRPAD(str,len,padstr)\n\nReturns the string str, right-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\nURL: https://mariadb.com/kb/en/rpad/\n\n','MariaDB> SELECT RPAD(\'hi\',5,\'?\');\n -> \'hi???\'\nMariaDB> SELECT RPAD(\'hi\',1,\'?\');\n -> \'h\'\n','https://mariadb.com/kb/en/rpad/'),(155,'CREATE DATABASE',39,'Syntax:\nCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n [create_specification] ...\n\ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nCREATE DATABASE creates a database with the given name. To use this\nstatement, you need the CREATE privilege for the database. CREATE\nSCHEMA is a synonym for CREATE DATABASE.\n\nURL: https://mariadb.com/kb/en/create-database/\n\n','','https://mariadb.com/kb/en/create-database/'),(156,'DEC',22,'DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED]\n[ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nThese types are synonyms for DECIMAL. The FIXED synonym is available\nfor compatibility with other database systems.\n\nURL: https://mariadb.com/kb/en/dec-numeric-fixed/\n\n','','https://mariadb.com/kb/en/dec-numeric-fixed/'),(157,'VAR_POP',16,'Syntax:\nVAR_POP(expr)\n\nReturns the population standard variance of expr. It considers rows as\nthe whole population, not as a sample, so it has the number of rows as\nthe denominator. You can also use VARIANCE(), which is equivalent but\nis not standard SQL.\n\nVAR_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_pop/\n\n','','https://mariadb.com/kb/en/var_pop/'),(158,'ELT',37,'Syntax:\nELT(N,str1,str2,str3,...)\n\nReturns str1 if N = 1, str2 if N = 2, and so on. Returns NULL if N is\nless than 1 or greater than the number of arguments. ELT() is the\ncomplement of FIELD().\n\nURL: https://mariadb.com/kb/en/elt/.html\n\n','MariaDB> SELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'ej\'\nMariaDB> SELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'foo\'\n','https://mariadb.com/kb/en/elt/.html'),(159,'ALTER VIEW',39,'Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW and the effect is the same as\nfor CREATE OR REPLACE VIEW. See [HELP CREATE VIEW]. This statement\nrequires the CREATE VIEW and DROP privileges for the view, and some\nprivilege for each column referred to in the SELECT statement. ALTER\nVIEW is permitted only to the definer or users with the SUPER\nprivilege.\n\nURL: https://mariadb.com/kb/en/alter-view/\n\n','','https://mariadb.com/kb/en/alter-view/'),(160,'SHOW DATABASES',26,'Syntax:\nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW DATABASES lists the databases on the MySQL server host. SHOW\nSCHEMAS is a synonym for SHOW DATABASES. The LIKE clause, if present,\nindicates which database names to match. The WHERE clause can be given\nto select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou see only those databases for which you have some kind of privilege,\nunless you have the global SHOW DATABASES privilege. You can also get\nthis list using the mysqlshow command.\n\nIf the server was started with the --skip-show-database option, you\ncannot use this statement at all unless you have the SHOW DATABASES\nprivilege.\n\nURL: https://mariadb.com/kb/en/show-databases/\n\n','','https://mariadb.com/kb/en/show-databases/'),(161,'~',19,'Syntax:\n~\n\nInvert all bits.\n\nURL: https://mariadb.com/kb/en/3489/\n\n','MariaDB> SELECT 5 & ~1;\n -> 4\n','https://mariadb.com/kb/en/3489/'),(162,'TEXT',22,'TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 65,535 (216 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TEXT value is stored using a 2-byte length prefix that\nindicates the number of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest TEXT type large enough to hold\nvalues M characters long.\n\nURL: https://mariadb.com/kb/en/text/\n\n','','https://mariadb.com/kb/en/text/'),(163,'CONCAT_WS',37,'Syntax:\nCONCAT_WS(separator,str1,str2,...)\n\nCONCAT_WS() stands for Concatenate With Separator and is a special form\nof CONCAT(). The first argument is the separator for the rest of the\narguments. The separator is added between the strings to be\nconcatenated. The separator can be a string, as can the rest of the\narguments. If the separator is NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/concat_ws/\n\n','MariaDB> SELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last Name\');\n -> \'First name,Second name,Last Name\'\nMariaDB> SELECT CONCAT_WS(\',\',\'First name\',NULL,\'Last Name\');\n -> \'First name,Last Name\'\n','https://mariadb.com/kb/en/concat_ws/'),(164,'ROW_COUNT',17,'Syntax:\nROW_COUNT()\n\nBefore MySQL 5.5.5, ROW_COUNT() returns the number of rows changed,\ndeleted, or inserted by the last statement if it was an UPDATE, DELETE,\nor INSERT. For other statements, the value may not be meaningful.\n\nAs of MySQL 5.5.5, ROW_COUNT() returns a value as follows:\n\no DDL statements: 0. This applies to statements such as CREATE TABLE or\n DROP TABLE.\n\no DML statements other than SELECT: The number of affected rows. This\n applies to statements such as UPDATE, INSERT, or DELETE (as before),\n but now also to statements such as ALTER TABLE and LOAD DATA INFILE.\n\no SELECT: -1 if the statement returns a result set, or the number of\n rows \"affected\" if it does not. For example, for SELECT * FROM t1,\n ROW_COUNT() returns -1. For SELECT * FROM t1 INTO OUTFILE\n \'file_name\', ROW_COUNT() returns the number of rows written to the\n file.\n\no SIGNAL statements: 0.\n\nFor UPDATE statements, the affected-rows value by default is the number\nof rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() when connecting to mysqld, the affected-rows value\nis the number of rows \"found\"; that is, matched by the WHERE clause.\n\nFor REPLACE statements, the affected-rows value is 2 if the new row\nreplaced an old row, because in this case, one row was inserted after\nthe duplicate was deleted.\n\nFor INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows\nvalue is 1 if the row is inserted as a new row and 2 if an existing row\nis updated.\n\nThe ROW_COUNT() value is similar to the value from the\nmysql_affected_rows() C API function and the row count that the mysql\nclient displays following statement execution.\n\nURL: https://mariadb.com/kb/en/information-functions-row_count/\n\n','MariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> DELETE FROM t WHERE i IN(1,2);\nQuery OK, 2 rows affected (0.00 sec)\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/information-functions-row_count/'),(165,'ASIN',4,'Syntax:\nASIN(X)\n\nReturns the arc sine of X, that is, the value whose sine is X. Returns\nNULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/asin/\n\n','MariaDB> SELECT ASIN(0.2);\n -> 0.20135792079033\nMariaDB> SELECT ASIN(\'foo\');\n\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n1 row in set, 1 warning (0.00 sec)\n\nMariaDB> SHOW WARNINGS;\n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\' |\n+---------+------+-----------------------------------------+\n','https://mariadb.com/kb/en/asin/'),(166,'SIGN',4,'Syntax:\nSIGN(X)\n\nReturns the sign of the argument as -1, 0, or 1, depending on whether X\nis negative, zero, or positive.\n\nURL: https://mariadb.com/kb/en/sign/\n\n','MariaDB> SELECT SIGN(-32);\n -> -1\nMariaDB> SELECT SIGN(0);\n -> 0\nMariaDB> SELECT SIGN(234);\n -> 1\n','https://mariadb.com/kb/en/sign/'),(167,'SEC_TO_TIME',31,'Syntax:\nSEC_TO_TIME(seconds)\n\nReturns the seconds argument, converted to hours, minutes, and seconds,\nas a TIME value. The range of the result is constrained to that of the\nTIME data type. A warning occurs if the argument corresponds to a value\noutside that range.\n\nURL: https://mariadb.com/kb/en/sec_to_time/\n\n','MariaDB> SELECT SEC_TO_TIME(2378);\n -> \'00:39:38\'\nMariaDB> SELECT SEC_TO_TIME(2378) + 0;\n -> 3938\n','https://mariadb.com/kb/en/sec_to_time/'),(168,'FLOAT',22,'FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA small (single-precision) floating-point number. Permissible values\nare -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to\n3.402823466E+38. These are the theoretical limits, based on the IEEE\nstandard. The actual range might be slightly smaller depending on your\nhardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A single-precision floating-point\nnumber is accurate to approximately 7 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nUsing FLOAT might give you some unexpected problems because all\ncalculations in MySQL are done with double precision. See\nhttps://mariadb.com/kb/en/floating-point-accuracy/.\n\nURL: https://mariadb.com/kb/en/float/\n\n','','https://mariadb.com/kb/en/float/'),(169,'LOCATE',37,'Syntax:\nLOCATE(substr,str), LOCATE(substr,str,pos)\n\nThe first syntax returns the position of the first occurrence of\nsubstring substr in string str. The second syntax returns the position\nof the first occurrence of substring substr in string str, starting at\nposition pos. Returns 0 if substr is not in str.\n\nURL: https://mariadb.com/kb/en/locate/\n\n','MariaDB> SELECT LOCATE(\'bar\', \'foobarbar\');\n -> 4\nMariaDB> SELECT LOCATE(\'xbar\', \'foobar\');\n -> 0\nMariaDB> SELECT LOCATE(\'bar\', \'foobarbar\', 5);\n -> 7\n','https://mariadb.com/kb/en/locate/'),(170,'SHOW EVENTS',26,'Syntax:\nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement displays information about Event Manager events. It\nrequires the EVENT privilege for the database from which the events are\nto be shown.\n\nIn its simplest form, SHOW EVENTS lists all of the events in the\ncurrent schema:\n\nMariaDB> SELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n1 row in set (0.00 sec)\n\nMariaDB> SHOW EVENTS\\G\n*************************** 1. row ***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nTo see events for a specific schema, use the FROM clause. For example,\nto see events for the test schema, use the following statement:\n\nSHOW EVENTS FROM test;\n\nThe LIKE clause, if present, indicates which event names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-events/\n\n','','https://mariadb.com/kb/en/show-events/'),(171,'CHARSET',17,'Syntax:\nCHARSET(str)\n\nReturns the character set of the string argument.\n\nURL: https://mariadb.com/kb/en/charset/\n\n','MariaDB> SELECT CHARSET(\'abc\');\n -> \'latin1\'\nMariaDB> SELECT CHARSET(CONVERT(\'abc\' USING utf8));\n -> \'utf8\'\nMariaDB> SELECT CHARSET(USER());\n -> \'utf8\'\n','https://mariadb.com/kb/en/charset/'),(172,'SUBDATE',31,'Syntax:\nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, SUBDATE()\nis a synonym for DATE_SUB(). For information on the INTERVAL unit\nargument, see the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\nMariaDB> SELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\n\nThe second form enables the use of an integer value for days. In such\ncases, it is interpreted as the number of days to be subtracted from\nthe date or datetime expression expr.\n\nMariaDB> SELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n -> \'2007-12-02 12:00:00\'\n\nURL: https://mariadb.com/kb/en/subdate/\n\n','','https://mariadb.com/kb/en/subdate/'),(173,'DAYOFYEAR',31,'Syntax:\nDAYOFYEAR(date)\n\nReturns the day of the year for date, in the range 1 to 366.\n\nURL: https://mariadb.com/kb/en/dayofyear/\n\n','MariaDB> SELECT DAYOFYEAR(\'2007-02-03\');\n -> 34\n','https://mariadb.com/kb/en/dayofyear/'),(174,'%',4,'Syntax:\nN % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M. For more\ninformation, see the description for the MOD() function in\nhttps://mariadb.com/kb/en/mod/.\n\nURL: https://mariadb.com/kb/en/modulo-operator/\n\n','','https://mariadb.com/kb/en/modulo-operator/'),(175,'LONGTEXT',22,'LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\ncharacters. The effective maximum length is less if the value contains\nmulti-byte characters. The effective maximum length of LONGTEXT columns\nalso depends on the configured maximum packet size in the client/server\nprotocol and available memory. Each LONGTEXT value is stored using a\n4-byte length prefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longtext/\n\n','','https://mariadb.com/kb/en/longtext/'),(176,'KILL',26,'Syntax:\nKILL [CONNECTION | QUERY] thread_id\n\nEach connection to mysqld runs in a separate thread. You can see which\nthreads are running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement.\n\nKILL permits an optional CONNECTION or QUERY modifier:\n\no KILL CONNECTION is the same as KILL with no modifier: It terminates\n the connection associated with the given thread_id.\n\no KILL QUERY terminates the statement that the connection is currently\n executing, but leaves the connection itself intact.\n\nIf you have the PROCESS privilege, you can see all threads. If you have\nthe SUPER privilege, you can kill all threads and statements.\nOtherwise, you can see and kill only your own threads and statements.\n\nYou can also use the mysqladmin processlist and mysqladmin kill\ncommands to examine and kill threads.\n\n*Note*: You cannot use KILL with the Embedded MySQL Server library\nbecause the embedded server merely runs inside the threads of the host\napplication. It does not create any connection threads of its own.\n\nURL: https://mariadb.com/kb/en/data-manipulation-kill-connection-query/\n\n','','https://mariadb.com/kb/en/data-manipulation-kill-connection-query/'),(177,'DISJOINT',30,'Disjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially disjoint from (does\nnot intersect) g2.\n\nURL: https://mariadb.com/kb/en/disjoint/\n\n','','https://mariadb.com/kb/en/disjoint/'),(178,'ASTEXT',3,'AsText(g), AsWKT(g)\n\nConverts a value in internal geometry format to its WKT representation\nand returns the string result.\n\nURL: https://mariadb.com/kb/en/astext/\n\n','MariaDB> SET @g = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(GeomFromText(@g));\n+--------------------------+\n| AsText(GeomFromText(@g)) |\n+--------------------------+\n| LINESTRING(1 1,2 2,3 3) |\n+--------------------------+\n','https://mariadb.com/kb/en/astext/'),(179,'LPAD',37,'Syntax:\nLPAD(str,len,padstr)\n\nReturns the string str, left-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\n\nURL: https://mariadb.com/kb/en/lpad/\n\n','MariaDB> SELECT LPAD(\'hi\',4,\'??\');\n -> \'??hi\'\nMariaDB> SELECT LPAD(\'hi\',1,\'??\');\n -> \'h\'\n','https://mariadb.com/kb/en/lpad/'),(180,'DECLARE CONDITION',23,'Syntax:\nDECLARE condition_name CONDITION FOR condition_value\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n\nThe DECLARE ... CONDITION statement declares a named error condition,\nassociating a name with a condition that needs specific handling. The\nname can be referred to in a subsequent DECLARE ... HANDLER statement\n(see [HELP DECLARE HANDLER]).\n\nCondition declarations must appear before cursor or handler\ndeclarations.\n\nThe condition_value for DECLARE ... CONDITION can be a MySQL error code\n(a number) or an SQLSTATE value (a 5-character string literal). You\nshould not use MySQL error code 0 or SQLSTATE values that begin with\n\'00\', because those indicate success rather than an error condition.\nFor a list of MySQL error codes and SQLSTATE values, see\nhttps://mariadb.com/kb/en/mariadb-error-codes/.\n\nURL: https://mariadb.com/kb/en/declare-condition/\n\n','','https://mariadb.com/kb/en/declare-condition/'),(181,'OVERLAPS',30,'Overlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially overlaps g2. The term\nspatially overlaps is used if two geometries intersect and their\nintersection results in a geometry of the same dimension but not equal\nto either of the given geometries.\n\nURL: https://mariadb.com/kb/en/overlaps/\n\n','','https://mariadb.com/kb/en/overlaps/'),(182,'SET GLOBAL SQL_SLAVE_SKIP_COUNTER',8,'Syntax:\nSET GLOBAL sql_slave_skip_counter = N\n\nThis statement skips the next N events from the master. This is useful\nfor recovering from replication stops caused by a statement.\n\nThis statement is valid only when the slave threads are not running.\nOtherwise, it produces an error.\n\nURL: https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/\n\n','','https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/'),(183,'NUMGEOMETRIES',25,'NumGeometries(gc)\n\nReturns the number of geometries in the GeometryCollection value gc.\n\nURL: https://mariadb.com/kb/en/numgeometries/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT NumGeometries(GeomFromText(@gc));\n+----------------------------------+\n| NumGeometries(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n','https://mariadb.com/kb/en/numgeometries/'),(184,'MONTHNAME',31,'Syntax:\nMONTHNAME(date)\n\nReturns the full name of the month for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-locale/).\n\nURL: https://mariadb.com/kb/en/monthname/\n\n','MariaDB> SELECT MONTHNAME(\'2008-02-03\');\n -> \'February\'\n','https://mariadb.com/kb/en/monthname/'),(185,'CHANGE MASTER TO',8,'Syntax:\nCHANGE MASTER TO option [, option] ...\n\noption:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | IGNORE_SERVER_IDS = (server_id_list)\n\nserver_id_list:\n [server_id [, server_id] ... ]\n\nCHANGE MASTER TO changes the parameters that the slave server uses for\nconnecting to the master server, for reading the master binary log, and\nreading the slave relay log. It also updates the contents of the\nmaster.info and relay-log.info files. To use CHANGE MASTER TO, the\nslave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\nOptions not specified retain their value, except as indicated in the\nfollowing discussion. Thus, in most cases, there is no need to specify\noptions that do not change. For example, if the password to connect to\nyour MySQL master has changed, you just need to issue these statements\nto tell the slave about the new password:\n\nSTOP SLAVE; -- if replication was running\nCHANGE MASTER TO MASTER_PASSWORD=\'new3cret\';\nSTART SLAVE; -- if you want to restart replication\n\nMASTER_HOST, MASTER_USER, MASTER_PASSWORD, and MASTER_PORT provide\ninformation to the slave about how to connect to its master:\n\no MASTER_HOST and MASTER_PORT are the host name (or IP address) of the\n master host and its TCP/IP port.\n\n *Note*: Replication cannot use Unix socket files. You must be able to\n connect to the master MySQL server using TCP/IP.\n\n If you specify the MASTER_HOST or MASTER_PORT option, the slave\n assumes that the master server is different from before (even if the\n option value is the same as its current value.) In this case, the old\n values for the master binary log file name and position are\n considered no longer applicable, so if you do not specify\n MASTER_LOG_FILE and MASTER_LOG_POS in the statement,\n MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4 are silently appended to it.\n\n Setting MASTER_HOST=\'\' (that is, setting its value explicitly to an\n empty string) is not the same as not setting MASTER_HOST at all.\n Beginning with MySQL 5.5, trying to set MASTER_HOST to an empty\n string fails with an error. Previously, setting MASTER_HOST to an\n empty string caused START SLAVE subsequently to fail. (Bug #28796)\n\no MASTER_USER and MASTER_PASSWORD are the user name and password of the\n account to use for connecting to the master.\n\n In MySQL 5.5.20 and later, MASTER_USER cannot be made empty; setting\n MASTER_USER = \'\' or leaving it unset when setting a value for for\n MASTER_PASSWORD causes an error (Bug #13427949).\n\n Currently, a password used for a replication slave account is\n effectively limited to 32 characters in length; the password can be\n longer, but any excess characters are truncated. This is not due to\n any limit imposed by the MySQL Server generally, but rather is an\n issue specific to MySQL Replication. (For more information, see Bug\n #43439.)\n\n The text of a running CHANGE MASTER TO statement, including values\n for MASTER_USER and MASTER_PASSWORD, can be seen in the output of a\n concurrent SHOW PROCESSLIST statement.\n\nThe MASTER_SSL_xxx options provide information about using SSL for the\nconnection. They correspond to the --ssl-xxx options described in\nhttps://mariadb.com/kb/en/ssl-server-system-variables/, and\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-solutions-ssl.html.\nThese options can be changed even on slaves that are compiled without\nSSL support. They are saved to the master.info file, but are ignored if\nthe slave does not have SSL support enabled.\n\nMASTER_CONNECT_RETRY specifies how many seconds to wait between connect\nretries. The default is 60. The number of reconnection attempts is\nlimited by the --master-retry-count server option; for more\ninformation, see\nhttps://mariadb.com/kb/en/replication-and-binary-log-server-system-variables/.\n\nMASTER_HEARTBEAT_PERIOD sets the interval in seconds between\nreplication heartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is reset.\ninterval is a decimal value having the range 0 to 4294967 seconds and a\nresolution in milliseconds; the smallest nonzero value is 0.001.\nHeartbeats are sent by the master only if there are no unsent events in\nthe binary log file for a period longer than interval.\n\nSetting interval to 0 disables heartbeats altogether. The default value\nfor interval is equal to the value of slave_net_timeout divided by 2.\n\nSetting @@global.slave_net_timeout to a value less than that of the\ncurrent heartbeat interval results in a warning being issued. The\neffect of issuing RESET SLAVE on the heartbeat interval is to reset it\nto the default value.\n\nMASTER_LOG_FILE and MASTER_LOG_POS are the coordinates at which the\nslave I/O thread should begin reading from the master the next time the\nthread starts. RELAY_LOG_FILE and RELAY_LOG_POS are the coordinates at\nwhich the slave SQL thread should begin reading from the relay log the\nnext time the thread starts. If you specify either of MASTER_LOG_FILE\nor MASTER_LOG_POS, you cannot specify RELAY_LOG_FILE or RELAY_LOG_POS.\nIf neither of MASTER_LOG_FILE or MASTER_LOG_POS is specified, the slave\nuses the last coordinates of the slave SQL thread before CHANGE MASTER\nTO was issued. This ensures that there is no discontinuity in\nreplication, even if the slave SQL thread was late compared to the\nslave I/O thread, when you merely want to change, say, the password to\nuse.\n\nCHANGE MASTER TO deletes all relay log files and starts a new one,\nunless you specify RELAY_LOG_FILE or RELAY_LOG_POS. In that case, relay\nlog files are kept; the relay_log_purge global variable is set silently\nto 0.\n\nPrior to MySQL 5.5, RELAY_LOG_FILE required an absolute path. In MySQL\n5.5, the path can be relative, in which case the path is assumed to be\nrelative to the slave\'s data directory. (Bug #12190)\n\nIGNORE_SERVER_IDS was added in MySQL 5.5. This option takes a\ncomma-separated list of 0 or more server IDs. Events originating from\nthe corresponding servers are ignored, with the exception of log\nrotation and deletion events, which are still recorded in the relay\nlog.\n\nIn circular replication, the originating server normally acts as the\nterminator of its own events, so that they are not applied more than\nonce. Thus, this option is useful in circular replication when one of\nthe servers in the circle is removed. Suppose that you have a circular\nreplication setup with 4 servers, having server IDs 1, 2, 3, and 4, and\nserver 3 fails. When bridging the gap by starting replication from\nserver 2 to server 4, you can include IGNORE_SERVER_IDS = (3) in the\nCHANGE MASTER TO statement that you issue on server 4 to tell it to use\nserver 2 as its master instead of server 3. Doing so causes it to\nignore and not to propagate any statements that originated with the\nserver that is no longer in use.\n\nIf a CHANGE MASTER TO statement is issued without any IGNORE_SERVER_IDS\noption, any existing list is preserved; RESET SLAVE also has no effect\non the server ID list. To clear the list of ignored servers, it is\nnecessary to use the option with an empty list:\n\nCHANGE MASTER TO IGNORE_SERVER_IDS = ();\n\nIf IGNORE_SERVER_IDS contains the server\'s own ID and the server was\nstarted with the --replicate-same-server-id option enabled, an error\nresults.\n\nAlso beginning with MySQL 5.5, the master.info file and the output of\nSHOW SLAVE STATUS are extended to provide the list of servers that are\ncurrently ignored. For more information, see\nhttps://mariadb.com/kb/en/show-slave-status/, and\n[HELP SHOW SLAVE STATUS].\n\nBeginning with MySQL 5.5.5, invoking CHANGE MASTER TO causes the\nprevious values for MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE, and\nMASTER_LOG_POS to be written to the error log, along with other\ninformation about the slave\'s state prior to execution.\n\nCHANGE MASTER TO is useful for setting up a slave when you have the\nsnapshot of the master and have recorded the master binary log\ncoordinates corresponding to the time of the snapshot. After loading\nthe snapshot into the slave to synchronize it to the slave, you can run\nCHANGE MASTER TO MASTER_LOG_FILE=\'log_name\', MASTER_LOG_POS=log_pos on\nthe slave to specify the coordinates at which the slave should begin\nreading the master binary log.\n\nThe following example changes the master server the slave uses and\nestablishes the master binary log coordinates from which the slave\nbegins reading. This is used when you want to set up the slave to\nreplicate the master:\n\nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n\nThe next example shows an operation that is less frequently employed.\nIt is used when the slave has relay log files that you want it to\nexecute again for some reason. To do this, the master need not be\nreachable. You need only use CHANGE MASTER TO and start the SQL thread\n(START SLAVE SQL_THREAD):\n\nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n\nURL: https://mariadb.com/kb/en/change-master-to/\n\n','','https://mariadb.com/kb/en/change-master-to/'),(186,'DROP DATABASE',39,'Syntax:\nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n\nDROP DATABASE drops all tables in the database and deletes the\ndatabase. Be very careful with this statement! To use DROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is a synonym\nfor DROP DATABASE.\n\n*Important*: When a database is dropped, user privileges on the\ndatabase are not automatically dropped. See [HELP GRANT].\n\nIF EXISTS is used to prevent an error from occurring if the database\ndoes not exist.\n\nURL: https://mariadb.com/kb/en/drop-database/\n\n','','https://mariadb.com/kb/en/drop-database/'),(187,'MBREQUAL',6,'MBREqual(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are the same.\n\nURL: https://mariadb.com/kb/en/mbrequal/\n\n','','https://mariadb.com/kb/en/mbrequal/'),(188,'TIMESTAMP FUNCTION',31,'Syntax:\nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n\nWith a single argument, this function returns the date or datetime\nexpression expr as a datetime value. With two arguments, it adds the\ntime expression expr2 to the date or datetime expression expr1 and\nreturns the result as a datetime value.\n\nURL: https://mariadb.com/kb/en/timestamp-function/\n\n','MariaDB> SELECT TIMESTAMP(\'2003-12-31\');\n -> \'2003-12-31 00:00:00\'\nMariaDB> SELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'12:00:00\');\n -> \'2004-01-01 00:00:00\'\n','https://mariadb.com/kb/en/timestamp-function/'),(189,'PROCEDURE ANALYSE',33,'Syntax:\nANALYSE([max_elements[,max_memory]])\n\nANALYSE() examines the result from a query and returns an analysis of\nthe results that suggests optimal data types for each column that may\nhelp reduce table sizes. To obtain this analysis, append PROCEDURE\nANALYSE to the end of a SELECT statement:\n\nSELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])\n\nFor example:\n\nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n\nThe results show some statistics for the values returned by the query,\nand propose an optimal data type for the columns. This can be helpful\nfor checking your existing tables, or after importing new data. You may\nneed to try different settings for the arguments so that PROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n\nThe arguments are optional and are used as follows:\n\no max_elements (default 256) is the maximum number of distinct values\n that ANALYSE() notices per column. This is used by ANALYSE() to check\n whether the optimal data type should be of type ENUM; if there are\n more than max_elements distinct values, then ENUM is not a suggested\n type.\n\no max_memory (default 8192) is the maximum amount of memory that\n ANALYSE() should allocate per column while trying to find all\n distinct values.\n\nURL: https://mariadb.com/kb/en/procedure-analyse/\n\n','','https://mariadb.com/kb/en/procedure-analyse/'),(190,'HELP_VERSION',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25 (revision: 31914)\n\nThis information applies to MySQL 5.5 through 5.5.29.\n','',''),(191,'CHARACTER_LENGTH',37,'Syntax:\nCHARACTER_LENGTH(str)\n\nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n\nURL: https://mariadb.com/kb/en/character_length/\n\n','','https://mariadb.com/kb/en/character_length/'),(192,'SHOW GRANTS',26,'Syntax:\nSHOW GRANTS [FOR user]\n\nThis statement lists the GRANT statement or statements that must be\nissued to duplicate the privileges that are granted to a MySQL user\naccount. The account is named using the same format as for the GRANT\nstatement; for example, \'jeffrey\'@\'localhost\'. If you specify only the\nuser name part of the account name, a host name part of \'%\' is used.\nFor additional information about specifying account names, see [HELP\nGRANT].\n\nMariaDB> SHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION |\n+---------------------------------------------------------------------+\n\nTo list the privileges granted to the account that you are using to\nconnect to the server, you can use any of the following statements:\n\nSHOW GRANTS;\nSHOW GRANTS FOR CURRENT_USER;\nSHOW GRANTS FOR CURRENT_USER();\n\nIf SHOW GRANTS FOR CURRENT_USER (or any of the equivalent syntaxes) is\nused in DEFINER context, such as within a stored procedure that is\ndefined with SQL SECURITY DEFINER), the grants displayed are those of\nthe definer and not the invoker.\n\nURL: https://mariadb.com/kb/en/show-grants/\n\n','','https://mariadb.com/kb/en/show-grants/'),(193,'SHOW PRIVILEGES',26,'Syntax:\nSHOW PRIVILEGES\n\nSHOW PRIVILEGES shows the list of system privileges that the MySQL\nserver supports. The exact list of privileges depends on the version of\nyour server.\n\nURL: https://mariadb.com/kb/en/show-privileges/\n\n','','https://mariadb.com/kb/en/show-privileges/'),(194,'CREATE TABLESPACE',39,'Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n USE LOGFILE GROUP logfile_group\n [EXTENT_SIZE [=] extent_size]\n [INITIAL_SIZE [=] initial_size]\n [AUTOEXTEND_SIZE [=] autoextend_size]\n [MAX_SIZE [=] max_size]\n [NODEGROUP [=] nodegroup_id]\n [WAIT]\n [COMMENT [=] comment_text]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.','','https://mariadb.com/kb/en/create-tablespace/'),(195,'INSERT FUNCTION',37,'Syntax:\nINSERT(str,pos,len,newstr)\n\nReturns the string str, with the substring beginning at position pos\nand len characters long replaced by the string newstr. Returns the\noriginal string if pos is not within the length of the string. Replaces\nthe rest of the string from position pos if len is not within the\nlength of the rest of the string. Returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/insert-function/\n\n','MariaDB> SELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n -> \'QuWhattic\'\nMariaDB> SELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n -> \'Quadratic\'\nMariaDB> SELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n -> \'QuWhat\'\n','https://mariadb.com/kb/en/insert-function/'),(196,'CRC32',4,'Syntax:\nCRC32(expr)\n\nComputes a cyclic redundancy check value and returns a 32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The argument is\nexpected to be a string and (if possible) is treated as one if it is\nnot.\n\nURL: https://mariadb.com/kb/en/crc32/\n\n','MariaDB> SELECT CRC32(\'MySQL\');\n -> 3259397556\nMariaDB> SELECT CRC32(\'mysql\');\n -> 2501908538\n','https://mariadb.com/kb/en/crc32/'),(197,'XOR',15,'Syntax:\nXOR\n\nLogical XOR. Returns NULL if either operand is NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is nonzero,\notherwise 0 is returned.\n\nURL: https://mariadb.com/kb/en/xor/\n\n','MariaDB> SELECT 1 XOR 1;\n -> 0\nMariaDB> SELECT 1 XOR 0;\n -> 1\nMariaDB> SELECT 1 XOR NULL;\n -> NULL\nMariaDB> SELECT 1 XOR 1 XOR 1;\n -> 1\n','https://mariadb.com/kb/en/xor/'),(198,'STARTPOINT',13,'StartPoint(ls)\n\nReturns the Point that is the start point of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/startpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(StartPoint(GeomFromText(@ls)));\n+---------------------------------------+\n| AsText(StartPoint(GeomFromText(@ls))) |\n+---------------------------------------+\n| POINT(1 1) |\n+---------------------------------------+\n','https://mariadb.com/kb/en/startpoint/'),(199,'GRANT',10,'Syntax:\nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [, user_specification] ...\n [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]\n [WITH with_option ...]\n\nGRANT PROXY ON user_specification\n TO user_specification [, user_specification] ...\n [WITH GRANT OPTION]\n\nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n\npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nssl_option:\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n\nwith_option:\n GRANT OPTION\n | MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n\nThe GRANT statement grants privileges to MySQL user accounts. GRANT\nalso serves to specify other account characteristics such as use of\nsecure connections and limits on access to server resources. To use\nGRANT, you must have the GRANT OPTION privilege, and you must have the\nprivileges that you are granting.\n\nNormally, a database administrator first uses CREATE USER to create an\naccount, then GRANT to define its privileges and characteristics. For\nexample:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\nGRANT ALL ON db1.* TO \'jeffrey\'@\'localhost\';\nGRANT SELECT ON db2.invoice TO \'jeffrey\'@\'localhost\';\nGRANT USAGE ON *.* TO \'jeffrey\'@\'localhost\' WITH MAX_QUERIES_PER_HOUR 90;\n\nHowever, if an account named in a GRANT statement does not already\nexist, GRANT may create it under the conditions described later in the\ndiscussion of the NO_AUTO_CREATE_USER SQL mode.\n\nThe REVOKE statement is related to GRANT and enables administrators to\nremove account privileges. See [HELP REVOKE].\n\nWhen successfully executed from the mysql program, GRANT responds with\nQuery OK, 0 rows affected. To determine what privileges result from the\noperation, use SHOW GRANTS. See [HELP SHOW GRANTS].\n\nURL: https://mariadb.com/kb/en/grant/\n\n','','https://mariadb.com/kb/en/grant/'),(200,'DECLARE VARIABLE',23,'Syntax:\nDECLARE var_name [, var_name] ... type [DEFAULT value]\n\nThis statement declares local variables within stored programs. To\nprovide a default value for a variable, include a DEFAULT clause. The\nvalue can be specified as an expression; it need not be a constant. If\nthe DEFAULT clause is missing, the initial value is NULL.\n\nLocal variables are treated like stored routine parameters with respect\nto data type and overflow checking. See [HELP CREATE PROCEDURE].\n\nVariable declarations must appear before cursor or handler\ndeclarations.\n\nLocal variable names are not case sensitive. Permissible characters and\nquoting rules are the same as for other identifiers, as described in\nhttps://mariadb.com/kb/en/identifier-names/.\n\nThe scope of a local variable is the BEGIN ... END block within which\nit is declared. The variable can be referred to in blocks nested within\nthe declaring block, except those blocks that declare a variable with\nthe same name.\n\nURL: https://mariadb.com/kb/en/declare-variable/\n\n','','https://mariadb.com/kb/en/declare-variable/'),(201,'MPOLYFROMTEXT',3,'MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])\n\nConstructs a MULTIPOLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromtext/\n\n','','https://mariadb.com/kb/en/mpolyfromtext/'),(202,'MBRINTERSECTS',6,'MBRIntersects(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 intersect.\n\nURL: https://mariadb.com/kb/en/mbrintersects/\n\n','','https://mariadb.com/kb/en/mbrintersects/'),(203,'BIT_OR',16,'Syntax:\nBIT_OR(expr)\n\nReturns the bitwise OR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_or/\n\n','','https://mariadb.com/kb/en/bit_or/'),(204,'YEARWEEK',31,'Syntax:\nYEARWEEK(date), YEARWEEK(date,mode)\n\nReturns year and week for a date. The mode argument works exactly like\nthe mode argument to WEEK(). The year in the result may be different\nfrom the year in the date argument for the first and the last week of\nthe year.\n\nURL: https://mariadb.com/kb/en/yearweek/\n\n','MariaDB> SELECT YEARWEEK(\'1987-01-01\');\n -> 198653\n','https://mariadb.com/kb/en/yearweek/'),(205,'NOT BETWEEN',18,'Syntax:\nexpr NOT BETWEEN min AND max\n\nThis is the same as NOT (expr BETWEEN min AND max).\n\nURL: https://mariadb.com/kb/en/not-between/\n\n','','https://mariadb.com/kb/en/not-between/'),(206,'IS NOT',18,'Syntax:\nIS NOT boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is-not/\n\n','MariaDB> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not/'),(207,'LOG10',4,'Syntax:\nLOG10(X)\n\nReturns the base-10 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log10/\n\n','MariaDB> SELECT LOG10(2);\n -> 0.30102999566398\nMariaDB> SELECT LOG10(100);\n -> 2\nMariaDB> SELECT LOG10(-100);\n -> NULL\n','https://mariadb.com/kb/en/log10/'),(208,'SQRT',4,'Syntax:\nSQRT(X)\n\nReturns the square root of a nonnegative number X.\n\nURL: https://mariadb.com/kb/en/sqrt/\n\n','MariaDB> SELECT SQRT(4);\n -> 2\nMariaDB> SELECT SQRT(20);\n -> 4.4721359549996\nMariaDB> SELECT SQRT(-16);\n -> NULL\n','https://mariadb.com/kb/en/sqrt/'),(209,'DECIMAL',22,'DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nA packed \"exact\" fixed-point number. M is the total number of digits\n(the precision) and D is the number of digits after the decimal point\n(the scale). The decimal point and (for negative numbers) the \"-\" sign\nare not counted in M. If D is 0, values have no decimal point or\nfractional part. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30. If D is omitted,\nthe default is 0. If M is omitted, the default is 10.\n\nUNSIGNED, if specified, disallows negative values.\n\nAll basic calculations (+, -, *, /) with DECIMAL columns are done with\na precision of 65 digits.\n\nURL: https://mariadb.com/kb/en/decimal/\n\n','','https://mariadb.com/kb/en/decimal/'),(210,'CREATE INDEX',39,'Syntax:\nCREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [index_option] ...\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nCREATE INDEX is mapped to an ALTER TABLE statement to create indexes.\nSee [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY\nKEY; use ALTER TABLE instead. For more information about indexes, see\nhttps://mariadb.com/kb/en/optimization-and-indexes/.\n\nURL: https://mariadb.com/kb/en/create-index/\n\n','','https://mariadb.com/kb/en/create-index/'),(211,'CREATE FUNCTION',39,'The CREATE FUNCTION statement is used to create stored functions and\nuser-defined functions (UDFs):\n\no For information about creating stored functions, see [HELP CREATE\n PROCEDURE].\n\no For information about creating user-defined functions, see [HELP\n CREATE FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/create-function/\n\n','','https://mariadb.com/kb/en/create-function/'),(212,'ALTER DATABASE',39,'Syntax:\nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n\nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nALTER DATABASE enables you to change the overall characteristics of a\ndatabase. These characteristics are stored in the db.opt file in the\ndatabase directory. To use ALTER DATABASE, you need the ALTER privilege\non the database. ALTER SCHEMA is a synonym for ALTER DATABASE.\n\nThe database name can be omitted from the first syntax, in which case\nthe statement applies to the default database.\n\nNational Language Characteristics\n\nThe CHARACTER SET clause changes the default database character set.\nThe COLLATE clause changes the default database collation.\nhttps://mariadb.com/kb/en/data-types-character-sets-and-collations/, discusses\ncharacter set and collation names.\n\nYou can see what character sets and collations are available using,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION statements. See\n[HELP SHOW CHARACTER SET], and [HELP SHOW COLLATION], for more\ninformation.\n\nIf you change the default character set or collation for a database,\nstored routines that use the database defaults must be dropped and\nrecreated so that they use the new defaults. (In a stored routine,\nvariables with character data types use the database defaults if the\ncharacter set or collation are not specified explicitly. See [HELP\nCREATE PROCEDURE].)\n\nUpgrading from Versions Older than MySQL 5.1\n\nThe syntax that includes the UPGRADE DATA DIRECTORY NAME clause updates\nthe name of the directory associated with the database to use the\nencoding implemented in MySQL 5.1 for mapping database names to\ndatabase directory names (see\nhttps://mariadb.com/kb/en/identifier-to-file-name-mapping/). This\nclause is for use under these conditions:\n\no It is intended when upgrading MySQL to 5.1 or later from older\n versions.\n\no It is intended to update a database directory name to the current\n encoding format if the name contains special characters that need\n encoding.\n\no The statement is used by mysqlcheck (as invoked by mysql_upgrade).\n\nFor example, if a database in MySQL 5.0 has the name a-b-c, the name\ncontains instances of the - (dash) character. In MySQL 5.0, the\ndatabase directory is also named a-b-c, which is not necessarily safe\nfor all file systems. In MySQL 5.1 and later, the same database name is\nencoded as a@002db@002dc to produce a file system-neutral directory\nname.\n\nWhen a MySQL installation is upgraded to MySQL 5.1 or later from an\nolder version,the server displays a name such as a-b-c (which is in the\nold format) as #mysql50#a-b-c, and you must refer to the name using the\n#mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME in this case to\nexplicitly tell the server to re-encode the database directory name to\nthe current encoding format:\n\nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n\nAfter executing this statement, you can refer to the database as a-b-c\nwithout the special #mysql50# prefix.\n\nURL: https://mariadb.com/kb/en/alter-database/\n\n','','https://mariadb.com/kb/en/alter-database/'),(213,'GEOMETRYN',25,'GeometryN(gc,N)\n\nReturns the N-th geometry in the GeometryCollection value gc.\nGeometries are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/geometryn/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n','https://mariadb.com/kb/en/geometryn/'),(214,'<<',19,'Syntax:\n<<\n\nShifts a longlong (BIGINT) number to the left.\n\nURL: https://mariadb.com/kb/en/shift-left/\n\n','MariaDB> SELECT 1 << 2;\n -> 4\n','https://mariadb.com/kb/en/shift-left/'),(215,'SHOW TABLE STATUS',26,'Syntax:\nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLE STATUS works likes SHOW TABLES, but provides a lot of\ninformation about each non-TEMPORARY table. You can also get this list\nusing the mysqlshow --status db_name command. The LIKE clause, if\npresent, indicates which table names to match. The WHERE clause can be\ngiven to select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-table-status/\n\n','','https://mariadb.com/kb/en/show-table-status/'),(216,'MD5',12,'Syntax:\nMD5(str)\n\nCalculates an MD5 128-bit checksum for the string. The value is\nreturned as a string of 32 hex digits, or NULL if the argument was\nNULL. The return value can, for example, be used as a hash key. See the\nnotes at the beginning of this section about storing hash values\nefficiently.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/md5/\n\n','MariaDB> SELECT MD5(\'testing\');\n -> \'ae2b1fca515949e5d54fb22b8ed95575\'\n','https://mariadb.com/kb/en/md5/'),(217,'<',18,'Syntax:\n<\n\nLess than:\n\nURL: https://mariadb.com/kb/en/less-than/\n\n','MariaDB> SELECT 2 < 2;\n -> 0\n','https://mariadb.com/kb/en/less-than/'),(218,'UNIX_TIMESTAMP',31,'Syntax:\nUNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)\n\nIf called with no argument, returns a Unix timestamp (seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If UNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the argument as\nseconds since \'1970-01-01 00:00:00\' UTC. date may be a DATE string, a\nDATETIME string, a TIMESTAMP, or a number in the format YYMMDD or\nYYYYMMDD. The server interprets date as a value in the current time\nzone and converts it to an internal value in UTC. Clients can set their\ntime zone as described in\nhttps://mariadb.com/kb/en/time-zones/.\n\nURL: https://mariadb.com/kb/en/unix_timestamp/\n\n','MariaDB> SELECT UNIX_TIMESTAMP();\n -> 1196440210\nMariaDB> SELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n -> 1196440219\n','https://mariadb.com/kb/en/unix_timestamp/'),(219,'DAYOFMONTH',31,'Syntax:\nDAYOFMONTH(date)\n\nReturns the day of the month for date, in the range 1 to 31, or 0 for\ndates such as \'0000-00-00\' or \'2008-00-00\' that have a zero day part.\n\nURL: https://mariadb.com/kb/en/dayofmonth/\n\n','MariaDB> SELECT DAYOFMONTH(\'2007-02-03\');\n -> 3\n','https://mariadb.com/kb/en/dayofmonth/'),(220,'ASCII',37,'Syntax:\nASCII(str)\n\nReturns the numeric value of the leftmost character of the string str.\nReturns 0 if str is the empty string. Returns NULL if str is NULL.\nASCII() works for 8-bit characters.\n\nURL: https://mariadb.com/kb/en/ascii/\n\n','MariaDB> SELECT ASCII(\'2\');\n -> 50\nMariaDB> SELECT ASCII(2);\n -> 50\nMariaDB> SELECT ASCII(\'dx\');\n -> 100\n','https://mariadb.com/kb/en/ascii/'),(221,'DIV',4,'Syntax:\nDIV\n\nInteger division. Similar to FLOOR(), but is safe with BIGINT values.\n\nAs of MySQL 5.5.3, if either operand has a noninteger type, the\noperands are converted to DECIMAL and divided using DECIMAL arithmetic\nbefore converting the result to BIGINT. If the result exceeds BIGINT\nrange, an error occurs. Before MySQL 5.5.3, incorrect results may occur\nfor noninteger operands that exceed BIGINT range.\n\nURL: https://mariadb.com/kb/en/div/\n\n','MariaDB> SELECT 5 DIV 2;\n -> 2\n','https://mariadb.com/kb/en/div/'),(222,'RENAME USER',10,'Syntax:\nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n\nThe RENAME USER statement renames existing MySQL accounts. To use it,\nyou must have the global CREATE USER privilege or the UPDATE privilege\nfor the mysql database. An error occurs if any old account does not\nexist or any new account exists. Each account name uses the format\ndescribed in https://mariadb.com/kb/en/create-user/#account-names.\nFor example:\n\nRENAME USER \'jeffrey\'@\'localhost\' TO \'jeff\'@\'127.0.0.1\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nRENAME USER causes the privileges held by the old user to be those held\nby the new user. However, RENAME USER does not automatically drop or\ninvalidate databases or objects within them that the old user created.\nThis includes stored programs or views for which the DEFINER attribute\nnames the old user. Attempts to access such objects may produce an\nerror if they execute in definer security context. (For information\nabout security context, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.)\n\nThe privilege changes take effect as indicated in\nhttp://dev.mysql.com/doc/refman/5.5/en/privilege-changes.html.\n\nURL: https://mariadb.com/kb/en/rename-user/\n\n','','https://mariadb.com/kb/en/rename-user/'),(223,'SHOW SLAVE STATUS',26,'Syntax:\nSHOW SLAVE STATUS\n\nThis statement provides status information on essential parameters of\nthe slave threads. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nIf you issue this statement using the mysql client, you can use a \\G\nstatement terminator rather than a semicolon to obtain a more readable\nvertical layout:\n\nMariaDB> SHOW SLAVE STATUS\\G\n*************************** 1. row ***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: localhost\n Master_User: root\n Master_Port: 3306\n Connect_Retry: 3\n Master_Log_File: gbichot-bin.005\n Read_Master_Log_Pos: 79\n Relay_Log_File: gbichot-relay-bin.005\n Relay_Log_Pos: 548\n Relay_Master_Log_File: gbichot-bin.005\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB:\n Replicate_Ignore_DB:\n Replicate_Do_Table:\n Replicate_Ignore_Table:\n Replicate_Wild_Do_Table:\n Replicate_Wild_Ignore_Table:\n Last_Errno: 0\n Last_Error:\n Skip_Counter: 0\n Exec_Master_Log_Pos: 79\n Relay_Log_Space: 552\n Until_Condition: None\n Until_Log_File:\n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File:\n Master_SSL_CA_Path:\n Master_SSL_Cert:\n Master_SSL_Cipher:\n Master_SSL_Key:\n Seconds_Behind_Master: 8\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error:\n Last_SQL_Errno: 0\n Last_SQL_Error:\n Replicate_Ignore_Server_Ids: 0\n Master_Server_Id: 1\n\nURL: https://mariadb.com/kb/en/show-slave-status/\n\n','','https://mariadb.com/kb/en/show-slave-status/'),(224,'GEOMETRY',34,'MySQL provides a standard way of creating spatial columns for geometry\ntypes, for example, with CREATE TABLE or ALTER TABLE. Currently,\nspatial columns are supported for MyISAM, Aria, InnoDB and ARCHIVE\ntables. See also the annotations about spatial indexes under [HELP\nSPATIAL].\n\nURL: https://mariadb.com/kb/en/gis-functionality/\n\n','CREATE TABLE geom (g GEOMETRY);\n','https://mariadb.com/kb/en/gis-functionality/'),(225,'NUMPOINTS',13,'NumPoints(ls)\n\nReturns the number of Point objects in the LineString value ls.\n\nURL: https://mariadb.com/kb/en/numpoints/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n','https://mariadb.com/kb/en/numpoints/'),(226,'ALTER LOGFILE GROUP',39,'Syntax:\nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n','','https://mariadb.com/kb/en/alter-logfile-group/'),(227,'&',19,'Syntax:\n&\n\nBitwise AND:\n\nURL: https://mariadb.com/kb/en/bitwise_and/\n\n','MariaDB> SELECT 29 & 15;\n -> 13\n','https://mariadb.com/kb/en/bitwise_and/'),(228,'LOCALTIMESTAMP',31,'Syntax:\nLOCALTIMESTAMP, LOCALTIMESTAMP()\n\nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtimestamp/\n\n','','https://mariadb.com/kb/en/localtimestamp/'),(229,'ASSIGN-EQUAL',15,'Syntax:\n=\n\nThis operator is used to perform value assignments in two cases,\ndescribed in the next two paragraphs.\n\nWithin a SET statement, = is treated as an assignment operator that\ncauses the user variable on the left hand side of the operator to take\non the value to its right. (In other words, when used in a SET\nstatement, = is treated identically to :=.) The value on the right hand\nside may be a literal value, another variable storing a value, or any\nlegal expression that yields a scalar value, including the result of a\nquery (provided that this value is a scalar value). You can perform\nmultiple assignments in the same SET statement.\n\nIn the SET clause of an UPDATE statement, = also acts as an assignment\noperator; in this case, however, it causes the column named on the left\nhand side of the operator to assume the value given to the right,\nprovided any WHERE conditions that are part of the UPDATE are met. You\ncan make multiple assignments in the same SET clause of an UPDATE\nstatement.\n\nIn any other context, = is treated as a comparison operator.\n\nURL: https://mariadb.com/kb/en/assignment-operators-assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n','https://mariadb.com/kb/en/assignment-operators-assignment-operator/'),(230,'CONVERT',37,'Syntax:\nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n\nThe CONVERT() and CAST() functions take an expression of any type and\nproduce a result value of a specified type.\n\nThe type for the result can be one of the following values:\n\no BINARY[(N)]\n\no CHAR[(N)]\n\no DATE\n\no DATETIME\n\no DECIMAL[(M[,D])]\n\no SIGNED [INTEGER]\n\no TIME\n\no UNSIGNED [INTEGER]\n\nBINARY produces a string with the BINARY data type. See\nhttps://mariadb.com/kb/en/binary/ for a\ndescription of how this affects comparisons. If the optional length N\nis given, BINARY(N) causes the cast to use no more than N bytes of the\nargument. Values shorter than N bytes are padded with 0x00 bytes to a\nlength of N.\n\nCHAR(N) causes the cast to use no more than N characters of the\nargument.\n\nCAST() and CONVERT(... USING ...) are standard SQL syntax. The\nnon-USING form of CONVERT() is ODBC syntax.\n\nCONVERT() with USING is used to convert data between different\ncharacter sets. In MySQL, transcoding names are the same as the\ncorresponding character set names. For example, this statement converts\nthe string \'abc\' in the default character set to the corresponding\nstring in the utf8 character set:\n\nSELECT CONVERT(\'abc\' USING utf8);\n\nURL: https://mariadb.com/kb/en/convert/\n\n','SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);\n','https://mariadb.com/kb/en/convert/'),(231,'ADDDATE',31,'Syntax:\nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, ADDDATE()\nis a synonym for DATE_ADD(). The related function SUBDATE() is a\nsynonym for DATE_SUB(). For information on the INTERVAL unit argument,\nsee the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\nMariaDB> SELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\n\nWhen invoked with the days form of the second argument, MySQL treats it\nas an integer number of days to be added to expr.\n\nURL: https://mariadb.com/kb/en/adddate/\n\n','MariaDB> SELECT ADDDATE(\'2008-01-02\', 31);\n -> \'2008-02-02\'\n','https://mariadb.com/kb/en/adddate/'),(232,'REPEAT LOOP',23,'Syntax:\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\nThe statement list within a REPEAT statement is repeated until the\nsearch_condition expression is true. Thus, a REPEAT always enters the\nloop at least once. statement_list consists of one or more statements,\neach terminated by a semicolon (;) statement delimiter.\n\nA REPEAT statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/repeat-loop/\n\n','MariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE dorepeat(p1 INT)\n -> BEGIN\n -> SET @x = 0;\n -> REPEAT\n -> SET @x = @x + 1;\n -> UNTIL @x > p1 END REPEAT;\n -> END\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL dorepeat(1000)//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/repeat-loop/'),(233,'ALTER FUNCTION',39,'Syntax:\nALTER FUNCTION func_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nfunction. More than one change may be specified in an ALTER FUNCTION\nstatement. However, you cannot change the parameters or body of a\nstored function using this statement; to make such changes, you must\ndrop and re-create the function using DROP FUNCTION and CREATE\nFUNCTION.\n\nYou must have the ALTER ROUTINE privilege for the function. (That\nprivilege is granted automatically to the function creator.) If binary\nlogging is enabled, the ALTER FUNCTION statement might also require the\nSUPER privilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nURL: https://mariadb.com/kb/en/alter-function/\n\n','','https://mariadb.com/kb/en/alter-function/'),(234,'SMALLINT',22,'SMALLINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA small integer. The signed range is -32768 to 32767. The unsigned\nrange is 0 to 65535.\n\nURL: https://mariadb.com/kb/en/smallint/\n\n','','https://mariadb.com/kb/en/smallint/'),(235,'DOUBLE PRECISION',22,'DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED]\n[ZEROFILL]\n\nThese types are synonyms for DOUBLE. Exception: If the REAL_AS_FLOAT\nSQL mode is enabled, REAL is a synonym for FLOAT rather than DOUBLE.\n\nURL: https://mariadb.com/kb/en/double-precision/\n\n','','https://mariadb.com/kb/en/double-precision/'),(236,'ORD',37,'Syntax:\nORD(str)\n\nIf the leftmost character of the string str is a multi-byte character,\nreturns the code for that character, calculated from the numeric values\nof its constituent bytes using this formula:\n\n (1st byte code)\n+ (2nd byte code * 256)\n+ (3rd byte code * 2562) ...\n\nIf the leftmost character is not a multi-byte character, ORD() returns\nthe same value as the ASCII() function.\n\nURL: https://mariadb.com/kb/en/ord/\n\n','MariaDB> SELECT ORD(\'2\');\n -> 50\n','https://mariadb.com/kb/en/ord/'),(237,'DEALLOCATE PREPARE',8,'Syntax:\n{DEALLOCATE | DROP} PREPARE stmt_name\n\nTo deallocate a prepared statement produced with PREPARE, use a\nDEALLOCATE PREPARE statement that refers to the prepared statement\nname. Attempting to execute a prepared statement after deallocating it\nresults in an error.\n\nURL: https://mariadb.com/kb/en/deallocate-drop-prepared-statement/\n\n','','https://mariadb.com/kb/en/deallocate-drop-prepared-statement/'),(238,'ENVELOPE',36,'Envelope(g)\n\nReturns the Minimum Bounding Rectangle (MBR) for the geometry value g.\nThe result is returned as a Polygon value.\n\nThe polygon is defined by the corner points of the bounding box:\n\nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n\nURL: https://mariadb.com/kb/en/envelope/\n\n','MariaDB> SELECT AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\')));\n+-------------------------------------------------------+\n| AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\'))) |\n+-------------------------------------------------------+\n| POLYGON((1 1,2 1,2 2,1 2,1 1)) |\n+-------------------------------------------------------+\n','https://mariadb.com/kb/en/envelope/'),(239,'IS_FREE_LOCK',14,'Syntax:\nIS_FREE_LOCK(str)\n\nChecks whether the lock named str is free to use (that is, not locked).\nReturns 1 if the lock is free (no one is using the lock), 0 if the lock\nis in use, and NULL if an error occurs (such as an incorrect argument).\n\nURL: https://mariadb.com/kb/en/is_free_lock/\n\n','','https://mariadb.com/kb/en/is_free_lock/'),(240,'TOUCHES',30,'Touches(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially touches g2. Two\ngeometries spatially touch if the interiors of the geometries do not\nintersect, but the boundary of one of the geometries intersects either\nthe boundary or the interior of the other.\n\nURL: https://mariadb.com/kb/en/touches/\n\n','','https://mariadb.com/kb/en/touches/'),(241,'INET_ATON',14,'Syntax:\nINET_ATON(expr)\n\nGiven the dotted-quad representation of an IPv4 network address as a\nstring, returns an integer that represents the numeric value of the\naddress in network byte order (big endian). INET_ATON() returns NULL if\nit does not understand its argument.\n\nURL: https://mariadb.com/kb/en/inet_aton/\n\n','MariaDB> SELECT INET_ATON(\'10.0.5.9\');\n -> 167773449\n','https://mariadb.com/kb/en/inet_aton/'),(242,'UNCOMPRESS',12,'Syntax:\nUNCOMPRESS(string_to_uncompress)\n\nUncompresses a string compressed by the COMPRESS() function. If the\nargument is not a compressed value, the result is NULL. This function\nrequires MySQL to have been compiled with a compression library such as\nzlib. Otherwise, the return value is always NULL.\n\nURL: https://mariadb.com/kb/en/uncompress/\n\n','MariaDB> SELECT UNCOMPRESS(COMPRESS(\'any string\'));\n -> \'any string\'\nMariaDB> SELECT UNCOMPRESS(\'any string\');\n -> NULL\n','https://mariadb.com/kb/en/uncompress/'),(243,'AUTO_INCREMENT',22,'The AUTO_INCREMENT attribute can be used to generate a unique identity\nfor new rows:\n\nURL: https://mariadb.com/kb/en/auto_increment/\n\n','CREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n);\n\nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'lax\'),(\'whale\'),(\'ostrich\');\n\nSELECT * FROM animals;\n','https://mariadb.com/kb/en/auto_increment/'),(244,'ISSIMPLE',36,'IsSimple(g)\n\nCurrently, this function is a placeholder and should not be used. If\nimplemented, its behavior will be as described in the next paragraph.\n\nReturns 1 if the geometry value g has no anomalous geometric points,\nsuch as self-intersection or self-tangency. IsSimple() returns 0 if the\nargument is not simple, and -1 if it is NULL.\n\nThe description of each instantiable geometric class given earlier in\nthe chapter includes the specific conditions that cause an instance of\nthat class to be classified as not simple. (See [HELP Geometry\nhierarchy].)\n\nURL: https://mariadb.com/kb/en/issimple/\n\n','','https://mariadb.com/kb/en/issimple/'),(245,'- BINARY',4,'Syntax:\n-\n\nSubtraction:\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT 3-5;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(246,'GEOMCOLLFROMTEXT',3,'GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromtext/\n\n','','https://mariadb.com/kb/en/geomcollfromtext/'),(247,'WKT DEFINITION',3,'The Well-Known Text (WKT) representation of Geometry is designed to\nexchange geometry data in ASCII form. For a Backus-Naur grammar that\nspecifies the formal production rules for writing WKT values, see the\nOpenGIS specification document referenced in\nhttps://mariadb.com/kb/en/gis-resources/.\n\nURL: https://mariadb.com/kb/en/wkt-definition/\n\n','','https://mariadb.com/kb/en/wkt-definition/'),(248,'CURRENT_TIME',31,'Syntax:\nCURRENT_TIME, CURRENT_TIME()\n\nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n\nURL: https://mariadb.com/kb/en/current_time/\n\n','','https://mariadb.com/kb/en/current_time/'),(249,'REVOKE',10,'Syntax:\nREVOKE\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n\nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n\nREVOKE PROXY ON user\n FROM user [, user] ...\n\nThe REVOKE statement enables system administrators to revoke privileges\nfrom MySQL accounts. Each account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nREVOKE INSERT ON *.* FROM \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nFor details on the levels at which privileges exist, the permissible\npriv_type and priv_level values, and the syntax for specifying users\nand passwords, see [HELP GRANT]\n\nTo use the first REVOKE syntax, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are revoking.\n\nTo revoke all privileges, use the second syntax, which drops all\nglobal, database, table, column, and routine privileges for the named\nuser or users:\n\nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n\nTo use this REVOKE syntax, you must have the global CREATE USER\nprivilege or the UPDATE privilege for the mysql database.\n\nURL: https://mariadb.com/kb/en/revoke/\n\n','','https://mariadb.com/kb/en/revoke/'),(250,'LAST_INSERT_ID',17,'Syntax:\nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n\nLAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value\nrepresenting the first automatically generated value successfully\ninserted for an AUTO_INCREMENT column as a result of the most recently\nexecuted INSERT statement. The value of LAST_INSERT_ID() remains\nunchanged if no rows are successfully inserted.\n\nFor example, after inserting a row that generates an AUTO_INCREMENT\nvalue, you can get the value like this:\n\nMariaDB> SELECT LAST_INSERT_ID();\n -> 195\n\nThe currently executing statement does not affect the value of\nLAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table with its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain\nstable in the second statement; its value for the second and later rows\nis not affected by the earlier row insertions. (However, if you mix\nreferences to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is\nundefined.)\n\nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if the\nstatement is rolled back due to an error, the value of LAST_INSERT_ID()\nis left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID()\nis not restored to that before the transaction; it remains as it was at\nthe point of the ROLLBACK.\n\nWithin the body of a stored routine (procedure or function) or a\ntrigger, the value of LAST_INSERT_ID() changes the same way as for\nstatements executed outside the body of these kinds of objects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements depends on the\nkind of routine:\n\no If a stored procedure executes statements that change the value of\n LAST_INSERT_ID(), the changed value is seen by statements that follow\n the procedure call.\n\no For stored functions and triggers that change the value, the value is\n restored when the function or trigger ends, so following statements\n will not see a changed value.\n\nURL: https://mariadb.com/kb/en/last_insert_id/\n\n','','https://mariadb.com/kb/en/last_insert_id/'),(251,'LAST_DAY',31,'Syntax:\nLAST_DAY(date)\n\nTakes a date or datetime value and returns the corresponding value for\nthe last day of the month. Returns NULL if the argument is invalid.\n\nURL: https://mariadb.com/kb/en/last_day/\n\n','MariaDB> SELECT LAST_DAY(\'2003-02-05\');\n -> \'2003-02-28\'\nMariaDB> SELECT LAST_DAY(\'2004-02-05\');\n -> \'2004-02-29\'\nMariaDB> SELECT LAST_DAY(\'2004-01-01 01:01:01\');\n -> \'2004-01-31\'\nMariaDB> SELECT LAST_DAY(\'2003-03-32\');\n -> NULL\n','https://mariadb.com/kb/en/last_day/'),(252,'MEDIUMINT',22,'MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA medium-sized integer. The signed range is -8388608 to 8388607. The\nunsigned range is 0 to 16777215.\n\nURL: https://mariadb.com/kb/en/mediumint/\n\n','','https://mariadb.com/kb/en/mediumint/'),(253,'FLOOR',4,'Syntax:\nFLOOR(X)\n\nReturns the largest integer value not greater than X.\n\nURL: https://mariadb.com/kb/en/floor/\n\n','MariaDB> SELECT FLOOR(1.23);\n -> 1\nMariaDB> SELECT FLOOR(-1.23);\n -> -2\n','https://mariadb.com/kb/en/floor/'),(254,'RTRIM',37,'Syntax:\nRTRIM(str)\n\nReturns the string str with trailing space characters removed.\n\nURL: https://mariadb.com/kb/en/rtrim/\n\n','MariaDB> SELECT RTRIM(\'barbar \');\n -> \'barbar\'\n','https://mariadb.com/kb/en/rtrim/'),(255,'EXPLAIN',28,'Syntax:\nEXPLAIN [explain_type] SELECT select_options\n\nexplain_type:\n EXTENDED\n | PARTITIONS\n\nOr:\n\nEXPLAIN tbl_name\n\nThe EXPLAIN statement can be used either as a way to obtain information\nabout how MySQL executes a statement, or as a synonym for DESCRIBE:\n\no When you precede a SELECT statement with the keyword EXPLAIN, MySQL\n displays information from the optimizer about the query execution\n plan. That is, MySQL explains how it would process the statement,\n including information about how tables are joined and in which order.\n EXPLAIN EXTENDED can be used to obtain additional information.\n\n For information about using EXPLAIN and EXPLAIN EXTENDED to obtain\n query execution plan information, see\n https://mariadb.com/kb/en/explain/.\n\no EXPLAIN PARTITIONS is useful only when examining queries involving\n partitioned tables. For details, see\n http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.\n\no EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS\n FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see\n [HELP DESCRIBE], and [HELP SHOW COLUMNS].\n\nURL: https://mariadb.com/kb/en/explain/\n\n','','https://mariadb.com/kb/en/explain/'),(256,'DEGREES',4,'Syntax:\nDEGREES(X)\n\nReturns the argument X, converted from radians to degrees.\n\nURL: https://mariadb.com/kb/en/degrees/\n\n','MariaDB> SELECT DEGREES(PI());\n -> 180\nMariaDB> SELECT DEGREES(PI() / 2);\n -> 90\n','https://mariadb.com/kb/en/degrees/'),(257,'VARCHAR',22,'[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA variable-length string. M represents the maximum column length in\ncharacters. The range of M is 0 to 65,535. The effective maximum length\nof a VARCHAR is subject to the maximum row size (65,535 bytes, which is\nshared among all columns) and the character set used. For example, utf8\ncharacters can require up to three bytes per character, so a VARCHAR\ncolumn that uses the utf8 character set can be declared to be a maximum\nof 21,844 characters. See\nhttp://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html.\n\nMySQL stores VARCHAR values as a 1-byte or 2-byte length prefix plus\ndata. The length prefix indicates the number of bytes in the value. A\nVARCHAR column uses one length byte if values require no more than 255\nbytes, two length bytes if values may require more than 255 bytes.\n\n*Note*: MySQL 5.5 follows the standard SQL specification, and does not\nremove trailing spaces from VARCHAR values.\n\nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR is the\nstandard SQL way to define that a VARCHAR column should use some\npredefined character set. MySQL 4.1 and up uses utf8 as this predefined\ncharacter set.\nhttps://mariadb.com/kb/en/varchar/. NVARCHAR\nis shorthand for NATIONAL VARCHAR.\n\nURL: https://mariadb.com/kb/en/varchar/\n\n','','https://mariadb.com/kb/en/varchar/'),(258,'UNHEX',37,'Syntax:\n\nUNHEX(str)\n\nFor a string argument str, UNHEX(str) performs the inverse operation of\nHEX(str). That is, it interprets each pair of characters in the\nargument as a hexadecimal number and converts it to the character\nrepresented by the number. The return value is a binary string.\n\nURL: https://mariadb.com/kb/en/unhex/\n\n','MariaDB> SELECT UNHEX(\'4D7953514C\');\n -> \'MySQL\'\nMariaDB> SELECT 0x4D7953514C;\n -> \'MySQL\'\nMariaDB> SELECT UNHEX(HEX(\'string\'));\n -> \'string\'\nMariaDB> SELECT HEX(UNHEX(\'1267\'));\n -> \'1267\'\n','https://mariadb.com/kb/en/unhex/'),(259,'- UNARY',4,'Syntax:\n-\n\nUnary minus. This operator changes the sign of the operand.\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT - 2;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(260,'STD',16,'Syntax:\nSTD(expr)\n\nReturns the population standard deviation of expr. This is an extension\nto standard SQL. The standard SQL function STDDEV_POP() can be used\ninstead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/std/\n\n','','https://mariadb.com/kb/en/std/'),(261,'COS',4,'Syntax:\nCOS(X)\n\nReturns the cosine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/cos/\n\n','MariaDB> SELECT COS(PI());\n -> -1\n','https://mariadb.com/kb/en/cos/'),(262,'DATE FUNCTION',31,'Syntax:\nDATE(expr)\n\nExtracts the date part of the date or datetime expression expr.\n\nURL: https://mariadb.com/kb/en/date-function/\n\n','MariaDB> SELECT DATE(\'2003-12-31 01:02:03\');\n -> \'2003-12-31\'\n','https://mariadb.com/kb/en/date-function/'),(263,'DROP TRIGGER',39,'Syntax:\nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n\nThis statement drops a trigger. The schema (database) name is optional.\nIf the schema is omitted, the trigger is dropped from the default\nschema. DROP TRIGGER requires the TRIGGER privilege for the table\nassociated with the trigger.\n\nUse IF EXISTS to prevent an error from occurring for a trigger that\ndoes not exist. A NOTE is generated for a nonexistent trigger when\nusing IF EXISTS. See [HELP SHOW WARNINGS].\n\nTriggers for a table are also dropped if you drop the table.\n\nURL: https://mariadb.com/kb/en/drop-trigger/\n\n','','https://mariadb.com/kb/en/drop-trigger/'),(264,'RESET MASTER',8,'Syntax:\nRESET MASTER\n\nDeletes all binary log files listed in the index file, resets the\nbinary log index file to be empty, and creates a new binary log file.\nThis statement is intended to be used only when the master is started\nfor the first time.\n\nURL: https://mariadb.com/kb/en/reset-master/\n\n','','https://mariadb.com/kb/en/reset-master/'),(265,'TAN',4,'Syntax:\nTAN(X)\n\nReturns the tangent of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/tan/\n\n','MariaDB> SELECT TAN(PI());\n -> -1.2246063538224e-16\nMariaDB> SELECT TAN(PI()+1);\n -> 1.5574077246549\n','https://mariadb.com/kb/en/tan/'),(266,'PI',4,'Syntax:\nPI()\n\nReturns the value of π (pi). The default number of decimal places\ndisplayed is seven, but MySQL uses the full double-precision value\ninternally.\n\nURL: https://mariadb.com/kb/en/pi/\n\n','MariaDB> SELECT PI();\n -> 3.141593\nMariaDB> SELECT PI()+0.000000000000000000;\n -> 3.141592653589793116\n','https://mariadb.com/kb/en/pi/'),(267,'WEEKOFYEAR',31,'Syntax:\nWEEKOFYEAR(date)\n\nReturns the calendar week of the date as a number in the range from 1\nto 53. WEEKOFYEAR() is a compatibility function that is equivalent to\nWEEK(date,3).\n\nURL: https://mariadb.com/kb/en/weekofyear/\n\n','MariaDB> SELECT WEEKOFYEAR(\'2008-02-20\');\n -> 8\n','https://mariadb.com/kb/en/weekofyear/'),(268,'/',4,'Syntax:\n/\n\nDivision:\n\nURL: https://mariadb.com/kb/en/division-operator/\n\n','MariaDB> SELECT 3/5;\n -> 0.60\n','https://mariadb.com/kb/en/division-operator/'),(269,'PURGE BINARY LOGS',8,'Syntax:\nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n\nThe binary log is a set of files that contain information about data\nmodifications made by the MySQL server. The log consists of a set of\nbinary log files, plus an index file (see\nhttps://mariadb.com/kb/en/overview-of-the-binary-log/).\n\nThe PURGE BINARY LOGS statement deletes all the binary log files listed\nin the log index file prior to the specified log file name or date.\nBINARY and MASTER are synonyms. Deleted log files also are removed from\nthe list recorded in the index file, so that the given log file becomes\nthe first in the list.\n\nThis statement has no effect if the server was not started with the\n--log-bin option to enable binary logging.\n\nURL: https://mariadb.com/kb/en/sql-commands-purge-logs/\n\n','PURGE BINARY LOGS TO \'mysql-bin.010\';\nPURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\';\n','https://mariadb.com/kb/en/sql-commands-purge-logs/'),(270,'STDDEV_SAMP',16,'Syntax:\nSTDDEV_SAMP(expr)\n\nReturns the sample standard deviation of expr (the square root of\nVAR_SAMP().\n\nSTDDEV_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_samp/\n\n','','https://mariadb.com/kb/en/stddev_samp/'),(271,'SCHEMA',17,'Syntax:\nSCHEMA()\n\nThis function is a synonym for DATABASE().\n\nURL: https://mariadb.com/kb/en/schema/\n\n','','https://mariadb.com/kb/en/schema/'),(272,'MLINEFROMWKB',32,'MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])\n\nConstructs a MULTILINESTRING value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromwkb/\n\n','','https://mariadb.com/kb/en/mlinefromwkb/'),(273,'LOG2',4,'Syntax:\nLOG2(X)\n\nReturns the base-2 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log2/\n\n','MariaDB> SELECT LOG2(65536);\n -> 16\nMariaDB> SELECT LOG2(-100);\n -> NULL\n','https://mariadb.com/kb/en/log2/'),(274,'SUBTIME',31,'Syntax:\nSUBTIME(expr1,expr2)\n\nSUBTIME() returns expr1 - expr2 expressed as a value in the same format\nas expr1. expr1 is a time or datetime expression, and expr2 is a time\nexpression.\n\nURL: https://mariadb.com/kb/en/subtime/\n\n','MariaDB> SELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\');\n -> \'2007-12-30 22:58:58.999997\'\nMariaDB> SELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'-00:59:59.999999\'\n','https://mariadb.com/kb/en/subtime/'),(275,'UNCOMPRESSED_LENGTH',12,'Syntax:\nUNCOMPRESSED_LENGTH(compressed_string)\n\nReturns the length that the compressed string had before being\ncompressed.\n\nURL: https://mariadb.com/kb/en/uncompressed_length/\n\n','MariaDB> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n -> 30\n','https://mariadb.com/kb/en/uncompressed_length/'),(276,'DROP TABLE',39,'Syntax:\nDROP [TEMPORARY] TABLE [IF EXISTS]\n tbl_name [, tbl_name] ...\n [RESTRICT | CASCADE]\n\nDROP TABLE removes one or more tables. You must have the DROP privilege\nfor each table. All table data and the table definition are removed, so\nbe careful with this statement! If any of the tables named in the\nargument list do not exist, MySQL returns an error indicating by name\nwhich nonexisting tables it was unable to drop, but it also drops all\nof the tables in the list that do exist.\n\n*Important*: When a table is dropped, user privileges on the table are\nnot automatically dropped. See [HELP GRANT].\n\nNote that for a partitioned table, DROP TABLE permanently removes the\ntable definition, all of its partitions, and all of the data which was\nstored in those partitions. It also removes the partitioning definition\n(.par) file associated with the dropped table.\n\nUse IF EXISTS to prevent an error from occurring for tables that do not\nexist. A NOTE is generated for each nonexistent table when using IF\nEXISTS. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE are permitted to make porting easier. In MySQL\n5.5, they do nothing.\n\n*Note*: DROP TABLE automatically commits the current active\ntransaction, unless you use the TEMPORARY keyword.\n\nURL: https://mariadb.com/kb/en/drop-table/\n\n','','https://mariadb.com/kb/en/drop-table/'),(277,'POW',4,'Syntax:\nPOW(X,Y)\n\nReturns the value of X raised to the power of Y.\n\nURL: https://mariadb.com/kb/en/pow/\n\n','MariaDB> SELECT POW(2,2);\n -> 4\nMariaDB> SELECT POW(2,-2);\n -> 0.25\n','https://mariadb.com/kb/en/pow/'),(278,'SHOW CREATE TABLE',26,'Syntax:\nSHOW CREATE TABLE tbl_name\n\nShows the CREATE TABLE statement that creates the given table. To use\nthis statement, you must have some privilege for the table. This\nstatement also works with views.\nSHOW CREATE TABLE quotes table and column names according to the value\nof the sql_quote_show_create option. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/show-create-table/\n\n','MariaDB> SHOW CREATE TABLE t\\G\n*************************** 1. row ***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id INT(11) default NULL auto_increment,\n s char(60) default NULL,\n PRIMARY KEY (id)\n) ENGINE=MyISAM\n','https://mariadb.com/kb/en/show-create-table/'),(279,'DUAL',27,'You are permitted to specify DUAL as a dummy table name in situations\nwhere no tables are referenced:\n\nMariaDB> SELECT 1 + 1 FROM DUAL;\n -> 2\n\nDUAL is purely for the convenience of people who require that all\nSELECT statements should have FROM and possibly other clauses. MySQL\nmay ignore the clauses. MySQL does not require FROM DUAL if no tables\nare referenced.\n\nURL: https://mariadb.com/kb/en/dual/\n\n','','https://mariadb.com/kb/en/dual/'),(280,'INSTR',37,'Syntax:\nINSTR(str,substr)\n\nReturns the position of the first occurrence of substring substr in\nstring str. This is the same as the two-argument form of LOCATE(),\nexcept that the order of the arguments is reversed.\n\nURL: https://mariadb.com/kb/en/instr/\n\n','MariaDB> SELECT INSTR(\'foobarbar\', \'bar\');\n -> 4\nMariaDB> SELECT INSTR(\'xbar\', \'foobar\');\n -> 0\n','https://mariadb.com/kb/en/instr/'),(281,'NOW',31,'Syntax:\nNOW()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed in the\ncurrent time zone.\n\nURL: https://mariadb.com/kb/en/now/\n\n','MariaDB> SELECT NOW();\n -> \'2007-12-15 23:50:26\'\nMariaDB> SELECT NOW() + 0;\n -> 20071215235026.000000\n','https://mariadb.com/kb/en/now/'),(282,'SHOW ENGINES',26,'Syntax:\nSHOW [STORAGE] ENGINES\n\nSHOW ENGINES displays status information about the server\'s storage\nengines. This is particularly useful for checking whether a storage\nengine is supported, or to see what the default engine is.\n\nURL: https://mariadb.com/kb/en/show-engines/\n\n','','https://mariadb.com/kb/en/show-engines/'),(283,'>=',18,'Syntax:\n>=\n\nGreater than or equal:\n\nURL: https://mariadb.com/kb/en/greater-than-or-equal/\n\n','MariaDB> SELECT 2 >= 2;\n -> 1\n','https://mariadb.com/kb/en/greater-than-or-equal/'),(284,'EXP',4,'Syntax:\nEXP(X)\n\nReturns the value of e (the base of natural logarithms) raised to the\npower of X. The inverse of this function is LOG() (using a single\nargument only) or LN().\n\nURL: https://mariadb.com/kb/en/exp/\n\n','MariaDB> SELECT EXP(2);\n -> 7.3890560989307\nMariaDB> SELECT EXP(-2);\n -> 0.13533528323661\nMariaDB> SELECT EXP(0);\n -> 1\n','https://mariadb.com/kb/en/exp/'),(285,'LONGBLOB',22,'LONGBLOB\n\nA BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\nbytes. The effective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol and\navailable memory. Each LONGBLOB value is stored using a 4-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longblob/\n\n','','https://mariadb.com/kb/en/longblob/'),(286,'POINTN',13,'PointN(ls,N)\n\nReturns the N-th Point in the Linestring value ls. Points are numbered\nbeginning with 1.\n\nURL: https://mariadb.com/kb/en/pointn/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/pointn/'),(287,'YEAR DATA TYPE',22,'YEAR[(2|4)]\n\nA year in two-digit or four-digit format. The default is four-digit\nformat. YEAR(2) or YEAR(4) differ in display format, but have the same\nrange of values. In four-digit format, values display as 1901 to 2155,\nand 0000. In two-digit format, values display as 70 to 69, representing\nyears from 1970 to 2069. MySQL displays YEAR values in YYYY or\nYYformat, but permits assignment of values to YEAR columns using either\nstrings or numbers.\n\n*Note*: The YEAR(2) data type has certain issues that you should\nconsider before choosing to use it. As of MySQL 5.5.27, YEAR(2) is\ndeprecated. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/migrating-to-year4.html.\n\nFor additional information about YEAR display format and inerpretation\nof input values, see https://mariadb.com/kb/en/year-data-type/.\n\nURL: https://mariadb.com/kb/en/year-data-type/\n\n','','https://mariadb.com/kb/en/year-data-type/'),(288,'SUM',16,'Syntax:\nSUM([DISTINCT] expr)\n\nReturns the sum of expr. If the return set has no rows, SUM() returns\nNULL. The DISTINCT keyword can be used to sum only the distinct values\nof expr.\n\nSUM() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/sum/\n\n','','https://mariadb.com/kb/en/sum/'),(289,'OCT',37,'Syntax:\nOCT(N)\n\nReturns a string representation of the octal value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,8). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/oct/\n\n','MariaDB> SELECT OCT(12);\n -> \'14\'\n','https://mariadb.com/kb/en/oct/'),(290,'SYSDATE',31,'Syntax:\nSYSDATE()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context.\n\nSYSDATE() returns the time at which it executes. This differs from the\nbehavior for NOW(), which returns a constant time that indicates the\ntime at which the statement began to execute. (Within a stored function\nor trigger, NOW() returns the time at which the function or triggering\nstatement began to execute.)\n\nMariaDB> SELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |\n+---------------------+----------+---------------------+\n\nMariaDB> SELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |\n+---------------------+----------+---------------------+\n\nIn addition, the SET TIMESTAMP statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp settings in the\nbinary log have no effect on invocations of SYSDATE().\n\nBecause SYSDATE() can return different values even within the same\nstatement, and is not affected by SET TIMESTAMP, it is nondeterministic\nand therefore unsafe for replication if statement-based binary logging\nis used. If that is a problem, you can use row-based logging.\n\nAlternatively, you can use the --sysdate-is-now option to cause\nSYSDATE() to be an alias for NOW(). This works if the option is used on\nboth the master and the slave.\n\nThe nondeterministic nature of SYSDATE() also means that indexes cannot\nbe used for evaluating expressions that refer to it.\n\nURL: https://mariadb.com/kb/en/sysdate/\n\n','','https://mariadb.com/kb/en/sysdate/'),(291,'UNINSTALL PLUGIN',5,'Syntax:\nUNINSTALL PLUGIN plugin_name\n\nThis statement removes an installed server plugin. It requires the\nDELETE privilege for the mysql.plugin table.\n\nplugin_name must be the name of some plugin that is listed in the\nmysql.plugin table. The server executes the plugin\'s deinitialization\nfunction and removes the row for the plugin from the mysql.plugin\ntable, so that subsequent server restarts will not load and initialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s shared\nlibrary file.\n\nURL: https://mariadb.com/kb/en/uninstall-plugin/\n\n','','https://mariadb.com/kb/en/uninstall-plugin/'),(292,'ASBINARY',32,'AsBinary(g), AsWKB(g)\n\nConverts a value in internal geometry format to its WKB representation\nand returns the binary result.\n\nURL: https://mariadb.com/kb/en/asbinary/\n\n','SELECT AsBinary(g) FROM geom;\n','https://mariadb.com/kb/en/asbinary/'),(293,'REPEAT FUNCTION',37,'Syntax:\nREPEAT(str,count)\n\nReturns a string consisting of the string str repeated count times. If\ncount is less than 1, returns an empty string. Returns NULL if str or\ncount are NULL.\n\nURL: https://mariadb.com/kb/en/repeat-function/\n\n','MariaDB> SELECT REPEAT(\'MySQL\', 3);\n -> \'MySQLMySQLMySQL\'\n','https://mariadb.com/kb/en/repeat-function/'),(294,'SHOW TABLES',26,'Syntax:\nSHOW [FULL] TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLES lists the non-TEMPORARY tables in a given database. You can\nalso get this list using the mysqlshow db_name command. The LIKE\nclause, if present, indicates which table names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\n\nThis statement also lists any views in the database. The FULL modifier\nis supported such that SHOW FULL TABLES displays a second output\ncolumn. Values for the second column are BASE TABLE for a table and\nVIEW for a view.\n\nIf you have no privileges for a base table or view, it does not show up\nin the output from SHOW TABLES or mysqlshow db_name.\n\nURL: https://mariadb.com/kb/en/show-tables/\n\n','','https://mariadb.com/kb/en/show-tables/'),(295,'MAKEDATE',31,'Syntax:\nMAKEDATE(year,dayofyear)\n\nReturns a date, given year and day-of-year values. dayofyear must be\ngreater than 0 or the result is NULL.\n\nURL: https://mariadb.com/kb/en/makedate/\n\n','MariaDB> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n -> \'2011-01-31\', \'2011-02-01\'\nMariaDB> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n -> \'2011-12-31\', \'2014-12-31\'\nMariaDB> SELECT MAKEDATE(2011,0);\n -> NULL\n','https://mariadb.com/kb/en/makedate/'),(296,'BINARY OPERATOR',37,'Syntax:\nBINARY\n\nThe BINARY operator casts the string following it to a binary string.\nThis is an easy way to force a column comparison to be done byte by\nbyte rather than character by character. This causes the comparison to\nbe case sensitive even if the column is not defined as BINARY or BLOB.\nBINARY also causes trailing spaces to be significant.\n\nURL: https://mariadb.com/kb/en/binary-operator/\n\n','MariaDB> SELECT \'a\' = \'A\';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'A\';\n -> 0\nMariaDB> SELECT \'a\' = \'a \';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'a \';\n -> 0\n','https://mariadb.com/kb/en/binary-operator/'),(297,'MBROVERLAPS',6,'MBROverlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 overlap. The term spatially overlaps is\nused if two geometries intersect and their intersection results in a\ngeometry of the same dimension but not equal to either of the given\ngeometries.\n\nURL: https://mariadb.com/kb/en/mbroverlaps/\n\n','','https://mariadb.com/kb/en/mbroverlaps/'),(298,'SOUNDEX',37,'Syntax:\nSOUNDEX(str)\n\nReturns a soundex string from str. Two strings that sound almost the\nsame should have identical soundex strings. A standard soundex string\nis four characters long, but the SOUNDEX() function returns an\narbitrarily long string. You can use SUBSTRING() on the result to get a\nstandard soundex string. All nonalphabetic characters in str are\nignored. All international alphabetic characters outside the A-Z range\nare treated as vowels.\n\n*Important*: When using SOUNDEX(), you should be aware of the following\nlimitations:\n\no This function, as currently implemented, is intended to work well\n with strings that are in the English language only. Strings in other\n languages may not produce reliable results.\n\no This function is not guaranteed to provide consistent results with\n strings that use multi-byte character sets, including utf-8.\n\n We hope to remove these limitations in a future release. See Bug\n #22638 for more information.\n\nURL: https://mariadb.com/kb/en/soundex/\n\n','MariaDB> SELECT SOUNDEX(\'Hello\');\n -> \'H400\'\nMariaDB> SELECT SOUNDEX(\'Quadratically\');\n -> \'Q36324\'\n','https://mariadb.com/kb/en/soundex/'),(299,'MBRTOUCHES',6,'MBRTouches(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially touch if\nthe interiors of the geometries do not intersect, but the boundary of\none of the geometries intersects either the boundary or the interior of\nthe other.\n\nURL: https://mariadb.com/kb/en/mbrtouches/\n\n','','https://mariadb.com/kb/en/mbrtouches/'),(300,'DROP EVENT',39,'Syntax:\nDROP EVENT [IF EXISTS] event_name\n\nThis statement drops the event named event_name. The event immediately\nceases being active, and is deleted completely from the server.\n\nIf the event does not exist, the error ERROR 1517 (HY000): Unknown\nevent \'event_name\' results. You can override this and cause the\nstatement to generate a warning for nonexistent events instead using IF\nEXISTS.\n\nThis statement requires the EVENT privilege for the schema to which the\nevent to be dropped belongs.\n\nURL: https://mariadb.com/kb/en/drop-event/\n\n','','https://mariadb.com/kb/en/drop-event/'),(301,'INSERT SELECT',27,'Syntax:\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n\nWith INSERT ... SELECT, you can quickly insert many rows into a table\nfrom one or many tables. For example:\n\nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n\nURL: https://mariadb.com/kb/en/insert-select/\n\n','','https://mariadb.com/kb/en/insert-select/'),(302,'CREATE PROCEDURE',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n FUNCTION sp_name ([func_parameter[,...]])\n RETURNS type\n [characteristic ...] routine_body\n\nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n\nfunc_parameter:\n param_name type\n\ntype:\n Any valid MySQL data type\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nroutine_body:\n Valid SQL routine statement\n\nThese statements create stored routines. By default, a routine is\nassociated with the default database. To associate the routine\nexplicitly with a given database, specify the name as db_name.sp_name\nwhen you create it.\n\nThe CREATE FUNCTION statement is also used in MySQL to support UDFs\n(user-defined functions). See\nhttps://mariadb.com/kb/en/create-function-udf/. A UDF can\nbe regarded as an external stored function. Stored functions share\ntheir namespace with UDFs. See\nhttp://dev.mysql.com/doc/refman/5.5/en/function-resolution.html, for\nthe rules describing how the server interprets references to different\nkinds of functions.\n\nTo invoke a stored procedure, use the CALL statement (see [HELP CALL]).\nTo invoke a stored function, refer to it in an expression. The function\nreturns a value during expression evaluation.\n\nCREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE\nprivilege. They might also require the SUPER privilege, depending on\nthe DEFINER value, as described later in this section. If binary\nlogging is enabled, CREATE FUNCTION might require the SUPER privilege,\nas described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nBy default, MySQL automatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the routine creator. This behavior can be changed by\ndisabling the automatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nThe DEFINER and SQL SECURITY clauses specify the security context to be\nused when checking access privileges at routine execution time, as\ndescribed later in this section.\n\nIf the routine name is the same as the name of a built-in SQL function,\na syntax error occurs unless you use a space between the name and the\nfollowing parenthesis when defining the routine or invoking it later.\nFor this reason, avoid using the names of existing SQL functions for\nyour own stored routines.\n\nThe IGNORE_SPACE SQL mode applies to built-in functions, not to stored\nroutines. It is always permissible to have spaces after a stored\nroutine name, regardless of whether IGNORE_SPACE is enabled.\n\nThe parameter list enclosed within parentheses must always be present.\nIf there are no parameters, an empty parameter list of () should be\nused. Parameter names are not case sensitive.\n\nEach parameter is an IN parameter by default. To specify otherwise for\na parameter, use the keyword OUT or INOUT before the parameter name.\n\n*Note*: Specifying a parameter as IN, OUT, or INOUT is valid only for a\nPROCEDURE. For a FUNCTION, parameters are always regarded as IN\nparameters.\n\nAn IN parameter passes a value into a procedure. The procedure might\nmodify the value, but the modification is not visible to the caller\nwhen the procedure returns. An OUT parameter passes a value from the\nprocedure back to the caller. Its initial value is NULL within the\nprocedure, and its value is visible to the caller when the procedure\nreturns. An INOUT parameter is initialized by the caller, can be\nmodified by the procedure, and any change made by the procedure is\nvisible to the caller when the procedure returns.\n\nFor each OUT or INOUT parameter, pass a user-defined variable in the\nCALL statement that invokes the procedure so that you can obtain its\nvalue when the procedure returns. If you are calling the procedure from\nwithin another stored procedure or function, you can also pass a\nroutine parameter or local routine variable as an IN or INOUT\nparameter.\n\nThe following example shows a simple stored procedure that uses an OUT\nparameter:\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE simpleproc (OUT param1 INT)\n -> BEGIN\n -> SELECT COUNT(*) INTO param1 FROM t;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter ;\n\nMariaDB> CALL simpleproc(@a);\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @a;\n+------+\n| @a |\n+------+\n| 3 |\n+------+\n1 row in set (0.00 sec)\n\nThe example uses the mysql client delimiter command to change the\nstatement delimiter from ; to // while the procedure is being defined.\nThis enables the ; delimiter used in the procedure body to be passed\nthrough to the server rather than being interpreted by mysql itself.\nSee\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nThe RETURNS clause may be specified only for a FUNCTION, for which it\nis mandatory. It indicates the return type of the function, and the\nfunction body must contain a RETURN value statement. If the RETURN\nstatement returns a value of a different type, the value is coerced to\nthe proper type. For example, if a function specifies an ENUM or SET\nvalue in the RETURNS clause, but the RETURN statement returns an\ninteger, the value returned from the function is the string for the\ncorresponding ENUM member of set of SET members.\n\nThe following example function takes a parameter, performs an operation\nusing an SQL function, and returns the result. In this case, it is\nunnecessary to use delimiter because the function definition contains\nno internal ; statement delimiters:\n\nMariaDB> CREATE FUNCTION hello (s CHAR(20))\nMariaDB> RETURNS CHAR(50) DETERMINISTIC\n -> RETURN CONCAT(\'Hello, \',s,\'!\');\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n1 row in set (0.00 sec)\n\nParameter types and function return types can be declared to use any\nvalid data type, except that the COLLATE attribute cannot be used prior\nto MySQL 5.5.3. As of 5.5.3, COLLATE can be used if preceded by the\nCHARACTER SET attribute.\n\nThe routine_body consists of a valid SQL routine statement. This can be\na simple statement such as SELECT or INSERT, or a compound statement\nwritten using BEGIN and END. Compound statements can contain\ndeclarations, loops, and other control structure statements. The syntax\nfor these statements is described in\nhttps://mariadb.com/kb/programmatic-and-compound-statements.\n\nMySQL permits routines to contain DDL statements, such as CREATE and\nDROP. MySQL also permits stored procedures (but not stored functions)\nto contain SQL transaction statements such as COMMIT. Stored functions\nmay not contain statements that perform explicit or implicit commit or\nrollback. Support for these statements is not required by the SQL\nstandard, which states that each DBMS vendor may decide whether to\npermit them.\n\nStatements that return a result set can be used within a stored\nprocedure but not within a stored function. This prohibition includes\nSELECT statements that do not have an INTO var_list clause and other\nstatements such as SHOW, EXPLAIN, and CHECK TABLE. For statements that\ncan be determined at function definition time to return a result set, a\nNot allowed to return a result set from a function error occurs\n(ER_SP_NO_RETSET). For statements that can be determined only at\nruntime to return a result set, a PROCEDURE %s can\'t return a result\nset in the given context error occurs (ER_SP_BADSELECT).\n\nUSE statements within stored routines are not permitted. When a routine\nis invoked, an implicit USE db_name is performed (and undone when the\nroutine terminates). The causes the routine to have the given default\ndatabase while it executes. References to objects in databases other\nthan the routine default database should be qualified with the\nappropriate database name.\n\nFor additional information about statements that are not permitted in\nstored routines, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/\n.\n\nFor information about invoking stored procedures from within programs\nwritten in a language that has a MySQL interface, see [HELP CALL].\n\nMySQL stores the sql_mode system variable setting that is in effect at\nthe time a routine is created, and always executes the routine with\nthis setting in force, regardless of the server SQL mode in effect when\nthe routine is invoked.\n\nThe switch from the SQL mode of the invoker to that of the routine\noccurs after evaluation of arguments and assignment of the resulting\nvalues to routine parameters. If you define a routine in strict SQL\nmode but invoke it in nonstrict mode, assignment of arguments to\nroutine parameters does not take place in strict mode. If you require\nthat expressions passed to a routine be assigned in strict SQL mode,\nyou should invoke the routine with strict mode in effect.\n\nURL: https://mariadb.com/kb/en/create-procedure/\n\n','','https://mariadb.com/kb/en/create-procedure/'),(303,'VARBINARY',22,'VARBINARY(M)\n\nThe VARBINARY type is similar to the VARCHAR type, but stores binary\nbyte strings rather than nonbinary character strings. M represents the\nmaximum column length in bytes.\n\nURL: https://mariadb.com/kb/en/varbinary/\n\n','','https://mariadb.com/kb/en/varbinary/'),(304,'LOAD INDEX',26,'Syntax:\nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n\ntbl_index_list:\n tbl_name\n [PARTITION (partition_list | ALL)]\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe LOAD INDEX INTO CACHE statement preloads a table index into the key\ncache to which it has been assigned by an explicit CACHE INDEX\nstatement, or into the default key cache otherwise.\n\nLOAD INDEX INTO CACHE is used only for MyISAM tables. In MySQL 5.5, it\nis also supported for partitioned MyISAM tables; in addition, indexes\non partitioned tables can be preloaded for one, several, or all\npartitions.\n\nThe IGNORE LEAVES modifier causes only blocks for the nonleaf nodes of\nthe index to be preloaded.\n\nIGNORE LEAVES is also supported for partitioned MyISAM tables.\n\nURL: https://mariadb.com/kb/en/load-index/\n\n','','https://mariadb.com/kb/en/load-index/'),(305,'UNION',27,'Syntax:\nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n\nUNION is used to combine the result from multiple SELECT statements\ninto a single result set.\n\nThe column names from the first SELECT statement are used as the column\nnames for the results returned. Selected columns listed in\ncorresponding positions of each SELECT statement should have the same\ndata type. (For example, the first column selected by the first\nstatement should have the same type as the first column selected by the\nother statements.)\n\nURL: https://mariadb.com/kb/en/union/\n\n','','https://mariadb.com/kb/en/union/'),(306,'TO_DAYS',31,'Syntax:\nTO_DAYS(date)\n\nGiven a date date, returns a day number (the number of days since year\n0).\n\nURL: https://mariadb.com/kb/en/to_days/\n\n','MariaDB> SELECT TO_DAYS(950501);\n -> 728779\nMariaDB> SELECT TO_DAYS(\'2007-10-07\');\n -> 733321\n','https://mariadb.com/kb/en/to_days/'),(307,'NOT REGEXP',37,'Syntax:\nexpr NOT REGEXP pat, expr NOT RLIKE pat\n\nThis is the same as NOT (expr REGEXP pat).\n\nURL: https://mariadb.com/kb/en/not-regexp/\n\n','','https://mariadb.com/kb/en/not-regexp/'),(308,'SHOW INDEX',26,'Syntax:\nSHOW {INDEX | INDEXES | KEYS}\n {FROM | IN} tbl_name\n [{FROM | IN} db_name]\n [WHERE expr]\n\nSHOW INDEX returns table index information. The format resembles that\nof the SQLStatistics call in ODBC. This statement requires some\nprivilege for any column in the table.\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. These two statements are equivalent:\n\nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n\nThe WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou can also list a table\'s indexes with the mysqlshow -k db_name\ntbl_name command.\n\nURL: https://mariadb.com/kb/en/show-index/\n\n','','https://mariadb.com/kb/en/show-index/'),(309,'SHOW CREATE DATABASE',26,'Syntax:\nSHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n\nShows the CREATE DATABASE statement that creates the given database. If\nthe SHOW statement includes an IF NOT EXISTS clause, the output too\nincludes such a clause. SHOW CREATE SCHEMA is a synonym for SHOW CREATE\nDATABASE.\n\nURL: https://mariadb.com/kb/en/show-create-database/\n\n','MariaDB> SHOW CREATE DATABASE test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n\nMariaDB> SHOW CREATE SCHEMA test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n','https://mariadb.com/kb/en/show-create-database/'),(310,'LEAVE',23,'Syntax:\nLEAVE label\n\nThis statement is used to exit the flow control construct that has the\ngiven label. If the label is for the outermost stored program block,\nLEAVE exits the program.\n\nLEAVE can be used within BEGIN ... END or loop constructs (LOOP,\nREPEAT, WHILE).\n\nURL: https://mariadb.com/kb/en/leave/\n\n','','https://mariadb.com/kb/en/leave/'),(311,'NOT IN',18,'Syntax:\nexpr NOT IN (value,...)\n\nThis is the same as NOT (expr IN (value,...)).\n\nURL: https://mariadb.com/kb/en/not-in/\n\n','','https://mariadb.com/kb/en/not-in/'),(312,'!',15,'Syntax:\nNOT, !\n\nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is\nnonzero, and NOT NULL returns NULL.\n\nURL: https://mariadb.com/kb/en/not/\n\n','MariaDB> SELECT NOT 10;\n -> 0\nMariaDB> SELECT NOT 0;\n -> 1\nMariaDB> SELECT NOT NULL;\n -> NULL\nMariaDB> SELECT ! (1+1);\n -> 0\nMariaDB> SELECT ! 1+1;\n -> 1\n','https://mariadb.com/kb/en/not/'),(313,'DECLARE HANDLER',23,'Syntax:\nDECLARE handler_action HANDLER\n FOR condition_value [, condition_value] ...\n statement\n\nhandler_action:\n CONTINUE\n | EXIT\n | UNDO\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n\nThe DECLARE ... HANDLER statement specifies a handler that deals with\none or more conditions. If one of these conditions occurs, the\nspecified statement executes. statement can be a simple statement such\nas SET var_name = value, or a compound statement written using BEGIN\nand END (see [HELP BEGIN END]).\n\nHandler declarations must appear after variable or condition\ndeclarations.\n\nThe handler_action value indicates what action the handler takes after\nexecution of the handler statement:\n\no CONTINUE: Execution of the current program continues.\n\no EXIT: Execution terminates for the BEGIN ... END compound statement\n in which the handler is declared. This is true even if the condition\n occurs in an inner block.\n\no UNDO: Not supported.\n\nThe condition_value for DECLARE ... HANDLER indicates the specific\ncondition or class of conditions that activates the handler:\n\no A MySQL error code (a number) or an SQLSTATE value (a 5-character\n string literal). You should not use MySQL error code 0 or SQLSTATE\n values that begin with \'00\', because those indicate success rather\n than an error condition. For a list of MySQL error codes and SQLSTATE\n values, see\n https://mariadb.com/kb/en/mariadb-error-codes/.\n\no A condition name previously specified with DECLARE ... CONDITION. A\n condition name can be associated with a MySQL error code or SQLSTATE\n value. See [HELP DECLARE CONDITION].\n\no SQLWARNING is shorthand for the class of SQLSTATE values that begin\n with \'01\'.\n\no NOT FOUND is shorthand for the class of SQLSTATE values that begin\n with \'02\'. This is relevant within the context of cursors and is used\n to control what happens when a cursor reaches the end of a data set.\n If no more rows are available, a No Data condition occurs with\n SQLSTATE value \'02000\'. To detect this condition, you can set up a\n handler for it (or for a NOT FOUND condition). For an example, see\n https://mariadb.com/kb/en/cursor-overview/. This condition\n also occurs for SELECT ... INTO var_list statements that retrieve no\n rows.\n\no SQLEXCEPTION is shorthand for the class of SQLSTATE values that do\n not begin with \'00\', \'01\', or \'02\'.\n\nIf a condition occurs for which no handler has been declared, the\naction taken depends on the condition class:\n\no For SQLEXCEPTION conditions, the stored program terminates at the\n statement that raised the condition, as if there were an EXIT\n handler. If the program was called by another stored program, the\n calling program handles the condition using the handler selection\n rules applied to its own handlers.\n\no For SQLWARNING conditions, the program continues executing, as if\n there were a CONTINUE handler.\n\no For NOT FOUND conditions, if the condition was raised normally, the\n action is CONTINUE. If it was raised by SIGNAL or RESIGNAL, the\n action is EXIT.\n\nURL: https://mariadb.com/kb/en/declare-handler/\n\n','MariaDB> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE handlerdemo ()\n -> BEGIN\n -> DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 = 1;\n -> SET @x = 1;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 2;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 3;\n -> END;\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL handlerdemo()//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n +------+\n | @x |\n +------+\n | 3 |\n +------+\n 1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/declare-handler/'),(314,'DOUBLE',22,'DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA normal-size (double-precision) floating-point number. Permissible\nvalues are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and\n2.2250738585072014E-308 to 1.7976931348623157E+308. These are the\ntheoretical limits, based on the IEEE standard. The actual range might\nbe slightly smaller depending on your hardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A double-precision floating-point\nnumber is accurate to approximately 15 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nURL: https://mariadb.com/kb/en/double/\n\n','','https://mariadb.com/kb/en/double/'),(315,'TIME',22,'TIME\n\nA time. The range is \'-838:59:59\' to \'838:59:59\'. MySQL displays TIME\nvalues in \'HH:MM:SS\' format, but permits assignment of values to TIME\ncolumns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/time/\n\n','','https://mariadb.com/kb/en/time/'),(316,'&&',15,'Syntax:\nAND, &&\n\nLogical AND. Evaluates to 1 if all operands are nonzero and not NULL,\nto 0 if one or more operands are 0, otherwise NULL is returned.\n\nURL: https://mariadb.com/kb/en/and/\n\n','MariaDB> SELECT 1 && 1;\n -> 1\nMariaDB> SELECT 1 && 0;\n -> 0\nMariaDB> SELECT 1 && NULL;\n -> NULL\nMariaDB> SELECT 0 && NULL;\n -> 0\nMariaDB> SELECT NULL && 0;\n -> 0\n','https://mariadb.com/kb/en/and/'),(317,'X',11,'X(p)\n\nReturns the X-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/x/\n\n','MariaDB> SELECT X(POINT(56.7, 53.34));\n+-----------------------+\n| X(POINT(56.7, 53.34)) |\n+-----------------------+\n| 56.7 |\n+-----------------------+\n','https://mariadb.com/kb/en/x/'),(318,'SYSTEM_USER',17,'Syntax:\nSYSTEM_USER()\n\nSYSTEM_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/system_user/\n\n','','https://mariadb.com/kb/en/system_user/'),(319,'FOUND_ROWS',17,'Syntax:\nFOUND_ROWS()\n\nA SELECT statement may include a LIMIT clause to restrict the number of\nrows the server returns to the client. In some cases, it is desirable\nto know how many rows the statement would have returned without the\nLIMIT, but without running the statement again. To obtain this row\ncount, include a SQL_CALC_FOUND_ROWS option in the SELECT statement,\nand then invoke FOUND_ROWS() afterward:\n\nURL: https://mariadb.com/kb/en/found_rows/\n\n','MariaDB> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name\n -> WHERE id > 100 LIMIT 10;\nMariaDB> SELECT FOUND_ROWS();\n','https://mariadb.com/kb/en/found_rows/'),(320,'CROSSES',30,'Crosses(g1,g2)\n\nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon\nor a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise,\nreturns 0.\n\nThe term spatially crosses denotes a spatial relation between two given\ngeometries that has the following properties:\n\no The two geometries intersect\n\no Their intersection results in a geometry that has a dimension that is\n one less than the maximum dimension of the two given geometries\n\no Their intersection is not equal to either of the two given geometries\n\nURL: https://mariadb.com/kb/en/crosses/\n\n','','https://mariadb.com/kb/en/crosses/'),(321,'TRUNCATE TABLE',39,'Syntax:\nTRUNCATE [TABLE] tbl_name\n\nTRUNCATE TABLE empties a table completely. It requires the DROP\nprivilege.\n\nLogically, TRUNCATE TABLE is similar to a DELETE statement that deletes\nall rows, or a sequence of DROP TABLE and CREATE TABLE statements. To\nachieve high performance, it bypasses the DML method of deleting data.\nThus, it cannot be rolled back, it does not cause ON DELETE triggers to\nfire, and it cannot be performed for InnoDB tables with parent-child\nforeign key relationships.\n\nAlthough TRUNCATE TABLE is similar to DELETE, it is classified as a DDL\nstatement rather than a DML statement. It differs from DELETE in the\nfollowing ways in MySQL 5.5:\n\no Truncate operations drop and re-create the table, which is much\n faster than deleting rows one by one, particularly for large tables.\n\no Truncate operations cause an implicit commit, and so cannot be rolled\n back.\n\no Truncation operations cannot be performed if the session holds an\n active table lock.\n\no TRUNCATE TABLE fails for an InnoDB table if there are any FOREIGN KEY\n constraints from other tables that reference the table. Foreign key\n constraints between columns of the same table are permitted.\n\no Truncation operations do not return a meaningful value for the number\n of deleted rows. The usual result is \"0 rows affected,\" which should\n be interpreted as \"no information.\"\n\no As long as the table format file tbl_name.frm is valid, the table can\n be re-created as an empty table with TRUNCATE TABLE, even if the data\n or index files have become corrupted.\n\no Any AUTO_INCREMENT value is reset to its start value. This is true\n even for MyISAM and InnoDB, which normally do not reuse sequence\n values.\n\no When used with partitioned tables, TRUNCATE TABLE preserves the\n partitioning; that is, the data and index files are dropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\n\no The TRUNCATE TABLE statement does not invoke ON DELETE triggers.\n\nURL: https://mariadb.com/kb/en/truncate-table/\n\n','','https://mariadb.com/kb/en/truncate-table/'),(322,'BIT_XOR',16,'Syntax:\nBIT_XOR(expr)\n\nReturns the bitwise XOR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_xor/\n\n','','https://mariadb.com/kb/en/bit_xor/'),(323,'CURRENT_DATE',31,'Syntax:\nCURRENT_DATE, CURRENT_DATE()\n\nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n\nURL: https://mariadb.com/kb/en/current_date/\n\n','','https://mariadb.com/kb/en/current_date/'),(324,'START SLAVE',8,'Syntax:\nSTART SLAVE [thread_types]\n\nSTART SLAVE [SQL_THREAD] UNTIL\n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\n\nSTART SLAVE [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nSTART SLAVE with no thread_type options starts both of the slave\nthreads. The I/O thread reads events from the master server and stores\nthem in the relay log. The SQL thread reads events from the relay log\nand executes them. START SLAVE requires the SUPER privilege.\n\nIf START SLAVE succeeds in starting the slave threads, it returns\nwithout any error. However, even in that case, it might be that the\nslave threads start and then later stop (for example, because they do\nnot manage to connect to the master or read its binary log, or some\nother problem). START SLAVE does not warn you about this. You must\ncheck the slave\'s error log for error messages generated by the slave\nthreads, or check that they are running satisfactorily with SHOW SLAVE\nSTATUS.\n\nURL: https://mariadb.com/kb/en/start-slave/\n\n','','https://mariadb.com/kb/en/start-slave/'),(325,'AREA',2,'Area(poly)\n\nReturns as a double-precision number the area of the Polygon value\npoly, as measured in its spatial reference system.\n\nURL: https://mariadb.com/kb/en/area/\n\n','MariaDB> SET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))\';\nMariaDB> SELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n','https://mariadb.com/kb/en/area/'),(326,'FLUSH',26,'Syntax:\nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n\nThe FLUSH statement has several variant forms that clear or reload\nvarious internal caches, flush tables, or acquire locks. To execute\nFLUSH, you must have the RELOAD privilege. Specific flush options might\nrequire additional privileges, as described later.\n\nBy default, the server writes FLUSH statements to the binary log so\nthat they replicate to replication slaves. To suppress logging, use the\noptional NO_WRITE_TO_BINLOG keyword or its alias LOCAL.\n\n*Note*: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH\nREAD LOCK (with or without a table list) are not written to the binary\nlog in any case because they would cause problems if replicated to a\nslave.\n\nThe FLUSH statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nThe RESET statement is similar to FLUSH. See [HELP RESET], for\ninformation about using the RESET statement with replication.\n\nURL: https://mariadb.com/kb/en/flush/\n\n','','https://mariadb.com/kb/en/flush/'),(327,'BEGIN END',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\nBEGIN ... END syntax is used for writing compound statements, which can\nappear within stored programs (stored procedures and functions,\ntriggers, and events). A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords. statement_list\nrepresents a list of one or more statements, each terminated by a\nsemicolon (;) statement delimiter. The statement_list itself is\noptional, so the empty compound statement (BEGIN END) is legal.\n\nBEGIN ... END blocks can be nested.\n\nUse of multiple statements requires that a client is able to send\nstatement strings containing the ; statement delimiter. In the mysql\ncommand-line client, this is handled with the delimiter command.\nChanging the ; end-of-statement delimiter (for example, to //) permit ;\nto be used in a program body. For an example, see\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nA BEGIN ... END block can be labeled. See [HELP labels].\n\nURL: https://mariadb.com/kb/en/begin-end/\n\n','','https://mariadb.com/kb/en/begin-end/'),(328,'SHOW PROCEDURE STATUS',26,'Syntax:\nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is a MySQL extension. It returns characteristics of a\nstored procedure, such as the database, name, type, creator, creation\nand modification dates, and character set information. A similar\nstatement, SHOW FUNCTION STATUS, displays information about stored\nfunctions (see [HELP SHOW FUNCTION STATUS]).\n\nThe LIKE clause, if present, indicates which procedure or function\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-procedure-status/\n\n','MariaDB> SHOW PROCEDURE STATUS LIKE \'sp1\'\\G\n*************************** 1. row ***************************\n Db: test\n Name: sp1\n Type: PROCEDURE\n Definer: testuser@localhost\n Modified: 2004-08-03 15:29:37\n Created: 2004-08-03 15:29:37\n Security_type: DEFINER\n Comment:\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-procedure-status/'),(329,'DESCRIBE',28,'Syntax:\n{DESCRIBE | DESC} tbl_name [col_name | wild]\n\nDESCRIBE provides information about the columns in a table. It is a\nshortcut for SHOW COLUMNS FROM. These statements also display\ninformation for views. (See [HELP SHOW COLUMNS].)\n\ncol_name can be a column name, or a string containing the SQL \"%\" and\n\"_\" wildcard characters to obtain output only for the columns with\nnames matching the string. There is no need to enclose the string\nwithin quotation marks unless it contains spaces or other special\ncharacters.\n\nMariaDB> DESCRIBE City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nThe description for SHOW COLUMNS provides more information about the\noutput columns (see [HELP SHOW COLUMNS]).\n\nURL: https://mariadb.com/kb/en/describe/\n\n','','https://mariadb.com/kb/en/describe/'),(330,'SHOW WARNINGS',26,'Syntax:\nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW COUNT(*) WARNINGS\n\nSHOW WARNINGS shows information about the conditions (errors, warnings,\nand notes) that resulted from the last statement in the current session\nthat generated messages. It shows nothing if the last statement used a\ntable and generated no messages. (That is, a statement that uses a\ntable but generates no messages clears the message list.) Statements\nthat do not use tables and do not generate messages have no effect on\nthe message list.\n\nWarnings are generated for DML statements such as INSERT, UPDATE, and\nLOAD DATA INFILE as well as DDL statements such as CREATE TABLE and\nALTER TABLE.\n\nSHOW WARNINGS is also used following EXPLAIN EXTENDED, to display the\nextra information generated by EXPLAIN when the EXTENDED keyword is\nused. See https://mariadb.com/kb/en/explain#explain-extended.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nA related statement, SHOW ERRORS, shows only the error conditions (it\nexcludes warnings and notes). See [HELP SHOW ERRORS].\n\nThe SHOW COUNT(*) WARNINGS statement displays the total number of\nerrors, warnings, and notes. You can also retrieve this number from the\nwarning_count system variable:\n\nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n\nURL: https://mariadb.com/kb/en/show-warnings/\n\n','','https://mariadb.com/kb/en/show-warnings/'),(331,'DROP USER',10,'Syntax:\nDROP USER user [, user] ...\n\nThe DROP USER statement removes one or more MySQL accounts and their\nprivileges. It removes privilege rows for the account from all grant\ntables. To use this statement, you must have the global CREATE USER\nprivilege or the DELETE privilege for the mysql database. Each account\nname uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nDROP USER \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nURL: https://mariadb.com/kb/en/drop-user/\n\n','','https://mariadb.com/kb/en/drop-user/'),(332,'STDDEV_POP',16,'Syntax:\nSTDDEV_POP(expr)\n\nReturns the population standard deviation of expr (the square root of\nVAR_POP()). You can also use STD() or STDDEV(), which are equivalent\nbut not standard SQL.\n\nSTDDEV_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_pop/\n\n','','https://mariadb.com/kb/en/stddev_pop/'),(333,'SHOW CHARACTER SET',26,'Syntax:\nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n\nThe SHOW CHARACTER SET statement shows all available character sets.\nThe LIKE clause, if present, indicates which character set names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n\nURL: https://mariadb.com/kb/en/show-character-set/\n\n','','https://mariadb.com/kb/en/show-character-set/'),(334,'SUBSTRING',37,'Syntax:\nSUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n\nThe forms without a len argument return a substring from string str\nstarting at position pos. The forms with a len argument return a\nsubstring len characters long from string str, starting at position\npos. The forms that use FROM are standard SQL syntax. It is also\npossible to use a negative value for pos. In this case, the beginning\nof the substring is pos characters from the end of the string, rather\nthan the beginning. A negative value may be used for pos in any of the\nforms of this function.\n\nFor all forms of SUBSTRING(), the position of the first character in\nthe string from which the substring is to be extracted is reckoned as\n1.\n\nURL: https://mariadb.com/kb/en/substring/\n\n','MariaDB> SELECT SUBSTRING(\'Quadratically\',5);\n -> \'ratically\'\nMariaDB> SELECT SUBSTRING(\'foobarbar\' FROM 4);\n -> \'barbar\'\nMariaDB> SELECT SUBSTRING(\'Quadratically\',5,6);\n -> \'ratica\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -3);\n -> \'ila\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -5, 3);\n -> \'aki\'\nMariaDB> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);\n -> \'ki\'\n','https://mariadb.com/kb/en/substring/'),(335,'ISEMPTY',36,'IsEmpty(g)\n\nReturns 1 if the geometry value g is the empty geometry, 0 if it is not\nempty, and -1 if the argument is NULL. If the geometry is empty, it\nrepresents the empty point set.\n\nURL: https://mariadb.com/kb/en/isempty/\n\n','','https://mariadb.com/kb/en/isempty/'),(336,'SHOW FUNCTION STATUS',26,'Syntax:\nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is similar to SHOW PROCEDURE STATUS but for stored\nfunctions. See [HELP SHOW PROCEDURE STATUS].\n\nURL: https://mariadb.com/kb/en/show-function-status/\n\n','','https://mariadb.com/kb/en/show-function-status/'),(337,'LTRIM',37,'Syntax:\nLTRIM(str)\n\nReturns the string str with leading space characters removed.\n\nURL: https://mariadb.com/kb/en/ltrim/\n\n','MariaDB> SELECT LTRIM(\' barbar\');\n -> \'barbar\'\n','https://mariadb.com/kb/en/ltrim/'),(338,'INTERSECTS',30,'Intersects(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially intersects g2.\n\nURL: https://mariadb.com/kb/en/intersects/\n\n','','https://mariadb.com/kb/en/intersects/'),(339,'CALL',27,'Syntax:\nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n\nThe CALL statement invokes a stored procedure that was defined\npreviously with CREATE PROCEDURE.\n\nStored procedures that take no arguments can be invoked without\nparentheses. That is, CALL p() and CALL p are equivalent.\n\nCALL can pass back values to its caller using parameters that are\ndeclared as OUT or INOUT parameters. When the procedure returns, a\nclient program can also obtain the number of rows affected for the\nfinal statement executed within the routine: At the SQL level, call the\nROW_COUNT() function; from the C API, call the mysql_affected_rows()\nfunction.\n\nURL: https://mariadb.com/kb/en/call/\n\n','','https://mariadb.com/kb/en/call/'),(340,'MBRDISJOINT',6,'MBRDisjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are disjoint (do not intersect).\n\nURL: https://mariadb.com/kb/en/mbrdisjoint/\n\n','','https://mariadb.com/kb/en/mbrdisjoint/'),(341,'VALUES',14,'Syntax:\nVALUES(col_name)\n\nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the\nVALUES(col_name) function in the UPDATE clause to refer to column\nvalues from the INSERT portion of the statement. In other words,\nVALUES(col_name) in the UPDATE clause refers to the value of col_name\nthat would be inserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts. The VALUES()\nfunction is meaningful only in the ON DUPLICATE KEY UPDATE clause of\nINSERT statements and returns NULL otherwise. See\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nURL: https://mariadb.com/kb/en/values/\n\n','MariaDB> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n','https://mariadb.com/kb/en/values/'),(342,'SUBSTRING_INDEX',37,'Syntax:\nSUBSTRING_INDEX(str,delim,count)\n\nReturns the substring from string str before count occurrences of the\ndelimiter delim. If count is positive, everything to the left of the\nfinal delimiter (counting from the left) is returned. If count is\nnegative, everything to the right of the final delimiter (counting from\nthe right) is returned. SUBSTRING_INDEX() performs a case-sensitive\nmatch when searching for delim.\n\nURL: https://mariadb.com/kb/en/substring_index/\n\n','MariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2);\n -> \'www.mariadb\'\nMariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2);\n -> \'mariadb.org\'\n','https://mariadb.com/kb/en/substring_index/'),(343,'ENCODE',12,'Syntax:\nENCODE(str,pass_str)\n\nEncrypt str using pass_str as the password. To decrypt the result, use\nDECODE().\n\nThe result is a binary string of the same length as str.\n\nThe strength of the encryption is based on how good the random\ngenerator is. It should suffice for short strings.\n\nURL: https://mariadb.com/kb/en/encode/\n\n','','https://mariadb.com/kb/en/encode/'),(344,'LOOP',23,'Syntax:\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\nLOOP implements a simple loop construct, enabling repeated execution of\nthe statement list, which consists of one or more statements, each\nterminated by a semicolon (;) statement delimiter. The statements\nwithin the loop are repeated until the loop is terminated. Usually,\nthis is accomplished with a LEAVE statement. Within a stored function,\nRETURN can also be used, which exits the function entirely.\n\nNeglecting to include a loop-termination statement results in an\ninfinite loop.\n\nA LOOP statement can be labeled. For the rules regarding label use, see\n[HELP labels].\n\nURL: https://mariadb.com/kb/en/loop/\n\n','CREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN\n ITERATE label1;\n END IF;\n LEAVE label1;\n END LOOP label1;\n SET @x = p1;\nEND;\n','https://mariadb.com/kb/en/loop/'),(345,'TRUNCATE',4,'Syntax:\nTRUNCATE(X,D)\n\nReturns the number X, truncated to D decimal places. If D is 0, the\nresult has no decimal point or fractional part. D can be negative to\ncause D digits left of the decimal point of the value X to become zero.\n\nURL: https://mariadb.com/kb/en/truncate/\n\n','MariaDB> SELECT TRUNCATE(1.223,1);\n -> 1.2\nMariaDB> SELECT TRUNCATE(1.999,1);\n -> 1.9\nMariaDB> SELECT TRUNCATE(1.999,0);\n -> 1\nMariaDB> SELECT TRUNCATE(-1.999,1);\n -> -1.9\nMariaDB> SELECT TRUNCATE(122,-2);\n -> 100\nMariaDB> SELECT TRUNCATE(10.28*100,0);\n -> 1028\n','https://mariadb.com/kb/en/truncate/'),(346,'TIMESTAMPADD',31,'Syntax:\nTIMESTAMPADD(unit,interval,datetime_expr)\n\nAdds the integer expression interval to the date or datetime expression\ndatetime_expr. The unit for interval is given by the unit argument,\nwhich should be one of the following values: MICROSECOND\n(microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or\nYEAR.\n\nIt is possible to use FRAC_SECOND in place of MICROSECOND, but\nFRAC_SECOND is deprecated. FRAC_SECOND was removed in MySQL 5.5.3.\n\nThe unit value may be specified using one of keywords as shown, or with\na prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY both are legal.\n\nURL: https://mariadb.com/kb/en/timestampadd/\n\n','MariaDB> SELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n -> \'2003-01-02 00:01:00\'\nMariaDB> SELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n -> \'2003-01-09\'\n','https://mariadb.com/kb/en/timestampadd/'),(347,'SHOW',26,'SHOW has many forms that provide information about databases, tables,\ncolumns, or status information about the server. This section describes\nthose following:\n\nSHOW AUTHORS\nSHOW {BINARY | MASTER} LOGS\nSHOW BINLOG EVENTS [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE FUNCTION func_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW MASTER STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW SLAVE HOSTS\nSHOW SLAVE STATUS\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW [FULL] TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n\nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n\nIf the syntax for a given SHOW statement includes a LIKE \'pattern\'\npart, \'pattern\' is a string that can contain the SQL \"%\" and \"_\"\nwildcard characters. The pattern is useful for restricting statement\noutput to matching values.\n\nSeveral SHOW statements also accept a WHERE clause that provides more\nflexibility in specifying which rows to display. See\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show/\n\n','','https://mariadb.com/kb/en/show/'),(348,'GREATEST',18,'Syntax:\nGREATEST(value1,value2,...)\n\nWith two or more arguments, returns the largest (maximum-valued)\nargument. The arguments are compared using the same rules as for\nLEAST().\n\nURL: https://mariadb.com/kb/en/greatest/\n\n','MariaDB> SELECT GREATEST(2,0);\n -> 2\nMariaDB> SELECT GREATEST(34.0,3.0,5.0,767.0);\n -> 767.0\nMariaDB> SELECT GREATEST(\'B\',\'A\',\'C\');\n -> \'C\'\n','https://mariadb.com/kb/en/greatest/'),(349,'SHOW VARIABLES',26,'Syntax:\nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW VARIABLES shows the values of MySQL system variables. This\ninformation also can be obtained using the mysqladmin variables\ncommand. The LIKE clause, if present, indicates which variable names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. This\nstatement does not require any privilege. It requires only the ability\nto connect to the server.\n\nWith the GLOBAL modifier, SHOW VARIABLES displays the values that are\nused for new connections to MySQL. As of MySQL 5.5.3, if a variable has\nno global value, no value is displayed. Before 5.5.3, the session value\nis displayed. With SESSION, SHOW VARIABLES displays the values that are\nin effect for the current connection. If no modifier is present, the\ndefault is SESSION. LOCAL is a synonym for SESSION.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern. To obtain the row for a\nspecific variable, use a LIKE clause as shown:\n\nSHOW VARIABLES LIKE \'max_join_size\';\nSHOW SESSION VARIABLES LIKE \'max_join_size\';\n\nTo get a list of variables whose name match a pattern, use the \"%\"\nwildcard character in a LIKE clause:\n\nSHOW VARIABLES LIKE \'%size%\';\nSHOW GLOBAL VARIABLES LIKE \'%size%\';\n\nWildcard characters can be used in any position within the pattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard that matches\nany single character, you should escape it as \"\\_\" to match it\nliterally. In practice, this is rarely necessary.\n\nURL: https://mariadb.com/kb/en/show-variables/\n\n','','https://mariadb.com/kb/en/show-variables/'),(350,'BINLOG',26,'Syntax:\nBINLOG \'str\'\n\nBINLOG is an internal-use statement. It is generated by the mysqlbinlog\nprogram as the printable representation of certain events in binary log\nfiles. (See https://mariadb.com/kb/en/mysqlbinlog/.)\nThe \'str\' value is a base 64-encoded string the that server decodes to\ndetermine the data change indicated by the corresponding event. This\nstatement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/binlog/\n\n','','https://mariadb.com/kb/en/binlog/'),(351,'BIT_AND',16,'Syntax:\nBIT_AND(expr)\n\nReturns the bitwise AND of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_and/\n\n','','https://mariadb.com/kb/en/bit_and/'),(352,'SECOND',31,'Syntax:\nSECOND(time)\n\nReturns the second for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/second/\n\n','MariaDB> SELECT SECOND(\'10:05:03\');\n -> 3\n','https://mariadb.com/kb/en/second/'),(353,'ATAN2',4,'Syntax:\nATAN(Y,X), ATAN2(Y,X)\n\nReturns the arc tangent of the two variables X and Y. It is similar to\ncalculating the arc tangent of Y / X, except that the signs of both\narguments are used to determine the quadrant of the result.\n\nURL: https://mariadb.com/kb/en/atan2/\n\n','MariaDB> SELECT ATAN(-2,2);\n -> -0.78539816339745\nMariaDB> SELECT ATAN2(PI(),0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/atan2/'),(354,'MBRCONTAINS',6,'MBRContains(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\ncontains the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRWithin().\n\nURL: https://mariadb.com/kb/en/mbrcontains/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Point(1 1)\');\nMariaDB> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n','https://mariadb.com/kb/en/mbrcontains/'),(355,'HOUR',31,'Syntax:\nHOUR(time)\n\nReturns the hour for time. The range of the return value is 0 to 23 for\ntime-of-day values. However, the range of TIME values actually is much\nlarger, so HOUR can return values greater than 23.\n\nURL: https://mariadb.com/kb/en/hour/\n\n','MariaDB> SELECT HOUR(\'10:05:03\');\n -> 10\nMariaDB> SELECT HOUR(\'272:59:59\');\n -> 272\n','https://mariadb.com/kb/en/hour/'),(356,'SELECT',27,'Syntax:\nSELECT\n [ALL | DISTINCT | DISTINCTROW ]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position}\n [ASC | DESC], ... [WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position}\n [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n [PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n export_options\n | INTO DUMPFILE \'file_name\'\n | INTO var_name [, var_name]]\n [FOR UPDATE | LOCK IN SHARE MODE]]\n\nSELECT is used to retrieve rows selected from one or more tables, and\ncan include UNION statements and subqueries. See [HELP UNION], and\nhttps://mariadb.com/kb/en/subqueries/.\n\nThe most commonly used clauses of SELECT statements are these:\n\no Each select_expr indicates a column that you want to retrieve. There\n must be at least one select_expr.\n\no table_references indicates the table or tables from which to retrieve\n rows. Its syntax is described in [HELP JOIN].\n\no The WHERE clause, if given, indicates the condition or conditions\n that rows must satisfy to be selected. where_condition is an\n expression that evaluates to true for each row to be selected. The\n statement selects all rows if there is no WHERE clause.\n\n In the WHERE expression, you can use any of the functions and\n operators that MySQL supports, except for aggregate (summary)\n functions. See\n https://mariadb.com/kb/en/select#select-expressions, and\n https://mariadb.com/kb/en/functions-and-operators/.\n\nSELECT can also be used to retrieve rows computed without reference to\nany table.\n\nURL: https://mariadb.com/kb/en/select/\n\n','','https://mariadb.com/kb/en/select/'),(357,'COT',4,'Syntax:\nCOT(X)\n\nReturns the cotangent of X.\n\nURL: https://mariadb.com/kb/en/cot/\n\n','MariaDB> SELECT COT(12);\n -> -1.5726734063977\nMariaDB> SELECT COT(0);\n -> NULL\n','https://mariadb.com/kb/en/cot/'),(358,'SHOW CREATE EVENT',26,'Syntax:\nSHOW CREATE EVENT event_name\n\nThis statement displays the CREATE EVENT statement needed to re-create\na given event. It requires the EVENT privilege for the database from\nwhich the event is to be shown. For example (using the same event\ne_daily defined and then altered in [HELP SHOW EVENTS]):\n\nURL: https://mariadb.com/kb/en/show-create-event/\n\n','MariaDB> SHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row ***************************\n Event: e_daily\n sql_mode:\n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*)\n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-event/'),(359,'LOAD_FILE',37,'Syntax:\nLOAD_FILE(file_name)\n\nReads the file and returns the file contents as a string. To use this\nfunction, the file must be located on the server host, you must specify\nthe full path name to the file, and you must have the FILE privilege.\nThe file must be readable by all and its size less than\nmax_allowed_packet bytes. If the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nIf the file does not exist or cannot be read because one of the\npreceding conditions is not satisfied, the function returns NULL.\n\nThe character_set_filesystem system variable controls interpretation of\nfile names that are given as literal strings.\n\nURL: https://mariadb.com/kb/en/load_file/\n\n','MariaDB> UPDATE t\n SET blob_col=LOAD_FILE(\'/tmp/picture\')\n WHERE id=1;\n','https://mariadb.com/kb/en/load_file/'),(360,'POINTFROMTEXT',3,'PointFromText(wkt[,srid])\n\nConstructs a POINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromtext/\n\n','','https://mariadb.com/kb/en/pointfromtext/'),(361,'GROUP_CONCAT',16,'Syntax:\nGROUP_CONCAT(expr)\n\nThis function returns a string result with the concatenated non-NULL\nvalues from a group. It returns NULL if there are no non-NULL values.\nThe full syntax is as follows:\n\nGROUP_CONCAT([DISTINCT] expr [,expr ...]\n [ORDER BY {unsigned_integer | col_name | expr}\n [ASC | DESC] [,col_name ...]]\n [SEPARATOR str_val])\n\nURL: https://mariadb.com/kb/en/group_concat/\n\n','MariaDB> SELECT student_name,\n -> GROUP_CONCAT(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/group_concat/'),(362,'DATE_FORMAT',31,'Syntax:\nDATE_FORMAT(date,format)\n\nFormats the date value according to the format string.\n\nURL: https://mariadb.com/kb/en/date_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n -> \'Sunday October 2009\'\nMariaDB> SELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n -> \'22:23:00\'\nMariaDB> SELECT DATE_FORMAT(\'1900-10-04 22:23:00\',\n -> \'%D %y %a %d %m %b %j\');\n -> \'4th 00 Thu 04 10 Oct 277\'\nMariaDB> SELECT DATE_FORMAT(\'1997-10-04 22:23:00\',\n -> \'%H %k %I %r %T %S %w\');\n -> \'22 22 10 10:23:00 PM 22:23:00 00 6\'\nMariaDB> SELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n -> \'1998 52\'\nMariaDB> SELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n -> \'00\'\n','https://mariadb.com/kb/en/date_format/'),(363,'BENCHMARK',17,'Syntax:\nBENCHMARK(count,expr)\n\nThe BENCHMARK() function executes the expression expr repeatedly count\ntimes. It may be used to time how quickly MySQL processes the\nexpression. The result value is always 0. The intended use is from\nwithin the mysql client, which reports query execution times:\n\nURL: https://mariadb.com/kb/en/benchmark/\n\n','MariaDB> SELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (4.74 sec)\n','https://mariadb.com/kb/en/benchmark/'),(364,'YEAR',31,'Syntax:\nYEAR(date)\n\nReturns the year for date, in the range 1000 to 9999, or 0 for the\n\"zero\" date.\n\nURL: https://mariadb.com/kb/en/year/\n\n','MariaDB> SELECT YEAR(\'1987-01-01\');\n -> 1987\n','https://mariadb.com/kb/en/year/'),(365,'SHOW ENGINE',26,'Syntax:\nSHOW ENGINE engine_name {STATUS | MUTEX}\n\nSHOW ENGINE displays operational information about a storage engine.\nThe following statements currently are supported:\n\nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n\nSHOW ENGINE INNODB STATUS displays extensive information from the\nstandard InnoDB Monitor about the state of the InnoDB storage engine.\nFor information about the standard monitor and other InnoDB Monitors\nthat provide information about InnoDB processing, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-monitors.html.\n\nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics. The\nstatement displays the following fields:\n\no Type\n\n Always InnoDB.\n\no Name\n\n The source file where the mutex is implemented, and the line number\n in the file where the mutex is created. The line number may change\n depending on your version of MySQL.\n\no Status\n\n The mutex status. This field displays several values if UNIV_DEBUG\n was defined at MySQL compilation time (for example, in include/univ.i\n in the InnoDB part of the MySQL source tree). If UNIV_DEBUG was not\n defined, the statement displays only the os_waits value. In the\n latter case (without UNIV_DEBUG), the information on which the output\n is based is insufficient to distinguish regular mutexes and mutexes\n that protect rw-locks (which permit multiple readers or a single\n writer). Consequently, the output may appear to contain multiple rows\n for the same mutex.\n\n o count indicates how many times the mutex was requested.\n\n o spin_waits indicates how many times the spinlock had to run.\n\n o spin_rounds indicates the number of spinlock rounds. (spin_rounds\n divided by spin_waits provides the average round count.)\n\n o os_waits indicates the number of operating system waits. This\n occurs when the spinlock did not work (the mutex was not locked\n during the spinlock and it was necessary to yield to the operating\n system and wait).\n\n o os_yields indicates the number of times a the thread trying to lock\n a mutex gave up its timeslice and yielded to the operating system\n (on the presumption that permitting other threads to run will free\n the mutex so that it can be locked).\n\n o os_wait_times indicates the amount of time (in ms) spent in\n operating system waits, if the timed_mutexes system variable is 1\n (ON). If timed_mutexes is 0 (OFF), timing is disabled, so\n os_wait_times is 0. timed_mutexes is off by default.\n\nInformation from this statement can be used to diagnose system\nproblems. For example, large values of spin_waits and spin_rounds may\nindicate scalability problems.\n\nUse SHOW ENGINE PERFORMANCE_SCHEMA STATUS to inspect the internal\noperation of the Performance Schema code:\n\nMariaDB> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\\G\n...\n*************************** 3. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_size\nStatus: 76\n*************************** 4. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_count\nStatus: 10000\n*************************** 5. row ***************************\n Type: performance_schema\n Name: events_waits_history.memory\nStatus: 760000\n...\n*************************** 57. row ***************************\n Type: performance_schema\n Name: performance_schema.memory\nStatus: 26459600\n...\n\nThe intent of this statement is to help the DBA to understand the\neffects that different options have on memory requirements.\n\nName values consist of two parts, which name an internal buffer and an\nattribute of the buffer, respectively:\n\no Internal buffers that are exposed as a table in the\n performance_schema database are named after the table. Examples:\n events_waits_history.row_size, mutex_instances.row_count.\n\no Internal buffers that are not exposed as a table are named within\n parentheses. Examples: (pfs_cond_class).row_size,\n (pfs_mutex_class).memory.\n\no Values that apply to the Performance Schema as a whole begin with\n performance_schema. Example: performance_schema.memory.\n\nAttributes have these meanings:\n\no row_size cannot be changed. It is the size of the internal record\n used by the implementation.\n\no row_count can be changed depending on the configuration options.\n\no For a table, tbl_name.memory is the product of row_size multiplied by\n row_count. For the Performance Schema as a whole,\n performance_schema.memory is the sum of all the memory used (the sum\n of all other memory values).\n\nIn some cases, there is a direct relationship between a configuration\nparameter and a SHOW ENGINE value. For example,\nevents_waits_history_long.row_count corresponds to\nperformance_schema_events_waits_history_long_size. In other cases, the\nrelationship is more complex. For example,\nevents_waits_history.row_count corresponds to\nperformance_schema_events_waits_history_size (the number of rows per\nthread) multiplied by performance_schema_max_thread_instances ( the\nnumber of threads).\n\nURL: https://mariadb.com/kb/en/show-engine/\n\n','','https://mariadb.com/kb/en/show-engine/'),(366,'NAME_CONST',14,'Syntax:\nNAME_CONST(name,value)\n\nReturns the given value. When used to produce a result set column,\nNAME_CONST() causes the column to have the given name. The arguments\nshould be constants.\n\nMariaDB> SELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n\nURL: https://mariadb.com/kb/en/name_const/\n\n','','https://mariadb.com/kb/en/name_const/'),(367,'RELEASE_LOCK',14,'Syntax:\nRELEASE_LOCK(str)\n\nReleases the lock named by the string str that was obtained with\nGET_LOCK(). Returns 1 if the lock was released, 0 if the lock was not\nestablished by this thread (in which case the lock is not released),\nand NULL if the named lock did not exist. The lock does not exist if it\nwas never obtained by a call to GET_LOCK() or if it has previously been\nreleased.\n\nThe DO statement is convenient to use with RELEASE_LOCK(). See [HELP\nDO].\n\nURL: https://mariadb.com/kb/en/release_lock/\n\n','','https://mariadb.com/kb/en/release_lock/'),(368,'IS NULL',18,'Syntax:\nIS NULL\n\nTests whether a value is NULL.\n\nURL: https://mariadb.com/kb/en/is-null/\n\n','MariaDB> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n -> 0, 0, 1\n','https://mariadb.com/kb/en/is-null/'),(369,'CONVERT_TZ',31,'Syntax:\nCONVERT_TZ(dt,from_tz,to_tz)\n\nCONVERT_TZ() converts a datetime value dt from the time zone given by\nfrom_tz to the time zone given by to_tz and returns the resulting\nvalue. Time zones are specified as described in\nhttps://mariadb.com/kb/en/time-zones/. This\nfunction returns NULL if the arguments are invalid.\n\nURL: https://mariadb.com/kb/en/convert_tz/\n\n','MariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'GMT\',\'MET\');\n -> \'2004-01-01 13:00:00\'\nMariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'+00:00\',\'+10:00\');\n -> \'2004-01-01 22:00:00\'\n','https://mariadb.com/kb/en/convert_tz/'),(370,'TIME_TO_SEC',31,'Syntax:\nTIME_TO_SEC(time)\n\nReturns the time argument, converted to seconds.\n\nURL: https://mariadb.com/kb/en/time_to_sec/\n\n','MariaDB> SELECT TIME_TO_SEC(\'22:23:00\');\n -> 80580\nMariaDB> SELECT TIME_TO_SEC(\'00:39:38\');\n -> 2378\n','https://mariadb.com/kb/en/time_to_sec/'),(371,'WEEKDAY',31,'Syntax:\nWEEKDAY(date)\n\nReturns the weekday index for date (0 = Monday, 1 = Tuesday, ... 6 =\nSunday).\n\nURL: https://mariadb.com/kb/en/weekday/\n\n','MariaDB> SELECT WEEKDAY(\'2008-02-03 22:23:00\');\n -> 6\nMariaDB> SELECT WEEKDAY(\'2007-11-06\');\n -> 1\n','https://mariadb.com/kb/en/weekday/'),(372,'EXPORT_SET',37,'Syntax:\nEXPORT_SET(bits,on,off[,separator[,number_of_bits]])\n\nReturns a string such that for every bit set in the value bits, you get\nan on string and for every bit not set in the value, you get an off\nstring. Bits in bits are examined from right to left (from low-order to\nhigh-order bits). Strings are added to the result from left to right,\nseparated by the separator string (the default being the comma\ncharacter \",\"). The number of bits examined is given by number_of_bits,\nwhich has a default of 64 if not specified. number_of_bits is silently\nclipped to 64 if larger than 64. It is treated as an unsigned integer,\nso a value of -1 is effectively the same as 64.\n\nURL: https://mariadb.com/kb/en/export_set/\n\n','MariaDB> SELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n -> \'Y,N,Y,N\'\nMariaDB> SELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n -> \'0,1,1,0,0,0,0,0,0,0\'\n','https://mariadb.com/kb/en/export_set/'),(373,'ALTER SERVER',39,'Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. See [HELP CREATE\nSERVER]. The corresponding fields in the mysql.servers table are\nupdated accordingly. This statement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/alter-server/\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','https://mariadb.com/kb/en/alter-server/'),(374,'RESIGNAL',23,'Syntax:\nRESIGNAL [condition_value]\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nRESIGNAL passes on the error condition information that is available\nduring execution of a condition handler within a compound statement\ninside a stored procedure or function, trigger, or event. RESIGNAL may\nchange some or all information before passing it on. RESIGNAL is\nrelated to SIGNAL, but instead of originating a condition as SIGNAL\ndoes, RESIGNAL relays existing condition information, possibly after\nmodifying it.\n\nRESIGNAL makes it possible to both handle an error and return the error\ninformation. Otherwise, by executing an SQL statement within the\nhandler, information that caused the handler\'s activation is destroyed.\nRESIGNAL also can make some procedures shorter if a given handler can\nhandle part of a situation, then pass the condition \"up the line\" to\nanother handler.\n\nNo special privileges are required to execute the RESIGNAL statement.\n\nFor condition_value and signal_information_item, the definitions and\nrules are the same for RESIGNAL as for SIGNAL (see [HELP SIGNAL]).\n\nThe RESIGNAL statement takes condition_value and SET clauses, both of\nwhich are optional. This leads to several possible uses:\n\no RESIGNAL alone:\n\nRESIGNAL;\n\no RESIGNAL with new signal information:\n\nRESIGNAL SET signal_information_item [, signal_information_item] ...;\n\no RESIGNAL with a condition value and possibly new signal information:\n\nRESIGNAL condition_value\n [SET signal_information_item [, signal_information_item] ...];\n\nURL: https://mariadb.com/kb/en/resignal/\n\n','','https://mariadb.com/kb/en/resignal/'),(375,'TIME FUNCTION',31,'Syntax:\nTIME(expr)\n\nExtracts the time part of the time or datetime expression expr and\nreturns it as a string.\n\nURL: https://mariadb.com/kb/en/time-function/\n\n','MariaDB> SELECT TIME(\'2003-12-31 01:02:03\');\n -> \'01:02:03\'\nMariaDB> SELECT TIME(\'2003-12-31 01:02:03.000123\');\n -> \'01:02:03.000123\'\n','https://mariadb.com/kb/en/time-function/'),(376,'DATE_ADD',31,'Syntax:\nDATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)\n\nThese functions perform date arithmetic. The date argument specifies\nthe starting date or datetime value. expr is an expression specifying\nthe interval value to be added or subtracted from the starting date.\nexpr is a string; it may start with a \"-\" for negative intervals. unit\nis a keyword indicating the units in which the expression should be\ninterpreted.\n\nURL: https://mariadb.com/kb/en/date_add/\n\n','MariaDB> SELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n -> \'2009-01-01 00:00:00\'\nMariaDB> SELECT INTERVAL 1 DAY + \'2008-12-31\';\n -> \'2009-01-01\'\nMariaDB> SELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n -> \'2004-12-31 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2000-12-31 23:59:59\',\n -> INTERVAL 1 SECOND);\n -> \'2001-01-01 00:00:00\'\nMariaDB> SELECT DATE_ADD(\'2010-12-31 23:59:59\',\n -> INTERVAL 1 DAY);\n -> \'2011-01-01 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2100-12-31 23:59:59\',\n -> INTERVAL \'1:1\' MINUTE_SECOND);\n -> \'2101-01-01 00:01:00\'\nMariaDB> SELECT DATE_SUB(\'2005-01-01 00:00:00\',\n -> INTERVAL \'1 1:1:1\' DAY_SECOND);\n -> \'2004-12-30 22:58:59\'\nMariaDB> SELECT DATE_ADD(\'1900-01-01 00:00:00\',\n -> INTERVAL \'-1 10\' DAY_HOUR);\n -> \'1899-12-30 14:00:00\'\nMariaDB> SELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n -> \'1997-12-02\'\nMariaDB> SELECT DATE_ADD(\'1992-12-31 23:59:59.000002\',\n -> INTERVAL \'1.999999\' SECOND_MICROSECOND);\n -> \'1993-01-01 00:00:01.000001\'\n','https://mariadb.com/kb/en/date_add/'),(377,'CAST',37,'Syntax:\nCAST(expr AS type)\n\nThe CAST() function takes an expression of any type and produces a\nresult value of a specified type, similar to CONVERT(). See the\ndescription of CONVERT() for more information.\n\nURL: https://mariadb.com/kb/en/cast/\n\n','','https://mariadb.com/kb/en/cast/'),(378,'SOUNDS LIKE',37,'Syntax:\nexpr1 SOUNDS LIKE expr2\n\nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n\nURL: https://mariadb.com/kb/en/sounds-like/\n\n','','https://mariadb.com/kb/en/sounds-like/'),(379,'PERIOD_DIFF',31,'Syntax:\nPERIOD_DIFF(P1,P2)\n\nReturns the number of months between periods P1 and P2. P1 and P2\nshould be in the format YYMM or YYYYMM. Note that the period arguments\nP1 and P2 are not date values.\n\nURL: https://mariadb.com/kb/en/period_diff/\n\n','MariaDB> SELECT PERIOD_DIFF(200802,200703);\n -> 11\n','https://mariadb.com/kb/en/period_diff/'),(380,'LIKE',37,'Syntax:\nexpr LIKE pat [ESCAPE \'escape_char\']\n\nPattern matching using SQL simple regular expression comparison.\nReturns 1 (TRUE) or 0 (FALSE). If either expr or pat is NULL, the\nresult is NULL.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\nURL: https://mariadb.com/kb/en/like/\n\n','MariaDB> SELECT \'David!\' LIKE \'David_\';\n -> 1\nMariaDB> SELECT \'David!\' LIKE \'%D%v%\';\n -> 1\n','https://mariadb.com/kb/en/like/'),(381,'MULTIPOINT',24,'MultiPoint(pt1,pt2,...)\n\nConstructs a MultiPoint value using Point or WKB Point arguments.\n\nURL: https://mariadb.com/kb/en/multipoint/\n\n','','https://mariadb.com/kb/en/multipoint/'),(382,'>>',19,'Syntax:\n>>\n\nShifts a longlong (BIGINT) number to the right.\n\nURL: https://mariadb.com/kb/en/shift-right/\n\n','MariaDB> SELECT 4 >> 2;\n -> 1\n','https://mariadb.com/kb/en/shift-right/'),(383,'FETCH',23,'Syntax:\nFETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...\n\nThis statement fetches the next row for the SELECT statement associated\nwith the specified cursor (which must be open), and advances the cursor\npointer. If a row exists, the fetched columns are stored in the named\nvariables. The number of columns retrieved by the SELECT statement must\nmatch the number of output variables specified in the FETCH statement.\n\nIf no more rows are available, a No Data condition occurs with SQLSTATE\nvalue \'02000\'. To detect this condition, you can set up a handler for\nit (or for a NOT FOUND condition). For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/fetch/\n\n','','https://mariadb.com/kb/en/fetch/'),(384,'AVG',16,'Syntax:\nAVG([DISTINCT] expr)\n\nReturns the average value of expr. The DISTINCT option can be used to\nreturn the average of the distinct values of expr.\n\nAVG() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/avg/\n\n','MariaDB> SELECT student_name, AVG(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/avg/'),(385,'TRUE FALSE',29,'The constants TRUE and FALSE evaluate to 1 and 0, respectively. The\nconstant names can be written in any lettercase.\n\nMariaDB> SELECT TRUE, true, FALSE, false;\n -> 1, 1, 0, 0\n\nURL: https://mariadb.com/kb/en/true-false/\n\n','','https://mariadb.com/kb/en/true-false/'),(386,'MBRWITHIN',6,'MBRWithin(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\nis within the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRContains().\n\nURL: https://mariadb.com/kb/en/mbrwithin/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nMariaDB> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n','https://mariadb.com/kb/en/mbrwithin/'),(387,'SESSION_USER',17,'Syntax:\nSESSION_USER()\n\nSESSION_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/session_user/\n\n','','https://mariadb.com/kb/en/session_user/'),(388,'IN',18,'Syntax:\nexpr IN (value,...)\n\nReturns 1 if expr is equal to any of the values in the IN list, else\nreturns 0. If all values are constants, they are evaluated according to\nthe type of expr and sorted. The search for the item then is done using\na binary search. This means IN is very quick if the IN value list\nconsists entirely of constants. Otherwise, type conversion takes place\naccording to the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the arguments.\n\nURL: https://mariadb.com/kb/en/in/\n\n','MariaDB> SELECT 2 IN (0,3,5,7);\n -> 0\nMariaDB> SELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n -> 1\n','https://mariadb.com/kb/en/in/'),(389,'QUOTE',37,'Syntax:\nQUOTE(str)\n\nQuotes a string to produce a result that can be used as a properly\nescaped data value in an SQL statement. The string is returned enclosed\nby single quotation marks and with each instance of backslash (\"\\\"),\nsingle quote (\"\'\"), ASCII NUL, and Control+Z preceded by a backslash.\nIf the argument is NULL, the return value is the word \"NULL\" without\nenclosing single quotation marks.\n\nURL: https://mariadb.com/kb/en/quote/\n\n','MariaDB> SELECT QUOTE(\'Don\\\'t!\');\n -> \'Don\\\'t!\'\nMariaDB> SELECT QUOTE(NULL);\n -> NULL\n','https://mariadb.com/kb/en/quote/'),(390,'HELP COMMAND',26,'Syntax:\nMariaDB> help search_string\n\nIf you provide an argument to the help command, mysql uses it as a\nsearch string to access server-side help from the contents of the MySQL\nReference Manual. The proper operation of this command requires that\nthe help tables in the mysql database be initialized with help topic\ninformation .\n\nIf there is no match for the search string, the search fails:\n\nMariaDB> help me\n\nNothing found\nPlease try to run \'help contents\' for a list of all accessible topics\n\nUse help contents to see a list of the help categories:\n\nMariaDB> help contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing categories:\n Account Management\n Administration\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Language Structure\n Plugins\n Storage Engines\n Stored Routines\n Table Maintenance\n Transactions\n Triggers\n\nIf the search string matches multiple items, mysql shows a list of\nmatching topics:\n\nMariaDB> help logs\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following topics:\n SHOW\n SHOW BINARY LOGS\n SHOW ENGINE\n SHOW LOGS\n\nUse a topic as the search string to see the help entry for that topic:\n\nMariaDB> help show binary logs\nName: \'SHOW BINARY LOGS\'\nDescription:\nSyntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [purge-binary-logs], that shows how\nto determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(391,'QUARTER',31,'Syntax:\nQUARTER(date)\n\nReturns the quarter of the year for date, in the range 1 to 4.\n\nURL: https://mariadb.com/kb/en/quarter/\n\n','MariaDB> SELECT QUARTER(\'2008-04-01\');\n -> 2\n','https://mariadb.com/kb/en/quarter/'),(392,'POSITION',37,'Syntax:\nPOSITION(substr IN str)\n\nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n\nURL: https://mariadb.com/kb/en/position/\n\n','','https://mariadb.com/kb/en/position/'),(393,'SHOW CREATE FUNCTION',26,'Syntax:\nSHOW CREATE FUNCTION func_name\n\nThis statement is similar to SHOW CREATE PROCEDURE but for stored\nfunctions. See [HELP SHOW CREATE PROCEDURE].\n\nURL: https://mariadb.com/kb/en/show-create-function/\n\n','','https://mariadb.com/kb/en/show-create-function/'),(394,'IS_USED_LOCK',14,'Syntax:\nIS_USED_LOCK(str)\n\nChecks whether the lock named str is in use (that is, locked). If so,\nit returns the connection identifier of the client that holds the lock.\nOtherwise, it returns NULL.\n\nURL: https://mariadb.com/kb/en/is_used_lock/\n\n','','https://mariadb.com/kb/en/is_used_lock/'),(395,'POLYFROMTEXT',3,'PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])\n\nConstructs a POLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromtext/\n\n','','https://mariadb.com/kb/en/polyfromtext/'),(396,'DES_ENCRYPT',12,'Syntax:\nDES_ENCRYPT(str[,{key_num|key_str}])\n\nEncrypts the string with the given key using the Triple-DES algorithm.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nThe encryption key to use is chosen based on the second argument to\nDES_ENCRYPT(), if one was given. With no argument, the first key from\nthe DES key file is used. With a key_num argument, the given key number\n(0 to 9) from the DES key file is used. With a key_str argument, the\ngiven key string is used to encrypt str.\n\nThe key file can be specified with the --des-key-file server option.\n\nThe return string is a binary string where the first character is\nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT() returns NULL.\n\nThe 128 is added to make it easier to recognize an encrypted key. If\nyou use a string key, key_num is 127.\n\nThe string length for the result is given by this formula:\n\nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n\nEach line in the DES key file has the following format:\n\nkey_num des_key_str\n\nEach key_num value must be a number in the range from 0 to 9. Lines in\nthe file may be in any order. des_key_str is the string that is used to\nencrypt the message. There should be at least one space between the\nnumber and the key. The first key is the default key that is used if\nyou do not specify any key argument to DES_ENCRYPT().\n\nYou can tell MySQL to read new key values from the key file with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD privilege.\n\nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted column\nvalues, without giving the end user the right to decrypt those values.\n\nURL: https://mariadb.com/kb/en/des_encrypt/\n\n','MariaDB> SELECT customer_address FROM customer_table \n > WHERE crypted_credit_card = DES_ENCRYPT(\'credit_card_number\');\n','https://mariadb.com/kb/en/des_encrypt/'),(397,'CEIL',4,'Syntax:\nCEIL(X)\n\nCEIL() is a synonym for CEILING().\n\nURL: https://mariadb.com/kb/en/ceil/\n\n','','https://mariadb.com/kb/en/ceil/'),(398,'LENGTH',37,'Syntax:\nLENGTH(str)\n\nReturns the length of the string str, measured in bytes. A multi-byte\ncharacter counts as multiple bytes. This means that for a string\ncontaining five 2-byte characters, LENGTH() returns 10, whereas\nCHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/length/\n\n','MariaDB> SELECT LENGTH(\'text\');\n -> 4\n','https://mariadb.com/kb/en/length/'),(399,'STR_TO_DATE',31,'Syntax:\nSTR_TO_DATE(str,format)\n\nThis is the inverse of the DATE_FORMAT() function. It takes a string\nstr and a format string format. STR_TO_DATE() returns a DATETIME value\nif the format string contains both date and time parts, or a DATE or\nTIME value if the string contains only date or time parts. If the date,\ntime, or datetime value extracted from str is illegal, STR_TO_DATE()\nreturns NULL and produces a warning.\n\nThe server scans str attempting to match format to it. The format\nstring can contain literal characters and format specifiers beginning\nwith %. Literal characters in format must match literally in str.\nFormat specifiers in format must match a date or time part in str. For\nthe specifiers that can be used in format, see the DATE_FORMAT()\nfunction description.\n\nMariaDB> SELECT STR_TO_DATE(\'01,5,2013\',\'%d,%m,%Y\');\n -> \'2013-05-01\'\nMariaDB> SELECT STR_TO_DATE(\'May 1, 2013\',\'%M %d,%Y\');\n -> \'2013-05-01\'\n\nScanning starts at the beginning of str and fails if format is found\nnot to match. Extra characters at the end of str are ignored.\n\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'a%h:%i:%s\');\n -> \'09:30:17\'\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'%h:%i:%s\');\n -> NULL\nMariaDB> SELECT STR_TO_DATE(\'09:30:17a\',\'%h:%i:%s\');\n -> \'09:30:17\'\n\nUnspecified date or time parts have a value of 0, so incompletely\nspecified values in str produce a result with some or all parts set to\n0:\n\nMariaDB> SELECT STR_TO_DATE(\'abc\',\'abc\');\n -> \'0000-00-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%m\');\n -> \'0000-09-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%s\');\n -> \'00:00:09\'\n\nURL: https://mariadb.com/kb/en/str_to_date/\n\n','','https://mariadb.com/kb/en/str_to_date/'),(400,'Y',11,'Y(p)\n\nReturns the Y-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/y/\n\n','MariaDB> SELECT Y(POINT(56.7, 53.34));\n+-----------------------+\n| Y(POINT(56.7, 53.34)) |\n+-----------------------+\n| 53.34 |\n+-----------------------+\n','https://mariadb.com/kb/en/y/'),(401,'CHECKSUM TABLE',20,'Syntax:\nCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]\n\nCHECKSUM TABLE reports a table checksum. This statement requires the\nSELECT privilege for the table.\n\nWith QUICK, the live table checksum is reported if it is available, or\nNULL otherwise. This is very fast. A live checksum is enabled by\nspecifying the CHECKSUM=1 table option when you create the table;\ncurrently, this is supported only for MyISAM tables. See [HELP CREATE\nTABLE].\n\nWith EXTENDED, the entire table is read row by row and the checksum is\ncalculated. This can be very slow for large tables.\n\nIf neither QUICK nor EXTENDED is specified, MySQL returns a live\nchecksum if the table storage engine supports it and scans the table\notherwise.\n\nFor a nonexistent table, CHECKSUM TABLE returns NULL and generates a\nwarning.\n\nIn MySQL 5.5, CHECKSUM TABLE returns 0 for partitioned tables unless\nyou include the EXTENDED option. This issue is resolved in MySQL 5.6.\n(Bug #11933226, Bug #60681)\n\nThe checksum value depends on the table row format. If the row format\nchanges, the checksum also changes. For example, the storage format for\nVARCHAR changed between MySQL 4.1 and 5.0, so if a 4.1 table is\nupgraded to MySQL 5.0, the checksum value may change.\n\nURL: https://mariadb.com/kb/en/checksum-table/\n\n','','https://mariadb.com/kb/en/checksum-table/'),(402,'NUMINTERIORRINGS',2,'NumInteriorRings(poly)\n\nReturns the number of interior rings in the Polygon value poly.\n\nURL: https://mariadb.com/kb/en/numinteriorrings/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n','https://mariadb.com/kb/en/numinteriorrings/'),(403,'INTERIORRINGN',2,'InteriorRingN(poly,N)\n\nReturns the N-th interior ring for the Polygon value poly as a\nLineString. Rings are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/interiorringn/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n','https://mariadb.com/kb/en/interiorringn/'),(404,'UTC_TIME',31,'Syntax:\nUTC_TIME, UTC_TIME()\n\nReturns the current UTC time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_time/\n\n','MariaDB> SELECT UTC_TIME(), UTC_TIME() + 0;\n -> \'18:07:53\', 180753.000000\n','https://mariadb.com/kb/en/utc_time/'),(405,'DROP FUNCTION',39,'The DROP FUNCTION statement is used to drop stored functions and\nuser-defined functions (UDFs):\n\no For information about dropping stored functions, see [HELP DROP\n PROCEDURE].\n\no For information about dropping user-defined functions, see [HELP DROP\n FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/drop-function/\n\n','','https://mariadb.com/kb/en/drop-function/'),(406,'ALTER EVENT',39,'Syntax:\nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO event_body]\n\nThe ALTER EVENT statement changes one or more of the characteristics of\nan existing event without the need to drop and recreate it. The syntax\nfor each of the DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE /\nDISABLE, and DO clauses is exactly the same as when used with CREATE\nEVENT. (See [HELP CREATE EVENT].)\n\nAny user can alter an event defined on a database for which that user\nhas the EVENT privilege. When a user executes a successful ALTER EVENT\nstatement, that user becomes the definer for the affected event.\n\nALTER EVENT works only with an existing event:\n\nMariaDB> ALTER EVENT no_such_event \n > ON SCHEDULE \n > EVERY \'2:3\' DAY_HOUR;\nERROR 1517 (HY000): Unknown event \'no_such_event\'\n\nURL: https://mariadb.com/kb/en/alter-event/\n\n','','https://mariadb.com/kb/en/alter-event/'),(407,'STDDEV',16,'Syntax:\nSTDDEV(expr)\n\nReturns the population standard deviation of expr. This function is\nprovided for compatibility with Oracle. The standard SQL function\nSTDDEV_POP() can be used instead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev/\n\n','','https://mariadb.com/kb/en/stddev/'),(408,'DATE_SUB',31,'Syntax:\nDATE_SUB(date,INTERVAL expr unit)\n\nSee the description for DATE_ADD().\n\nURL: https://mariadb.com/kb/en/date_sub/\n\n','','https://mariadb.com/kb/en/date_sub/'),(409,'PERIOD_ADD',31,'Syntax:\nPERIOD_ADD(P,N)\n\nAdds N months to period P (in the format YYMM or YYYYMM). Returns a\nvalue in the format YYYYMM. Note that the period argument P is not a\ndate value.\n\nURL: https://mariadb.com/kb/en/period_add/\n\n','MariaDB> SELECT PERIOD_ADD(200801,2);\n -> 200803\n','https://mariadb.com/kb/en/period_add/'),(410,'|',19,'Syntax:\n|\n\nBitwise OR:\n\nURL: https://mariadb.com/kb/en/bitwise-or/\n\n','MariaDB> SELECT 29 | 15;\n -> 31\n','https://mariadb.com/kb/en/bitwise-or/'),(411,'GEOMFROMTEXT',3,'GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])\n\nConstructs a geometry value of any type using its WKT representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromtext/\n\n','','https://mariadb.com/kb/en/geomfromtext/'),(412,'UUID_SHORT',14,'Syntax:\nUUID_SHORT()\n\nReturns a \"short\" universal identifier as a 64-bit unsigned integer\n(rather than a string-form 128-bit identifier as returned by the UUID()\nfunction).\n\nThe value of UUID_SHORT() is guaranteed to be unique if the following\nconditions hold:\n\no The server_id of the current host is unique among your set of master\n and slave servers\n\no server_id is between 0 and 255\n\no You do not set back your system time for your server between mysqld\n restarts\n\no You do not invoke UUID_SHORT() on average more than 16 million times\n per second between mysqld restarts\n\nThe UUID_SHORT() return value is constructed this way:\n\n (server_id & 255) << 56\n+ (server_startup_time_in_seconds << 24)\n+ incremented_variable++;\n\nURL: https://mariadb.com/kb/en/uuid_short/\n\n','MariaDB> SELECT UUID_SHORT();\n -> 92395783831158784\n','https://mariadb.com/kb/en/uuid_short/'),(413,'RIGHT',37,'Syntax:\nRIGHT(str,len)\n\nReturns the rightmost len characters from the string str, or NULL if\nany argument is NULL.\n\nURL: https://mariadb.com/kb/en/right/\n\n','MariaDB> SELECT RIGHT(\'foobarbar\', 4);\n -> \'rbar\'\n','https://mariadb.com/kb/en/right/'),(414,'DATEDIFF',31,'Syntax:\nDATEDIFF(expr1,expr2)\n\nDATEDIFF() returns expr1 - expr2 expressed as a value in days from one\ndate to the other. expr1 and expr2 are date or date-and-time\nexpressions. Only the date parts of the values are used in the\ncalculation.\n\nURL: https://mariadb.com/kb/en/datediff/\n\n','MariaDB> SELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n -> 1\nMariaDB> SELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n -> -31\n','https://mariadb.com/kb/en/datediff/'),(415,'DROP TABLESPACE',39,'Syntax:\nDROP TABLESPACE tablespace_name\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/drop-tablespace/\n\n','','https://mariadb.com/kb/en/drop-tablespace/'),(416,'DROP PROCEDURE',39,'Syntax:\nDROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name\n\nThis statement is used to drop a stored procedure or function. That is,\nthe specified routine is removed from the server. You must have the\nALTER ROUTINE privilege for the routine. (If the\nautomatic_sp_privileges system variable is enabled, that privilege and\nEXECUTE are granted automatically to the routine creator when the\nroutine is created and dropped from the creator when the routine is\ndropped. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n)\n\nThe IF EXISTS clause is a MySQL extension. It prevents an error from\noccurring if the procedure or function does not exist. A warning is\nproduced that can be viewed with SHOW WARNINGS.\n\nURL: https://mariadb.com/kb/en/drop-procedure/\n\n','','https://mariadb.com/kb/en/drop-procedure/'),(417,'CHECK TABLE',20,'Syntax:\nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n\noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED}\n\nCHECK TABLE checks a table or tables for errors. CHECK TABLE works for\nInnoDB, MyISAM, ARCHIVE, and CSV tables. For MyISAM tables, the key\nstatistics are updated as well.\n\nTo check a table, you must have some privilege for it.\n\nCHECK TABLE can also check views for problems, such as tables that are\nreferenced in the view definition that no longer exist.\n\nCHECK TABLE is supported for partitioned tables, and you can use ALTER\nTABLE ... CHECK PARTITION to check one or more partitions; for more\ninformation, see [HELP ALTER TABLE].\n\nURL: https://mariadb.com/kb/en/sql-commands-check-table/\n\n','','https://mariadb.com/kb/en/sql-commands-check-table/'),(418,'BIN',37,'Syntax:\nBIN(N)\n\nReturns a string representation of the binary value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,2). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/bin/\n\n','MariaDB> SELECT BIN(12);\n -> \'1100\'\n','https://mariadb.com/kb/en/bin/'),(419,'INSTALL PLUGIN',5,'Syntax:\nINSTALL PLUGIN plugin_name SONAME \'shared_library_name\'\n\nThis statement installs a server plugin. It requires the INSERT\nprivilege for the mysql.plugin table.\n\nplugin_name is the name of the plugin as defined in the plugin\ndescriptor structure contained in the library file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/plugin-data-structures.html).\nPlugin names are not case sensitive. For maximal compatibility, plugin\nnames should be limited to ASCII letters, digits, and underscore\nbecause they are used in C source files, shell command lines, M4 and\nBourne shell scripts, and SQL environments.\n\nshared_library_name is the name of the shared library that contains the\nplugin code. The name includes the file name extension (for example,\nlibmyplugin.so, libmyplugin.dll, or libmyplugin.dylib).\n\nThe shared library must be located in the plugin directory (the\ndirectory named by the plugin_dir system variable). The library must be\nin the plugin directory itself, not in a subdirectory. By default,\nplugin_dir is the plugin directory under the directory named by the\npkglibdir configuration variable, but it can be changed by setting the\nvalue of plugin_dir at server startup. For example, set its value in a\nmy.cnf file:\n\n[mysqld]\nplugin_dir=/path/to/plugin/directory\n\nIf the value of plugin_dir is a relative path name, it is taken to be\nrelative to the MySQL base directory (the value of the basedir system\nvariable).\n\nINSTALL PLUGIN loads and initializes the plugin code to make the plugin\navailable for use. A plugin is initialized by executing its\ninitialization function, which handles any setup that the plugin must\nperform before it can be used. When the server shuts down, it executes\nthe deinitialization function for each plugin that is loaded so that\nthe plugin has a change to perform any final cleanup.\n\nINSTALL PLUGIN also registers the plugin by adding a line that\nindicates the plugin name and library file name to the mysql.plugin\ntable. At server startup, the server loads and initializes any plugin\nthat is listed in the mysql.plugin table. This means that a plugin is\ninstalled with INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the server is\nstarted with the --skip-grant-tables option.\n\nA plugin library can contain multiple plugins. For each of them to be\ninstalled, use a separate INSTALL PLUGIN statement. Each statement\nnames a different plugin, but all of them specify the same library\nname.\n\nURL: https://mariadb.com/kb/en/install-plugin/\n\n','','https://mariadb.com/kb/en/install-plugin/'),(420,'DECLARE CURSOR',23,'Syntax:\nDECLARE cursor_name CURSOR FOR select_statement\n\nThis statement declares a cursor and associates it with a SELECT\nstatement that retrieves the rows to be traversed by the cursor. To\nfetch the rows later, use a FETCH statement. The number of columns\nretrieved by the SELECT statement must match the number of output\nvariables specified in the FETCH statement.\n\nThe SELECT statement cannot have an INTO clause.\n\nCursor declarations must appear before handler declarations and after\nvariable and condition declarations.\n\nA stored program may contain multiple cursor declarations, but each\ncursor declared in a given block must have a unique name. For an\nexample, see https://mariadb.com/kb/en/programmatic-and-compound-statements-cursors/.\n\nFor information available through SHOW statements, it is possible in\nmany cases to obtain equivalent information by using a cursor with an\nINFORMATION_SCHEMA table.\n\nURL: https://mariadb.com/kb/en/declare-cursor/\n\n','','https://mariadb.com/kb/en/declare-cursor/'),(421,'LOAD DATA',27,'Syntax:\nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number {LINES | ROWS}]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD DATA INFILE statement reads rows from a text file into a table\nat a very high speed. The file name must be given as a literal string.\n\nLOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. (See\nhttps://mariadb.com/kb/en/select-into/.) To write data\nfrom a table to a file, use SELECT ... INTO OUTFILE. To read the file\nback into a table, use LOAD DATA INFILE. The syntax of the FIELDS and\nLINES clauses is the same for both statements. Both clauses are\noptional, but FIELDS must precede LINES if both are specified.\n\nFor more information about the efficiency of INSERT versus LOAD DATA\nINFILE and speeding up LOAD DATA INFILE, see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-speed.html.\n\nThe character set indicated by the character_set_database system\nvariable is used to interpret the information in the file. SET NAMES\nand the setting of character_set_client do not affect interpretation of\ninput. If the contents of the input file use a character set that\ndiffers from the default, it is usually preferable to specify the\ncharacter set of the file by using the CHARACTER SET clause. A\ncharacter set of binary specifies \"no conversion.\"\n\nLOAD DATA INFILE interprets all fields in the file as having the same\ncharacter set, regardless of the data types of the columns into which\nfield values are loaded. For proper interpretation of file contents,\nyou must ensure that it was written with the correct character set. For\nexample, if you write a data file with mysqldump -T or by issuing a\nSELECT ... INTO OUTFILE statement in mysql, be sure to use a\n--default-character-set option with mysqldump or mysql so that output\nis written in the character set to be used when the file is loaded with\nLOAD DATA INFILE.\n\n*Note*: It is not possible to load data files that use the ucs2, utf16,\nor utf32 character set.\n\nThe character_set_filesystem system variable controls the\ninterpretation of the file name.\n\nYou can also load data files by using the mysqlimport utility; it\noperates by sending a LOAD DATA INFILE statement to the server. The\n--local option causes mysqlimport to read data files from the client\nhost. You can specify the --compress option to get better performance\nover slow networks if the client and server support the compressed\nprotocol. See https://mariadb.com/kb/en/mysqlimport/.\n\nIf you use LOW_PRIORITY, execution of the LOAD DATA statement is\ndelayed until no other clients are reading from the table. This affects\nonly storage engines that use only table-level locking (such as MyISAM,\nMEMORY, and MERGE).\n\nIf you specify CONCURRENT with a MyISAM table that satisfies the\ncondition for concurrent inserts (that is, it contains no free blocks\nin the middle), other threads can retrieve data from the table while\nLOAD DATA is executing. Using this option affects the performance of\nLOAD DATA a bit, even if no other thread is using the table at the same\ntime.\n\nPrior to MySQL 5.5.1, CONCURRENT was not replicated when using\nstatement-based replication (see Bug #34628). However, it is replicated\nwhen using row-based replication, regardless of the version. See\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-features-load-data.h\ntml, for more information.\n\nThe LOCAL keyword, if specified, is interpreted with respect to the\nclient end of the connection:\n\no If LOCAL is specified, the file is read by the client program on the\n client host and sent to the server. The file can be given as a full\n path name to specify its exact location. If given as a relative path\n name, the name is interpreted relative to the directory in which the\n client program was started.\n\n When using LOCAL with LOAD DATA, a copy of the file is created in the\n server\'s temporary directory. This is not the directory determined by\n the value of tmpdir or slave_load_tmpdir, but rather the operating\n system\'s temporary directory, and is not configurable in the MySQL\n Server. (Typically the system temporary directory is /tmp on Linux\n systems and C:\\WINDOWS\\TEMP on Windows.) Lack of sufficient space for\n the copy in this directory can cause the LOAD DATA LOCAL statement to\n fail.\n\no If LOCAL is not specified, the file must be located on the server\n host and is read directly by the server. The server uses the\n following rules to locate the file:\n\n o If the file name is an absolute path name, the server uses it as\n given.\n\n o If the file name is a relative path name with one or more leading\n components, the server searches for the file relative to the\n server\'s data directory.\n\n o If a file name with no leading components is given, the server\n looks for the file in the database directory of the default\n database.\n\nNote that, in the non-LOCAL case, these rules mean that a file named as\n./myfile.txt is read from the server\'s data directory, whereas the file\nnamed as myfile.txt is read from the database directory of the default\ndatabase. For example, if db1 is the default database, the following\nLOAD DATA statement reads the file data.txt from the database directory\nfor db1, even though the statement explicitly loads the file into a\ntable in the db2 database:\n\nLOAD DATA INFILE \'data.txt\' INTO TABLE db2.my_table;\n\nWindows path names are specified using forward slashes rather than\nbackslashes. If you do use backslashes, you must double them.\n\nFor security reasons, when reading text files located on the server,\nthe files must either reside in the database directory or be readable\nby all. Also, to use LOAD DATA INFILE on server files, you must have\nthe FILE privilege. See\nhttps://mariadb.com/kb/en/grant/. For\nnon-LOCAL load operations, if the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nURL: https://mariadb.com/kb/en/load-data-infile/\n\n','','https://mariadb.com/kb/en/load-data-infile/'),(422,'MULTILINESTRING',24,'MultiLineString(ls1,ls2,...)\n\nConstructs a MultiLineString value using LineString or WKB LineString\narguments.\n\nURL: https://mariadb.com/kb/en/multilinestring/\n\n','','https://mariadb.com/kb/en/multilinestring/'),(423,'LOCALTIME',31,'Syntax:\nLOCALTIME, LOCALTIME()\n\nLOCALTIME and LOCALTIME() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtime/\n\n','','https://mariadb.com/kb/en/localtime/'),(424,'SHOW RELAYLOG EVENTS',26,'Syntax:\nSHOW RELAYLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the relay log of a replication slave. If you do not\nspecify \'log_name\', the first relay log is displayed. This statement\nhas no effect on the master.\n\nURL: https://mariadb.com/kb/en/show-relaylog-events/\n\n','','https://mariadb.com/kb/en/show-relaylog-events/'),(425,'MPOINTFROMTEXT',3,'MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])\n\nConstructs a MULTIPOINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromtext/\n\n','','https://mariadb.com/kb/en/mpointfromtext/'),(426,'BLOB',22,'BLOB[(M)]\n\nA BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each\nBLOB value is stored using a 2-byte length prefix that indicates the\nnumber of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest BLOB type large enough to hold\nvalues M bytes long.\n\nURL: https://mariadb.com/kb/en/blob/\n\n','','https://mariadb.com/kb/en/blob/'),(427,'SHA1',12,'Syntax:\nSHA1(str), SHA(str)\n\nCalculates an SHA-1 160-bit checksum for the string, as described in\nRFC 3174 (Secure Hash Algorithm). The value is returned as a string of\n40 hex digits, or NULL if the argument was NULL. One of the possible\nuses for this function is as a hash key. See the notes at the beginning\nof this section about storing hash values efficiently. You can also use\nSHA1() as a cryptographic function for storing passwords. SHA() is\nsynonymous with SHA1().\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha1/\n\n','MariaDB> SELECT SHA1(\'abc\');\n -> \'a9993e364706816aba3e25717850c26c9cd0d89d\'\n','https://mariadb.com/kb/en/sha1/'),(428,'SUBSTR',37,'Syntax:\nSUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str\nFROM pos FOR len)\n\nSUBSTR() is a synonym for SUBSTRING().\n\nURL: https://mariadb.com/kb/en/substr/\n\n','','https://mariadb.com/kb/en/substr/'),(429,'PASSWORD',12,'Syntax:\nPASSWORD(str)\n\nCalculates and returns a hashed password string from the plaintext\npassword str and returns a nonbinary string in the connection character\nset (a binary string before MySQL 5.5.3), or NULL if the argument is\nNULL. This function is the SQL interface to the algorithm used by the\nserver to encrypt MySQL passwords for storage in the mysql.user grant\ntable.\n\nThe password hashing method used by PASSWORD() depends on the value of\nthe old_passwords system variable:\n\nURL: https://mariadb.com/kb/en/password/\n\n','MariaDB> SET old_passwords = 0;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+-------------------------------------------+\n| PASSWORD(\'mypass\') |\n+-------------------------------------------+\n| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |\n+-------------------------------------------+\n\nMariaDB> SET old_passwords = 1;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+--------------------+\n| PASSWORD(\'mypass\') |\n+--------------------+\n| 6f8c114b58f2ce9e |\n+--------------------+\n','https://mariadb.com/kb/en/password/'),(430,'CHAR',22,'[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA fixed-length string that is always right-padded with spaces to the\nspecified length when stored. M represents the column length in\ncharacters. The range of M is 0 to 255. If M is omitted, the length is\n1.\n\n*Note*: Trailing spaces are removed when CHAR values are retrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n\nURL: https://mariadb.com/kb/en/char/\n\n','','https://mariadb.com/kb/en/char/'),(431,'UTC_DATE',31,'Syntax:\nUTC_DATE, UTC_DATE()\n\nReturns the current UTC date as a value in \'YYYY-MM-DD\' or YYYYMMDD\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_date/\n\n','MariaDB> SELECT UTC_DATE(), UTC_DATE() + 0;\n -> \'2003-08-14\', 20030814\n','https://mariadb.com/kb/en/utc_date/'),(432,'DIMENSION',36,'Dimension(g)\n\nReturns the inherent dimension of the geometry value g. The result can\nbe -1, 0, 1, or 2. The meaning of these values is given in\nhttps://mariadb.com/kb/en/dimension/.\n\nURL: https://mariadb.com/kb/en/dimension/\n\n','MariaDB> SELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n','https://mariadb.com/kb/en/dimension/'),(433,'COUNT DISTINCT',16,'Syntax:\nCOUNT(DISTINCT expr,[expr...])\n\nReturns a count of the number of rows with different non-NULL expr\nvalues.\n\nCOUNT(DISTINCT) returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count-distinct/\n\n','MariaDB> SELECT COUNT(DISTINCT results) FROM student;\n','https://mariadb.com/kb/en/count-distinct/'),(434,'BIT',22,'BIT[(M)]\n\nA bit-field type. M indicates the number of bits per value, from 1 to\n64. The default is 1 if M is omitted.\n\nURL: https://mariadb.com/kb/en/bit/\n\n','','https://mariadb.com/kb/en/bit/'),(435,'EQUALS',30,'Equals(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially equal to g2.\n\nURL: https://mariadb.com/kb/en/equals/\n\n','','https://mariadb.com/kb/en/equals/'),(436,'SHOW CREATE VIEW',26,'Syntax:\nSHOW CREATE VIEW view_name\n\nThis statement shows a CREATE VIEW statement that creates the given\nview.\n\nURL: https://mariadb.com/kb/en/show-create-view/\n\n','','https://mariadb.com/kb/en/show-create-view/'),(437,'INTERVAL',18,'Syntax:\nINTERVAL(N,N1,N2,N3,...)\n\nReturns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All\narguments are treated as integers. It is required that N1 < N2 < N3 <\n... < Nn for this function to work correctly. This is because a binary\nsearch is used (very fast).\n\nURL: https://mariadb.com/kb/en/interval/\n\n','MariaDB> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\n -> 3\nMariaDB> SELECT INTERVAL(10, 1, 10, 100, 1000);\n -> 2\nMariaDB> SELECT INTERVAL(22, 23, 30, 44, 200);\n -> 0\n','https://mariadb.com/kb/en/interval/'),(438,'FROM_DAYS',31,'Syntax:\nFROM_DAYS(N)\n\nGiven a day number N, returns a DATE value.\n\nURL: https://mariadb.com/kb/en/from_days/\n\n','MariaDB> SELECT FROM_DAYS(730669);\n -> \'2007-07-03\'\n','https://mariadb.com/kb/en/from_days/'),(439,'ALTER PROCEDURE',39,'Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nURL: https://mariadb.com/kb/en/alter-procedure/\n\n','','https://mariadb.com/kb/en/alter-procedure/'),(440,'BIT_COUNT',19,'Syntax:\nBIT_COUNT(N)\n\nReturns the number of bits that are set in the argument N.\n\nURL: https://mariadb.com/kb/en/bit_count/\n\n','MariaDB> SELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n -> 4, 3\n','https://mariadb.com/kb/en/bit_count/'),(441,'OCTET_LENGTH',37,'Syntax:\nOCTET_LENGTH(str)\n\nOCTET_LENGTH() is a synonym for LENGTH().\n\nURL: https://mariadb.com/kb/en/octet_length/\n\n','','https://mariadb.com/kb/en/octet_length/'),(442,'UTC_TIMESTAMP',31,'Syntax:\nUTC_TIMESTAMP, UTC_TIMESTAMP()\n\nReturns the current UTC date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is used in a string or numeric context.\n\nURL: https://mariadb.com/kb/en/utc_timestamp/\n\n','MariaDB> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n -> \'2003-08-14 18:08:04\', 20030814180804.000000\n','https://mariadb.com/kb/en/utc_timestamp/'),(443,'AES_ENCRYPT',12,'Syntax:\nAES_ENCRYPT(str,key_str)\n\nAES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of\ndata using the official AES (Advanced Encryption Standard) algorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit key length is\nused, but you can extend it up to 256 bits by modifying the source. We\nchose 128 bits because it is much faster and it is secure enough for\nmost purposes.\n\nAES_ENCRYPT() encrypts a string and returns a binary string.\nAES_DECRYPT() decrypts the encrypted string and returns the original\nstring. The input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n\nBecause AES is a block-level algorithm, padding is used to encode\nuneven length strings and so the result string length may be calculated\nusing this formula:\n\n16 * (trunc(string_length / 16) + 1)\n\nIf AES_DECRYPT() detects invalid data or incorrect padding, it returns\nNULL. However, it is possible for AES_DECRYPT() to return a non-NULL\nvalue (possibly garbage) if the input data or the key is invalid.\n\nYou can use the AES functions to store data in an encrypted form by\nmodifying your queries:\n\nURL: https://mariadb.com/kb/en/aes_encrypt/\n\n','INSERT INTO t VALUES (1,AES_ENCRYPT(\'text\',\'password\'));\n','https://mariadb.com/kb/en/aes_encrypt/'),(444,'+',4,'Syntax:\n+\n\nAddition:\n\nURL: https://mariadb.com/kb/en/addition-operator/\n\n','MariaDB> SELECT 3+5;\n -> 8\n','https://mariadb.com/kb/en/addition-operator/'),(445,'INET_NTOA',14,'Syntax:\nINET_NTOA(expr)\n\nGiven a numeric IPv4 network address in network byte order, returns the\ndotted-quad representation of the address as a string. INET_NTOA()\nreturns NULL if it does not understand its argument.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/inet_ntoa/\n\n','MariaDB> SELECT INET_NTOA(167773449);\n -> \'10.0.5.9\'\n','https://mariadb.com/kb/en/inet_ntoa/'),(446,'ACOS',4,'Syntax:\nACOS(X)\n\nReturns the arc cosine of X, that is, the value whose cosine is X.\nReturns NULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/acos/\n\n','MariaDB> SELECT ACOS(1);\n -> 0\nMariaDB> SELECT ACOS(1.0001);\n -> NULL\nMariaDB> SELECT ACOS(0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/acos/'),(447,'ISOLATION',8,'Syntax:\nSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL\n {\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n }\n\nThis statement sets the transaction isolation level, used for\noperations on InnoDB tables.\n\nScope of the Isolation Level\n\nYou can set the isolation level globally, for the current session, or\nfor the next transaction:\n\no With the GLOBAL keyword, the statement sets the default transaction\n level globally for all subsequent sessions. Existing sessions are\n unaffected.\n\no With the SESSION keyword, the statement sets the default transaction\n level for all subsequent transactions performed within the current\n session.\n\no Without any SESSION or GLOBAL keyword, the statement sets the\n isolation level for the next (not started) transaction performed\n within the current session.\n\nA change to the global default isolation level requires the SUPER\nprivilege. Any session is free to change its session isolation level\n(even in the middle of a transaction), or the isolation level for its\nnext transaction.\n\nSET TRANSACTION ISOLATION LEVEL without GLOBAL or SESSION is not\npermitted while there is an active transaction:\n\nMariaDB> START TRANSACTION;\nQuery OK, 0 rows affected (0.02 sec)\n\nMariaDB> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction isolation level can\'t be changed\nwhile a transaction is in progress\n\nTo set the global default isolation level at server startup, use the\n--transaction-isolation=level option to mysqld on the command line or\nin an option file. Values of level for this option use dashes rather\nthan spaces, so the permissible values are READ-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example, to set\nthe default isolation level to REPEATABLE READ, use these lines in the\n[mysqld] section of an option file:\n\n[mysqld]\ntransaction-isolation = REPEATABLE-READ\n\nIt is possible to check or set the global and session transaction\nisolation levels at runtime by using the tx_isolation system variable:\n\nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\nSET GLOBAL tx_isolation=\'REPEATABLE-READ\';\nSET SESSION tx_isolation=\'SERIALIZABLE\';\n\nDetails and Usage of Isolation Levels\n\nInnoDB supports each of the transaction isolation levels described here\nusing different locking strategies. You can enforce a high degree of\nconsistency with the default REPEATABLE READ level, for operations on\ncrucial data where ACID compliance is important. Or you can relax the\nconsistency rules with READ COMMITTED or even READ UNCOMMITTED, in\nsituations such as bulk reporting where precise consistency and\nrepeatable results are less important than minimizing the amount of\noverhead for locking. SERIALIZABLE enforces even stricter rules than\nREPEATABLE READ, and is used mainly in specialized situations, such as\nwith XA transactions and for troubleshooting issues with concurrency\nand deadlocks.\n\nFor full information about how these isolation levels work with InnoDB\ntransactions, see\nhttp://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html.\nIn particular, for additional information about InnoDB record-level\nlocks and how it uses them to execute various types of statements, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html\nand http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html.\n\nThe following list describes how MySQL supports the different\ntransaction levels. The list goes from the most commonly used level to\nthe least used.\n\no REPEATABLE READ\n\n This is the default isolation level for InnoDB. For consistent reads,\n there is an important difference from the READ COMMITTED isolation\n level: All consistent reads within the same transaction read the\n snapshot established by the first read. This convention means that if\n you issue several plain (nonlocking) SELECT statements within the\n same transaction, these SELECT statements are consistent also with\n respect to each other. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n UPDATE, and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition, or a\n range-type search condition. For a unique index with a unique search\n condition, InnoDB locks only the index record found, not the gap\n before it. For other search conditions, InnoDB locks the index range\n scanned, using gap locks or next-key (gap plus index-record) locks to\n block insertions by other sessions into the gaps covered by the\n range.\n\no READ COMMITTED\n\n A somewhat Oracle-like isolation level with respect to consistent\n (nonlocking) reads: Each consistent read, even within the same\n transaction, sets and reads its own fresh snapshot. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n InnoDB locks only index records, not the gaps before them, and thus\n permits the free insertion of new records next to locked records. For\n UPDATE and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition (such as\n WHERE id = 100), or a range-type search condition (such as WHERE id >\n 100). For a unique index with a unique search condition, InnoDB locks\n only the index record found, not the gap before it. For range-type\n searches, InnoDB locks the index range scanned, using gap locks or\n next-key (gap plus index-record) locks to block insertions by other\n sessions into the gaps covered by the range. This is necessary\n because \"phantom rows\" must be blocked for MySQL replication and\n recovery to work.\n\n *Note*: In MySQL 5.5, if the READ COMMITTED isolation level is used\n or the innodb_locks_unsafe_for_binlog system variable is enabled,\n there is no InnoDB gap locking except for foreign-key constraint\n checking and duplicate-key checking. Also, record locks for\n nonmatching rows are released after MySQL has evaluated the WHERE\n condition. If you use READ COMMITTED or enable\n innodb_locks_unsafe_for_binlog, you must use row-based binary\n logging.\n\no READ UNCOMMITTED\n\n SELECT statements are performed in a nonlocking fashion, but a\n possible earlier version of a row might be used. Thus, using this\n isolation level, such reads are not consistent. This is also called a\n \"dirty read.\" Otherwise, this isolation level works like READ\n COMMITTED.\n\no SERIALIZABLE\n\n This level is like REPEATABLE READ, but InnoDB implicitly converts\n all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if\n autocommit is disabled. If autocommit is enabled, the SELECT is its\n own transaction. It therefore is known to be read only and can be\n serialized if performed as a consistent (nonlocking) read and need\n not block for other transactions. (To force a plain SELECT to block\n if other transactions have modified the selected rows, disable\n autocommit.)\n\nURL: https://mariadb.com/kb/en/set-transaction-isolation-level/\n\n','','https://mariadb.com/kb/en/set-transaction-isolation-level/'),(448,'CEILING',4,'Syntax:\nCEILING(X)\n\nReturns the smallest integer value not less than X.\n\nURL: https://mariadb.com/kb/en/ceiling/\n\n','MariaDB> SELECT CEILING(1.23);\n -> 2\nMariaDB> SELECT CEILING(-1.23);\n -> -1\n','https://mariadb.com/kb/en/ceiling/'),(449,'SIN',4,'Syntax:\nSIN(X)\n\nReturns the sine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/sin/\n\n','MariaDB> SELECT SIN(PI());\n -> 1.2246063538224e-16\nMariaDB> SELECT ROUND(SIN(PI()));\n -> 0\n','https://mariadb.com/kb/en/sin/'),(450,'DAYOFWEEK',31,'Syntax:\nDAYOFWEEK(date)\n\nReturns the weekday index for date (1 = Sunday, 2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC standard.\n\nURL: https://mariadb.com/kb/en/dayofweek/\n\n','MariaDB> SELECT DAYOFWEEK(\'2007-02-03\');\n -> 7\n','https://mariadb.com/kb/en/dayofweek/'),(451,'SHOW PROCESSLIST',26,'Syntax:\nSHOW [FULL] PROCESSLIST\n\nSHOW PROCESSLIST shows you which threads are running. You can also get\nthis information from the INFORMATION_SCHEMA PROCESSLIST table or the\nmysqladmin processlist command. If you have the PROCESS privilege, you\ncan see all threads. Otherwise, you can see only your own threads (that\nis, threads associated with the MySQL account that you are using). If\nyou do not use the FULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n\nURL: https://mariadb.com/kb/en/show-processlist/\n\n','','https://mariadb.com/kb/en/show-processlist/'),(452,'LINEFROMWKB',32,'LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])\n\nConstructs a LINESTRING value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromwkb/\n\n','','https://mariadb.com/kb/en/linefromwkb/'),(453,'GEOMETRYTYPE',36,'GeometryType(g)\n\nReturns as a binary string the name of the geometry type of which the\ngeometry instance g is a member. The name corresponds to one of the\ninstantiable Geometry subclasses.\n\nURL: https://mariadb.com/kb/en/geometrytype/\n\n','MariaDB> SELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n','https://mariadb.com/kb/en/geometrytype/'),(454,'CREATE VIEW',39,'Syntax:\nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThe CREATE VIEW statement creates a new view, or replaces an existing\none if the OR REPLACE clause is given. If the view does not exist,\nCREATE OR REPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR REPLACE VIEW is the same as ALTER VIEW.\n\nThe select_statement is a SELECT statement that provides the definition\nof the view. (When you select from the view, you select in effect using\nthe SELECT statement.) select_statement can select from base tables or\nother views.\n\nThe view definition is \"frozen\" at creation time, so changes to the\nunderlying tables afterward do not affect the view definition. For\nexample, if a view is defined as SELECT * on a table, new columns added\nto the table later do not become part of the view.\n\nThe ALGORITHM clause affects how MySQL processes the view. The DEFINER\nand SQL SECURITY clauses specify the security context to be used when\nchecking access privileges at view invocation time. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates to rows in\ntables referenced by the view. These clauses are described later in\nthis section.\n\nThe CREATE VIEW statement requires the CREATE VIEW privilege for the\nview, and some privilege for each column selected by the SELECT\nstatement. For columns used elsewhere in the SELECT statement you must\nhave the SELECT privilege. If the OR REPLACE clause is present, you\nmust also have the DROP privilege for the view. CREATE VIEW might also\nrequire the SUPER privilege, depending on the DEFINER value, as\ndescribed later in this section.\n\nWhen a view is referenced, privilege checking occurs as described later\nin this section.\n\nA view belongs to a database. By default, a new view is created in the\ndefault database. To create the view explicitly in a given database,\nspecify the name as db_name.view_name when you create it:\n\nMariaDB> CREATE VIEW test.v AS SELECT * FROM t;\n\nWithin a database, base tables and views share the same namespace, so a\nbase table and a view cannot have the same name.\n\nColumns retrieved by the SELECT statement can be simple references to\ntable columns. They can also be expressions that use functions,\nconstant values, operators, and so forth.\n\nViews must have unique column names with no duplicates, just like base\ntables. By default, the names of the columns retrieved by the SELECT\nstatement are used for the view column names. To define explicit names\nfor the view columns, the optional column_list clause can be given as a\nlist of comma-separated identifiers. The number of names in column_list\nmust be the same as the number of columns retrieved by the SELECT\nstatement.\n\nUnqualified table or view names in the SELECT statement are interpreted\nwith respect to the default database. A view can refer to tables or\nviews in other databases by qualifying the table or view name with the\nproper database name.\n\nA view can be created from many kinds of SELECT statements. It can\nrefer to base tables or other views. It can use joins, UNION, and\nsubqueries. The SELECT need not even refer to any tables. The following\nexample defines a view that selects two columns from another table, as\nwell as an expression calculated from those columns:\n\nMariaDB> CREATE TABLE t (qty INT, price INT);\nMariaDB> INSERT INTO t VALUES(3, 50);\nMariaDB> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;\nMariaDB> SELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n\nA view definition is subject to the following restrictions:\n\no The SELECT statement cannot contain a subquery in the FROM clause.\n\no The SELECT statement cannot refer to system or user variables.\n\no Within a stored program, the definition cannot refer to program\n parameters or local variables.\n\no The SELECT statement cannot refer to prepared statement parameters.\n\no Any table or view referred to in the definition must exist. However,\n after a view has been created, it is possible to drop a table or view\n that the definition refers to. In this case, use of the view results\n in an error. To check a view definition for problems of this kind,\n use the CHECK TABLE statement.\n\no The definition cannot refer to a TEMPORARY table, and you cannot\n create a TEMPORARY view.\n\no Any tables named in the view definition must exist at definition\n time.\n\no You cannot associate a trigger with a view.\n\no Aliases for column names in the SELECT statement are checked against\n the maximum column length of 64 characters (not the maximum alias\n length of 256 characters).\n\nORDER BY is permitted in a view definition, but it is ignored if you\nselect from a view using a statement that has its own ORDER BY.\n\nFor other options or clauses in the definition, they are added to the\noptions or clauses of the statement that references the view, but the\neffect is undefined. For example, if a view definition includes a LIMIT\nclause, and you select from the view using a statement that has its own\nLIMIT clause, it is undefined which limit applies. This same principle\napplies to options such as ALL, DISTINCT, or SQL_SMALL_RESULT that\nfollow the SELECT keyword, and to clauses such as INTO, FOR UPDATE,\nLOCK IN SHARE MODE, and PROCEDURE.\n\nIf you create a view and then change the query processing environment\nby changing system variables, that may affect the results that you get\nfrom the view:\n\nMariaDB> CREATE VIEW v (mycol) AS SELECT \'abc\';\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SET sql_mode = \'\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol |\n+-------+\n1 row in set (0.01 sec)\n\nMariaDB> SET sql_mode = \'ANSI_QUOTES\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc |\n+-------+\n1 row in set (0.00 sec)\n\nThe DEFINER and SQL SECURITY clauses determine which MySQL account to\nuse when checking access privileges for the view when a statement is\nexecuted that references the view. The valid SQL SECURITY\ncharacteristic values are DEFINER and INVOKER. These indicate that the\nrequired privileges must be held by the user who defined or invoked the\nview, respectively. The default SQL SECURITY value is DEFINER.\n\nIf a user value is given for the DEFINER clause, it should be a MySQL\naccount specified as \'user_name\'@\'host_name\' (the same format used in\nthe GRANT statement), CURRENT_USER, or CURRENT_USER(). The default\nDEFINER value is the user who executes the CREATE VIEW statement. This\nis the same as specifying DEFINER = CURRENT_USER explicitly.\n\nIf you specify the DEFINER clause, these rules determine the valid\nDEFINER user values:\n\no If you do not have the SUPER privilege, the only valid user value is\n your own account, either specified literally or by using\n CURRENT_USER. You cannot set the definer to some other account.\n\no If you have the SUPER privilege, you can specify any syntactically\n valid account name. If the account does not actually exist, a warning\n is generated.\n\no Although it is possible to create a view with a nonexistent DEFINER\n account, an error occurs when the view is referenced if the SQL\n SECURITY value is DEFINER but the definer account does not exist.\n\nFor more information about view security, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nWithin a view definition, CURRENT_USER returns the view\'s DEFINER value\nby default. For views defined with the SQL SECURITY INVOKER\ncharacteristic, CURRENT_USER returns the account for the view\'s\ninvoker. For information about user auditing within views, see\nhttp://dev.mysql.com/doc/refman/5.5/en/account-activity-auditing.html.\n\nWithin a stored routine that is defined with the SQL SECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER value. This\nalso affects a view defined within such a routine, if the view\ndefinition contains a DEFINER value of CURRENT_USER.\n\nView privileges are checked like this:\n\no At view definition time, the view creator must have the privileges\n needed to use the top-level objects accessed by the view. For\n example, if the view definition refers to table columns, the creator\n must have some privilege for each column in the select list of the\n definition, and the SELECT privilege for each column used elsewhere\n in the definition. If the definition refers to a stored function,\n only the privileges needed to invoke the function can be checked. The\n privileges required at function invocation time can be checked only\n as it executes: For different invocations, different execution paths\n within the function might be taken.\n\no The user who references a view must have appropriate privileges to\n access it (SELECT to select from it, INSERT to insert into it, and so\n forth.)\n\no When a view has been referenced, privileges for objects accessed by\n the view are checked against the privileges held by the view DEFINER\n account or invoker, depending on whether the SQL SECURITY\n characteristic is DEFINER or INVOKER, respectively.\n\no If reference to a view causes execution of a stored function,\n privilege checking for statements executed within the function depend\n on whether the function SQL SECURITY characteristic is DEFINER or\n INVOKER. If the security characteristic is DEFINER, the function runs\n with the privileges of the DEFINER account. If the characteristic is\n INVOKER, the function runs with the privileges determined by the\n view\'s SQL SECURITY characteristic.\n\nExample: A view might depend on a stored function, and that function\nmight invoke other stored routines. For example, the following view\ninvokes a stored function f():\n\nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n\nSuppose that f() contains a statement such as this:\n\nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n\nThe privileges required for executing statements within f() need to be\nchecked when f() executes. This might mean that privileges are needed\nfor p1() or p2(), depending on the execution path within f(). Those\nprivileges must be checked at runtime, and the user who must possess\nthe privileges is determined by the SQL SECURITY values of the view v\nand the function f().\n\nThe DEFINER and SQL SECURITY clauses for views are extensions to\nstandard SQL. In standard SQL, views are handled using the rules for\nSQL SECURITY DEFINER. The standard says that the definer of the view,\nwhich is the same as the owner of the view\'s schema, gets applicable\nprivileges on the view (for example, SELECT) and may grant them. MySQL\nhas no concept of a schema \"owner\", so MySQL adds a clause to identify\nthe definer. The DEFINER clause is an extension where the intent is to\nhave what the standard has; that is, a permanent record of who defined\nthe view. This is why the default DEFINER value is the account of the\nview creator.\n\nThe optional ALGORITHM clause is a MySQL extension to standard SQL. It\naffects how MySQL processes the view. ALGORITHM takes three values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is UNDEFINED if\nno ALGORITHM clause is present. For more information, see\nhttps://mariadb.com/kb/en/view-algorithms/.\n\nSome views are updatable. That is, you can use them in statements such\nas UPDATE, DELETE, or INSERT to update the contents of the underlying\ntable. For a view to be updatable, there must be a one-to-one\nrelationship between the rows in the view and the rows in the\nunderlying table. There are also certain other constructs that make a\nview nonupdatable.\n\nThe WITH CHECK OPTION clause can be given for an updatable view to\nprevent inserts or updates to rows except those for which the WHERE\nclause in the select_statement is true.\n\nIn a WITH CHECK OPTION clause for an updatable view, the LOCAL and\nCASCADED keywords determine the scope of check testing when the view is\ndefined in terms of another view. The LOCAL keyword restricts the CHECK\nOPTION only to the view being defined. CASCADED causes the checks for\nunderlying views to be evaluated as well. When neither keyword is\ngiven, the default is CASCADED.\n\nFor more information about updatable views and the WITH CHECK OPTION\nclause, see\nhttps://mariadb.com/kb/en/inserting-and-updating-with-views/.\n\nURL: https://mariadb.com/kb/en/create-view/\n\n','','https://mariadb.com/kb/en/create-view/'),(455,'TRIM',37,'Syntax:\nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr\nFROM] str)\n\nReturns the string str with all remstr prefixes or suffixes removed. If\nnone of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is\nassumed. remstr is optional and, if not specified, spaces are removed.\n\nURL: https://mariadb.com/kb/en/trim/\n\n','MariaDB> SELECT TRIM(\' bar \');\n -> \'bar\'\nMariaDB> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');\n -> \'barxxx\'\nMariaDB> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');\n -> \'bar\'\nMariaDB> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');\n -> \'barx\'\n','https://mariadb.com/kb/en/trim/'),(456,'IS',18,'Syntax:\nIS boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is/\n\n','MariaDB> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n -> 1, 1, 1\n','https://mariadb.com/kb/en/is/'),(457,'GET_FORMAT',31,'Syntax:\nGET_FORMAT({DATE|TIME|DATETIME}, {\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n\nReturns a format string. This function is useful in combination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n\nURL: https://mariadb.com/kb/en/get_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n -> \'03.10.2003\'\nMariaDB> SELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n -> \'2003-10-31\'\n','https://mariadb.com/kb/en/get_format/'),(458,'TINYBLOB',22,'TINYBLOB\n\nA BLOB column with a maximum length of 255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a 1-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinyblob/\n\n','','https://mariadb.com/kb/en/tinyblob/'),(459,'SIGNAL',23,'Syntax:\nSIGNAL condition_value\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nSIGNAL is the way to \"return\" an error. SIGNAL provides error\ninformation to a handler, to an outer portion of the application, or to\nthe client. Also, it provides control over the error\'s characteristics\n(error number, SQLSTATE value, message). Without SIGNAL, it is\nnecessary to resort to workarounds such as deliberately referring to a\nnonexistent table to cause a routine to return an error.\n\nNo special privileges are required to execute the SIGNAL statement.\n\nThe condition_value in a SIGNAL statement indicates the error value to\nbe returned. It can be an SQLSTATE value (a 5-character string literal)\nor a condition_name that refers to a named condition previously defined\nwith DECLARE ... CONDITION (see [HELP DECLARE CONDITION]).\n\nAn SQLSTATE value can indicate errors, warnings, or \"not found.\" The\nfirst two characters of the value indicate its error class, as\ndiscussed in\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items. Some signal values cause statement termination; see\nhttps://mariadb.com/kb/en/signal/#signal-effects.\n\nThe SQLSTATE value for a SIGNAL statement should not start with \'00\'\nbecause such values indicate success and are not valid for signaling an\nerror. This is true whether the SQLSTATE value is specified directly in\nthe SIGNAL statement or in a named condition referred to in the\nstatement. If the value is invalid, a Bad SQLSTATE error occurs.\n\nTo signal a generic SQLSTATE value, use \'45000\', which means \"unhandled\nuser-defined exception.\"\n\nThe SIGNAL statement optionally includes a SET clause that contains\nmultiple signal items, in a comma-separated list of\ncondition_information_item_name = simple_value_specification\nassignments.\n\nEach condition_information_item_name may be specified only once in the\nSET clause. Otherwise, a Duplicate condition information item error\noccurs.\n\nValid simple_value_specification designators can be specified using\nstored procedure or function parameters, stored program local variables\ndeclared with DECLARE, user-defined variables, system variables, or\nliterals. A character literal may include a _charset introducer.\n\nFor information about permissible condition_information_item_name\nvalues, see\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items.\n\nURL: https://mariadb.com/kb/en/signal/\n\n','CREATE PROCEDURE p (pval INT)\nBEGIN\n DECLARE specialty CONDITION FOR SQLSTATE \'45000\';\n IF pval = 0 THEN\n SIGNAL SQLSTATE \'01000\';\n ELSEIF pval = 1 THEN\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSEIF pval = 2 THEN\n SIGNAL specialty\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSE\n SIGNAL SQLSTATE \'01000\'\n SET MESSAGE_TEXT = \'A warning occurred\', MYSQL_ERRNO = 1000;\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\', MYSQL_ERRNO = 1001;\n END IF;\nEND;\n','https://mariadb.com/kb/en/signal/'),(460,'SAVEPOINT',8,'Syntax:\nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n\nInnoDB supports the SQL statements SAVEPOINT, ROLLBACK TO SAVEPOINT,\nRELEASE SAVEPOINT and the optional WORK keyword for ROLLBACK.\n\nURL: https://mariadb.com/kb/en/savepoint/\n\n','','https://mariadb.com/kb/en/savepoint/'),(461,'USER',17,'Syntax:\nUSER()\n\nReturns the current MySQL user name and host name as a string in the\nutf8 character set.\n\nURL: https://mariadb.com/kb/en/user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\n','https://mariadb.com/kb/en/user/'),(462,'LABELS',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nLabels are permitted for BEGIN ... END blocks and for the LOOP, REPEAT,\nand WHILE statements. Label use for those statements follows these\nrules:\n\no begin_label must be followed by a colon.\n\no begin_label can be given without end_label. If end_label is present,\n it must be the same as begin_label.\n\no end_label cannot be given without begin_label.\n\no Labels at the same nesting level must be distinct.\n\no Labels can be up to 16 characters long.\n\nTo refer to a label within the labeled construct, use an ITERATE or\nLEAVE statement. The following example uses those statements to\ncontinue iterating or terminate the loop:\n\nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN ITERATE label1; END IF;\n LEAVE label1;\n END LOOP label1;\nEND;\n\nThe scope of a block label does not include the code for handlers\ndeclared within the block. For details, see [HELP DECLARE HANDLER].\n\nURL: https://mariadb.com/kb/en/labels/\n\n','','https://mariadb.com/kb/en/labels/'),(463,'ALTER TABLE',39,'Syntax:\nALTER [ONLINE | OFFLINE] [IGNORE] TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (index_col_name,...)\n reference_definition\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] col_name\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} index_name\n | DROP FOREIGN KEY fk_symbol\n | MAX_ROWS = rows\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO|AS] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | FORCE\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO (partition_definitions)]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | PARTITION BY partitioning_expression\n | REMOVE PARTITIONING\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\ntable_options:\n table_option [[,] table_option] ... (see CREATE TABLE options)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\nPartitioning-related clauses for ALTER TABLE can be used with\npartitioned tables for repartitioning, for adding, dropping, merging,\nand splitting partitions, and for performing partitioning maintenance.\nFor more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations\n.html.\n\nFollowing the table name, specify the alterations to be made. If none\nare given, ALTER TABLE does nothing.\n\nURL: https://mariadb.com/kb/en/alter-table/\n\n','','https://mariadb.com/kb/en/alter-table/'),(464,'MPOINTFROMWKB',32,'MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])\n\nConstructs a MULTIPOINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromwkb/\n\n','','https://mariadb.com/kb/en/mpointfromwkb/'),(465,'CHAR BYTE',22,'The CHAR BYTE data type is an alias for the BINARY data type. This is a\ncompatibility feature.\n\nURL: https://mariadb.com/kb/en/char-byte/\n\n','','https://mariadb.com/kb/en/char-byte/'),(466,'REPAIR TABLE',20,'Syntax:\nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n\nREPAIR TABLE repairs a possibly corrupted table. By default, it has the\nsame effect as myisamchk --recover tbl_name. REPAIR TABLE works for\nMyISAM, ARCHIVE, and CSV tables. See\nhttps://mariadb.com/kb/en/myisam-storage-engine/, and\nhttps://mariadb.com/kb/en/archive/, and\nhttps://mariadb.com/kb/en/csv/\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nREPAIR TABLE is supported for partitioned tables. However, the USE_FRM\noption cannot be used with this statement on a partitioned table.\n\nYou can use ALTER TABLE ... REPAIR PARTITION to repair one or more\npartitions; for more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/repair-table/\n\n','','https://mariadb.com/kb/en/repair-table/'),(467,'MERGE',39,'The MERGE storage engine, also known as the MRG_MyISAM engine, is a\ncollection of identical MyISAM tables that can be used as one.\n\"Identical\" means that all tables have identical column and index\ninformation. You cannot merge MyISAM tables in which the columns are\nlisted in a different order, do not have exactly the same columns, or\nhave the indexes in different order. However, any or all of the MyISAM\ntables can be compressed with myisampack. See\nhttps://mariadb.com/kb/en/myisampack/. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS do not\nmatter.\n\nURL: https://mariadb.com/kb/en/merge/\n\n','MariaDB> CREATE TABLE t1 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> CREATE TABLE t2 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> INSERT INTO t1 (message) VALUES (\'Testing\'),(\'table\'),(\'t1\');\nMariaDB> INSERT INTO t2 (message) VALUES (\'Testing\'),(\'table\'),(\'t2\');\nMariaDB> CREATE TABLE total (\n -> a INT NOT NULL AUTO_INCREMENT,\n -> message CHAR(20), INDEX(a))\n -> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n','https://mariadb.com/kb/en/merge/'),(468,'CREATE TABLE',39,'Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n select_statement\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT default_value]\n [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [STORAGE {DISK|MEMORY|DEFAULT}]\n [reference_definition]\n\ndata_type:\n BIT[(length)]\n | TINYINT[(length)] [UNSIGNED] [ZEROFILL]\n | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]\n | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]\n | INT[(length)] [UNSIGNED] [ZEROFILL]\n | INTEGER[(length)] [UNSIGNED] [ZEROFILL]\n | BIGINT[(length)] [UNSIGNED] [ZEROFILL]\n | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | DATE\n | TIME\n | TIMESTAMP\n | DATETIME\n | YEAR\n | CHAR[(length)]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | VARCHAR(length)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | BINARY[(length)]\n | VARBINARY(length)\n | TINYBLOB\n | BLOB\n | MEDIUMBLOB\n | LONGBLOB\n | TINYTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | TEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | MEDIUMTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | LONGTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | ENUM(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | SET(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | spatial_type\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES \n {LESS THAN {(expr | value_list) | MAXVALUE} \n | \n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n\nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some valid select statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nRules for permissible table names are given in\nhttps://mariadb.com/kb/en/identifier-names/. By default,\nthe table is created in the default database, using the InnoDB storage\nengine. An error occurs if the table exists, if there is no default\ndatabase, or if the database does not exist.\n\nURL: https://mariadb.com/kb/en/create-table/\n\n','','https://mariadb.com/kb/en/create-table/'),(469,'>',18,'Syntax:\n>\n\nGreater than:\n\nURL: https://mariadb.com/kb/en/greater-than/\n\n','MariaDB> SELECT 2 > 2;\n -> 0\n','https://mariadb.com/kb/en/greater-than/'),(470,'ANALYZE TABLE',20,'Syntax:\nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nANALYZE TABLE analyzes and stores the key distribution for a table.\nDuring the analysis, the table is locked with a read lock for InnoDB\nand MyISAM. This statement works with InnoDB, Aria and MyISAM tables.\nFor MyISAM tables, this statement is equivalent to using myisamchk\n--analyze.\n\nFor more information on how the analysis works within InnoDB, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html.\n\nMySQL uses the stored key distribution to decide the order in which\ntables should be joined when you perform a join on something other than\na constant. In addition, key distributions can be used when deciding\nwhich indexes to use for a specific table within a query.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nANALYZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... ANALYZE PARTITION to analyze one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/analyze-table/\n\n','','https://mariadb.com/kb/en/analyze-table/'),(471,'MICROSECOND',31,'Syntax:\nMICROSECOND(expr)\n\nReturns the microseconds from the time or datetime expression expr as a\nnumber in the range from 0 to 999999.\n\nURL: https://mariadb.com/kb/en/microsecond/\n\n','MariaDB> SELECT MICROSECOND(\'12:00:00.123456\');\n -> 123456\nMariaDB> SELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n -> 10\n','https://mariadb.com/kb/en/microsecond/'),(472,'CONSTRAINT',39,'InnoDB supports foreign keys, which let you cross-reference related\ndata across tables, and foreign key constraints, which help keep this\nspread-out data consistent. The syntax for an InnoDB foreign key\nconstraint definition in the CREATE TABLE or ALTER TABLE statement\nlooks like this:\n\n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\nURL: https://mariadb.com/kb/en/constraint/\n\n','CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n','https://mariadb.com/kb/en/constraint/'),(473,'CREATE SERVER',39,'Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nwithin the servers table within the mysql database. This statement\nrequires the SUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name should be mysql, and may be quoted with single\nquotation marks. Other values for wrapper_name are not currently\nsupported.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*: Note that the OWNER option is currently not applied, and has no\neffect on the ownership or operation of the server connection that is\ncreated.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: https://mariadb.com/kb/en/create-server/\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE \'test\');\n','https://mariadb.com/kb/en/create-server/'),(474,'FIELD',37,'Syntax:\nFIELD(str,str1,str2,str3,...)\n\nReturns the index (position) of str in the str1, str2, str3, ... list.\nReturns 0 if str is not found.\n\nIf all arguments to FIELD() are strings, all arguments are compared as\nstrings. If all arguments are numbers, they are compared as numbers.\nOtherwise, the arguments are compared as double.\n\nIf str is NULL, the return value is 0 because NULL fails equality\ncomparison with any value. FIELD() is the complement of ELT().\n\nURL: https://mariadb.com/kb/en/field/\n\n','MariaDB> SELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 2\nMariaDB> SELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 0\n','https://mariadb.com/kb/en/field/'),(475,'MAKETIME',31,'Syntax:\nMAKETIME(hour,minute,second)\n\nReturns a time value calculated from the hour, minute, and second\narguments.\n\nURL: https://mariadb.com/kb/en/maketime/\n\n','MariaDB> SELECT MAKETIME(12,15,30);\n -> \'12:15:30\'\n','https://mariadb.com/kb/en/maketime/'),(476,'CURDATE',31,'Syntax:\nCURDATE()\n\nReturns the current date as a value in \'YYYY-MM-DD\' or YYYYMMDD format,\ndepending on whether the function is used in a string or numeric\ncontext.\n\nURL: https://mariadb.com/kb/en/curdate/\n\n','MariaDB> SELECT CURDATE();\n -> \'2008-06-13\'\nMariaDB> SELECT CURDATE() + 0;\n -> 20080613\n','https://mariadb.com/kb/en/curdate/'),(477,'SET PASSWORD',10,'Syntax:\nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'cleartext password\')\n | OLD_PASSWORD(\'cleartext password\')\n | \'encrypted password\'\n }\n\nThe SET PASSWORD statement assigns a password to an existing MySQL user\naccount. When the read_only system variable is enabled, the SUPER\nprivilege is required to use SET PASSWORD, in addition to whatever\nother privileges might be required.\n\nIf the password is specified using the PASSWORD() or OLD_PASSWORD()\nfunction, the cleartext (unencrypted) password should be given as the\nargument to the function, which hashes the password and returns the\nencrypted password string. If the password is specified without using\neither function, it should be the already encrypted password value as a\nliteral string. In all cases, the encrypted password string must be in\nthe format required by the authentication method used for the account.\n\nThe old_passwords system variable value determines the hashing method\nused by PASSWORD(). If you specify the password using that function and\nSET PASSWORD rejects the password as not being in the correct format,\nit may be necessary to set old_passwords to change the hashing method.\nFor descriptions of the permitted values, see\nhttps://mariadb.com/kb/en/server-system-variables#old_passwords.\n\nWith no FOR user clause, this statement sets the password for the\ncurrent user. (To see which account the server authenticated you as,\ninvoke the CURRENT_USER() function.) Any client who successfully\nconnects to the server using a nonanonymous account can change the\npassword for that account.\n\nWith a FOR user clause, this statement sets the password for the named\nuser. You must have the UPDATE privilege for the mysql database to do\nthis. The user account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. The user\nvalue should be given as \'user_name\'@\'host_name\', where \'user_name\' and\n\'host_name\' are exactly as listed in the User and Host columns of the\nmysql.user table row. (If you specify only a user name, a host name of\n\'%\' is used.) For example, to set the password for an account with User\nand Host column values of \'bob\' and \'%.example.org\', write the\nstatement like this:\n\nSET PASSWORD FOR \'bob\'@\'%.example.org\' = PASSWORD(\'cleartext password\');\n\nURL: https://mariadb.com/kb/en/set-password/\n\n','','https://mariadb.com/kb/en/set-password/'),(478,'ALTER TABLESPACE',39,'Syntax:\nALTER TABLESPACE tablespace_name\n {ADD|DROP} DATAFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/alter-tablespace/\n\n','','https://mariadb.com/kb/en/alter-tablespace/'),(479,'IF FUNCTION',7,'Syntax:\nIF(expr1,expr2,expr3)\n\nIf expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns\nexpr2; otherwise it returns expr3. IF() returns a numeric or string\nvalue, depending on the context in which it is used.\n\nURL: https://mariadb.com/kb/en/if-function/\n\n','MariaDB> SELECT IF(1>2,2,3);\n -> 3\nMariaDB> SELECT IF(1<2,\'yes\',\'no\');\n -> \'yes\'\nMariaDB> SELECT IF(STRCMP(\'test\',\'test1\'),\'no\',\'yes\');\n -> \'no\'\n','https://mariadb.com/kb/en/if-function/'),(480,'ENUM',22,'ENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nAn enumeration. A string object that can have only one value, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or the special \'\'\nerror value. An ENUM column can have a maximum of 65,535 distinct\nvalues. ENUM values are represented internally as integers.\n\nURL: https://mariadb.com/kb/en/enum/\n\n','','https://mariadb.com/kb/en/enum/'),(481,'DATABASE',17,'Syntax:\nDATABASE()\n\nReturns the default (current) database name as a string in the utf8\ncharacter set. If there is no default database, DATABASE() returns\nNULL. Within a stored routine, the default database is the database\nthat the routine is associated with, which is not necessarily the same\nas the database that is the default in the calling context.\n\nURL: https://mariadb.com/kb/en/database/\n\n','MariaDB> SELECT DATABASE();\n -> \'test\'\n','https://mariadb.com/kb/en/database/'),(482,'POINTFROMWKB',32,'PointFromWKB(wkb[,srid])\n\nConstructs a POINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromwkb/\n\n','','https://mariadb.com/kb/en/pointfromwkb/'),(483,'POWER',4,'Syntax:\nPOWER(X,Y)\n\nThis is a synonym for POW().\n\nURL: https://mariadb.com/kb/en/power/\n\n','','https://mariadb.com/kb/en/power/'),(484,'ATAN',4,'Syntax:\nATAN(X)\n\nReturns the arc tangent of X, that is, the value whose tangent is X.\n\nURL: https://mariadb.com/kb/en/atan/\n\n','MariaDB> SELECT ATAN(2);\n -> 1.1071487177941\nMariaDB> SELECT ATAN(-2);\n -> -1.1071487177941\n','https://mariadb.com/kb/en/atan/'),(485,'STRCMP',37,'Syntax:\nSTRCMP(expr1,expr2)\n\nSTRCMP() returns 0 if the strings are the same, -1 if the first\nargument is smaller than the second according to the current sort\norder, and 1 otherwise.\n\nURL: https://mariadb.com/kb/en/strcmp/\n\n','MariaDB> SELECT STRCMP(\'text\', \'text2\');\n -> -1\nMariaDB> SELECT STRCMP(\'text2\', \'text\');\n -> 1\nMariaDB> SELECT STRCMP(\'text\', \'text\');\n -> 0\n','https://mariadb.com/kb/en/strcmp/'),(486,'INSERT DELAYED',27,'Syntax:\nINSERT DELAYED ...\n\nThe DELAYED option for the INSERT statement is a MySQL extension to\nstandard SQL that is very useful if you have clients that cannot or\nneed not wait for the INSERT to complete. This is a common situation\nwhen you use MySQL for logging and you also periodically run SELECT and\nUPDATE statements that take a long time to complete.\n\nWhen a client uses INSERT DELAYED, it gets an okay from the server at\nonce, and the row is queued to be inserted when the table is not in use\nby any other thread.\n\nAnother major benefit of using INSERT DELAYED is that inserts from many\nclients are bundled together and written in one block. This is much\nfaster than performing many separate inserts.\n\nNote that INSERT DELAYED is slower than a normal INSERT if the table is\nnot otherwise in use. There is also the additional overhead for the\nserver to handle a separate thread for each table for which there are\ndelayed rows. This means that you should use INSERT DELAYED only when\nyou are really sure that you need it.\n\nThe queued rows are held only in memory until they are inserted into\nthe table. This means that if you terminate mysqld forcibly (for\nexample, with kill -9) or if mysqld dies unexpectedly, any queued rows\nthat have not been written to disk are lost.\n\nThere are some constraints on the use of DELAYED:\n\no INSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE, and BLACKHOLE\n tables. For engines that do not support DELAYED, an error occurs.\n\no An error occurs for INSERT DELAYED if used with a table that has been\n locked with LOCK TABLES because the insert must be handled by a\n separate thread, not by the session that holds the lock.\n\no For MyISAM tables, if there are no free blocks in the middle of the\n data file, concurrent SELECT and INSERT statements are supported.\n Under these circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\n\no INSERT DELAYED should be used only for INSERT statements that specify\n value lists. The server ignores DELAYED for INSERT ... SELECT or\n INSERT ... ON DUPLICATE KEY UPDATE statements.\n\no Because the INSERT DELAYED statement returns immediately, before the\n rows are inserted, you cannot use LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\n\no DELAYED rows are not visible to SELECT statements until they actually\n have been inserted.\n\no Prior to MySQL 5.5.7, INSERT DELAYED was treated as a normal INSERT\n if the statement inserted multiple rows, binary logging was enabled,\n and the global logging format was statement-based (that is, whenever\n binlog_format was set to STATEMENT). Beginning with MySQL 5.5.7,\n INSERT DELAYED is always handled as a simple INSERT (that is, without\n the DELAYED option) whenever the value of binlog_format is STATEMENT\n or MIXED. (In the latter case, the statement no longer triggers a\n switch to row-based logging, and so is logged using the\n statement-based format.)\n\n This does not apply when using row-based binary logging mode\n (binlog_format set to ROW), in which INSERT DELAYED statements are\n always executed using the DELAYED option as specified, and logged as\n row-update events.\n\no DELAYED is ignored on slave replication servers, so that INSERT\n DELAYED is treated as a normal INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than the master.\n\no Pending INSERT DELAYED statements are lost if a table is write locked\n and ALTER TABLE is used to modify the table structure.\n\no INSERT DELAYED is not supported for views.\n\no INSERT DELAYED is not supported for partitioned tables.\n\nURL: https://mariadb.com/kb/en/insert-delayed/\n\n','','https://mariadb.com/kb/en/insert-delayed/'),(487,'SHOW PROFILE',26,'Syntax:\nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n\ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n\nThe SHOW PROFILE and SHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements executed\nduring the course of the current session.\n\nProfiling is controlled by the profiling session variable, which has a\ndefault value of 0 (OFF). Profiling is enabled by setting profiling to\n1 or ON:\n\nMariaDB> SET profiling = 1;\n\nSHOW PROFILES displays a list of the most recent statements sent to the\nserver. The size of the list is controlled by the\nprofiling_history_size session variable, which has a default value of\n15. The maximum value is 100. Setting the value to 0 has the practical\neffect of disabling profiling.\n\nAll statements are profiled except SHOW PROFILE and SHOW PROFILES, so\nyou will find neither of those statements in the profile list.\nMalformed statements are profiled. For example, SHOW PROFILING is an\nillegal statement, and a syntax error occurs if you try to execute it,\nbut it will show up in the profiling list.\n\nSHOW PROFILE displays detailed information about a single statement.\nWithout the FOR QUERY n clause, the output pertains to the most\nrecently executed statement. If FOR QUERY n is included, SHOW PROFILE\ndisplays information for statement n. The values of n correspond to the\nQuery_ID values displayed by SHOW PROFILES.\n\nThe LIMIT row_count clause may be given to limit the output to\nrow_count rows. If LIMIT is given, OFFSET offset may be added to begin\nthe output offset rows into the full set of rows.\n\nBy default, SHOW PROFILE displays Status and Duration columns. The\nStatus values are like the State values displayed by SHOW PROCESSLIST,\nalthough there might be some minor differences in interpretion for the\ntwo statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.5/en/thread-information.html).\n\nOptional type values may be specified to display specific additional\ntypes of information:\n\no ALL displays all information\n\no BLOCK IO displays counts for block input and output operations\n\no CONTEXT SWITCHES displays counts for voluntary and involuntary\n context switches\n\no CPU displays user and system CPU usage times\n\no IPC displays counts for messages sent and received\n\no MEMORY is not currently implemented\n\no PAGE FAULTS displays counts for major and minor page faults\n\no SOURCE displays the names of functions from the source code, together\n with the name and line number of the file in which the function\n occurs\n\no SWAPS displays swap counts\n\nProfiling is enabled per session. When a session ends, its profiling\ninformation is lost.\n\nURL: https://mariadb.com/kb/en/show-profile/\n\n','MariaDB> SELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> SET profiling = 1;\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> DROP TABLE IF EXISTS t1;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nMariaDB> CREATE TABLE T1 (id INT);\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SHOW PROFILES;\n+----------+----------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+----------+--------------------------+\n| 0 | 0.000088 | SET PROFILING = 1 |\n| 1 | 0.000136 | DROP TABLE IF EXISTS t1 |\n| 2 | 0.011947 | CREATE TABLE t1 (id INT) |\n+----------+----------+--------------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| checking permissions | 0.000040 |\n| creating table | 0.000056 |\n| After create | 0.011363 |\n| query end | 0.000375 |\n| freeing items | 0.000089 |\n| logging slow query | 0.000019 |\n| cleaning up | 0.000005 |\n+----------------------+----------+\n7 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE FOR QUERY 1;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| query end | 0.000107 |\n| freeing items | 0.000008 |\n| logging slow query | 0.000015 |\n| cleaning up | 0.000006 |\n+--------------------+----------+\n4 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE CPU FOR QUERY 2;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| checking permissions | 0.000040 | 0.000038 | 0.000002 |\n| creating table | 0.000056 | 0.000028 | 0.000028 |\n| After create | 0.011363 | 0.000217 | 0.001571 |\n| query end | 0.000375 | 0.000013 | 0.000028 |\n| freeing items | 0.000089 | 0.000010 | 0.000014 |\n| logging slow query | 0.000019 | 0.000009 | 0.000010 |\n| cleaning up | 0.000005 | 0.000003 | 0.000002 |\n+----------------------+----------+----------+------------+\n7 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-profile/'),(488,'SHOW PROCEDURE CODE',26,'Syntax:\nSHOW PROCEDURE CODE proc_name\n\nThis statement is a MySQL extension that is available only for servers\nthat have been built with debugging support. It displays a\nrepresentation of the internal implementation of the named stored\nprocedure. A similar statement, SHOW FUNCTION CODE, displays\ninformation about stored functions (see [HELP SHOW FUNCTION CODE]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table.\n\nIf the named routine is available, each statement produces a result\nset. Each row in the result set corresponds to one \"instruction\" in the\nroutine. The first column is Pos, which is an ordinal number beginning\nwith 0. The second column is Instruction, which contains an SQL\nstatement (usually changed from the original source), or a directive\nwhich has meaning only to the stored-routine handler.\n\nURL: https://mariadb.com/kb/en/show-procedure-code/\n\n','MariaDB> DELIMITER //\nMariaDB> CREATE PROCEDURE p1 ()\n -> BEGIN\n -> DECLARE fanta INT DEFAULT 55;\n -> DROP TABLE t2;\n -> LOOP\n -> INSERT INTO t3 VALUES (fanta);\n -> END LOOP;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n4 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-procedure-code/'),(489,'MEDIUMTEXT',22,'MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 16,777,215 (224 - 1) characters.\nThe effective maximum length is less if the value contains multi-byte\ncharacters. Each MEDIUMTEXT value is stored using a 3-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumtext/\n\n','','https://mariadb.com/kb/en/mediumtext/'),(490,'LN',4,'Syntax:\nLN(X)\n\nReturns the natural logarithm of X; that is, the base-e logarithm of X.\nIf X is less than or equal to 0, then NULL is returned.\n\nURL: https://mariadb.com/kb/en/ln/\n\n','MariaDB> SELECT LN(2);\n -> 0.69314718055995\nMariaDB> SELECT LN(-2);\n -> NULL\n','https://mariadb.com/kb/en/ln/'),(491,'RETURN',23,'Syntax:\nRETURN expr\n\nThe RETURN statement terminates execution of a stored function and\nreturns the value expr to the function caller. There must be at least\none RETURN statement in a stored function. There may be more than one\nif the function has multiple exit points.\n\nThis statement is not used in stored procedures, triggers, or events.\nThe LEAVE statement can be used to exit a stored program of those\ntypes.\n\nURL: https://mariadb.com/kb/en/return/\n\n','','https://mariadb.com/kb/en/return/'),(492,'SHOW COLLATION',26,'Syntax:\nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement lists collations supported by the server. By default,\nthe output from SHOW COLLATION includes all available collations. The\nLIKE clause, if present, indicates which collation names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | | 0 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |\n| latin1_danish_ci | latin1 | 15 | | | 0 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 0 |\n| latin1_general_ci | latin1 | 48 | | | 0 |\n| latin1_general_cs | latin1 | 49 | | | 0 |\n| latin1_spanish_ci | latin1 | 94 | | | 0 |\n+-------------------+---------+----+---------+----------+---------+\n\nURL: https://mariadb.com/kb/en/show-collation/\n\n','','https://mariadb.com/kb/en/show-collation/'),(493,'LOG',4,'Syntax:\nLOG(X), LOG(B,X)\n\nIf called with one parameter, this function returns the natural\nlogarithm of X. If X is less than or equal to 0, then NULL is returned.\n\nThe inverse of this function (when called with a single argument) is\nthe EXP() function.\n\nURL: https://mariadb.com/kb/en/log/\n\n','MariaDB> SELECT LOG(2);\n -> 0.69314718055995\nMariaDB> SELECT LOG(-2);\n -> NULL\n','https://mariadb.com/kb/en/log/'),(494,'SET SQL_LOG_BIN',8,'Syntax:\nSET sql_log_bin = {0|1}\n\nThe sql_log_bin variable controls whether logging to the binary log is\ndone. The default value is 1 (do logging). To change logging for the\ncurrent session, change the session value of this variable. The session\nuser must have the SUPER privilege to set this variable.\n\nBeginning with MySQL 5.5.5, it is no longer possible to set\n@@session.sql_log_bin within a transaction or subquery. (Bug #53437)\n\nURL: https://mariadb.com/kb/en/set-sql_log_bin/\n\n','','https://mariadb.com/kb/en/set-sql_log_bin/'),(495,'!=',18,'Syntax:\n<>, !=\n\nNot equal:\n\nURL: https://mariadb.com/kb/en/not-equal/\n\n','MariaDB> SELECT \'.01\' <> \'0.01\';\n -> 1\nMariaDB> SELECT .01 <> \'0.01\';\n -> 0\nMariaDB> SELECT \'zapp\' <> \'zappp\';\n -> 1\n','https://mariadb.com/kb/en/not-equal/'),(496,'WHILE',23,'Syntax:\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nThe statement list within a WHILE statement is repeated as long as the\nsearch_condition expression is true. statement_list consists of one or\nmore SQL statements, each terminated by a semicolon (;) statement\ndelimiter.\n\nA WHILE statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/while/\n\n','CREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n\n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n END WHILE;\nEND;\n','https://mariadb.com/kb/en/while/'),(497,'AES_DECRYPT',12,'Syntax:\nAES_DECRYPT(crypt_str,key_str)\n\nThis function decrypts data using the official AES (Advanced Encryption\nStandard) algorithm. For more information, see the description of\nAES_ENCRYPT().\n\nURL: https://mariadb.com/kb/en/aes_decrypt/\n\n','','https://mariadb.com/kb/en/aes_decrypt/'),(498,'DAYNAME',31,'Syntax:\nDAYNAME(date)\n\nReturns the name of the weekday for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-system-variables#lc_time_names).\n\nURL: https://mariadb.com/kb/en/dayname/\n\n','MariaDB> SELECT DAYNAME(\'2007-02-03\');\n -> \'Saturday\'\n','https://mariadb.com/kb/en/dayname/'),(499,'COERCIBILITY',17,'Syntax:\nCOERCIBILITY(str)\n\nReturns the collation coercibility value of the string argument.\n\nURL: https://mariadb.com/kb/en/coercibility/\n\n','MariaDB> SELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n -> 0\nMariaDB> SELECT COERCIBILITY(USER());\n -> 3\nMariaDB> SELECT COERCIBILITY(\'abc\');\n -> 4\n','https://mariadb.com/kb/en/coercibility/'),(500,'INT',22,'INT[(M)] [UNSIGNED] [ZEROFILL]\n\nA normal-size integer. The signed range is -2147483648 to 2147483647.\nThe unsigned range is 0 to 4294967295.\n\nURL: https://mariadb.com/kb/en/int/\n\n','','https://mariadb.com/kb/en/int/'),(501,'GLENGTH',13,'GLength(ls)\n\nReturns as a double-precision number the length of the LineString value\nls in its associated spatial reference.\n\nURL: https://mariadb.com/kb/en/glength/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.8284271247462 |\n+----------------------------+\n','https://mariadb.com/kb/en/glength/'),(502,'RADIANS',4,'Syntax:\nRADIANS(X)\n\nReturns the argument X, converted from degrees to radians. (Note that\nπ radians equals 180 degrees.)\n\nURL: https://mariadb.com/kb/en/radians/\n\n','MariaDB> SELECT RADIANS(90);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/radians/'),(503,'COLLATION',17,'Syntax:\nCOLLATION(str)\n\nReturns the collation of the string argument.\n\nURL: https://mariadb.com/kb/en/collation/\n\n','MariaDB> SELECT COLLATION(\'abc\');\n -> \'latin1_swedish_ci\'\nMariaDB> SELECT COLLATION(_utf8\'abc\');\n -> \'utf8_general_ci\'\n','https://mariadb.com/kb/en/collation/'),(504,'COALESCE',18,'Syntax:\nCOALESCE(value,...)\n\nReturns the first non-NULL value in the list, or NULL if there are no\nnon-NULL values.\n\nURL: https://mariadb.com/kb/en/coalesce/\n\n','MariaDB> SELECT COALESCE(NULL,1);\n -> 1\nMariaDB> SELECT COALESCE(NULL,NULL,NULL);\n -> NULL\n','https://mariadb.com/kb/en/coalesce/'),(505,'VERSION',17,'Syntax:\nVERSION()\n\nReturns a string that indicates the MySQL server version. The string\nuses the utf8 character set. The value might have a suffix in addition\nto the version number. See the description of the version system\nvariable in\nhttps://mariadb.com/kb/en/server-system-variables#version.\n\nURL: https://mariadb.com/kb/en/version/\n\n','MariaDB> SELECT VERSION();\n -> \'5.5.29-standard\'\n','https://mariadb.com/kb/en/version/'),(506,'MAKE_SET',37,'Syntax:\nMAKE_SET(bits,str1,str2,...)\n\nReturns a set value (a string containing substrings separated by \",\"\ncharacters) consisting of the strings that have the corresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL\nvalues in str1, str2, ... are not appended to the result.\n\nURL: https://mariadb.com/kb/en/make_set/\n\n','MariaDB> SELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n -> \'a\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n -> \'hello,world\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n -> \'hello\'\nMariaDB> SELECT MAKE_SET(0,\'a\',\'b\',\'c\');\n -> \'\'\n','https://mariadb.com/kb/en/make_set/'),(507,'FIND_IN_SET',37,'Syntax:\nFIND_IN_SET(str,strlist)\n\nReturns a value in the range of 1 to N if the string str is in the\nstring list strlist consisting of N substrings. A string list is a\nstring composed of substrings separated by \",\" characters. If the first\nargument is a constant string and the second is a column of type SET,\nthe FIND_IN_SET() function is optimized to use bit arithmetic. Returns\n0 if str is not in strlist or if strlist is the empty string. Returns\nNULL if either argument is NULL. This function does not work properly\nif the first argument contains a comma (\",\") character.\n\nURL: https://mariadb.com/kb/en/find_in_set/\n\n','MariaDB> SELECT FIND_IN_SET(\'b\',\'a,b,c,d\');\n -> 2\n','https://mariadb.com/kb/en/find_in_set/'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `host` +-- + +DROP TABLE IF EXISTS `host`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `host` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `host` +-- + +LOCK TABLES `host` WRITE; +/*!40000 ALTER TABLE `host` DISABLE KEYS */; +/*!40000 ALTER TABLE `host` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `index_stats` +-- + +DROP TABLE IF EXISTS `index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `index_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `prefix_arity` int(11) unsigned NOT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `index_stats` +-- + +LOCK TABLES `index_stats` WRITE; +/*!40000 ALTER TABLE `index_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_index_stats` +-- + +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_index_stats` +-- + +LOCK TABLES `innodb_index_stats` WRITE; +/*!40000 ALTER TABLE `innodb_index_stats` DISABLE KEYS */; +INSERT INTO `innodb_index_stats` VALUES ('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:11:18','n_diff_pfx01',0,1,'domain_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:11:18','n_diff_pfx02',0,1,'domain_id,sub_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:11:18','n_leaf_pages',1,NULL,'Number of leaf pages in the index'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:11:18','size',1,NULL,'Number of pages in the index'); +/*!40000 ALTER TABLE `innodb_index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_table_stats` +-- + +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_table_stats` +-- + +LOCK TABLES `innodb_table_stats` WRITE; +/*!40000 ALTER TABLE `innodb_table_stats` DISABLE KEYS */; +INSERT INTO `innodb_table_stats` VALUES ('mysql','gtid_slave_pos','2020-05-31 16:11:18',0,1,0); +/*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT '0', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 16:11:21'),('asus','root','','',1,'','2020-05-31 16:11:21'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_mapping` +-- + +DROP TABLE IF EXISTS `roles_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_mapping` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Admin_option` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + UNIQUE KEY `Host` (`Host`,`User`,`Role`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Granted roles'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_mapping` +-- + +LOCK TABLES `roles_mapping` WRITE; +/*!40000 ALTER TABLE `roles_mapping` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_mapping` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` char(64) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(80) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT '0', + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` char(64) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `table_stats` +-- + +DROP TABLE IF EXISTS `table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `table_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `cardinality` bigint(21) unsigned DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `table_stats` +-- + +LOCK TABLES `table_stats` WRITE; +/*!40000 ALTER TABLE `table_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT '0', + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', + `ssl_cipher` blob NOT NULL, + `x509_issuer` blob NOT NULL, + `x509_subject` blob NOT NULL, + `max_questions` int(11) unsigned NOT NULL DEFAULT '0', + `max_updates` int(11) unsigned NOT NULL DEFAULT '0', + `max_connections` int(11) unsigned NOT NULL DEFAULT '0', + `max_user_connections` int(11) NOT NULL DEFAULT '0', + `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, + `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N'),('asus','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N'),('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N'),('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N'),('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N'),('asus','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N'); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 19:11:50 diff --git a/mysql-test/std_data/mysql_database_10.1.dump b/mysql-test/std_data/mysql_database_10.1.dump new file mode 100644 index 00000000000..c46a4be8a17 --- /dev/null +++ b/mysql-test/std_data/mysql_database_10.1.dump @@ -0,0 +1,906 @@ +-- MySQL dump 10.16 Distrib 10.1.45-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 10.1.45-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `column_stats` +-- + +DROP TABLE IF EXISTS `column_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, + `nulls_ratio` decimal(12,4) DEFAULT NULL, + `avg_length` decimal(12,4) DEFAULT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + `hist_size` tinyint(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `column_stats` +-- + +LOCK TABLES `column_stats` WRITE; +/*!40000 ALTER TABLE `column_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `column_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT '0', + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gtid_slave_pos` +-- + +DROP TABLE IF EXISTS `gtid_slave_pos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gtid_slave_pos` ( + `domain_id` int(10) unsigned NOT NULL, + `sub_id` bigint(20) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `seq_no` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`domain_id`,`sub_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Replication slave GTID position'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gtid_slave_pos` +-- + +LOCK TABLES `gtid_slave_pos` WRITE; +/*!40000 ALTER TABLE `gtid_slave_pos` DISABLE KEYS */; +/*!40000 ALTER TABLE `gtid_slave_pos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control flow functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry constructors',34,''),(25,'GeometryCollection properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (0,'JOIN'),(1,'HOST'),(2,'REPEAT'),(3,'SERIALIZABLE'),(4,'REPLACE'),(5,'AT'),(6,'SCHEDULE'),(7,'RETURNS'),(8,'STARTS'),(9,'MASTER_SSL_CA'),(10,'NCHAR'),(11,'COLUMNS'),(12,'COMPLETION'),(13,'WORK'),(14,'DATETIME'),(15,'MODE'),(16,'OPEN'),(17,'INTEGER'),(18,'ESCAPE'),(19,'VALUE'),(20,'MASTER_SSL_VERIFY_SERVER_CERT'),(21,'SQL_BIG_RESULT'),(22,'DROP'),(23,'GEOMETRYCOLLECTIONFROMWKB'),(24,'EVENTS'),(25,'MONTH'),(26,'PROFILES'),(27,'DUPLICATE'),(28,'REPLICATION'),(29,'UNLOCK'),(30,'INNODB'),(31,'YEAR_MONTH'),(32,'SUBJECT'),(33,'PREPARE'),(34,'LOCK'),(35,'NDB'),(36,'CHECK'),(37,'FULL'),(38,'INT4'),(39,'BY'),(40,'NO'),(41,'MINUTE'),(42,'PARTITION'),(43,'DATA'),(44,'DAY'),(45,'SHARE'),(46,'REAL'),(47,'SEPARATOR'),(48,'MESSAGE_TEXT'),(49,'MASTER_HEARTBEAT_PERIOD'),(50,'DELETE'),(51,'ON'),(52,'COLUMN_NAME'),(53,'CONNECTION'),(54,'CLOSE'),(55,'X509'),(56,'USE'),(57,'SUBCLASS_ORIGIN'),(58,'WHERE'),(59,'PRIVILEGES'),(60,'SPATIAL'),(61,'EVENT'),(62,'SUPER'),(63,'SQL_BUFFER_RESULT'),(64,'IGNORE'),(65,'SHA2'),(66,'QUICK'),(67,'SIGNED'),(68,'OFFLINE'),(69,'SECURITY'),(70,'AUTOEXTEND_SIZE'),(71,'NDBCLUSTER'),(72,'POLYGONFROMWKB'),(73,'FALSE'),(74,'LEVEL'),(75,'FORCE'),(76,'BINARY'),(77,'TO'),(78,'CHANGE'),(79,'CURRENT_USER'),(80,'HOUR_MINUTE'),(81,'UPDATE'),(82,'PRESERVE'),(83,'TABLE_NAME'),(84,'INTO'),(85,'FEDERATED'),(86,'VARYING'),(87,'MAX_SIZE'),(88,'HOUR_SECOND'),(89,'VARIABLE'),(90,'ROLLBACK'),(91,'PROCEDURE'),(92,'TIMESTAMP'),(93,'IMPORT'),(94,'AGAINST'),(95,'CHECKSUM'),(96,'COUNT'),(97,'LONGBINARY'),(98,'THEN'),(99,'INSERT'),(100,'ENGINES'),(101,'HANDLER'),(102,'PORT'),(103,'DAY_SECOND'),(104,'EXISTS'),(105,'MUTEX'),(106,'HELP_DATE'),(107,'RELEASE'),(108,'BOOLEAN'),(109,'MOD'),(110,'DEFAULT'),(111,'TYPE'),(112,'NO_WRITE_TO_BINLOG'),(113,'OPTIMIZE'),(114,'SQLSTATE'),(115,'RESET'),(116,'CLASS_ORIGIN'),(117,'INSTALL'),(118,'ITERATE'),(119,'DO'),(120,'BIGINT'),(121,'SET'),(122,'ISSUER'),(123,'DATE'),(124,'STATUS'),(125,'FULLTEXT'),(126,'COMMENT'),(127,'MASTER_CONNECT_RETRY'),(128,'INNER'),(129,'RELAYLOG'),(130,'STOP'),(131,'MASTER_LOG_FILE'),(132,'MRG_MYISAM'),(133,'PRECISION'),(134,'REQUIRE'),(135,'TRAILING'),(136,'PARTITIONS'),(137,'LONG'),(138,'OPTION'),(139,'REORGANIZE'),(140,'ELSE'),(141,'DEALLOCATE'),(142,'IO_THREAD'),(143,'CASE'),(144,'CIPHER'),(145,'CONTINUE'),(146,'FROM'),(147,'READ'),(148,'LEFT'),(149,'ELSEIF'),(150,'MINUTE_SECOND'),(151,'COMPACT'),(152,'DEC'),(153,'FOR'),(154,'WARNINGS'),(155,'MIN_ROWS'),(156,'STRING'),(157,'CONDITION'),(158,'ENCLOSED'),(159,'FUNCTION'),(160,'AGGREGATE'),(161,'FIELDS'),(162,'INT3'),(163,'ARCHIVE'),(164,'AVG_ROW_LENGTH'),(165,'ADD'),(166,'KILL'),(167,'FLOAT4'),(168,'TABLESPACE'),(169,'VIEW'),(170,'REPEATABLE'),(171,'INFILE'),(172,'HELP_VERSION'),(173,'ORDER'),(174,'USING'),(175,'CONSTRAINT_CATALOG'),(176,'MIDDLEINT'),(177,'GRANT'),(178,'UNSIGNED'),(179,'DECIMAL'),(180,'GEOMETRYFROMTEXT'),(181,'INDEXES'),(182,'FOREIGN'),(183,'CACHE'),(184,'HOSTS'),(185,'MYSQL_ERRNO'),(186,'COMMIT'),(187,'SCHEMAS'),(188,'LEADING'),(189,'SNAPSHOT'),(190,'CONSTRAINT_NAME'),(191,'DECLARE'),(192,'LOAD'),(193,'SQL_CACHE'),(194,'CONVERT'),(195,'DYNAMIC'),(196,'COLLATE'),(197,'POLYGONFROMTEXT'),(198,'BYTE'),(199,'GLOBAL'),(200,'LINESTRINGFROMWKB'),(201,'WHEN'),(202,'HAVING'),(203,'AS'),(204,'STARTING'),(205,'RELOAD'),(206,'AUTOCOMMIT'),(207,'REVOKE'),(208,'GRANTS'),(209,'OUTER'),(210,'CURSOR_NAME'),(211,'FLOOR'),(212,'EXPLAIN'),(213,'WITH'),(214,'AFTER'),(215,'STD'),(216,'CSV'),(217,'DISABLE'),(218,'UNINSTALL'),(219,'OUTFILE'),(220,'LOW_PRIORITY'),(221,'FILE'),(222,'NODEGROUP'),(223,'SCHEMA'),(224,'SONAME'),(225,'POW'),(226,'DUAL'),(227,'MULTIPOINTFROMWKB'),(228,'INDEX'),(229,'MULTIPOINTFROMTEXT'),(230,'DEFINER'),(231,'MASTER_BIND'),(232,'REMOVE'),(233,'EXTENDED'),(234,'MULTILINESTRINGFROMWKB'),(235,'CROSS'),(236,'CONTRIBUTORS'),(237,'NATIONAL'),(238,'GROUP'),(239,'SHA'),(240,'ONLINE'),(241,'UNDO'),(242,'IGNORE_SERVER_IDS'),(243,'ZEROFILL'),(244,'CLIENT'),(245,'MASTER_PASSWORD'),(246,'OWNER'),(247,'RELAY_LOG_FILE'),(248,'TRUE'),(249,'CHARACTER'),(250,'MASTER_USER'),(251,'SCHEMA_NAME'),(252,'TABLE'),(253,'ENGINE'),(254,'INSERT_METHOD'),(255,'CASCADE'),(256,'RELAY_LOG_POS'),(257,'SQL_CALC_FOUND_ROWS'),(258,'UNION'),(259,'MYISAM'),(260,'LEAVE'),(261,'MODIFY'),(262,'MATCH'),(263,'MASTER_LOG_POS'),(264,'DISTINCTROW'),(265,'DESC'),(266,'TIME'),(267,'NUMERIC'),(268,'EXPANSION'),(269,'CODE'),(270,'CURSOR'),(271,'GEOMETRYCOLLECTIONFROMTEXT'),(272,'CHAIN'),(273,'LOGFILE'),(274,'FLUSH'),(275,'CREATE'),(276,'DESCRIBE'),(277,'EXTENT_SIZE'),(278,'MAX_UPDATES_PER_HOUR'),(279,'INT2'),(280,'PROCESSLIST'),(281,'ENDS'),(282,'LOGS'),(283,'DISCARD'),(284,'HEAP'),(285,'SOUNDS'),(286,'BETWEEN'),(287,'MULTILINESTRINGFROMTEXT'),(288,'REPAIR'),(289,'PACK_KEYS'),(290,'FAST'),(291,'VALUES'),(292,'CALL'),(293,'LOOP'),(294,'VARCHARACTER'),(295,'BEFORE'),(296,'TRUNCATE'),(297,'SHOW'),(298,'ALL'),(299,'REDUNDANT'),(300,'USER_RESOURCES'),(301,'PARTIAL'),(302,'BINLOG'),(303,'END'),(304,'SECOND'),(305,'AND'),(306,'FLOAT8'),(307,'PREV'),(308,'HOUR'),(309,'SELECT'),(310,'DATABASES'),(311,'OR'),(312,'IDENTIFIED'),(313,'WRAPPER'),(314,'MASTER_SSL_CIPHER'),(315,'SQL_SLAVE_SKIP_COUNTER'),(316,'BOTH'),(317,'BOOL'),(318,'YEAR'),(319,'MASTER_PORT'),(320,'CONCURRENT'),(321,'HELP'),(322,'UNIQUE'),(323,'TRIGGERS'),(324,'PROCESS'),(325,'OPTIONS'),(326,'RESIGNAL'),(327,'CONSISTENT'),(328,'MASTER_SSL'),(329,'DATE_ADD'),(330,'MAX_CONNECTIONS_PER_HOUR'),(331,'LIKE'),(332,'PLUGIN'),(333,'FETCH'),(334,'IN'),(335,'COLUMN'),(336,'DUMPFILE'),(337,'USAGE'),(338,'EXECUTE'),(339,'MEMORY'),(340,'CEIL'),(341,'QUERY'),(342,'MASTER_HOST'),(343,'LINES'),(344,'SQL_THREAD'),(345,'SERVER'),(346,'MAX_QUERIES_PER_HOUR'),(347,'MASTER_SSL_CERT'),(348,'MULTIPOLYGONFROMWKB'),(349,'TRANSACTION'),(350,'DAY_MINUTE'),(351,'STDDEV'),(352,'DATE_SUB'),(353,'REBUILD'),(354,'GEOMETRYFROMWKB'),(355,'INT1'),(356,'RENAME'),(357,'PARSER'),(358,'RIGHT'),(359,'ALTER'),(360,'MAX_ROWS'),(361,'SOCKET'),(362,'STRAIGHT_JOIN'),(363,'NATURAL'),(364,'VARIABLES'),(365,'ESCAPED'),(366,'SHA1'),(367,'KEY_BLOCK_SIZE'),(368,'PASSWORD'),(369,'OFFSET'),(370,'CHAR'),(371,'NEXT'),(372,'ERRORS'),(373,'SQL_LOG_BIN'),(374,'TEMPORARY'),(375,'COMMITTED'),(376,'SQL_SMALL_RESULT'),(377,'UPGRADE'),(378,'BEGIN'),(379,'DELAY_KEY_WRITE'),(380,'PROFILE'),(381,'MEDIUM'),(382,'INTERVAL'),(383,'SSL'),(384,'DAY_HOUR'),(385,'NAME'),(386,'REFERENCES'),(387,'AES_ENCRYPT'),(388,'STORAGE'),(389,'ISOLATION'),(390,'CEILING'),(391,'EVERY'),(392,'INT8'),(393,'AUTHORS'),(394,'RESTRICT'),(395,'UNCOMMITTED'),(396,'LINESTRINGFROMTEXT'),(397,'IS'),(398,'NOT'),(399,'ANALYSE'),(400,'DATAFILE'),(401,'DES_KEY_FILE'),(402,'SIGNAL'),(403,'COMPRESSED'),(404,'START'),(405,'PLUGINS'),(406,'SAVEPOINT'),(407,'IF'),(408,'ROWS'),(409,'PRIMARY'),(410,'PURGE'),(411,'LAST'),(412,'USER'),(413,'EXIT'),(414,'KEYS'),(415,'LIMIT'),(416,'KEY'),(417,'MERGE'),(418,'UNTIL'),(419,'SQL_NO_CACHE'),(420,'DELAYED'),(421,'CONSTRAINT_SCHEMA'),(422,'ANALYZE'),(423,'CONSTRAINT'),(424,'SERIAL'),(425,'ACTION'),(426,'WRITE'),(427,'INITIAL_SIZE'),(428,'SESSION'),(429,'DATABASE'),(430,'NULL'),(431,'POWER'),(432,'USE_FRM'),(433,'TERMINATED'),(434,'SLAVE'),(435,'NVARCHAR'),(436,'ASC'),(437,'RETURN'),(438,'OPTIONALLY'),(439,'ENABLE'),(440,'DIRECTORY'),(441,'MAX_USER_CONNECTIONS'),(442,'WHILE'),(443,'LOCAL'),(444,'DISTINCT'),(445,'AES_DECRYPT'),(446,'MASTER_SSL_KEY'),(447,'NONE'),(448,'TABLES'),(449,'<>'),(450,'RLIKE'),(451,'TRIGGER'),(452,'COLLATION'),(453,'SHUTDOWN'),(454,'HIGH_PRIORITY'),(455,'BTREE'),(456,'FIRST'),(457,'COALESCE'),(458,'WAIT'),(459,'CATALOG_NAME'),(460,'MASTER'),(461,'FIXED'),(462,'MULTIPOLYGONFROMTEXT'),(463,'ROW_FORMAT'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (1,0),(356,0),(473,1),(232,2),(447,3),(3,4),(130,4),(421,4),(89,5),(89,6),(406,6),(97,7),(89,8),(185,9),(430,10),(21,11),(347,11),(421,11),(463,11),(468,11),(89,12),(406,12),(146,13),(230,14),(88,15),(356,15),(18,16),(106,16),(134,16),(347,16),(97,17),(500,17),(380,18),(3,19),(104,19),(243,19),(374,19),(459,19),(185,20),(356,21),(9,22),(30,22),(34,22),(87,22),(186,22),(237,22),(263,22),(276,22),(300,22),(331,22),(405,22),(415,22),(416,22),(463,22),(478,22),(108,23),(122,24),(170,24),(424,24),(376,25),(82,26),(104,27),(199,28),(36,29),(347,30),(468,30),(376,31),(199,32),(35,33),(237,33),(36,34),(356,34),(468,35),(417,36),(463,36),(468,36),(21,37),(294,37),(347,37),(451,37),(468,37),(500,38),(48,39),(77,39),(83,39),(130,39),(199,39),(356,39),(361,39),(421,39),(463,39),(468,39),(468,40),(472,40),(376,41),(463,42),(468,42),(212,43),(421,43),(468,43),(473,43),(376,44),(356,45),(97,46),(314,46),(361,47),(374,48),(459,48),(185,49),(48,50),(468,50),(472,50),(1,51),(89,51),(406,51),(472,51),(374,52),(459,52),(176,53),(468,53),(51,54),(106,54),(199,55),(1,56),(55,56),(194,56),(374,57),(459,57),(48,58),(83,58),(106,58),(193,59),(199,59),(249,59),(210,60),(463,60),(89,61),(300,61),(358,61),(406,61),(199,62),(356,63),(1,64),(83,64),(104,64),(130,64),(356,64),(421,64),(463,64),(66,65),(48,66),(417,66),(466,66),(230,67),(87,68),(210,68),(463,68),(199,69),(194,70),(468,71),(91,72),(482,72),(385,73),(447,74),(1,75),(39,76),(230,76),(269,76),(185,77),(269,77),(460,77),(185,78),(463,78),(89,79),(406,79),(376,80),(83,81),(104,81),(356,81),(472,81),(89,82),(406,82),(374,83),(459,83),(3,84),(104,84),(304,84),(356,84),(468,85),(257,86),(194,87),(376,88),(129,89),(146,90),(460,90),(17,91),(189,91),(302,91),(328,91),(347,91),(356,91),(416,91),(439,91),(488,91),(99,92),(188,92),(421,93),(463,93),(88,94),(401,95),(468,95),(69,96),(330,96),(433,96),(285,97),(28,98),(57,98),(85,98),(104,99),(195,99),(301,99),(486,99),(282,100),(347,100),(106,101),(313,101),(473,102),(376,103),(9,104),(30,104),(89,104),(155,104),(186,104),(276,104),(300,104),(347,105),(365,105),(109,106),(146,107),(460,107),(24,108),(88,108),(113,109),(174,109),(3,110),(104,110),(155,110),(200,110),(212,110),(243,110),(463,110),(468,110),(463,111),(115,112),(326,112),(466,112),(470,112),(115,113),(463,113),(374,114),(459,114),(38,115),(119,115),(151,115),(264,115),(374,116),(459,116),(419,117),(124,118),(89,119),(125,119),(406,119),(496,119),(221,120),(3,121),(83,121),(104,121),(129,121),(130,121),(146,121),(155,121),(182,121),(212,121),(333,121),(347,121),(356,121),(374,121),(421,121),(459,121),(463,121),(468,121),(472,121),(477,121),(494,121),(199,122),(132,123),(230,123),(262,123),(376,123),(58,124),(137,124),(215,124),(223,124),(328,124),(336,124),(347,124),(365,124),(210,125),(463,125),(468,125),(89,126),(194,126),(210,126),(406,126),(468,126),(185,127),(1,128),(424,129),(52,130),(185,131),(468,132),(314,133),(199,134),(455,135),(255,136),(285,137),(199,138),(249,138),(463,139),(57,140),(85,140),(237,141),(52,142),(324,142),(57,143),(85,143),(199,144),(313,145),(48,146),(122,146),(347,146),(356,146),(424,146),(455,146),(36,147),(106,147),(447,147),(1,148),(28,149),(376,150),(468,151),(209,152),(180,153),(313,153),(347,153),(356,153),(420,153),(330,154),(347,154),(468,155),(97,156),(180,157),(421,158),(34,159),(68,159),(97,159),(211,159),(233,159),(302,159),(336,159),(347,159),(393,159),(405,159),(416,159),(97,160),(347,161),(421,161),(252,162),(468,163),(463,164),(468,164),(60,165),(194,165),(463,165),(478,165),(176,166),(168,167),(194,168),(415,168),(463,168),(478,168),(30,169),(159,169),(454,169),(447,170),(130,171),(421,171),(190,172),(48,173),(83,173),(356,173),(361,173),(463,173),(1,174),(48,174),(86,174),(374,175),(459,175),(252,176),(199,177),(249,177),(24,178),(128,178),(168,178),(209,178),(230,178),(314,178),(500,178),(97,179),(156,179),(230,179),(411,180),(347,181),(463,182),(468,182),(472,182),(473,182),(101,183),(151,183),(304,183),(145,184),(347,184),(374,185),(459,185),(146,186),(160,187),(347,187),(455,188),(146,189),(374,190),(459,190),(180,191),(200,191),(313,191),(420,191),(304,192),(421,192),(356,193),(230,194),(377,194),(468,195),(155,196),(212,196),(468,196),(395,197),(465,198),(129,199),(137,199),(182,199),(349,199),(447,199),(452,200),(57,201),(85,201),(356,202),(1,203),(36,203),(356,203),(421,204),(199,205),(146,206),(249,207),(192,208),(347,208),(1,209),(374,210),(459,210),(221,211),(255,212),(88,213),(199,213),(210,213),(463,213),(468,213),(463,214),(260,215),(421,216),(468,216),(89,217),(406,217),(463,217),(291,218),(356,219),(3,220),(36,220),(48,220),(83,220),(104,220),(130,220),(421,220),(199,221),(194,222),(155,223),(186,223),(212,223),(309,223),(347,223),(97,224),(277,225),(279,226),(464,227),(1,228),(60,228),(87,228),(101,228),(210,228),(304,228),(308,228),(347,228),(463,228),(468,228),(425,229),(89,230),(406,230),(185,231),(463,232),(255,233),(466,233),(272,234),(1,235),(7,236),(347,236),(257,237),(430,237),(194,238),(226,238),(356,238),(427,239),(87,240),(210,240),(463,240),(313,241),(185,242),(24,243),(128,243),(168,243),(209,243),(314,243),(500,243),(199,244),(185,245),(473,246),(185,247),(385,248),(130,249),(155,249),(212,249),(257,249),(333,249),(347,249),(356,249),(421,249),(430,249),(468,249),(185,250),(374,251),(459,251),(60,252),(110,252),(115,252),(215,252),(276,252),(278,252),(321,252),(347,252),(401,252),(417,252),(463,252),(466,252),(468,252),(470,252),(194,253),(347,253),(365,253),(415,253),(463,253),(468,253),(478,253),(468,254),(30,255),(276,255),(468,255),(472,255),(185,256),(356,257),(305,258),(468,259),(310,260),(463,261),(88,262),(185,263),(356,264),(329,265),(356,265),(361,265),(230,266),(315,266),(375,266),(209,267),(88,268),(68,269),(488,269),(420,270),(246,271),(146,272),(194,273),(226,273),(151,274),(326,274),(17,275),(22,275),(60,275),(77,275),(89,275),(97,275),(155,275),(194,275),(210,275),(211,275),(278,275),(302,275),(309,275),(347,275),(358,275),(393,275),(454,275),(468,275),(473,275),(329,276),(194,277),(199,278),(234,279),(347,280),(451,280),(89,281),(39,282),(269,282),(347,282),(463,283),(468,284),(378,285),(147,286),(107,287),(463,288),(466,288),(468,289),(417,290),(3,291),(104,291),(339,292),(344,293),(257,294),(269,295),(321,296),(463,296),(7,297),(10,297),(17,297),(21,297),(25,297),(33,297),(39,297),(58,297),(68,297),(69,297),(82,297),(122,297),(134,297),(137,297),(145,297),(160,297),(170,297),(192,297),(193,297),(215,297),(223,297),(278,297),(282,297),(294,297),(308,297),(309,297),(328,297),(330,297),(333,297),(336,297),(347,297),(349,297),(358,297),(365,297),(393,297),(424,297),(451,297),(487,297),(488,297),(492,297),(38,298),(199,298),(249,298),(305,298),(356,298),(468,299),(326,300),(468,301),(122,302),(350,302),(28,303),(57,303),(85,303),(232,303),(327,303),(344,303),(496,303),(376,304),(147,305),(316,305),(314,306),(106,307),(376,308),(3,309),(104,309),(255,309),(301,309),(356,309),(160,310),(347,310),(141,311),(77,312),(130,312),(199,312),(473,313),(185,314),(182,315),(455,316),(24,317),(111,317),(376,318),(185,319),(130,320),(421,320),(118,321),(390,321),(463,322),(25,323),(347,323),(199,324),(373,325),(473,325),(374,326),(146,327),(185,328),(376,329),(199,330),(347,331),(378,331),(291,332),(347,332),(419,332),(383,333),(88,334),(122,334),(356,334),(424,334),(463,335),(356,336),(199,337),(86,338),(199,338),(356,339),(397,340),(88,341),(151,341),(176,341),(185,342),(130,343),(421,343),(52,344),(324,344),(9,345),(373,345),(473,345),(199,346),(185,347),(123,348),(146,349),(447,349),(376,350),(407,351),(376,352),(463,353),(144,354),(24,355),(110,356),(222,356),(406,356),(463,356),(210,357),(463,357),(468,357),(1,358),(60,359),(159,359),(199,359),(212,359),(226,359),(233,359),(373,359),(406,359),(439,359),(463,359),(478,359),(463,360),(468,360),(473,361),(1,362),(356,362),(1,363),(347,364),(349,364),(421,365),(427,366),(468,367),(77,368),(199,368),(473,368),(477,368),(356,369),(230,370),(465,370),(106,371),(69,372),(347,372),(494,373),(276,374),(447,375),(356,376),(212,377),(417,377),(146,378),(327,378),(468,379),(487,380),(417,381),(89,382),(376,382),(199,383),(376,384),(212,385),(199,386),(468,386),(472,386),(443,387),(282,388),(447,389),(448,390),(89,391),(128,392),(10,393),(347,393),(30,394),(276,394),(472,394),(447,395),(56,396),(84,397),(206,397),(368,397),(456,397),(84,398),(89,398),(155,398),(206,398),(312,398),(189,399),(194,400),(478,400),(326,401),(459,402),(468,403),(146,404),(324,404),(33,405),(460,406),(9,407),(28,407),(30,407),(89,407),(155,407),(186,407),(276,407),(300,407),(479,407),(130,408),(463,409),(269,410),(106,411),(77,412),(222,412),(331,412),(473,412),(313,413),(308,414),(347,414),(463,414),(48,415),(83,415),(106,415),(122,415),(356,415),(424,415),(60,416),(104,416),(463,416),(468,416),(472,416),(468,417),(232,418),(356,419),(3,420),(104,420),(486,420),(374,421),(459,421),(463,422),(470,422),(463,423),(468,423),(243,424),(468,424),(468,425),(472,425),(36,426),(194,427),(478,427),(129,428),(137,428),(349,428),(447,428),(155,429),(186,429),(212,429),(309,429),(347,429),(473,429),(84,430),(368,430),(472,430),(483,431),(466,432),(421,433),(38,434),(52,434),(89,434),(145,434),(223,434),(324,434),(406,434),(257,435),(356,436),(361,436),(491,437),(421,438),(89,439),(406,439),(463,439),(212,440),(468,440),(199,441),(496,442),(36,443),(115,443),(130,443),(326,443),(421,443),(466,443),(470,443),(0,444),(96,444),(288,444),(305,444),(356,444),(361,444),(384,444),(433,444),(497,445),(185,446),(199,447),(36,448),(134,448),(294,448),(347,448),(495,449),(27,450),(22,451),(263,451),(347,451),(347,452),(492,452),(199,453),(104,454),(356,454),(210,455),(106,456),(463,456),(468,456),(463,457),(194,458),(478,458),(374,459),(459,459),(39,460),(58,460),(185,460),(264,460),(269,460),(209,461),(468,461),(201,462),(468,463); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (0,'MIN',16,'Syntax:\nMIN([DISTINCT] expr)\n\nReturns the minimum value of expr. MIN() may take a string argument; in\nsuch cases, it returns the minimum string value.\nThe DISTINCT keyword can be used to find the minimum of the distinct values\nof expr, however, this produces the same result as omitting DISTINCT.\n\nMIN() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/min/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/min/'),(1,'JOIN',27,'MySQL supports the following JOIN syntaxes for the table_references\npart of SELECT statements and multiple-table DELETE and UPDATE\nstatements:\n\ntable_references:\n table_reference [, table_reference] ...\n\ntable_reference:\n table_factor\n | join_table\n\ntable_factor:\n tbl_name [[AS] alias] [index_hint_list]\n | table_subquery [AS] alias\n | ( table_references )\n | { OJ table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n\njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor [join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON conditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor\n\njoin_condition:\n ON conditional_expr\n | USING (column_list)\n\nindex_hint_list:\n index_hint [, index_hint] ...\n\nindex_hint:\n USE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n\nindex_list:\n index_name [, index_name] ...\n\nA table reference is also known as a join expression.\n\nThe syntax of table_factor is extended in comparison with the SQL\nStandard. The latter accepts only table_reference, not a list of them\ninside a pair of parentheses.\n\nThis is a conservative extension if we consider each comma in a list of\ntable_reference items as equivalent to an inner join. For example:\n\nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nis equivalent to:\n\nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nIn MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents\n(they can replace each other). In standard SQL, they are not\nequivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used\notherwise.\n\nIn general, parentheses can be ignored in join expressions containing\nonly inner join operations.\n\nIndex hints can be specified to affect how the MySQL optimizer makes\nuse of indexes. For more information, see\nhttps://mariadb.com/kb/en/how-to-force-query-plans/.\n\nURL: https://mariadb.com/kb/en/join-syntax/\n\n','SELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id\n WHERE right_tbl.id IS NULL;\n','https://mariadb.com/kb/en/join-syntax/'),(2,'HEX',37,'Syntax:\nHEX(str), HEX(N)\n\nFor a string argument str, HEX() returns a hexadecimal string\nrepresentation of str where each character in str is converted to two\nhexadecimal digits. The inverse of this operation is performed by the\nUNHEX() function.\n\nFor a numeric argument N, HEX() returns a hexadecimal string\nrepresentation of the value of N treated as a longlong (BIGINT) number.\nThis is equivalent to CONV(N,10,16). The inverse of this operation is\nperformed by CONV(HEX(N),16,10).\n\nURL: https://mariadb.com/kb/en/hex/\n\n','MariaDB> SELECT 0x616263, HEX(\'abc\'), UNHEX(HEX(\'abc\'));\n -> \'abc\', 616263, \'abc\'\nMariaDB> SELECT HEX(255), CONV(HEX(255),16,10);\n -> \'FF\', 255\n','https://mariadb.com/kb/en/hex/'),(3,'REPLACE',27,'Syntax:\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n\nREPLACE works exactly like INSERT, except that if an old row in the\ntable has the same value as a new row for a PRIMARY KEY or a UNIQUE\nindex, the old row is deleted before the new row is inserted. See [HELP\nINSERT].\n\nREPLACE is a MySQL extension to the SQL standard. It either inserts, or\ndeletes and inserts. For another MySQL extension to standard SQL---that\neither inserts or updates---see\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nNote that unless the table has a PRIMARY KEY or UNIQUE index, using a\nREPLACE statement makes no sense. It becomes equivalent to INSERT,\nbecause there is no index to be used to determine whether a new row\nduplicates another.\n\nValues for all columns are taken from the values specified in the\nREPLACE statement. Any missing columns are set to their default values,\njust as happens for INSERT. You cannot refer to values from the current\nrow and use them in the new row. If you use an assignment such as SET\ncol_name = col_name + 1, the reference to the column name on the right\nhand side is treated as DEFAULT(col_name), so the assignment is\nequivalent to SET col_name = DEFAULT(col_name) + 1.\n\nTo use REPLACE, you must have both the INSERT and DELETE privileges for\nthe table.\n\nURL: https://mariadb.com/kb/en/replace/\n\n','','https://mariadb.com/kb/en/replace/'),(4,'CONTAINS',30,'Contains(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 completely contains g2. This\ntests the opposite relationship as Within().\n\nURL: https://mariadb.com/kb/en/contains/\n\n','','https://mariadb.com/kb/en/contains/'),(5,'SRID',36,'SRID(g)\n\nReturns an integer indicating the Spatial Reference System ID for the\ngeometry value g.\n\nIn MySQL, the SRID value is just an integer associated with the\ngeometry value. All calculations are done assuming Euclidean (planar)\ngeometry.\n\nURL: https://mariadb.com/kb/en/srid/\n\n','MariaDB> SELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n','https://mariadb.com/kb/en/srid/'),(6,'CURRENT_TIMESTAMP',31,'Syntax:\nCURRENT_TIMESTAMP, CURRENT_TIMESTAMP()\n\nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/current_timestamp/\n\n','','https://mariadb.com/kb/en/current_timestamp/'),(7,'SHOW CONTRIBUTORS',26,'Syntax:\nSHOW CONTRIBUTORS\n\nThe SHOW CONTRIBUTORS statement displays information about the people\nwho contribute to MySQL source or to causes that we support. For each\ncontributor, it displays Name, Location, and Comment values.\n\nURL: https://mariadb.com/kb/en/show-contributors/\n\n','','https://mariadb.com/kb/en/show-contributors/'),(8,'VARIANCE',16,'Syntax:\nVARIANCE(expr)\n\nReturns the population standard variance of expr. This is an extension\nto standard SQL. The standard SQL function VAR_POP() can be used\ninstead.\n\nVARIANCE() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/variance/\n\n','','https://mariadb.com/kb/en/variance/'),(9,'DROP SERVER',39,'Syntax:\nDROP SERVER [ IF EXISTS ] server_name\n\nDrops the server definition for the server named server_name. The\ncorresponding row within the mysql.servers table will be deleted. This\nstatement requires the SUPER privilege.\n\nDropping a server for a table does not affect any FEDERATED tables that\nused this connection information when they were created. See [HELP\nCREATE SERVER].\n\nURL: https://mariadb.com/kb/en/drop-server/\n\n','','https://mariadb.com/kb/en/drop-server/'),(10,'SHOW AUTHORS',26,'Syntax:\nSHOW AUTHORS\n\nThe SHOW AUTHORS statement displays information about the people who\nwork on MySQL. For each author, it displays Name, Location, and Comment\nvalues.\n\nURL: https://mariadb.com/kb/en/show-authors/\n\n','','https://mariadb.com/kb/en/show-authors/'),(11,'VAR_SAMP',16,'Syntax:\nVAR_SAMP(expr)\n\nReturns the sample variance of expr. That is, the denominator is the\nnumber of rows minus one.\n\nVAR_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_samp/\n\n','','https://mariadb.com/kb/en/var_samp/'),(12,'CONCAT',37,'Syntax:\nCONCAT(str1,str2,...)\n\nReturns the string that results from concatenating the arguments. May\nhave one or more arguments. If all arguments are nonbinary strings, the\nresult is a nonbinary string. If the arguments include any binary\nstrings, the result is a binary string. A numeric argument is converted\nto its equivalent string form. This is a nonbinary string as of MySQL\n5.5.3. Before 5.5.3, it is a binary string; to to avoid that and\nproduce a nonbinary string, you can use an explicit type cast, as in\nthis example:\n\nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n\nCONCAT() returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/concat/\n\n','MariaDB> SELECT CONCAT(\'My\', \'S\', \'QL\');\n -> \'MySQL\'\nMariaDB> SELECT CONCAT(\'My\', NULL, \'QL\');\n -> NULL\nMariaDB> SELECT CONCAT(14.3);\n -> \'14.3\'\n','https://mariadb.com/kb/en/concat/'),(13,'GEOMETRY HIERARCHY',34,'Geometry is the base class. It is an abstract class. The instantiable\nsubclasses of Geometry are restricted to zero-, one-, and\ntwo-dimensional geometric objects that exist in two-dimensional\ncoordinate space. All instantiable geometry classes are defined so that\nvalid instances of a geometry class are topologically closed (that is,\nall defined geometries include their boundary).\n\nThe base Geometry class has subclasses for Point, Curve, Surface, and\nGeometryCollection:\n\no Point represents zero-dimensional objects.\n\no Curve represents one-dimensional objects, and has subclass\n LineString, with sub-subclasses Line and LinearRing.\n\no Surface is designed for two-dimensional objects and has subclass\n Polygon.\n\no GeometryCollection has specialized zero-, one-, and two-dimensional\n collection classes named MultiPoint, MultiLineString, and\n MultiPolygon for modeling geometries corresponding to collections of\n Points, LineStrings, and Polygons, respectively. MultiCurve and\n MultiSurface are introduced as abstract superclasses that generalize\n the collection interfaces to handle Curves and Surfaces.\n\nGeometry, Curve, Surface, MultiCurve, and MultiSurface are defined as\nnoninstantiable classes. They define a common set of methods for their\nsubclasses and are included for extensibility.\n\nPoint, LineString, Polygon, GeometryCollection, MultiPoint,\nMultiLineString, and MultiPolygon are instantiable classes.\n\nURL: https://mariadb.com/kb/en/geometry-hierarchy/\n\n','','https://mariadb.com/kb/en/geometry-hierarchy/'),(14,'CHAR FUNCTION',37,'Syntax:\nCHAR(N,... [USING charset_name])\n\nCHAR() interprets each argument N as an integer and returns a string\nconsisting of the characters given by the code values of those\nintegers. NULL values are skipped.\nBy default, CHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n\nMariaDB> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n\nIf USING is given and the result string is illegal for the given\ncharacter set, a warning is issued. Also, if strict SQL mode is\nenabled, the result from CHAR() becomes NULL.\n\nURL: https://mariadb.com/kb/en/char-function/\n\n','MariaDB> SELECT CHAR(77,121,83,81,\'76\');\n -> \'MySQL\'\nMariaDB> SELECT CHAR(77,77.3,\'77.3\');\n -> \'MMM\'\n','https://mariadb.com/kb/en/char-function/'),(15,'DATETIME',22,'DATETIME\n\nA date and time combination. The supported range is \'1000-01-01\n00:00:00\' to \'9999-12-31 23:59:59\'. MySQL displays DATETIME values in\n\'YYYY-MM-DD HH:MM:SS\' format, but permits assignment of values to\nDATETIME columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/datetime/\n\n','','https://mariadb.com/kb/en/datetime/'),(16,'SHOW CREATE TRIGGER',26,'Syntax:\nSHOW CREATE TRIGGER trigger_name\n\nThis statement shows a CREATE TRIGGER statement that creates the given\ntrigger.\n\nURL: https://mariadb.com/kb/en/show-create-trigger/\n\n','','https://mariadb.com/kb/en/show-create-trigger/'),(17,'SHOW CREATE PROCEDURE',26,'Syntax:\nSHOW CREATE PROCEDURE proc_name\n\nThis statement is a MySQL extension. It returns the exact string that\ncan be used to re-create the named stored procedure. A similar\nstatement, SHOW CREATE FUNCTION, displays information about stored\nfunctions (see [HELP SHOW CREATE FUNCTION]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table. If you do not have privileges\nfor the routine itself, the value displayed for the Create Procedure or\nCreate Function field will be NULL.\n\nURL: https://mariadb.com/kb/en/show-create-procedure/\n\n','MariaDB> SHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row ***************************\n Procedure: simpleproc\n sql_mode:\n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nMariaDB> SHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row ***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-procedure/'),(18,'OPEN',23,'Syntax:\nOPEN cursor_name\n\nThis statement opens a previously declared cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/open/\n\n','','https://mariadb.com/kb/en/open/'),(19,'INTEGER',22,'INTEGER[(M)] [UNSIGNED] [ZEROFILL]\n\nThis type is a synonym for INT.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-int\n\n','','https://mariadb.com/kb/en/sql_language-data_types-int'),(20,'LOWER',37,'Syntax:\nLOWER(str)\n\nReturns the string str with all characters changed to lowercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT LOWER(\'QUADRATICALLY\');\n -> \'quadratically\'\n\nLOWER() (and UPPER()) are ineffective when applied to binary strings\n(BINARY, VARBINARY, BLOB). To perform lettercase conversion, convert\nthe string to a nonbinary string:\n\nMariaDB> SET @str = BINARY \'New York\';\nMariaDB> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+-------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+-------------+-----------------------------------+\n| New York | new york |\n+-------------+-----------------------------------+\n\nURL: https://mariadb.com/kb/en/lower/\n\n','','https://mariadb.com/kb/en/lower/'),(21,'SHOW COLUMNS',26,'Syntax:\nSHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW COLUMNS displays information about the columns in a given table.\nIt also works for views. The LIKE clause, if present, indicates which\ncolumn names to match. The WHERE clause can be given to select rows\nusing more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nSHOW COLUMNS displays information only for those columns for which you\nhave some privilege.\n\nMariaDB> SHOW COLUMNS FROM City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nIf the data types differ from what you expect them to be based on a\nCREATE TABLE statement, note that MySQL sometimes changes data types\nwhen you create or alter a table. The conditions under which this\noccurs are described in\nhttps://mariadb.com/kb/en/silent-column-changes/.\n\nThe FULL keyword causes the output to include the column collation and\ncomments, as well as the privileges you have for each column.\n\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. In other words, these two statements are equivalent:\n\nMariaDB> SHOW COLUMNS FROM mytable FROM mydb;\nMariaDB> SHOW COLUMNS FROM mydb.mytable;\n\nSHOW COLUMNS displays the following values for each table column:\n\nField indicates the column name.\n\nType indicates the column data type.\n\nCollation indicates the collation for nonbinary string columns, or NULL\nfor other columns. This value is displayed only if you use the FULL\nkeyword.\n\nThe Null field contains YES if NULL values can be stored in the column,\nNO if not.\n\nThe Key field indicates whether the column is indexed:\n\no If Key is empty, the column either is not indexed or is indexed only\n as a secondary column in a multiple-column, nonunique index.\n\no If Key is PRI, the column is a PRIMARY KEY or is one of the columns\n in a multiple-column PRIMARY KEY.\n\no If Key is UNI, the column is the first column of a UNIQUE index. (A\n UNIQUE index permits multiple NULL values, but you can tell whether\n the column permits NULL by checking the Null field.)\n\no If Key is MUL, the column is the first column of a nonunique index in\n which multiple occurrences of a given value are permitted within the\n column.\n\nIf more than one of the Key values applies to a given column of a\ntable, Key displays the one with the highest priority, in the order\nPRI, UNI, MUL.\n\nA UNIQUE index may be displayed as PRI if it cannot contain NULL values\nand there is no PRIMARY KEY in the table. A UNIQUE index may display as\nMUL if several columns form a composite UNIQUE index; although the\ncombination of the columns is unique, each column can still hold\nmultiple occurrences of a given value.\n\nThe Default field indicates the default value that is assigned to the\ncolumn. This is NULL if the column has an explicit default of NULL, or\nif the column definition has no DEFAULT clause.\n\nThe Extra field contains any additional information that is available\nabout a given column. The value is nonempty in these cases:\nauto_increment for columns that have the AUTO_INCREMENT attribute; on\nupdate CURRENT_TIMESTAMP for TIMESTAMP columns that have the ON UPDATE\nCURRENT_TIMESTAMP attribute.\n\nPrivileges indicates the privileges you have for the column. This value\nis displayed only if you use the FULL keyword.\n\nComment indicates any comment the column has. This value is displayed\nonly if you use the FULL keyword.\n\nSHOW FIELDS is a synonym for SHOW COLUMNS. You can also list a table\'s\ncolumns with the mysqlshow db_name tbl_name command.\n\nThe DESCRIBE statement provides information similar to SHOW COLUMNS.\nSee [HELP DESCRIBE].\n\nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX statements\nalso provide information about tables. See [HELP SHOW].\n\nURL: https://mariadb.com/kb/en/show-columns/\n\n','','https://mariadb.com/kb/en/show-columns/'),(22,'CREATE TRIGGER',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name trigger_time trigger_event\n ON tbl_name FOR EACH ROW trigger_body\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section. If\nbinary logging is enabled, CREATE TRIGGER might require the SUPER\nprivilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time. See later in\nthis section for more information.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\ntrigger_event indicates the kind of statement that activates the\ntrigger. The trigger_event can be one of the following:\n\no INSERT: The trigger is activated whenever a new row is inserted into\n the table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger is activated whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger is activated whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. However,\n DROP TABLE and TRUNCATE TABLE statements on the table do not activate\n this trigger, because they do not use DELETE. Dropping a partition\n does not activate DELETE triggers, either. See [HELP TRUNCATE TABLE].\n\nURL: https://mariadb.com/kb/en/create-trigger/\n\n','','https://mariadb.com/kb/en/create-trigger/'),(23,'MONTH',31,'Syntax:\nMONTH(date)\n\nReturns the month for date, in the range 1 to 12 for January to\nDecember, or 0 for dates such as \'0000-00-00\' or \'2008-00-00\' that have\na zero month part.\n\nURL: https://mariadb.com/kb/en/month/\n\n','MariaDB> SELECT MONTH(\'2008-02-03\');\n -> 2\n','https://mariadb.com/kb/en/month/'),(24,'TINYINT',22,'TINYINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA very small integer. The signed range is -128 to 127. The unsigned\nrange is 0 to 255.\n\nURL: https://mariadb.com/kb/en/tinyint/\n\n','','https://mariadb.com/kb/en/tinyint/'),(25,'SHOW TRIGGERS',26,'Syntax:\nSHOW TRIGGERS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TRIGGERS lists the triggers currently defined for tables in a\ndatabase (the default database unless a FROM clause is given). This\nstatement returns results only for databases and tables for which you\nhave the TRIGGER privilege. The LIKE clause, if present, indicates\nwhich table names to match and causes the statement to display triggers\nfor those tables. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nFor the trigger ins_sum as defined in\nhttps://mariadb.com/kb/en/triggers/, the output of\nthis statement is as shown here:\n\nMariaDB> SHOW TRIGGERS LIKE \'acc%\'\\G\n*************************** 1. row ***************************\n Trigger: ins_sum\n Event: INSERT\n Table: account\n Statement: SET @sum = @sum + NEW.amount\n Timing: BEFORE\n Created: NULL\n sql_mode:\n Definer: myname@localhost\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\ncharacter_set_client is the session value of the character_set_client\nsystem variable when the trigger was created. collation_connection is\nthe session value of the collation_connection system variable when the\ntrigger was created. Database Collation is the collation of the\ndatabase with which the trigger is associated.\n\nURL: https://mariadb.com/kb/en/show-triggers/\n\n','','https://mariadb.com/kb/en/show-triggers/'),(26,'MASTER_POS_WAIT',14,'Syntax:\nMASTER_POS_WAIT(log_name,log_pos[,timeout])\n\nThis function is useful for control of master/slave synchronization. It\nblocks until the slave has read and applied all updates up to the\nspecified position in the master log. The return value is the number of\nlog events the slave had to wait for to advance to the specified\nposition. The function returns NULL if the slave SQL thread is not\nstarted, the slave\'s master information is not initialized, the\narguments are incorrect, or an error occurs. It returns -1 if the\ntimeout has been exceeded. If the slave SQL thread stops while\nMASTER_POS_WAIT() is waiting, the function returns NULL. If the slave\nis past the specified position, the function returns immediately.\n\nIf a timeout value is specified, MASTER_POS_WAIT() stops waiting when\ntimeout seconds have elapsed. timeout must be greater than 0; a zero or\nnegative timeout means no timeout.\n\nURL: https://mariadb.com/kb/en/master_pos_wait/\n\n','','https://mariadb.com/kb/en/master_pos_wait/'),(27,'REGEXP',37,'Syntax:\nexpr REGEXP pat, expr RLIKE pat\n\nPerforms a pattern match of a string expression expr against a pattern\npat. The pattern can be an extended regular expression. The syntax for\nregular expressions is discussed in\nhttps://mariadb.com/kb/en/regexp/. Returns 1 if expr\nmatches pat; otherwise it returns 0. If either expr or pat is NULL, the\nresult is NULL. RLIKE is a synonym for REGEXP, provided for mSQL\ncompatibility.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\n*Note*: Because MySQL uses the C escape syntax in strings (for example,\n\"\\n\" to represent the newline character), you must double any \"\\\" that\nyou use in your REGEXP strings.\n\nREGEXP is not case sensitive, except when used with binary strings.\n\nURL: https://mariadb.com/kb/en/regexp/\n\n','MariaDB> SELECT \'Monty!\' REGEXP \'.*\';\n -> 1\nMariaDB> SELECT \'new*\\n*line\' REGEXP \'new\\\\*.\\\\*line\';\n -> 1\nMariaDB> SELECT \'a\' REGEXP \'A\', \'a\' REGEXP BINARY \'A\';\n -> 1 0\nMariaDB> SELECT \'a\' REGEXP \'^[a-d]\';\n -> 1\n','https://mariadb.com/kb/en/regexp/'),(28,'IF STATEMENT',23,'Syntax:\nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF\n\nThe IF statement for stored programs implements a basic conditional\nconstruct.\n\n*Note*: There is also an IF() function, which differs from the IF\nstatement described here. See\nhttps://mariadb.com/kb/en/if-function/. The\nIF statement can have THEN, ELSE, and ELSEIF clauses, and it is\nterminated with END IF.\n\nIf the search_condition evaluates to true, the corresponding THEN or\nELSEIF clause statement_list executes. If no search_condition matches,\nthe ELSE clause statement_list executes.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nURL: https://mariadb.com/kb/en/if-statement/\n\n','','https://mariadb.com/kb/en/if-statement/'),(29,'^',19,'Syntax:\n^\n\nBitwise XOR:\n\nURL: https://mariadb.com/kb/en/bitwise-xor/\n\n','MariaDB> SELECT 1 ^ 1;\n -> 0\nMariaDB> SELECT 1 ^ 0;\n -> 1\nMariaDB> SELECT 11 ^ 3;\n -> 8\n','https://mariadb.com/kb/en/bitwise-xor/'),(30,'DROP VIEW',39,'Syntax:\nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n\nDROP VIEW removes one or more views. You must have the DROP privilege\nfor each view. If any of the views named in the argument list do not\nexist, MySQL returns an error indicating by name which nonexisting\nviews it was unable to drop, but it also drops all of the views in the\nlist that do exist.\n\nThe IF EXISTS clause prevents an error from occurring for views that\ndon\'t exist. When this clause is given, a NOTE is generated for each\nnonexistent view. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE, if given, are parsed and ignored.\n\nURL: https://mariadb.com/kb/en/drop-view/\n\n','','https://mariadb.com/kb/en/drop-view/'),(31,'WITHIN',30,'Within(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially within g2. This\ntests the opposite relationship as Contains().\n\nURL: https://mariadb.com/kb/en/within/\n\n','','https://mariadb.com/kb/en/within/'),(32,'WEEK',31,'Syntax:\nWEEK(date[,mode])\n\nThis function returns the week number for date. The two-argument form\nof WEEK() enables you to specify whether the week starts on Sunday or\nMonday and whether the return value should be in the range from 0 to 53\nor from 1 to 53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/week/\n\n','MariaDB> SELECT WEEK(\'2008-02-20\');\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',0);\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',1);\n -> 8\nMariaDB> SELECT WEEK(\'2008-12-31\',1);\n -> 53\n','https://mariadb.com/kb/en/week/'),(33,'SHOW PLUGINS',26,'Syntax:\nSHOW PLUGINS\n\nSHOW PLUGINS displays information about server plugins. Plugin\ninformation is also available in the INFORMATION_SCHEMA.PLUGINS table.\nSee https://mariadb.com/kb/en/information_schemaplugins-table/.\n\nExample of SHOW PLUGINS output:\n\nMariaDB> SHOW PLUGINS\\G\n*************************** 1. row ***************************\n Name: binlog\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 2. row ***************************\n Name: CSV\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 3. row ***************************\n Name: MEMORY\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 4. row ***************************\n Name: MyISAM\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n...\n\nURL: https://mariadb.com/kb/en/show-plugins/\n\n','','https://mariadb.com/kb/en/show-plugins/'),(34,'DROP FUNCTION UDF',21,'Syntax:\nDROP FUNCTION function_name\n\nThis statement drops the user-defined function (UDF) named\nfunction_name.\n\nTo drop a function, you must have the DELETE privilege for the mysql\ndatabase. This is because DROP FUNCTION removes a row from the\nmysql.func system table that records the function\'s name, type, and\nshared library name.\n\nURL: https://mariadb.com/kb/en/drop-function-udf/\n\n','','https://mariadb.com/kb/en/drop-function-udf/'),(35,'PREPARE',8,'Syntax:\nPREPARE stmt_name FROM preparable_stmt\n\nThe PREPARE statement prepares a statement and assigns it a name,\nstmt_name, by which to refer to the statement later. Statement names\nare not case sensitive. preparable_stmt is either a string literal or a\nuser variable that contains the text of the statement. The text must\nrepresent a single SQL statement, not multiple statements. Within the\nstatement, \"?\" characters can be used as parameter markers to indicate\nwhere data values are to be bound to the query later when you execute\nit. The \"?\" characters should not be enclosed within quotation marks,\neven if you intend to bind them to string values. Parameter markers can\nbe used only where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n\nIf a prepared statement with the given name already exists, it is\ndeallocated implicitly before the new statement is prepared. This means\nthat if the new statement contains an error and cannot be prepared, an\nerror is returned and no statement with the given name exists.\n\nA prepared statement is executed with EXECUTE and released with\nDEALLOCATE PREPARE.\n\nThe scope of a prepared statement is the session within which it is\ncreated. Other sessions cannot see it.\n\nURL: https://mariadb.com/kb/en/prepare-statement/\n\n','','https://mariadb.com/kb/en/prepare-statement/'),(36,'LOCK',8,'Syntax:\nLOCK TABLES\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n\nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n\nUNLOCK TABLES\n\nMySQL enables client sessions to acquire table locks explicitly for the\npurpose of cooperating with other sessions for access to tables, or to\nprevent other sessions from modifying tables during periods when a\nsession requires exclusive access to them. A session can acquire or\nrelease locks only for itself. One session cannot acquire locks for\nanother session or release locks held by another session.\n\nLocks may be used to emulate transactions or to get more speed when\nupdating tables. This is explained in more detail later in this\nsection.\n\nLOCK TABLES explicitly acquires table locks for the current client\nsession. Table locks can be acquired for base tables or views. You must\nhave the LOCK TABLES privilege, and the SELECT privilege for each\nobject to be locked.\n\nFor view locking, LOCK TABLES adds all base tables used in the view to\nthe set of tables to be locked and locks them automatically. If you\nlock a table explicitly with LOCK TABLES, any tables used in triggers\nare also locked implicitly, as described in\nhttps://mariadb.com/kb/en/triggers-and-implicit-locks/.\n\nUNLOCK TABLES explicitly releases any table locks held by the current\nsession. LOCK TABLES implicitly releases any table locks held by the\ncurrent session before acquiring new locks.\n\nAnother use for UNLOCK TABLES is to release the global read lock\nacquired with the FLUSH TABLES WITH READ LOCK statement, which enables\nyou to lock all tables in all databases. See [HELP FLUSH]. (This is a\nvery convenient way to get backups if you have a file system such as\nVeritas that can take snapshots in time.)\n\nURL: https://mariadb.com/kb/en/transactions-lock/\n\n','','https://mariadb.com/kb/en/transactions-lock/'),(37,'UPDATEXML',37,'Syntax:\nUpdateXML(xml_target, xpath_expr, new_xml)\n\nThis function replaces a single portion of a given fragment of XML\nmarkup xml_target with a new XML fragment new_xml, and then returns the\nchanged XML. The portion of xml_target that is replaced matches an\nXPath expression xpath_expr supplied by the user. In MySQL 5.5, the\nXPath expression can contain at most 127 characters. (This limitation\nis lifted in MySQL 5.6.)\n\nIf no expression matching xpath_expr is found, or if multiple matches\nare found, the function returns the original xml_target XML fragment.\nAll three arguments should be strings.\n\nURL: https://mariadb.com/kb/en/updatexml/\n\n','MariaDB> SELECT\n -> UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n -> UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n -> UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n -> \\G\n\n*************************** 1. row ***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n','https://mariadb.com/kb/en/updatexml/'),(38,'RESET SLAVE',8,'Syntax:\nRESET SLAVE [ALL]\n\nRESET SLAVE makes the slave forget its replication position in the\nmaster\'s binary log. This statement is meant to be used for a clean\nstart: It deletes the master.info and relay-log.info files, all the\nrelay log files, and starts a new relay log file. To use RESET SLAVE,\nthe slave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\n*Note*: All relay log files are deleted, even if they have not been\ncompletely executed by the slave SQL thread. (This is a condition\nlikely to exist on a replication slave if you have issued a STOP SLAVE\nstatement or if the slave is highly loaded.)\n\nIn MySQL 5.5 (unlike the case in MySQL 5.1 and earlier), RESET SLAVE\ndoes not change any replication connection parameters such as master\nhost, master port, master user, or master password, which are retained\nin memory. This means that START SLAVE can be issued without requiring\na CHANGE MASTER TO statement following RESET SLAVE.\n\nIn MySQL 5.5.16 and later, you can use RESET SLAVE ALL to reset these\nconnection parameters (Bug #11809016). Connection parameters are also\nreset if the slave mysqld is shut down.\n\nIf the slave SQL thread was in the middle of replicating temporary\ntables when it was stopped, and RESET SLAVE is issued, these replicated\ntemporary tables are deleted on the slave.\n\nURL: https://mariadb.com/kb/en/reset-slave-connection_name/\n\n','','https://mariadb.com/kb/en/reset-slave-connection_name/'),(39,'SHOW BINARY LOGS',26,'Syntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [HELP PURGE BINARY LOGS], that shows\nhow to determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/show-binary-logs/\n\n','','https://mariadb.com/kb/en/show-binary-logs/'),(40,'POLYGON',24,'Polygon(ls1,ls2,...)\n\nConstructs a Polygon value from a number of LineString or WKB\nLineString arguments. If any argument does not represent a LinearRing\n(that is, not a closed and simple LineString), the return value is\nNULL.\n\nURL: https://mariadb.com/kb/en/polygon/\n\n','','https://mariadb.com/kb/en/polygon/'),(41,'MINUTE',31,'Syntax:\nMINUTE(time)\n\nReturns the minute for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/minute/\n\n','MariaDB> SELECT MINUTE(\'2008-02-03 10:05:03\');\n -> 5\n','https://mariadb.com/kb/en/minute/'),(42,'DAY',31,'Syntax:\nDAY(date)\n\nDAY() is a synonym for DAYOFMONTH().\n\nURL: https://mariadb.com/kb/en/day/\n\n','','https://mariadb.com/kb/en/day/'),(43,'MID',37,'Syntax:\nMID(str,pos,len)\n\nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n\nURL: https://mariadb.com/kb/en/mid/\n\n','','https://mariadb.com/kb/en/mid/'),(44,'UUID',14,'Syntax:\nUUID()\n\nReturns a Universal Unique Identifier (UUID) generated according to\n\"DCE 1.1: Remote Procedure Call\" (Appendix A) CAE (Common Applications\nEnvironment) Specifications published by The Open Group in October 1997\n(Document Number C706,\nhttp://www.opengroup.org/public/pubs/catalog/c706.htm).\n\nA UUID is designed as a number that is globally unique in space and\ntime. Two calls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate computers\nthat are not connected to each other.\n\nA UUID is a 128-bit number represented by a utf8 string of five\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format:\n\no The first three numbers are generated from a timestamp.\n\no The fourth number preserves temporal uniqueness in case the timestamp\n value loses monotonicity (for example, due to daylight saving time).\n\no The fifth number is an IEEE 802 node number that provides spatial\n uniqueness. A random number is substituted if the latter is not\n available (for example, because the host computer has no Ethernet\n card, or we do not know how to find the hardware address of an\n interface on your operating system). In this case, spatial uniqueness\n cannot be guaranteed. Nevertheless, a collision should have very low\n probability.\n\n Currently, the MAC address of an interface is taken into account only\n on FreeBSD and Linux. On other operating systems, MySQL uses a\n randomly generated 48-bit number.\n\nURL: https://mariadb.com/kb/en/uuid/\n\n','MariaDB> SELECT UUID();\n -> \'6ccd780c-baba-1026-9564-0040f4311e29\'\n','https://mariadb.com/kb/en/uuid/'),(45,'LINESTRING',24,'LineString(pt1,pt2,...)\n\nConstructs a LineString value from a number of Point or WKB Point\narguments. If the number of arguments is less than two, the return\nvalue is NULL.\n\nURL: https://mariadb.com/kb/en/linestring/\n\n','','https://mariadb.com/kb/en/linestring/'),(46,'SLEEP',14,'Syntax:\nSLEEP(duration)\n\nSleeps (pauses) for the number of seconds given by the duration\nargument, then returns 0. If SLEEP() is interrupted, it returns 1. The\nduration may have a fractional part given in microseconds.\n\nURL: https://mariadb.com/kb/en/sleep/\n\n','','https://mariadb.com/kb/en/sleep/'),(47,'CONNECTION_ID',17,'Syntax:\nCONNECTION_ID()\n\nReturns the connection ID (thread ID) for the connection. Every\nconnection has an ID that is unique among the set of currently\nconnected clients.\n\nURL: https://mariadb.com/kb/en/connection_id/\n\n','MariaDB> SELECT CONNECTION_ID();\n -> 23786\n','https://mariadb.com/kb/en/connection_id/'),(48,'DELETE',27,'Syntax:\nSingle-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n\nOr:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n\nFor the single-table syntax, the DELETE statement deletes rows from\ntbl_name and returns a count of the number of deleted rows. This count\ncan be obtained by calling the ROW_COUNT() function (see\nhttps://mariadb.com/kb/en/information-functions-row_count/). The\nWHERE clause, if given, specifies the conditions that identify which\nrows to delete. With no WHERE clause, all rows are deleted. If the\nORDER BY clause is specified, the rows are deleted in the order that is\nspecified. The LIMIT clause places a limit on the number of rows that\ncan be deleted.\n\nFor the multiple-table syntax, DELETE deletes from each tbl_name the\nrows that satisfy the conditions. In this case, ORDER BY and LIMIT\ncannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe deleted. It is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nCurrently, you cannot delete from a table and select from the same\ntable in a subquery.\n\nYou need the DELETE privilege on a table to delete rows from it. You\nneed only the SELECT privilege for any columns that are only read, such\nas those named in the WHERE clause.\n\nAs stated, a DELETE statement with no WHERE clause deletes all rows. A\nfaster way to do this, when you do not need to know the number of\ndeleted rows, is to use TRUNCATE TABLE. However, within a transaction\nor if you have a lock on the table, TRUNCATE TABLE cannot be used\nwhereas DELETE can. See [HELP TRUNCATE TABLE], and [HELP LOCK].\n\nURL: https://mariadb.com/kb/en/delete/\n\n','','https://mariadb.com/kb/en/delete/'),(49,'ROUND',4,'Syntax:\nROUND(X), ROUND(X,D)\n\nRounds the argument X to D decimal places. The rounding algorithm\ndepends on the data type of X. D defaults to 0 if not specified. D can\nbe negative to cause D digits left of the decimal point of the value X\nto become zero.\n\nURL: https://mariadb.com/kb/en/round/\n\n','MariaDB> SELECT ROUND(-1.23);\n -> -1\nMariaDB> SELECT ROUND(-1.58);\n -> -2\nMariaDB> SELECT ROUND(1.58);\n -> 2\nMariaDB> SELECT ROUND(1.298, 1);\n -> 1.3\nMariaDB> SELECT ROUND(1.298, 0);\n -> 1\nMariaDB> SELECT ROUND(23.298, -1);\n -> 20\n','https://mariadb.com/kb/en/round/'),(50,'NULLIF',7,'Syntax:\nNULLIF(expr1,expr2)\n\nReturns NULL if expr1 = expr2 is true, otherwise returns expr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.\n\nURL: https://mariadb.com/kb/en/nullif/\n\n','MariaDB> SELECT NULLIF(1,1);\n -> NULL\nMariaDB> SELECT NULLIF(1,2);\n -> 1\n','https://mariadb.com/kb/en/nullif/'),(51,'CLOSE',23,'Syntax:\nCLOSE cursor_name\n\nThis statement closes a previously opened cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nAn error occurs if the cursor is not open.\n\nIf not closed explicitly, a cursor is closed at the end of the BEGIN\n... END block in which it was declared.\n\nURL: https://mariadb.com/kb/en/close/\n\n','','https://mariadb.com/kb/en/close/'),(52,'STOP SLAVE',8,'Syntax:\nSTOP SLAVE [thread_types]\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nStops the slave threads. STOP SLAVE requires the SUPER privilege.\nRecommended best practice is to execute STOP SLAVE on the slave before\nstopping the slave server (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-shutdown.html, for more\ninformation).\n\nWhen using the row-based logging format: You should execute STOP SLAVE\non the slave prior to shutting down the slave server if you are\nreplicating any tables that use a nontransactional storage engine (see\nthe Note later in this section). In MySQL 5.5.9 and later, you can also\nuse STOP SLAVE SQL_THREAD for this purpose.\n\nLike START SLAVE, this statement may be used with the IO_THREAD and\nSQL_THREAD options to name the thread or threads to be stopped.\n\n*Note*: In MySQL 5.5, STOP SLAVE waits until the current replication\nevent group affecting one or more non-transactional tables has finished\nexecuting (if there is any such replication group), or until the user\nissues a KILL QUERY or KILL CONNECTION statement. (Bug #319, Bug\n#38205)\n\nURL: https://mariadb.com/kb/en/stop-slave/\n\n','','https://mariadb.com/kb/en/stop-slave/'),(53,'TIMEDIFF',31,'Syntax:\nTIMEDIFF(expr1,expr2)\n\nTIMEDIFF() returns expr1 - expr2 expressed as a time value. expr1 and\nexpr2 are time or date-and-time expressions, but both must be of the\nsame type.\n\nThe result returned by TIMEDIFF() is limited to the range allowed for\nTIME values. Alternatively, you can use either of the functions\nTIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.\n\nURL: https://mariadb.com/kb/en/timediff/\n\n','MariaDB> SELECT TIMEDIFF(\'2000:01:01 00:00:00\',\n -> \'2000:01:01 00:00:00.000001\');\n -> \'-00:00:00.000001\'\nMariaDB> SELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\',\n -> \'2008-12-30 01:01:01.000002\');\n -> \'46:58:57.999999\'\n','https://mariadb.com/kb/en/timediff/'),(54,'REPLACE FUNCTION',37,'Syntax:\nREPLACE(str,from_str,to_str)\n\nReturns the string str with all occurrences of the string from_str\nreplaced by the string to_str. REPLACE() performs a case-sensitive\nmatch when searching for from_str.\n\nURL: https://mariadb.com/kb/en/replace-function/\n\n','MariaDB> SELECT REPLACE(\'www.mariadb.org\', \'w\', \'Ww\');\n -> \'WwWwWw.mariadb.org\'\n','https://mariadb.com/kb/en/replace-function/'),(55,'USE',28,'Syntax:\nUSE db_name\n\nThe USE db_name statement tells MySQL to use the db_name database as\nthe default (current) database for subsequent statements. The database\nremains the default until the end of the session or another USE\nstatement is issued:\n\nUSE db1;\nSELECT COUNT(*) FROM mytable; # selects from db1.mytable\nUSE db2;\nSELECT COUNT(*) FROM mytable; # selects from db2.mytable\n\nURL: https://mariadb.com/kb/en/use/\n\n','','https://mariadb.com/kb/en/use/'),(56,'LINEFROMTEXT',3,'LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])\n\nConstructs a LINESTRING value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromtext/\n\n','','https://mariadb.com/kb/en/linefromtext/'),(57,'CASE OPERATOR',7,'Syntax:\nCASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN\nresult ...] [ELSE result] END\n\nCASE WHEN [condition] THEN result [WHEN [condition] THEN result ...]\n[ELSE result] END\n\nThe first version returns the result where value=compare_value. The\nsecond version returns the result for the first condition that is true.\nIf there was no matching result value, the result after ELSE is\nreturned, or NULL if there is no ELSE part.\n\nURL: https://mariadb.com/kb/en/case-operator/\n\n','MariaDB> SELECT CASE 1 WHEN 1 THEN \'one\'\n -> WHEN 2 THEN \'two\' ELSE \'more\' END;\n -> \'one\'\nMariaDB> SELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n -> \'true\'\nMariaDB> SELECT CASE BINARY \'B\'\n -> WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END;\n -> NULL\n','https://mariadb.com/kb/en/case-operator/'),(58,'SHOW MASTER STATUS',26,'Syntax:\nSHOW MASTER STATUS\n\nThis statement provides status information about the binary log files\nof the master. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nExample:\n\nMariaDB> SHOW MASTER STATUS;\n+---------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+---------------+----------+--------------+------------------+\n| mysql-bin.003 | 73 | test | manual,mysql |\n+---------------+----------+--------------+------------------+\n\nURL: https://mariadb.com/kb/en/show-master-status/\n\n','','https://mariadb.com/kb/en/show-master-status/'),(59,'ADDTIME',31,'Syntax:\nADDTIME(expr1,expr2)\n\nADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time\nor datetime expression, and expr2 is a time expression.\n\nURL: https://mariadb.com/kb/en/addtime/\n\n','MariaDB> SELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1 1:1:1.000002\');\n -> \'2008-01-02 01:01:01.000001\'\nMariaDB> SELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'03:00:01.999997\'\n','https://mariadb.com/kb/en/addtime/'),(60,'SPATIAL',34,'For MyISAM tables, MySQL can create spatial indexes using syntax\nsimilar to that for creating regular indexes, but extended with the\nSPATIAL keyword. Currently, columns in spatial indexes must be declared\nNOT NULL. The following examples demonstrate how to create spatial\nindexes:\n\no With CREATE TABLE:\n\nCREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;\n\no With ALTER TABLE:\n\nALTER TABLE geom ADD SPATIAL INDEX(g);\n\no With CREATE INDEX:\n\nCREATE SPATIAL INDEX sp_index ON geom (g);\n\nFor MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage\nengines that support nonspatial indexing of spatial columns, the engine\ncreates a B-tree index. A B-tree index on spatial values will be useful\nfor exact-value lookups, but not for range scans.\n\nFor more information on indexing spatial columns, see [HELP CREATE\nINDEX].\n\nTo drop spatial indexes, use ALTER TABLE or DROP INDEX:\n\no With ALTER TABLE:\n\nALTER TABLE geom DROP INDEX g;\n\no With DROP INDEX:\n\nDROP INDEX sp_index ON geom;\n\nExample: Suppose that a table geom contains more than 32,000\ngeometries, which are stored in the column g of type GEOMETRY. The\ntable also has an AUTO_INCREMENT column fid for storing object ID\nvalues.\n\nURL: https://mariadb.com/kb/en/spatial/\n\n','','https://mariadb.com/kb/en/spatial/'),(61,'TO_SECONDS',31,'Syntax:\nTO_SECONDS(expr)\n\nGiven a date or datetime expr, returns a the number of seconds since\nthe year 0. If expr is not a valid date or datetime value, returns\nNULL.\n\nURL: https://mariadb.com/kb/en/to_seconds/\n\n','MariaDB> SELECT TO_SECONDS(950501);\n -> 62966505600\nMariaDB> SELECT TO_SECONDS(\'2009-11-29\');\n -> 63426672000\nMariaDB> SELECT TO_SECONDS(\'2009-11-29 13:43:32\');\n -> 63426721412\nMariaDB> SELECT TO_SECONDS( NOW() );\n -> 63426721458\n','https://mariadb.com/kb/en/to_seconds/'),(62,'TIMESTAMPDIFF',31,'Syntax:\nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n\nReturns datetime_expr2 - datetime_expr1, where datetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One expression may be\na date and the other a datetime; a date value is treated as a datetime\nhaving the time part \'00:00:00\' where necessary. The unit for the\nresult (an integer) is given by the unit argument. The legal values for\nunit are the same as those listed in the description of the\nTIMESTAMPADD() function.\n\nURL: https://mariadb.com/kb/en/timestampdiff/\n\n','MariaDB> SELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n -> 3\nMariaDB> SELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n -> -1\nMariaDB> SELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01 12:05:55\');\n -> 128885\n','https://mariadb.com/kb/en/timestampdiff/'),(63,'UPPER',37,'Syntax:\nUPPER(str)\n\nReturns the string str with all characters changed to uppercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT UPPER(\'Hej\');\n -> \'HEJ\'\n\nSee the description of LOWER() for information that also applies to\nUPPER(), such as information about how to perform lettercase conversion\nof binary strings (BINARY, VARBINARY, BLOB) for which these functions\nare ineffective.\n\nURL: https://mariadb.com/kb/en/upper/\n\n','','https://mariadb.com/kb/en/upper/'),(64,'FROM_UNIXTIME',31,'Syntax:\nFROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)\n\nReturns a representation of the unix_timestamp argument as a value in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the function is used in a string or numeric context. The value\nis expressed in the current time zone. unix_timestamp is an internal\ntimestamp value such as is produced by the UNIX_TIMESTAMP() function.\n\nIf format is given, the result is formatted according to the format\nstring, which is used the same way as listed in the entry for the\nDATE_FORMAT() function.\n\nURL: https://mariadb.com/kb/en/from_unixtime/\n\n','MariaDB> SELECT FROM_UNIXTIME(1196440219);\n -> \'2007-11-30 10:30:19\'\nMariaDB> SELECT FROM_UNIXTIME(1196440219) + 0;\n -> 20071130103019.000000\nMariaDB> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),\n -> \'%Y %D %M %h:%i:%s %x\');\n -> \'2007 30th November 10:30:59 2007\'\n','https://mariadb.com/kb/en/from_unixtime/'),(65,'MEDIUMBLOB',22,'MEDIUMBLOB\n\nA BLOB column with a maximum length of 16,777,215 (224 - 1) bytes. Each\nMEDIUMBLOB value is stored using a 3-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumblob/\n\n','','https://mariadb.com/kb/en/mediumblob/'),(66,'SHA2',12,'Syntax:\nSHA2(str, hash_length)\n\nCalculates the SHA-2 family of hash functions (SHA-224, SHA-256,\nSHA-384, and SHA-512). The first argument is the cleartext string to be\nhashed. The second argument indicates the desired bit length of the\nresult, which must have a value of 224, 256, 384, 512, or 0 (which is\nequivalent to 256). If either argument is NULL or the hash length is\nnot one of the permitted values, the return value is NULL. Otherwise,\nthe function result is a hash value containing the desired number of\nbits. See the notes at the beginning of this section about storing hash\nvalues efficiently.\n\nAs of MySQL 5.5.6, the return value is a nonbinary string in the\nconnection character set. Before 5.5.6, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha2/\n\n','MariaDB> SELECT SHA2(\'abc\', 224);\n -> \'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\'\n','https://mariadb.com/kb/en/sha2/'),(67,'IFNULL',7,'Syntax:\nIFNULL(expr1,expr2)\n\nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it returns\nexpr2. IFNULL() returns a numeric or string value, depending on the\ncontext in which it is used.\n\nURL: https://mariadb.com/kb/en/ifnull/\n\n','MariaDB> SELECT IFNULL(1,0);\n -> 1\nMariaDB> SELECT IFNULL(NULL,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,\'yes\');\n -> \'yes\'\n','https://mariadb.com/kb/en/ifnull/'),(68,'SHOW FUNCTION CODE',26,'Syntax:\nSHOW FUNCTION CODE func_name\n\nThis statement is similar to SHOW PROCEDURE CODE but for stored\nfunctions. See [HELP SHOW PROCEDURE CODE].\n\nURL: https://mariadb.com/kb/en/show-function-code/\n\n','','https://mariadb.com/kb/en/show-function-code/'),(69,'SHOW ERRORS',26,'Syntax:\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW COUNT(*) ERRORS\n\nThis statement is similar to SHOW WARNINGS, except that it displays\ninformation only for errors, rather than for errors, warnings, and\nnotes.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nThe SHOW COUNT(*) ERRORS statement displays the number of errors. You\ncan also retrieve this number from the error_count variable:\n\nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n\nSHOW ERRORS and error_count apply only to errors, not warnings or\nnotes. In other respects, they are similar to SHOW WARNINGS and\nwarning_count. In particular, SHOW ERRORS cannot display information\nfor more than max_error_count messages, and error_count can exceed the\nvalue of max_error_count if the number of errors exceeds\nmax_error_count.\n\nURL: https://mariadb.com/kb/en/show-errors/\n\n','','https://mariadb.com/kb/en/show-errors/'),(70,'LEAST',18,'Syntax:\nLEAST(value1,value2,...)\n\nWith two or more arguments, returns the smallest (minimum-valued)\nargument. The arguments are compared using the following rules:\n\no If any argument is NULL, the result is NULL. No comparison is needed.\n\no If the return value is used in an INTEGER context or all arguments\n are integer-valued, they are compared as integers.\n\no If the return value is used in a REAL context or all arguments are\n real-valued, they are compared as reals.\n\no If the arguments comprise a mix of numbers and strings, they are\n compared as numbers.\n\no If any argument is a nonbinary (character) string, the arguments are\n compared as nonbinary strings.\n\no In all other cases, the arguments are compared as binary strings.\n\nURL: https://mariadb.com/kb/en/least/\n\n','MariaDB> SELECT LEAST(2,0);\n -> 0\nMariaDB> SELECT LEAST(34.0,3.0,5.0,767.0);\n -> 3.0\nMariaDB> SELECT LEAST(\'B\',\'A\',\'C\');\n -> \'A\'\n','https://mariadb.com/kb/en/least/'),(71,'=',18,'=\n\nEqual:\n\nURL: https://mariadb.com/kb/en/equal/\n\n','MariaDB> SELECT 1 = 0;\n -> 0\nMariaDB> SELECT \'0\' = 0;\n -> 1\nMariaDB> SELECT \'0.0\' = 0;\n -> 1\nMariaDB> SELECT \'0.01\' = 0;\n -> 0\nMariaDB> SELECT \'.01\' = 0.01;\n -> 1\n','https://mariadb.com/kb/en/equal/'),(72,'REVERSE',37,'Syntax:\nREVERSE(str)\n\nReturns the string str with the order of the characters reversed.\n\nURL: https://mariadb.com/kb/en/reverse/\n\n','MariaDB> SELECT REVERSE(\'abc\');\n -> \'cba\'\n','https://mariadb.com/kb/en/reverse/'),(73,'ISNULL',18,'Syntax:\nISNULL(expr)\n\nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n\nURL: https://mariadb.com/kb/en/isnull/\n\n','MariaDB> SELECT ISNULL(1+1);\n -> 0\nMariaDB> SELECT ISNULL(1/0);\n -> 1\n','https://mariadb.com/kb/en/isnull/'),(74,'BINARY',22,'BINARY(M)\n\nThe BINARY type is similar to the CHAR type, but stores binary byte\nstrings rather than nonbinary character strings. M represents the\ncolumn length in bytes.\n\nURL: https://mariadb.com/kb/en/binary/\n\n','','https://mariadb.com/kb/en/binary/'),(75,'BLOB DATA TYPE',22,'A BLOB is a binary large object that can hold a variable amount of\ndata. The four BLOB types are TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB.\nThese differ only in the maximum length of the values they can hold.\nThe four TEXT types are TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. These\ncorrespond to the four BLOB types and have the same maximum lengths and\nstorage requirements. See\nhttps://mariadb.com/kb/en/data-type-storage-requirements/.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-blob/\n\n','','https://mariadb.com/kb/en/sql_language-data_types-blob/'),(76,'BOUNDARY',36,'Boundary(g)\n\nReturns a geometry that is the closure of the combinatorial boundary of\nthe geometry value g.\n\nURL: https://mariadb.com/kb/en/boundary/\n\n','','https://mariadb.com/kb/en/boundary/'),(77,'CREATE USER',10,'Syntax:\nCREATE USER user_specification\n [, user_specification] ...\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nThe CREATE USER statement creates new MySQL accounts. To use it, you\nmust have the global CREATE USER privilege or the INSERT privilege for\nthe mysql database. For each account, CREATE USER creates a new row in\nthe mysql.user table and assigns the account no privileges. An error\noccurs if the account already exists.\n\nEach account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nThe user specification may indicate how the user should authenticate\nwhen connecting to the server:\n\no To enable the user to connect with no password (which is insecure),\n include no IDENTIFIED BY clause:\n\nCREATE USER \'jeffrey\'@\'localhost\';\n\n In this case, the account uses built-in authentication and clients\n must provide no password.\n\no To assign a password, use IDENTIFIED BY with the literal plaintext\n password value:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To avoid specifying the plaintext password if you know its hash value\n (the value that PASSWORD() would return for the password), specify\n the hash value preceded by the keyword PASSWORD:\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED BY PASSWORD \'*90E462C37378CED12064BB3388827D2BA3A9B689\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To authenticate the account using a specific authentication plugin,\n use IDENTIFIED WITH, where auth_plugin is the plugin name. It can be\n an unquoted name or a quoted string literal. \'auth_string\' is an\n optional quoted string literal to pass to the plugin. The plugin\n interprets the meaning of the string, so its format is plugin\n specific. Consult the documentation for a given plugin for\n information about the authentication string values it accepts.\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED WITH my_auth_plugin;\n\n For connections that use this account, the server invokes the named\n plugin and clients must provide credentials as required for the\n authentication method that the plugin implements. If the server\n cannot find the plugin, either at account-creation time or connect\n time, an error occurs. IDENTIFIED WITH can be used as of MySQL 5.5.7.\n\nThe IDENTIFIED BY and IDENTIFIED WITH clauses are mutually exclusive,\nso at most one of them can be specified for a given user.\n\nFor additional information about setting passwords, see\nhttps://mariadb.com/kb/en/create-user/.\n\nURL: https://mariadb.com/kb/en/create-user/\n\n','','https://mariadb.com/kb/en/create-user/'),(78,'POINT',24,'Point(x,y)\n\nConstructs a Point using its coordinates.\n\nURL: https://mariadb.com/kb/en/point/\n\n','','https://mariadb.com/kb/en/point/'),(79,'CURRENT_USER',17,'Syntax:\nCURRENT_USER, CURRENT_USER()\n\nReturns the user name and host name combination for the MySQL account\nthat the server used to authenticate the current client. This account\ndetermines your access privileges. The return value is a string in the\nutf8 character set.\n\nThe value of CURRENT_USER() can differ from the value of USER().\n\nURL: https://mariadb.com/kb/en/current_user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\nMariaDB> SELECT * FROM mysql.user;\nERROR 1044: Access denied for user \'\'@\'localhost\' to\ndatabase \'mysql\'\nMariaDB> SELECT CURRENT_USER();\n -> \'@localhost\'\n','https://mariadb.com/kb/en/current_user/'),(80,'LCASE',37,'Syntax:\nLCASE(str)\n\nLCASE() is a synonym for LOWER().\n\nURL: https://mariadb.com/kb/en/lcase/\n\n','','https://mariadb.com/kb/en/lcase/'),(81,'<=',18,'Syntax:\n<=\n\nLess than or equal:\n\nURL: https://mariadb.com/kb/en/less-than-or-equal/\n\n','MariaDB> SELECT 0.1 <= 2;\n -> 1\n','https://mariadb.com/kb/en/less-than-or-equal/'),(82,'SHOW PROFILES',26,'Syntax:\nSHOW PROFILES\n\nThe SHOW PROFILES statement, together with SHOW PROFILE, displays\nprofiling information that indicates resource usage for statements\nexecuted during the course of the current session. For more\ninformation, see [HELP SHOW PROFILE].\n\nURL: https://mariadb.com/kb/en/show-profiles/\n\n','','https://mariadb.com/kb/en/show-profiles/'),(83,'UPDATE',27,'Syntax:\nSingle-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_reference\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n\nFor the single-table syntax, the UPDATE statement updates columns of\nexisting rows in the named table with new values. The SET clause\nindicates which columns to modify and the values they should be given.\nEach value can be given as an expression, or the keyword DEFAULT to set\na column explicitly to its default value. The WHERE clause, if given,\nspecifies the conditions that identify which rows to update. With no\nWHERE clause, all rows are updated. If the ORDER BY clause is\nspecified, the rows are updated in the order that is specified. The\nLIMIT clause places a limit on the number of rows that can be updated.\n\nFor the multiple-table syntax, UPDATE updates rows in each table named\nin table_references that satisfy the conditions. In this case, ORDER BY\nand LIMIT cannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe updated. For expression syntax, see\nhttp://dev.mysql.com/doc/refman/5.5/en/expressions.html.\n\ntable_references and where_condition are is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nYou need the UPDATE privilege only for columns referenced in an UPDATE\nthat are actually updated. You need only the SELECT privilege for any\ncolumns that are read but not modified.\n\nThe UPDATE statement supports the following modifiers:\n\no With the LOW_PRIORITY keyword, execution of the UPDATE is delayed\n until no other clients are reading from the table. This affects only\n storage engines that use only table-level locking (such as MyISAM,\n MEMORY, and MERGE).\n\no With the IGNORE keyword, the update statement does not abort even if\n errors occur during the update. Rows for which duplicate-key\n conflicts occur are not updated. Rows for which columns are updated\n to values that would cause data conversion errors are updated to the\n closest valid values instead.\n\nURL: https://mariadb.com/kb/en/update/\n\n','','https://mariadb.com/kb/en/update/'),(84,'IS NOT NULL',18,'Syntax:\nIS NOT NULL\n\nTests whether a value is not NULL.\n\nURL: https://mariadb.com/kb/en/is-not-null/\n\n','MariaDB> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not-null/'),(85,'CASE STATEMENT',23,'Syntax:\nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nOr:\n\nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nThe CASE statement for stored programs implements a complex conditional\nconstruct.\n\n*Note*: There is also a CASE expression, which differs from the CASE\nstatement described here. See\nhttps://mariadb.com/kb/en/case-operator/. The\nCASE statement cannot have an ELSE NULL clause, and it is terminated\nwith END CASE instead of END.\n\nFor the first syntax, case_value is an expression. This value is\ncompared to the when_value expression in each WHEN clause until one of\nthem is equal. When an equal when_value is found, the corresponding\nTHEN clause statement_list executes. If no when_value is equal, the\nELSE clause statement_list executes, if there is one.\n\nThis syntax cannot be used to test for equality with NULL because NULL\n= NULL is false. See\nhttps://mariadb.com/kb/en/null-values/.\n\nFor the second syntax, each WHEN clause search_condition expression is\nevaluated until one is true, at which point its corresponding THEN\nclause statement_list executes. If no search_condition is equal, the\nELSE clause statement_list executes, if there is one.\n\nIf no when_value or search_condition matches the value tested and the\nCASE statement contains no ELSE clause, a Case not found for CASE\nstatement error results.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nTo handle situations where no value is matched by any WHEN clause, use\nan ELSE containing an empty BEGIN ... END block, as shown in this\nexample. (The indentation used here in the ELSE clause is for purposes\nof clarity only, and is not otherwise significant.)\n\nDELIMITER |\n\nCREATE PROCEDURE p()\n BEGIN\n DECLARE v INT DEFAULT 1;\n\n CASE v\n WHEN 2 THEN SELECT v;\n WHEN 3 THEN SELECT 0;\n ELSE\n BEGIN\n END;\n END CASE;\n END;\n |\n\nURL: https://mariadb.com/kb/en/case-statement/\n\n','','https://mariadb.com/kb/en/case-statement/'),(86,'EXECUTE STATEMENT',8,'Syntax:\nEXECUTE stmt_name\n [USING @var_name [, @var_name] ...]\n\nAfter preparing a statement with PREPARE, you execute it with an\nEXECUTE statement that refers to the prepared statement name. If the\nprepared statement contains any parameter markers, you must supply a\nUSING clause that lists user variables containing the values to be\nbound to the parameters. Parameter values can be supplied only by user\nvariables, and the USING clause must name exactly as many variables as\nthe number of parameter markers in the statement.\n\nYou can execute a given prepared statement multiple times, passing\ndifferent variables to it or setting the variables to different values\nbefore each execution.\n\nURL: https://mariadb.com/kb/en/execute-statement/\n\n','','https://mariadb.com/kb/en/execute-statement/'),(87,'DROP INDEX',39,'Syntax:\nDROP [ONLINE|OFFLINE] INDEX index_name ON tbl_name\n\nDROP INDEX drops the index named index_name from the table tbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop the index.\nSee [HELP ALTER TABLE].\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: https://mariadb.com/kb/en/drop-index/\n\n','','https://mariadb.com/kb/en/drop-index/'),(88,'MATCH AGAINST',37,'Syntax:\nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n\nMySQL has support for full-text indexing and searching:\n\no A full-text index in MySQL is an index of type FULLTEXT.\n\no Full-text indexes can be used only with MyISAM tables, and can be\n created only for CHAR, VARCHAR, or TEXT columns.\n\no A FULLTEXT index definition can be given in the CREATE TABLE\n statement when a table is created, or added later using ALTER TABLE\n or CREATE INDEX.\n\no For large data sets, it is much faster to load your data into a table\n that has no FULLTEXT index and then create the index after that, than\n to load data into a table that has an existing FULLTEXT index.\n\nFull-text searching is performed using MATCH() ... AGAINST syntax.\nMATCH() takes a comma-separated list that names the columns to be\nsearched. AGAINST takes a string to search for, and an optional\nmodifier that indicates what type of search to perform. The search\nstring must be a literal string, not a variable or a column name. There\nare three types of full-text searches:\n\no A natural language search interprets the search string as a phrase in\n natural human language (a phrase in free text). There are no special\n operators. The stopword list applies. In addition, words that are\n present in 50% or more of the rows are considered common and do not\n match.\n\n Full-text searches are natural language searches if the IN NATURAL\n LANGUAGE MODE modifier is given or if no modifier is given. For more\n information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-natural-language-mode\n .\n\no A boolean search interprets the search string using the rules of a\n special query language. The string contains the words to search for.\n It can also contain operators that specify requirements such that a\n word must be present or absent in matching rows, or that it should be\n weighted higher or lower than usual. Common words such as \"some\" or\n \"then\" are stopwords and do not match if present in the search\n string. The IN BOOLEAN MODE modifier specifies a boolean search. For\n more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-boolean-mode.\n\no A query expansion search is a modification of a natural language\n search. The search string is used to perform a natural language\n search. Then words from the most relevant rows returned by the search\n are added to the search string and the search is done again. The\n query returns the rows from the second search. The IN NATURAL\n LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier\n specifies a query expansion search. For more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#with-query-expansion.\n\nURL: https://mariadb.com/kb/en/match-against/\n\n','MariaDB> SELECT id, body, MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE) AS score\n -> FROM articles WHERE MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |\n| 6 | When configured properly, MySQL ... | 1.3114095926285 |\n+----+-------------------------------------+-----------------+\n2 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/match-against/'),(89,'CREATE EVENT',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n EVENT\n [IF NOT EXISTS]\n event_name\n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO event_body;\n\nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval\n [STARTS timestamp [+ INTERVAL interval] ...]\n [ENDS timestamp [+ INTERVAL interval] ...]\n\ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n\nThis statement creates and schedules a new event. The event will not\nrun unless the Event Scheduler is enabled. For information about\nchecking Event Scheduler status and enabling it if necessary, see\nhttps://mariadb.com/kb/en/events/.\n\nCREATE EVENT requires the EVENT privilege for the schema in which the\nevent is to be created. It might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section.\n\nThe minimum requirements for a valid CREATE EVENT statement are as\nfollows:\n\no The keywords CREATE EVENT plus an event name, which uniquely\n identifies the event in a database schema.\n\no An ON SCHEDULE clause, which determines when and how often the event\n executes.\n\no A DO clause, which contains the SQL statement to be executed by an\n event.\n\nThis is an example of a minimal CREATE EVENT statement:\n\nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n\nThe previous statement creates an event named myevent. This event\nexecutes once---one hour following its creation---by running an SQL\nstatement that increments the value of the myschema.mytable table\'s\nmycol column by 1.\n\nThe event_name must be a valid MySQL identifier with a maximum length\nof 64 characters. Event names are not case sensitive, so you cannot\nhave two events named myevent and MyEvent in the same schema. In\ngeneral, the rules governing event names are the same as those for\nnames of stored routines. See\nhttps://mariadb.com/kb/en/identifier-names/.\n\nAn event is associated with a schema. If no schema is indicated as part\nof event_name, the default (current) schema is assumed. To create an\nevent in a specific schema, qualify the event name with a schema using\nschema_name.event_name syntax.\n\nURL: https://mariadb.com/kb/en/create-event/\n\n','','https://mariadb.com/kb/en/create-event/'),(90,'ABS',4,'Syntax:\nABS(X)\n\nReturns the absolute value of X.\n\nURL: https://mariadb.com/kb/en/abs/\n\n','MariaDB> SELECT ABS(2);\n -> 2\nMariaDB> SELECT ABS(-32);\n -> 32\n','https://mariadb.com/kb/en/abs/'),(91,'POLYFROMWKB',32,'PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])\n\nConstructs a POLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromwkb/\n\n','','https://mariadb.com/kb/en/polyfromwkb/'),(92,'NOT LIKE',37,'Syntax:\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n\nThis is the same as NOT (expr LIKE pat [ESCAPE \'escape_char\']).\n\nURL: https://mariadb.com/kb/en/not-like/\n\n','','https://mariadb.com/kb/en/not-like/'),(93,'SPACE',37,'Syntax:\nSPACE(N)\n\nReturns a string consisting of N space characters.\n\nURL: https://mariadb.com/kb/en/space/\n\n','MariaDB> SELECT SPACE(6);\n -> \' \'\n','https://mariadb.com/kb/en/space/'),(94,'MBR DEFINITION',6,'Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding\ngeometry, formed by the minimum and maximum (X,Y) coordinates:\n\nURL: https://mariadb.com/kb/en/mbr-definition/\n\n','((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n','https://mariadb.com/kb/en/mbr-definition/'),(95,'GEOMETRYCOLLECTION',24,'GeometryCollection(g1,g2,...)\n\nConstructs a GeometryCollection.\n\nURL: https://mariadb.com/kb/en/geometrycollection/\n\n','','https://mariadb.com/kb/en/geometrycollection/'),(96,'MAX',16,'Syntax:\nMAX([DISTINCT] expr)\n\nReturns the maximum value of expr. MAX() may take a string argument; in\nsuch cases, it returns the maximum string value. See\nhttps://mariadb.com/kb/en/max/. The DISTINCT\nkeyword can be used to find the maximum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMAX() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/max/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/max/'),(97,'CREATE FUNCTION UDF',21,'Syntax:\nCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n\nA user-defined function (UDF) is a way to extend MySQL with a new\nfunction that works like a native (built-in) MySQL function such as\nABS() or CONCAT().\n\nfunction_name is the name that should be used in SQL statements to\ninvoke the function. The RETURNS clause indicates the type of the\nfunction\'s return value. DECIMAL is a legal value after RETURNS, but\ncurrently DECIMAL functions return string values and should be written\nlike STRING functions.\n\nshared_library_name is the basename of the shared object file that\ncontains the code that implements the function. The file must be\nlocated in the plugin directory. This directory is given by the value\nof the plugin_dir system variable. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/udf-compiling.html.\n\nTo create a function, you must have the INSERT privilege for the mysql\ndatabase. This is necessary because CREATE FUNCTION adds a row to the\nmysql.func system table that records the function\'s name, type, and\nshared library name. If you do not have this table, you should run the\nmysql_upgrade command to create it. See\nhttps://mariadb.com/kb/en/mysql_upgrade/.\n\nURL: https://mariadb.com/kb/en/create-function-udf/\n\n','','https://mariadb.com/kb/en/create-function-udf/'),(98,'*',4,'Syntax:\n*\n\nMultiplication:\n\nURL: https://mariadb.com/kb/en/multiplication-operator/\n\n','MariaDB> SELECT 3*5;\n -> 15\nMariaDB> SELECT 18014398509481984*18014398509481984.0;\n -> 324518553658426726783156020576256.0\nMariaDB> SELECT 18014398509481984*18014398509481984;\n -> 0\n','https://mariadb.com/kb/en/multiplication-operator/'),(99,'TIMESTAMP',22,'TIMESTAMP\n\nA timestamp. The range is \'1970-01-01 00:00:01\' UTC to \'2038-01-19\n03:14:07\' UTC. TIMESTAMP values are stored as the number of seconds\nsince the epoch (\'1970-01-01 00:00:00\' UTC). A TIMESTAMP cannot\nrepresent the value \'1970-01-01 00:00:00\' because that is equivalent to\n0 seconds from the epoch and the value 0 is reserved for representing\n\'0000-00-00 00:00:00\', the \"zero\" TIMESTAMP value.\n\nUnless specified otherwise, the first TIMESTAMP column in a table is\ndefined to be automatically set to the date and time of the most recent\nmodification if not explicitly assigned a value. This makes TIMESTAMP\nuseful for recording the timestamp of an INSERT or UPDATE operation.\nYou can also set any TIMESTAMP column to the current date and time by\nassigning it a NULL value, unless it has been defined with the NULL\nattribute to permit NULL values. The automatic initialization and\nupdating to the current date and time can be specified using DEFAULT\nCURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, as described\nin\nhttps://mariadb.com/kb/en/timestamp/.\n\n*Note*: The TIMESTAMP format that was used prior to MySQL 4.1 is not\nsupported in MySQL 5.5; see MySQL 3.23, 4.0, 4.1 Reference Manual for\ninformation regarding the old format.\n\nURL: https://mariadb.com/kb/en/timestamp/\n\n','','https://mariadb.com/kb/en/timestamp/'),(100,'DES_DECRYPT',12,'Syntax:\nDES_DECRYPT(crypt_str[,key_str])\n\nDecrypts a string encrypted with DES_ENCRYPT(). If an error occurs,\nthis function returns NULL.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nIf no key_str argument is given, DES_DECRYPT() examines the first byte\nof the encrypted string to determine the DES key number that was used\nto encrypt the original string, and then reads the key from the DES key\nfile to decrypt the message. For this to work, the user must have the\nSUPER privilege. The key file can be specified with the --des-key-file\nserver option.\n\nIf you pass this function a key_str argument, that string is used as\nthe key for decrypting the message.\n\nIf the crypt_str argument does not appear to be an encrypted string,\nMySQL returns the given crypt_str.\n\nURL: https://mariadb.com/kb/en/des_decrypt/\n\n','','https://mariadb.com/kb/en/des_decrypt/'),(101,'CACHE INDEX',26,'Syntax:\nCACHE INDEX\n tbl_index_list [, tbl_index_list] ...\n [PARTITION (partition_list | ALL)]\n IN key_cache_name\n\ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe CACHE INDEX statement assigns table indexes to a specific key\ncache. It is used only for MyISAM tables. After the indexes have been\nassigned, they can be preloaded into the cache if desired with LOAD\nINDEX INTO CACHE.\n\nThe following statement assigns indexes from the tables t1, t2, and t3\nto the key cache named hot_cache:\n\nMariaDB> CACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n\nURL: https://mariadb.com/kb/en/cache-index/\n\n','','https://mariadb.com/kb/en/cache-index/'),(102,'ENDPOINT',13,'EndPoint(ls)\n\nReturns the Point that is the endpoint of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/endpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/endpoint/'),(103,'COMPRESS',12,'Syntax:\nCOMPRESS(string_to_compress)\n\nCompresses a string and returns the result as a binary string. This\nfunction requires MySQL to have been compiled with a compression\nlibrary such as zlib. Otherwise, the return value is always NULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n\nURL: https://mariadb.com/kb/en/compress/\n\n','MariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n -> 21\nMariaDB> SELECT LENGTH(COMPRESS(\'\'));\n -> 0\nMariaDB> SELECT LENGTH(COMPRESS(\'a\'));\n -> 13\nMariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n -> 15\n','https://mariadb.com/kb/en/compress/'),(104,'INSERT',27,'Syntax:\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nINSERT inserts new rows into an existing table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based on\nexplicitly specified values. The INSERT ... SELECT form inserts rows\nselected from another table or tables. INSERT ... SELECT is discussed\nfurther in [HELP INSERT SELECT].\n\nURL: https://mariadb.com/kb/en/insert/\n\n','','https://mariadb.com/kb/en/insert/'),(105,'COUNT',16,'Syntax:\nCOUNT(expr)\n\nReturns a count of the number of non-NULL values of expr in the rows\nretrieved by a SELECT statement. The result is a BIGINT value.\n\nCOUNT() returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count/\n\n','MariaDB> SELECT student.student_name,COUNT(*)\n -> FROM student,course\n -> WHERE student.student_id=course.student_id\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/count/'),(106,'HANDLER',27,'Syntax:\nHANDLER tbl_name OPEN [ [AS] alias]\n\nHANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ { FIRST | NEXT }\n [ WHERE where_condition ] [LIMIT ... ]\n\nHANDLER tbl_name CLOSE\n\nThe HANDLER statement provides direct access to table storage engine\ninterfaces. It is available for MyISAM and InnoDB tables.\n\nURL: https://mariadb.com/kb/en/handler-commands/\n\n','','https://mariadb.com/kb/en/handler-commands/'),(107,'MLINEFROMTEXT',3,'MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])\n\nConstructs a MULTILINESTRING value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromtext/\n\n','','https://mariadb.com/kb/en/mlinefromtext/'),(108,'GEOMCOLLFROMWKB',32,'GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkb[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromwkb/\n\n','','https://mariadb.com/kb/en/geomcollfromwkb/'),(109,'HELP_DATE',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25\n','',''),(110,'RENAME TABLE',39,'Syntax:\nRENAME TABLE tbl_name TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n\nThis statement renames one or more tables.\n\nThe rename operation is done atomically, which means that no other\nsession can access any of the tables while the rename is running. For\nexample, if you have an existing table old_table, you can create\nanother table new_table that has the same structure but is empty, and\nthen replace the existing table with the empty one as follows (assuming\nthat backup_table does not already exist):\n\nURL: https://mariadb.com/kb/en/rename-table/\n\n','CREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO old_table;\n','https://mariadb.com/kb/en/rename-table/'),(111,'BOOLEAN',22,'BOOL, BOOLEAN\n\nThese types are synonyms for TINYINT(1). A value of zero is considered\nfalse. Nonzero values are considered true:\n\nMariaDB> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n\nMariaDB> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nMariaDB> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nHowever, the values TRUE and FALSE are merely aliases for 1 and 0,\nrespectively, as shown here:\n\nMariaDB> SELECT IF(0 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n\nMariaDB> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n\nThe last two statements display the results shown because 2 is equal to\nneither 1 nor 0.\n\nURL: https://mariadb.com/kb/en/boolean/\n\n','','https://mariadb.com/kb/en/boolean/'),(112,'DEFAULT',14,'Syntax:\nDEFAULT(col_name)\n\nReturns the default value for a table column. An error results if the\ncolumn has no default value.\n\nURL: https://mariadb.com/kb/en/default/\n\n','MariaDB> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\n','https://mariadb.com/kb/en/default/'),(113,'MOD',4,'Syntax:\nMOD(N,M), N % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M.\n\nURL: https://mariadb.com/kb/en/mod/\n\n','MariaDB> SELECT MOD(234, 10);\n -> 4\nMariaDB> SELECT 253 % 7;\n -> 1\nMariaDB> SELECT MOD(29,9);\n -> 2\nMariaDB> SELECT 29 MOD 9;\n -> 2\n','https://mariadb.com/kb/en/mod/'),(114,'TINYTEXT',22,'TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 255 (28 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TINYTEXT value is stored using a 1-byte length prefix\nthat indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinytext/\n\n','','https://mariadb.com/kb/en/tinytext/'),(115,'OPTIMIZE TABLE',20,'Syntax:\nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nOPTIMIZE TABLE should be used if you have deleted a large part of a\ntable or if you have made many changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT columns).\nDeleted rows are maintained in a linked list and subsequent INSERT\noperations reuse old row positions. You can use OPTIMIZE TABLE to\nreclaim the unused space and to defragment the data file. After\nextensive changes to a table, this statement may also improve\nperformance of statements that use the table, sometimes significantly.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nOPTIMIZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... OPTIMIZE PARTITION to optimize one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/optimize-table/\n\n','','https://mariadb.com/kb/en/optimize-table/'),(116,'DECODE',12,'Syntax:\nDECODE(crypt_str,pass_str)\n\nDecrypts the encrypted string crypt_str using pass_str as the password.\ncrypt_str should be a string returned from ENCODE().\n\nURL: https://mariadb.com/kb/en/decode/\n\n','','https://mariadb.com/kb/en/decode/'),(117,'<=>',18,'Syntax:\n<=>\n\nNULL-safe equal. This operator performs an equality comparison like the\n= operator, but returns 1 rather than NULL if both operands are NULL,\nand 0 rather than NULL if one operand is NULL.\n\nURL: https://mariadb.com/kb/en/null-safe-equal/\n\n','MariaDB> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\n -> 1, 1, 0\nMariaDB> SELECT 1 = 1, NULL = NULL, 1 = NULL;\n -> 1, NULL, NULL\n','https://mariadb.com/kb/en/null-safe-equal/'),(118,'HELP STATEMENT',28,'Syntax:\nHELP \'search_string\'\n\nThe HELP statement returns online information from the MySQL Reference\nmanual. Its proper operation requires that the help tables in the mysql\ndatabase be initialized with help topic information.\n\nThe HELP statement searches the help tables for the given search string\nand displays the result of the search. The search string is not case\nsensitive.\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(119,'RESET',26,'Syntax:\nRESET reset_option [, reset_option] ...\n\nThe RESET statement is used to clear the state of various server\noperations. You must have the RELOAD privilege to execute RESET.\n\nRESET acts as a stronger version of the FLUSH statement. See [HELP\nFLUSH].\n\nThe RESET statement causes an implicit commit. See\nhttps://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/.\n\nURL: https://mariadb.com/kb/en/reset/\n\n','','https://mariadb.com/kb/en/reset/'),(120,'GET_LOCK',14,'Syntax:\nGET_LOCK(str,timeout)\n\nTries to obtain a lock with a name given by the string str, using a\ntimeout of timeout seconds. Returns 1 if the lock was obtained\nsuccessfully, 0 if the attempt timed out (for example, because another\nclient has previously locked the name), or NULL if an error occurred\n(such as running out of memory or the thread was killed with mysqladmin\nkill). If you have a lock obtained with GET_LOCK(), it is released when\nyou execute RELEASE_LOCK(), execute a new GET_LOCK(), or your\nconnection terminates (either normally or abnormally). Locks obtained\nwith GET_LOCK() do not interact with transactions. That is, committing\na transaction does not release any such locks obtained during the\ntransaction.\n\nThis function can be used to implement application locks or to simulate\nrecord locks. Names are locked on a server-wide basis. If a name has\nbeen locked by one client, GET_LOCK() blocks any request by another\nclient for a lock with the same name. This enables clients that agree\non a given lock name to use the name to perform cooperative advisory\nlocking. But be aware that it also enables a client that is not among\nthe set of cooperating clients to lock a name, either inadvertently or\ndeliberately, and thus prevent any of the cooperating clients from\nlocking that name. One way to reduce the likelihood of this is to use\nlock names that are database-specific or application-specific. For\nexample, use lock names of the form db_name.str or app_name.str.\n\nURL: https://mariadb.com/kb/en/get_lock/\n\n','MariaDB> SELECT GET_LOCK(\'lock1\',10);\n -> 1\nMariaDB> SELECT IS_FREE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT GET_LOCK(\'lock2\',10);\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock1\');\n -> NULL\n','https://mariadb.com/kb/en/get_lock/'),(121,'UCASE',37,'Syntax:\nUCASE(str)\n\nUCASE() is a synonym for UPPER().\n\nURL: https://mariadb.com/kb/en/ucase/\n\n','','https://mariadb.com/kb/en/ucase/'),(122,'SHOW BINLOG EVENTS',26,'Syntax:\nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the binary log. If you do not specify \'log_name\',\nthe first binary log is displayed.\n\nURL: https://mariadb.com/kb/en/show-binlog-events/\n\n','','https://mariadb.com/kb/en/show-binlog-events/'),(123,'MPOLYFROMWKB',32,'MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])\n\nConstructs a MULTIPOLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromwkb/\n\n','','https://mariadb.com/kb/en/mpolyfromwkb/'),(124,'ITERATE',23,'Syntax:\nITERATE label\n\nITERATE can appear only within LOOP, REPEAT, and WHILE statements.\nITERATE means \"start the loop again.\"\n\nURL: https://mariadb.com/kb/en/iterate/\n\n','','https://mariadb.com/kb/en/iterate/'),(125,'DO',27,'Syntax:\nDO expr [, expr] ...\n\nDO executes the expressions but does not return any results. In most\nrespects, DO is shorthand for SELECT expr, ..., but has the advantage\nthat it is slightly faster when you do not care about the result.\n\nDO is useful primarily with functions that have side effects, such as\nRELEASE_LOCK().\n\nURL: https://mariadb.com/kb/en/do/\n\n','','https://mariadb.com/kb/en/do/'),(126,'CURTIME',31,'Syntax:\nCURTIME()\n\nReturns the current time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context. The value is expressed in the current time zone.\n\nURL: https://mariadb.com/kb/en/curtime/\n\n','MariaDB> SELECT CURTIME();\n -> \'23:50:26\'\nMariaDB> SELECT CURTIME() + 0;\n -> 235026.000000\n','https://mariadb.com/kb/en/curtime/'),(127,'CHAR_LENGTH',37,'Syntax:\nCHAR_LENGTH(str)\n\nReturns the length of the string str, measured in characters. A\nmulti-byte character counts as a single character. This means that for\na string containing five 2-byte characters, LENGTH() returns 10,\nwhereas CHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/char_length/\n\n','','https://mariadb.com/kb/en/char_length/'),(128,'BIGINT',22,'BIGINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to 18446744073709551615.\n\nSERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.\n\nURL: https://mariadb.com/kb/en/bigint/\n\n','','https://mariadb.com/kb/en/bigint/'),(129,'SET',26,'Syntax:\nSET variable_assignment [, variable_assignment] ...\n\nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n\nThe SET statement assigns values to different types of variables that\naffect the operation of the server or your client. Older versions of\nMySQL employed SET OPTION, but this syntax is deprecated in favor of\nSET without OPTION.\n\nURL: https://mariadb.com/kb/en/set/\n\n','','https://mariadb.com/kb/en/set/'),(130,'LOAD XML',27,'Syntax:\nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD XML statement reads data from an XML file into a table. The\nfile_name must be given as a literal string. The tagname in the\noptional ROWS IDENTIFIED BY clause must also be given as a literal\nstring, and must be surrounded by angle brackets (< and >).\n\nLOAD XML acts as the complement of running the mysql client in XML\noutput mode (that is, starting the client with the --xml option). To\nwrite data from a table to an XML file, use a command such as the\nfollowing one from the system shell:\n\nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n\nTo read the file back into a table, use LOAD XML INFILE. By default,\nthe element is considered to be the equivalent of a database\ntable row; this can be changed using the ROWS IDENTIFIED BY clause.\n\nThis statement supports three different XML formats:\n\no Column names as attributes and column values as attribute values:\n\n\n\no Column names as tags and column values as the content of these tags:\n\n\n value1\n value2\n\n\no Column names are the name attributes of tags, and values are\n the contents of these tags:\n\n\n value1\n value2\n\n\n This is the format used by other MySQL tools, such as mysqldump.\n\nAll 3 formats can be used in the same XML file; the import routine\nautomatically detects the format for each row and interprets it\ncorrectly. Tags are matched based on the tag or attribute name and the\ncolumn name.\n\nThe following clauses work essentially the same way for LOAD XML as\nthey do for LOAD DATA:\n\no LOW_PRIORITY or CONCURRENT\n\no LOCAL\n\no REPLACE or IGNORE\n\no CHARACTER SET\n\no (column_or_user_var,...)\n\no SET\n\nSee [HELP LOAD DATA], for more information about these clauses.\n\nThe IGNORE number LINES or IGNORE number ROWS clause causes the first\nnumber rows in the XML file to be skipped. It is analogous to the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n\nURL: https://mariadb.com/kb/en/load-xml/\n\n','','https://mariadb.com/kb/en/load-xml/'),(131,'CONV',4,'Syntax:\nCONV(N,from_base,to_base)\n\nConverts numbers between different number bases. Returns a string\nrepresentation of the number N, converted from base from_base to base\nto_base. Returns NULL if any argument is NULL. The argument N is\ninterpreted as an integer, but may be specified as an integer or a\nstring. The minimum base is 2 and the maximum base is 36. If to_base is\na negative number, N is regarded as a signed number. Otherwise, N is\ntreated as unsigned. CONV() works with 64-bit precision.\n\nURL: https://mariadb.com/kb/en/conv/\n\n','MariaDB> SELECT CONV(\'a\',16,2);\n -> \'1010\'\nMariaDB> SELECT CONV(\'6E\',18,8);\n -> \'172\'\nMariaDB> SELECT CONV(-17,10,-18);\n -> \'-H\'\nMariaDB> SELECT CONV(10+\'10\'+\'10\'+0xa,10,10);\n -> \'40\'\n','https://mariadb.com/kb/en/conv/'),(132,'DATE',22,'DATE\n\nA date. The supported range is \'1000-01-01\' to \'9999-12-31\'. MySQL\ndisplays DATE values in \'YYYY-MM-DD\' format, but permits assignment of\nvalues to DATE columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/date/\n\n','','https://mariadb.com/kb/en/date/'),(133,'ASSIGN-VALUE',15,'Syntax:\n:=\n\nAssignment operator. Causes the user variable on the left hand side of\nthe operator to take on the value to its right. The value on the right\nhand side may be a literal value, another variable storing a value, or\nany legal expression that yields a scalar value, including the result\nof a query (provided that this value is a scalar value). You can\nperform multiple assignments in the same SET statement. You can perform\nmultiple assignments in the same statement-\n\nUnlike =, the := operator is never interpreted as a comparison\noperator. This means you can use := in any valid SQL statement (not\njust in SET statements) to assign a value to a variable.\n\nURL: https://mariadb.com/kb/en/assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n\nMariaDB> SELECT @var1:=COUNT(*) FROM t1;\n -> 4\nMariaDB> SELECT @var1;\n -> 4\n','https://mariadb.com/kb/en/assignment-operator/'),(134,'SHOW OPEN TABLES',26,'Syntax:\nSHOW OPEN TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW OPEN TABLES lists the non-TEMPORARY tables that are currently open\nin the table cache. See\nhttp://dev.mysql.com/doc/refman/5.5/en/table-cache.html. The FROM\nclause, if present, restricts the tables shown to those present in the\ndb_name database. The LIKE clause, if present, indicates which table\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-open-tables/\n\n','','https://mariadb.com/kb/en/show-open-tables/'),(135,'EXTRACT',31,'Syntax:\nEXTRACT(unit FROM date)\n\nThe EXTRACT() function uses the same kinds of unit specifiers as\nDATE_ADD() or DATE_SUB(), but extracts parts from the date rather than\nperforming date arithmetic.\n\nURL: https://mariadb.com/kb/en/extract/\n\n','MariaDB> SELECT EXTRACT(YEAR FROM \'2009-07-02\');\n -> 2009\nMariaDB> SELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n -> 200907\nMariaDB> SELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n -> 20102\nMariaDB> SELECT EXTRACT(MICROSECOND\n -> FROM \'2003-01-02 10:30:00.000123\');\n -> 123\n','https://mariadb.com/kb/en/extract/'),(136,'ENCRYPT',12,'Syntax:\nENCRYPT(str[,salt])\n\nEncrypts str using the Unix crypt() system call and returns a binary\nstring. The salt argument must be a string with at least two characters\nor the result will be NULL. If no salt argument is given, a random\nvalue is used.\n\nURL: https://mariadb.com/kb/en/encrypt/\n\n','MariaDB> SELECT ENCRYPT(\'hello\');\n -> \'VxuFAJXVARROc\'\n','https://mariadb.com/kb/en/encrypt/'),(137,'SHOW STATUS',26,'Syntax:\nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW STATUS provides server status information. This information also\ncan be obtained using the mysqladmin extended-status command. The LIKE\nclause, if present, indicates which variable names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\nThis statement does not require any privilege. It requires only the\nability to connect to the server.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern:\n\nMariaDB> SHOW STATUS LIKE \'Key%\';\n+--------------------+----------+\n| Variable_name | Value |\n+--------------------+----------+\n| Key_blocks_used | 14955 |\n| Key_read_requests | 96854827 |\n| Key_reads | 162040 |\n| Key_write_requests | 7589728 |\n| Key_writes | 3813196 |\n+--------------------+----------+\n\nWith the GLOBAL modifier, SHOW STATUS displays the status values for\nall connections to MySQL. With SESSION, it displays the status values\nfor the current connection. If no modifier is present, the default is\nSESSION. LOCAL is a synonym for SESSION.\n\nSome status variables have only a global value. For these, you get the\nsame value for both GLOBAL and SESSION. The scope for each status\nvariable is listed at\nhttps://mariadb.com/kb/en/server-status-variables/.\n\nEach invocation of the SHOW STATUS statement uses an internal temporary\ntable and increments the global Created_tmp_tables value.\n\nURL: https://mariadb.com/kb/en/show-status/\n\n','','https://mariadb.com/kb/en/show-status/'),(138,'EXTRACTVALUE',37,'Syntax:\nExtractValue(xml_frag, xpath_expr)\n\nExtractValue() takes two string arguments, a fragment of XML markup\nxml_frag and an XPath expression xpath_expr (also known as a locator);\nit returns the text (CDATA) of the first text node which is a child of\nthe elements or elements matched by the XPath expression. In MySQL 5.5,\nthe XPath expression can contain at most 127 characters. (This\nlimitation is lifted in MySQL 5.6.)\n\nUsing this function is the equivalent of performing a match using the\nxpath_expr after appending /text(). In other words,\nExtractValue(\'Sakila\', \'/a/b\') and\nExtractValue(\'Sakila\', \'/a/b/text()\') produce the same\nresult.\n\nIf multiple matches are found, the content of the first child text node\nof each matching element is returned (in the order matched) as a\nsingle, space-delimited string.\n\nIf no matching text node is found for the expression (including the\nimplicit /text())---for whatever reason, as long as xpath_expr is\nvalid, and xml_frag consists of elements which are properly nested and\nclosed---an empty string is returned. No distinction is made between a\nmatch on an empty element and no match at all. This is by design.\n\nIf you need to determine whether no matching element was found in\nxml_frag or such an element was found but contained no child text\nnodes, you should test the result of an expression that uses the XPath\ncount() function. For example, both of these statements return an empty\nstring, as shown here:\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nHowever, you can determine whether there was actually a matching\nelement using the following:\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 1 |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n1 row in set (0.01 sec)\n\n*Important*: ExtractValue() returns only CDATA, and does not return any\ntags that might be contained within a matching tag, nor any of their\ncontent (see the result returned as val1 in the following example).\n\nURL: https://mariadb.com/kb/en/extractvalue/\n\n','MariaDB> SELECT\n -> ExtractValue(\'cccddd\', \'/a\') AS val1,\n -> ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n -> ExtractValue(\'cccddd\', \'//b\') AS val3,\n -> ExtractValue(\'cccddd\', \'/b\') AS val4,\n -> ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n\n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n','https://mariadb.com/kb/en/extractvalue/'),(139,'OLD_PASSWORD',12,'Syntax:\nOLD_PASSWORD(str)\n\nOLD_PASSWORD() was added when the implementation of PASSWORD() was\nchanged in MySQL 4.1 to improve security. OLD_PASSWORD() returns the\nvalue of the pre-4.1 implementation of PASSWORD() as a string, and is\nintended to permit you to reset passwords for any pre-4.1 clients that\nneed to connect to your version 5.5 MySQL server without locking them\nout. See http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/old_password/\n\n','','https://mariadb.com/kb/en/old_password/'),(140,'FORMAT',37,'Syntax:\nFORMAT(X,D[,locale])\n\nFormats the number X to a format like \'#,###,###.##\', rounded to D\ndecimal places, and returns the result as a string. If D is 0, the\nresult has no decimal point or fractional part.\n\nThe optional third parameter enables a locale to be specified to be\nused for the result number\'s decimal point, thousands separator, and\ngrouping between separators. Permissible locale values are the same as\nthe legal values for the lc_time_names system variable (see\nhttps://mariadb.com/kb/en/server-locale/). If no\nlocale is specified, the default is \'en_US\'.\n\nURL: https://mariadb.com/kb/en/format/\n\n','MariaDB> SELECT FORMAT(12332.123456, 4);\n -> \'12,332.1235\'\nMariaDB> SELECT FORMAT(12332.1,4);\n -> \'12,332.1000\'\nMariaDB> SELECT FORMAT(12332.2,0);\n -> \'12,332\'\nMariaDB> SELECT FORMAT(12332.2,2,\'de_DE\');\n -> \'12.332,20\'\n','https://mariadb.com/kb/en/format/'),(141,'||',15,'Syntax:\nOR, ||\n\nLogical OR. When both operands are non-NULL, the result is 1 if any\noperand is nonzero, and 0 otherwise. With a NULL operand, the result is\n1 if the other operand is nonzero, and NULL otherwise. If both operands\nare NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/or/\n\n','MariaDB> SELECT 1 || 1;\n -> 1\nMariaDB> SELECT 1 || 0;\n -> 1\nMariaDB> SELECT 0 || 0;\n -> 0\nMariaDB> SELECT 0 || NULL;\n -> NULL\nMariaDB> SELECT 1 || NULL;\n -> 1\n','https://mariadb.com/kb/en/or/'),(142,'BIT_LENGTH',37,'Syntax:\nBIT_LENGTH(str)\n\nReturns the length of the string str in bits.\n\nURL: https://mariadb.com/kb/en/bit_length/\n\n','MariaDB> SELECT BIT_LENGTH(\'text\');\n -> 32\n','https://mariadb.com/kb/en/bit_length/'),(143,'EXTERIORRING',2,'ExteriorRing(poly)\n\nReturns the exterior ring of the Polygon value poly as a LineString.\n\nURL: https://mariadb.com/kb/en/exteriorring/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n','https://mariadb.com/kb/en/exteriorring/'),(144,'GEOMFROMWKB',32,'GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkb[,srid])\n\nConstructs a geometry value of any type using its WKB representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromwkb/\n\n','','https://mariadb.com/kb/en/geomfromwkb/'),(145,'SHOW SLAVE HOSTS',26,'Syntax:\nSHOW SLAVE HOSTS\n\nDisplays a list of replication slaves currently registered with the\nmaster. (Before MySQL 5.5.3, only slaves started with the\n--report-host=host_name option are visible in this list.)\n\nThe list is displayed on any server (not just the master server). The\noutput looks like this:\n\nMariaDB> SHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\n\no Server_id: The unique server ID of the slave server, as configured in\n the server\'s option file, or on the command line with\n --server-id=value.\n\no Host: The host name of the slave server, as configured in the\n server\'s option file, or on the command line with\n --report-host=host_name. Note that this can differ from the machine\n name as configured in the operating system.\n\no Port: The port the slave server is listening on.\n\n In MySQL 5.5.23 and later, a zero in this column means that the slave\n port (--report-port) was not set. Prior to MySQL 5.5.23, 3306 was\n used as the default in such cases (Bug #13333431).\n\no Master_id: The unique server ID of the master server that the slave\n server is replicating from.\n\nSome MySQL versions report another variable, Rpl_recovery_rank. This\nvariable was never used, and was removed in MySQL 5.5.3. (Bug #13963)\n\nURL: https://mariadb.com/kb/en/show-slave-hosts/\n\n','','https://mariadb.com/kb/en/show-slave-hosts/'),(146,'START TRANSACTION',8,'Syntax:\nSTART TRANSACTION [WITH CONSISTENT SNAPSHOT]\nBEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n\nThese statements provide control over use of transactions:\n\no START TRANSACTION or BEGIN start a new transaction.\n\no COMMIT commits the current transaction, making its changes permanent.\n\no ROLLBACK rolls back the current transaction, canceling its changes.\n\no SET autocommit disables or enables the default autocommit mode for\n the current session.\n\nBy default, MySQL runs with autocommit mode enabled. This means that as\nsoon as you execute a statement that updates (modifies) a table, MySQL\nstores the update on disk to make it permanent. The change cannot be\nrolled back.\n\nTo disable autocommit mode implicitly for a single series of\nstatements, use the START TRANSACTION statement:\n\nSTART TRANSACTION;\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\nUPDATE table2 SET summary=@A WHERE type=1;\nCOMMIT;\n\nWith START TRANSACTION, autocommit remains disabled until you end the\ntransaction with COMMIT or ROLLBACK. The autocommit mode then reverts\nto its previous state.\n\nYou can also begin a transaction like this:\n\nSTART TRANSACTION WITH CONSISTENT SNAPSHOT;\n\nThe WITH CONSISTENT SNAPSHOT option starts a consistent read for\nstorage engines that are capable of it. This applies only to InnoDB.\nThe effect is the same as issuing a START TRANSACTION followed by a\nSELECT from any InnoDB table. See\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html. The\nWITH CONSISTENT SNAPSHOT option does not change the current transaction\nisolation level, so it provides a consistent snapshot only if the\ncurrent isolation level is one that permits consistent read (REPEATABLE\nREAD or SERIALIZABLE).\n\n*Important*: Many APIs used for writing MySQL client applications (such\nas JDBC) provide their own methods for starting transactions that can\n(and sometimes should) be used instead of sending a START TRANSACTION\nstatement from the client. See\nhttp://dev.mysql.com/doc/refman/5.5/en/connectors-apis.html, or the\ndocumentation for your API, for more information.\n\nTo disable autocommit mode explicitly, use the following statement:\n\nSET autocommit=0;\n\nAfter disabling autocommit mode by setting the autocommit variable to\nzero, changes to transaction-safe tables (such as those for InnoDB) are not made permanent immediately. You must use COMMIT to\nstore your changes to disk or ROLLBACK to ignore the changes.\n\nautocommit is a session variable and must be set for each session. To\ndisable autocommit mode for each new connection, see the description of\nthe autocommit system variable at\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nBEGIN and BEGIN WORK are supported as aliases of START TRANSACTION for\ninitiating a transaction. START TRANSACTION is standard SQL syntax and\nis the recommended way to start an ad-hoc transaction.\n\nThe BEGIN statement differs from the use of the BEGIN keyword that\nstarts a BEGIN ... END compound statement. The latter does not begin a\ntransaction. See [HELP BEGIN END].\n\n*Note*: Within all stored programs (stored procedures and functions,\ntriggers, and events), the parser treats BEGIN [WORK] as the beginning\nof a BEGIN ... END block. Begin a transaction in this context with\nSTART TRANSACTION instead.\n\nThe optional WORK keyword is supported for COMMIT and ROLLBACK, as are\nthe CHAIN and RELEASE clauses. CHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of the\ncompletion_type system variable determines the default completion\nbehavior. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nThe AND CHAIN clause causes a new transaction to begin as soon as the\ncurrent one ends, and the new transaction has the same isolation level\nas the just-terminated transaction. The RELEASE clause causes the\nserver to disconnect the current client session after terminating the\ncurrent transaction. Including the NO keyword suppresses CHAIN or\nRELEASE completion, which can be useful if the completion_type system\nvariable is set to cause chaining or release completion by default.\n\nURL: https://mariadb.com/kb/en/start-transaction/\n\n','','https://mariadb.com/kb/en/start-transaction/'),(147,'BETWEEN AND',18,'Syntax:\nexpr BETWEEN min AND max\n\nIf expr is greater than or equal to min and expr is less than or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is equivalent\nto the expression (min <= expr AND expr <= max) if all the arguments\nare of the same type. Otherwise type conversion takes place according\nto the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the three arguments.\n\nURL: https://mariadb.com/kb/en/between-and/\n\n','MariaDB> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;\n -> 1, 0\nMariaDB> SELECT 1 BETWEEN 2 AND 3;\n -> 0\nMariaDB> SELECT \'b\' BETWEEN \'a\' AND \'c\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'3\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'x-3\';\n -> 0\n','https://mariadb.com/kb/en/between-and/'),(148,'MULTIPOLYGON',24,'MultiPolygon(poly1,poly2,...)\n\nConstructs a MultiPolygon value from a set of Polygon or WKB Polygon\narguments.\n\nURL: https://mariadb.com/kb/en/multipolygon/\n\n','','https://mariadb.com/kb/en/multipolygon/'),(149,'TIME_FORMAT',31,'Syntax:\nTIME_FORMAT(time,format)\n\nThis is used like the DATE_FORMAT() function, but the format string may\ncontain format specifiers only for hours, minutes, seconds, and\nmicroseconds. Other specifiers produce a NULL value or 0.\n\nURL: https://mariadb.com/kb/en/time_format/\n\n','MariaDB> SELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n -> \'100 100 04 04 4\'\n','https://mariadb.com/kb/en/time_format/'),(150,'LEFT',37,'Syntax:\nLEFT(str,len)\n\nReturns the leftmost len characters from the string str, or NULL if any\nargument is NULL.\n\nURL: https://mariadb.com/kb/en/left/\n\n','MariaDB> SELECT LEFT(\'foobarbar\', 5);\n -> \'fooba\'\n','https://mariadb.com/kb/en/left/'),(151,'FLUSH QUERY CACHE',26,'You can defragment the query cache to better utilize its memory with\nthe FLUSH QUERY CACHE statement. The statement does not remove any\nqueries from the cache.\n\nThe RESET QUERY CACHE statement removes all query results from the\nquery cache. The FLUSH TABLES statement also does this.\n\nURL: https://mariadb.com/kb/en/flush-query-cache/\n\n','','https://mariadb.com/kb/en/flush-query-cache/'),(152,'SET DATA TYPE',22,'SET(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA set. A string object that can have zero or more values, each of which\nmust be chosen from the list of values \'value1\', \'value2\', ... A SET\ncolumn can have a maximum of 64 members. SET values are represented\ninternally as integers.\n\nURL: https://mariadb.com/kb/en/set-data-type/\n\n','','https://mariadb.com/kb/en/set-data-type/'),(153,'RAND',4,'Syntax:\nRAND(), RAND(N)\n\nReturns a random floating-point value v in the range 0 <= v < 1.0. If a\nconstant integer argument N is specified, it is used as the seed value,\nwhich produces a repeatable sequence of column values. In the following\nexample, note that the sequences of values produced by RAND(3) is the\nsame both places where it occurs.\n\nURL: https://mariadb.com/kb/en/rand/\n\n','MariaDB> CREATE TABLE t (i INT);\nQuery OK, 0 rows affected (0.42 sec)\n\nMariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.61914388706828 |\n| 2 | 0.93845168309142 |\n| 3 | 0.83482678498591 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.35877890638893 |\n| 2 | 0.28941420772058 |\n| 3 | 0.37073435016976 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.01 sec)\n','https://mariadb.com/kb/en/rand/'),(154,'RPAD',37,'Syntax:\nRPAD(str,len,padstr)\n\nReturns the string str, right-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\nURL: https://mariadb.com/kb/en/rpad/\n\n','MariaDB> SELECT RPAD(\'hi\',5,\'?\');\n -> \'hi???\'\nMariaDB> SELECT RPAD(\'hi\',1,\'?\');\n -> \'h\'\n','https://mariadb.com/kb/en/rpad/'),(155,'CREATE DATABASE',39,'Syntax:\nCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n [create_specification] ...\n\ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nCREATE DATABASE creates a database with the given name. To use this\nstatement, you need the CREATE privilege for the database. CREATE\nSCHEMA is a synonym for CREATE DATABASE.\n\nURL: https://mariadb.com/kb/en/create-database/\n\n','','https://mariadb.com/kb/en/create-database/'),(156,'DEC',22,'DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED]\n[ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nThese types are synonyms for DECIMAL. The FIXED synonym is available\nfor compatibility with other database systems.\n\nURL: https://mariadb.com/kb/en/dec-numeric-fixed/\n\n','','https://mariadb.com/kb/en/dec-numeric-fixed/'),(157,'VAR_POP',16,'Syntax:\nVAR_POP(expr)\n\nReturns the population standard variance of expr. It considers rows as\nthe whole population, not as a sample, so it has the number of rows as\nthe denominator. You can also use VARIANCE(), which is equivalent but\nis not standard SQL.\n\nVAR_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_pop/\n\n','','https://mariadb.com/kb/en/var_pop/'),(158,'ELT',37,'Syntax:\nELT(N,str1,str2,str3,...)\n\nReturns str1 if N = 1, str2 if N = 2, and so on. Returns NULL if N is\nless than 1 or greater than the number of arguments. ELT() is the\ncomplement of FIELD().\n\nURL: https://mariadb.com/kb/en/elt/.html\n\n','MariaDB> SELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'ej\'\nMariaDB> SELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'foo\'\n','https://mariadb.com/kb/en/elt/.html'),(159,'ALTER VIEW',39,'Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW and the effect is the same as\nfor CREATE OR REPLACE VIEW. See [HELP CREATE VIEW]. This statement\nrequires the CREATE VIEW and DROP privileges for the view, and some\nprivilege for each column referred to in the SELECT statement. ALTER\nVIEW is permitted only to the definer or users with the SUPER\nprivilege.\n\nURL: https://mariadb.com/kb/en/alter-view/\n\n','','https://mariadb.com/kb/en/alter-view/'),(160,'SHOW DATABASES',26,'Syntax:\nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW DATABASES lists the databases on the MySQL server host. SHOW\nSCHEMAS is a synonym for SHOW DATABASES. The LIKE clause, if present,\nindicates which database names to match. The WHERE clause can be given\nto select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou see only those databases for which you have some kind of privilege,\nunless you have the global SHOW DATABASES privilege. You can also get\nthis list using the mysqlshow command.\n\nIf the server was started with the --skip-show-database option, you\ncannot use this statement at all unless you have the SHOW DATABASES\nprivilege.\n\nURL: https://mariadb.com/kb/en/show-databases/\n\n','','https://mariadb.com/kb/en/show-databases/'),(161,'~',19,'Syntax:\n~\n\nInvert all bits.\n\nURL: https://mariadb.com/kb/en/3489/\n\n','MariaDB> SELECT 5 & ~1;\n -> 4\n','https://mariadb.com/kb/en/3489/'),(162,'TEXT',22,'TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 65,535 (216 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TEXT value is stored using a 2-byte length prefix that\nindicates the number of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest TEXT type large enough to hold\nvalues M characters long.\n\nURL: https://mariadb.com/kb/en/text/\n\n','','https://mariadb.com/kb/en/text/'),(163,'CONCAT_WS',37,'Syntax:\nCONCAT_WS(separator,str1,str2,...)\n\nCONCAT_WS() stands for Concatenate With Separator and is a special form\nof CONCAT(). The first argument is the separator for the rest of the\narguments. The separator is added between the strings to be\nconcatenated. The separator can be a string, as can the rest of the\narguments. If the separator is NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/concat_ws/\n\n','MariaDB> SELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last Name\');\n -> \'First name,Second name,Last Name\'\nMariaDB> SELECT CONCAT_WS(\',\',\'First name\',NULL,\'Last Name\');\n -> \'First name,Last Name\'\n','https://mariadb.com/kb/en/concat_ws/'),(164,'ROW_COUNT',17,'Syntax:\nROW_COUNT()\n\nBefore MySQL 5.5.5, ROW_COUNT() returns the number of rows changed,\ndeleted, or inserted by the last statement if it was an UPDATE, DELETE,\nor INSERT. For other statements, the value may not be meaningful.\n\nAs of MySQL 5.5.5, ROW_COUNT() returns a value as follows:\n\no DDL statements: 0. This applies to statements such as CREATE TABLE or\n DROP TABLE.\n\no DML statements other than SELECT: The number of affected rows. This\n applies to statements such as UPDATE, INSERT, or DELETE (as before),\n but now also to statements such as ALTER TABLE and LOAD DATA INFILE.\n\no SELECT: -1 if the statement returns a result set, or the number of\n rows \"affected\" if it does not. For example, for SELECT * FROM t1,\n ROW_COUNT() returns -1. For SELECT * FROM t1 INTO OUTFILE\n \'file_name\', ROW_COUNT() returns the number of rows written to the\n file.\n\no SIGNAL statements: 0.\n\nFor UPDATE statements, the affected-rows value by default is the number\nof rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() when connecting to mysqld, the affected-rows value\nis the number of rows \"found\"; that is, matched by the WHERE clause.\n\nFor REPLACE statements, the affected-rows value is 2 if the new row\nreplaced an old row, because in this case, one row was inserted after\nthe duplicate was deleted.\n\nFor INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows\nvalue is 1 if the row is inserted as a new row and 2 if an existing row\nis updated.\n\nThe ROW_COUNT() value is similar to the value from the\nmysql_affected_rows() C API function and the row count that the mysql\nclient displays following statement execution.\n\nURL: https://mariadb.com/kb/en/information-functions-row_count/\n\n','MariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> DELETE FROM t WHERE i IN(1,2);\nQuery OK, 2 rows affected (0.00 sec)\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/information-functions-row_count/'),(165,'ASIN',4,'Syntax:\nASIN(X)\n\nReturns the arc sine of X, that is, the value whose sine is X. Returns\nNULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/asin/\n\n','MariaDB> SELECT ASIN(0.2);\n -> 0.20135792079033\nMariaDB> SELECT ASIN(\'foo\');\n\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n1 row in set, 1 warning (0.00 sec)\n\nMariaDB> SHOW WARNINGS;\n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\' |\n+---------+------+-----------------------------------------+\n','https://mariadb.com/kb/en/asin/'),(166,'SIGN',4,'Syntax:\nSIGN(X)\n\nReturns the sign of the argument as -1, 0, or 1, depending on whether X\nis negative, zero, or positive.\n\nURL: https://mariadb.com/kb/en/sign/\n\n','MariaDB> SELECT SIGN(-32);\n -> -1\nMariaDB> SELECT SIGN(0);\n -> 0\nMariaDB> SELECT SIGN(234);\n -> 1\n','https://mariadb.com/kb/en/sign/'),(167,'SEC_TO_TIME',31,'Syntax:\nSEC_TO_TIME(seconds)\n\nReturns the seconds argument, converted to hours, minutes, and seconds,\nas a TIME value. The range of the result is constrained to that of the\nTIME data type. A warning occurs if the argument corresponds to a value\noutside that range.\n\nURL: https://mariadb.com/kb/en/sec_to_time/\n\n','MariaDB> SELECT SEC_TO_TIME(2378);\n -> \'00:39:38\'\nMariaDB> SELECT SEC_TO_TIME(2378) + 0;\n -> 3938\n','https://mariadb.com/kb/en/sec_to_time/'),(168,'FLOAT',22,'FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA small (single-precision) floating-point number. Permissible values\nare -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to\n3.402823466E+38. These are the theoretical limits, based on the IEEE\nstandard. The actual range might be slightly smaller depending on your\nhardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A single-precision floating-point\nnumber is accurate to approximately 7 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nUsing FLOAT might give you some unexpected problems because all\ncalculations in MySQL are done with double precision. See\nhttps://mariadb.com/kb/en/floating-point-accuracy/.\n\nURL: https://mariadb.com/kb/en/float/\n\n','','https://mariadb.com/kb/en/float/'),(169,'LOCATE',37,'Syntax:\nLOCATE(substr,str), LOCATE(substr,str,pos)\n\nThe first syntax returns the position of the first occurrence of\nsubstring substr in string str. The second syntax returns the position\nof the first occurrence of substring substr in string str, starting at\nposition pos. Returns 0 if substr is not in str.\n\nURL: https://mariadb.com/kb/en/locate/\n\n','MariaDB> SELECT LOCATE(\'bar\', \'foobarbar\');\n -> 4\nMariaDB> SELECT LOCATE(\'xbar\', \'foobar\');\n -> 0\nMariaDB> SELECT LOCATE(\'bar\', \'foobarbar\', 5);\n -> 7\n','https://mariadb.com/kb/en/locate/'),(170,'SHOW EVENTS',26,'Syntax:\nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement displays information about Event Manager events. It\nrequires the EVENT privilege for the database from which the events are\nto be shown.\n\nIn its simplest form, SHOW EVENTS lists all of the events in the\ncurrent schema:\n\nMariaDB> SELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n1 row in set (0.00 sec)\n\nMariaDB> SHOW EVENTS\\G\n*************************** 1. row ***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nTo see events for a specific schema, use the FROM clause. For example,\nto see events for the test schema, use the following statement:\n\nSHOW EVENTS FROM test;\n\nThe LIKE clause, if present, indicates which event names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-events/\n\n','','https://mariadb.com/kb/en/show-events/'),(171,'CHARSET',17,'Syntax:\nCHARSET(str)\n\nReturns the character set of the string argument.\n\nURL: https://mariadb.com/kb/en/charset/\n\n','MariaDB> SELECT CHARSET(\'abc\');\n -> \'latin1\'\nMariaDB> SELECT CHARSET(CONVERT(\'abc\' USING utf8));\n -> \'utf8\'\nMariaDB> SELECT CHARSET(USER());\n -> \'utf8\'\n','https://mariadb.com/kb/en/charset/'),(172,'SUBDATE',31,'Syntax:\nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, SUBDATE()\nis a synonym for DATE_SUB(). For information on the INTERVAL unit\nargument, see the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\nMariaDB> SELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\n\nThe second form enables the use of an integer value for days. In such\ncases, it is interpreted as the number of days to be subtracted from\nthe date or datetime expression expr.\n\nMariaDB> SELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n -> \'2007-12-02 12:00:00\'\n\nURL: https://mariadb.com/kb/en/subdate/\n\n','','https://mariadb.com/kb/en/subdate/'),(173,'DAYOFYEAR',31,'Syntax:\nDAYOFYEAR(date)\n\nReturns the day of the year for date, in the range 1 to 366.\n\nURL: https://mariadb.com/kb/en/dayofyear/\n\n','MariaDB> SELECT DAYOFYEAR(\'2007-02-03\');\n -> 34\n','https://mariadb.com/kb/en/dayofyear/'),(174,'%',4,'Syntax:\nN % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M. For more\ninformation, see the description for the MOD() function in\nhttps://mariadb.com/kb/en/mod/.\n\nURL: https://mariadb.com/kb/en/modulo-operator/\n\n','','https://mariadb.com/kb/en/modulo-operator/'),(175,'LONGTEXT',22,'LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\ncharacters. The effective maximum length is less if the value contains\nmulti-byte characters. The effective maximum length of LONGTEXT columns\nalso depends on the configured maximum packet size in the client/server\nprotocol and available memory. Each LONGTEXT value is stored using a\n4-byte length prefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longtext/\n\n','','https://mariadb.com/kb/en/longtext/'),(176,'KILL',26,'Syntax:\nKILL [CONNECTION | QUERY] thread_id\n\nEach connection to mysqld runs in a separate thread. You can see which\nthreads are running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement.\n\nKILL permits an optional CONNECTION or QUERY modifier:\n\no KILL CONNECTION is the same as KILL with no modifier: It terminates\n the connection associated with the given thread_id.\n\no KILL QUERY terminates the statement that the connection is currently\n executing, but leaves the connection itself intact.\n\nIf you have the PROCESS privilege, you can see all threads. If you have\nthe SUPER privilege, you can kill all threads and statements.\nOtherwise, you can see and kill only your own threads and statements.\n\nYou can also use the mysqladmin processlist and mysqladmin kill\ncommands to examine and kill threads.\n\n*Note*: You cannot use KILL with the Embedded MySQL Server library\nbecause the embedded server merely runs inside the threads of the host\napplication. It does not create any connection threads of its own.\n\nURL: https://mariadb.com/kb/en/data-manipulation-kill-connection-query/\n\n','','https://mariadb.com/kb/en/data-manipulation-kill-connection-query/'),(177,'DISJOINT',30,'Disjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially disjoint from (does\nnot intersect) g2.\n\nURL: https://mariadb.com/kb/en/disjoint/\n\n','','https://mariadb.com/kb/en/disjoint/'),(178,'ASTEXT',3,'AsText(g), AsWKT(g)\n\nConverts a value in internal geometry format to its WKT representation\nand returns the string result.\n\nURL: https://mariadb.com/kb/en/astext/\n\n','MariaDB> SET @g = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(GeomFromText(@g));\n+--------------------------+\n| AsText(GeomFromText(@g)) |\n+--------------------------+\n| LINESTRING(1 1,2 2,3 3) |\n+--------------------------+\n','https://mariadb.com/kb/en/astext/'),(179,'LPAD',37,'Syntax:\nLPAD(str,len,padstr)\n\nReturns the string str, left-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\n\nURL: https://mariadb.com/kb/en/lpad/\n\n','MariaDB> SELECT LPAD(\'hi\',4,\'??\');\n -> \'??hi\'\nMariaDB> SELECT LPAD(\'hi\',1,\'??\');\n -> \'h\'\n','https://mariadb.com/kb/en/lpad/'),(180,'DECLARE CONDITION',23,'Syntax:\nDECLARE condition_name CONDITION FOR condition_value\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n\nThe DECLARE ... CONDITION statement declares a named error condition,\nassociating a name with a condition that needs specific handling. The\nname can be referred to in a subsequent DECLARE ... HANDLER statement\n(see [HELP DECLARE HANDLER]).\n\nCondition declarations must appear before cursor or handler\ndeclarations.\n\nThe condition_value for DECLARE ... CONDITION can be a MySQL error code\n(a number) or an SQLSTATE value (a 5-character string literal). You\nshould not use MySQL error code 0 or SQLSTATE values that begin with\n\'00\', because those indicate success rather than an error condition.\nFor a list of MySQL error codes and SQLSTATE values, see\nhttps://mariadb.com/kb/en/mariadb-error-codes/.\n\nURL: https://mariadb.com/kb/en/declare-condition/\n\n','','https://mariadb.com/kb/en/declare-condition/'),(181,'OVERLAPS',30,'Overlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially overlaps g2. The term\nspatially overlaps is used if two geometries intersect and their\nintersection results in a geometry of the same dimension but not equal\nto either of the given geometries.\n\nURL: https://mariadb.com/kb/en/overlaps/\n\n','','https://mariadb.com/kb/en/overlaps/'),(182,'SET GLOBAL SQL_SLAVE_SKIP_COUNTER',8,'Syntax:\nSET GLOBAL sql_slave_skip_counter = N\n\nThis statement skips the next N events from the master. This is useful\nfor recovering from replication stops caused by a statement.\n\nThis statement is valid only when the slave threads are not running.\nOtherwise, it produces an error.\n\nURL: https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/\n\n','','https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/'),(183,'NUMGEOMETRIES',25,'NumGeometries(gc)\n\nReturns the number of geometries in the GeometryCollection value gc.\n\nURL: https://mariadb.com/kb/en/numgeometries/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT NumGeometries(GeomFromText(@gc));\n+----------------------------------+\n| NumGeometries(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n','https://mariadb.com/kb/en/numgeometries/'),(184,'MONTHNAME',31,'Syntax:\nMONTHNAME(date)\n\nReturns the full name of the month for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-locale/).\n\nURL: https://mariadb.com/kb/en/monthname/\n\n','MariaDB> SELECT MONTHNAME(\'2008-02-03\');\n -> \'February\'\n','https://mariadb.com/kb/en/monthname/'),(185,'CHANGE MASTER TO',8,'Syntax:\nCHANGE MASTER TO option [, option] ...\n\noption:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | IGNORE_SERVER_IDS = (server_id_list)\n\nserver_id_list:\n [server_id [, server_id] ... ]\n\nCHANGE MASTER TO changes the parameters that the slave server uses for\nconnecting to the master server, for reading the master binary log, and\nreading the slave relay log. It also updates the contents of the\nmaster.info and relay-log.info files. To use CHANGE MASTER TO, the\nslave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\nOptions not specified retain their value, except as indicated in the\nfollowing discussion. Thus, in most cases, there is no need to specify\noptions that do not change. For example, if the password to connect to\nyour MySQL master has changed, you just need to issue these statements\nto tell the slave about the new password:\n\nSTOP SLAVE; -- if replication was running\nCHANGE MASTER TO MASTER_PASSWORD=\'new3cret\';\nSTART SLAVE; -- if you want to restart replication\n\nMASTER_HOST, MASTER_USER, MASTER_PASSWORD, and MASTER_PORT provide\ninformation to the slave about how to connect to its master:\n\no MASTER_HOST and MASTER_PORT are the host name (or IP address) of the\n master host and its TCP/IP port.\n\n *Note*: Replication cannot use Unix socket files. You must be able to\n connect to the master MySQL server using TCP/IP.\n\n If you specify the MASTER_HOST or MASTER_PORT option, the slave\n assumes that the master server is different from before (even if the\n option value is the same as its current value.) In this case, the old\n values for the master binary log file name and position are\n considered no longer applicable, so if you do not specify\n MASTER_LOG_FILE and MASTER_LOG_POS in the statement,\n MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4 are silently appended to it.\n\n Setting MASTER_HOST=\'\' (that is, setting its value explicitly to an\n empty string) is not the same as not setting MASTER_HOST at all.\n Beginning with MySQL 5.5, trying to set MASTER_HOST to an empty\n string fails with an error. Previously, setting MASTER_HOST to an\n empty string caused START SLAVE subsequently to fail. (Bug #28796)\n\no MASTER_USER and MASTER_PASSWORD are the user name and password of the\n account to use for connecting to the master.\n\n In MySQL 5.5.20 and later, MASTER_USER cannot be made empty; setting\n MASTER_USER = \'\' or leaving it unset when setting a value for for\n MASTER_PASSWORD causes an error (Bug #13427949).\n\n Currently, a password used for a replication slave account is\n effectively limited to 32 characters in length; the password can be\n longer, but any excess characters are truncated. This is not due to\n any limit imposed by the MySQL Server generally, but rather is an\n issue specific to MySQL Replication. (For more information, see Bug\n #43439.)\n\n The text of a running CHANGE MASTER TO statement, including values\n for MASTER_USER and MASTER_PASSWORD, can be seen in the output of a\n concurrent SHOW PROCESSLIST statement.\n\nThe MASTER_SSL_xxx options provide information about using SSL for the\nconnection. They correspond to the --ssl-xxx options described in\nhttps://mariadb.com/kb/en/ssl-server-system-variables/, and\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-solutions-ssl.html.\nThese options can be changed even on slaves that are compiled without\nSSL support. They are saved to the master.info file, but are ignored if\nthe slave does not have SSL support enabled.\n\nMASTER_CONNECT_RETRY specifies how many seconds to wait between connect\nretries. The default is 60. The number of reconnection attempts is\nlimited by the --master-retry-count server option; for more\ninformation, see\nhttps://mariadb.com/kb/en/replication-and-binary-log-server-system-variables/.\n\nMASTER_HEARTBEAT_PERIOD sets the interval in seconds between\nreplication heartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is reset.\ninterval is a decimal value having the range 0 to 4294967 seconds and a\nresolution in milliseconds; the smallest nonzero value is 0.001.\nHeartbeats are sent by the master only if there are no unsent events in\nthe binary log file for a period longer than interval.\n\nSetting interval to 0 disables heartbeats altogether. The default value\nfor interval is equal to the value of slave_net_timeout divided by 2.\n\nSetting @@global.slave_net_timeout to a value less than that of the\ncurrent heartbeat interval results in a warning being issued. The\neffect of issuing RESET SLAVE on the heartbeat interval is to reset it\nto the default value.\n\nMASTER_LOG_FILE and MASTER_LOG_POS are the coordinates at which the\nslave I/O thread should begin reading from the master the next time the\nthread starts. RELAY_LOG_FILE and RELAY_LOG_POS are the coordinates at\nwhich the slave SQL thread should begin reading from the relay log the\nnext time the thread starts. If you specify either of MASTER_LOG_FILE\nor MASTER_LOG_POS, you cannot specify RELAY_LOG_FILE or RELAY_LOG_POS.\nIf neither of MASTER_LOG_FILE or MASTER_LOG_POS is specified, the slave\nuses the last coordinates of the slave SQL thread before CHANGE MASTER\nTO was issued. This ensures that there is no discontinuity in\nreplication, even if the slave SQL thread was late compared to the\nslave I/O thread, when you merely want to change, say, the password to\nuse.\n\nCHANGE MASTER TO deletes all relay log files and starts a new one,\nunless you specify RELAY_LOG_FILE or RELAY_LOG_POS. In that case, relay\nlog files are kept; the relay_log_purge global variable is set silently\nto 0.\n\nPrior to MySQL 5.5, RELAY_LOG_FILE required an absolute path. In MySQL\n5.5, the path can be relative, in which case the path is assumed to be\nrelative to the slave\'s data directory. (Bug #12190)\n\nIGNORE_SERVER_IDS was added in MySQL 5.5. This option takes a\ncomma-separated list of 0 or more server IDs. Events originating from\nthe corresponding servers are ignored, with the exception of log\nrotation and deletion events, which are still recorded in the relay\nlog.\n\nIn circular replication, the originating server normally acts as the\nterminator of its own events, so that they are not applied more than\nonce. Thus, this option is useful in circular replication when one of\nthe servers in the circle is removed. Suppose that you have a circular\nreplication setup with 4 servers, having server IDs 1, 2, 3, and 4, and\nserver 3 fails. When bridging the gap by starting replication from\nserver 2 to server 4, you can include IGNORE_SERVER_IDS = (3) in the\nCHANGE MASTER TO statement that you issue on server 4 to tell it to use\nserver 2 as its master instead of server 3. Doing so causes it to\nignore and not to propagate any statements that originated with the\nserver that is no longer in use.\n\nIf a CHANGE MASTER TO statement is issued without any IGNORE_SERVER_IDS\noption, any existing list is preserved; RESET SLAVE also has no effect\non the server ID list. To clear the list of ignored servers, it is\nnecessary to use the option with an empty list:\n\nCHANGE MASTER TO IGNORE_SERVER_IDS = ();\n\nIf IGNORE_SERVER_IDS contains the server\'s own ID and the server was\nstarted with the --replicate-same-server-id option enabled, an error\nresults.\n\nAlso beginning with MySQL 5.5, the master.info file and the output of\nSHOW SLAVE STATUS are extended to provide the list of servers that are\ncurrently ignored. For more information, see\nhttps://mariadb.com/kb/en/show-slave-status/, and\n[HELP SHOW SLAVE STATUS].\n\nBeginning with MySQL 5.5.5, invoking CHANGE MASTER TO causes the\nprevious values for MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE, and\nMASTER_LOG_POS to be written to the error log, along with other\ninformation about the slave\'s state prior to execution.\n\nCHANGE MASTER TO is useful for setting up a slave when you have the\nsnapshot of the master and have recorded the master binary log\ncoordinates corresponding to the time of the snapshot. After loading\nthe snapshot into the slave to synchronize it to the slave, you can run\nCHANGE MASTER TO MASTER_LOG_FILE=\'log_name\', MASTER_LOG_POS=log_pos on\nthe slave to specify the coordinates at which the slave should begin\nreading the master binary log.\n\nThe following example changes the master server the slave uses and\nestablishes the master binary log coordinates from which the slave\nbegins reading. This is used when you want to set up the slave to\nreplicate the master:\n\nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n\nThe next example shows an operation that is less frequently employed.\nIt is used when the slave has relay log files that you want it to\nexecute again for some reason. To do this, the master need not be\nreachable. You need only use CHANGE MASTER TO and start the SQL thread\n(START SLAVE SQL_THREAD):\n\nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n\nURL: https://mariadb.com/kb/en/change-master-to/\n\n','','https://mariadb.com/kb/en/change-master-to/'),(186,'DROP DATABASE',39,'Syntax:\nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n\nDROP DATABASE drops all tables in the database and deletes the\ndatabase. Be very careful with this statement! To use DROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is a synonym\nfor DROP DATABASE.\n\n*Important*: When a database is dropped, user privileges on the\ndatabase are not automatically dropped. See [HELP GRANT].\n\nIF EXISTS is used to prevent an error from occurring if the database\ndoes not exist.\n\nURL: https://mariadb.com/kb/en/drop-database/\n\n','','https://mariadb.com/kb/en/drop-database/'),(187,'MBREQUAL',6,'MBREqual(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are the same.\n\nURL: https://mariadb.com/kb/en/mbrequal/\n\n','','https://mariadb.com/kb/en/mbrequal/'),(188,'TIMESTAMP FUNCTION',31,'Syntax:\nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n\nWith a single argument, this function returns the date or datetime\nexpression expr as a datetime value. With two arguments, it adds the\ntime expression expr2 to the date or datetime expression expr1 and\nreturns the result as a datetime value.\n\nURL: https://mariadb.com/kb/en/timestamp-function/\n\n','MariaDB> SELECT TIMESTAMP(\'2003-12-31\');\n -> \'2003-12-31 00:00:00\'\nMariaDB> SELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'12:00:00\');\n -> \'2004-01-01 00:00:00\'\n','https://mariadb.com/kb/en/timestamp-function/'),(189,'PROCEDURE ANALYSE',33,'Syntax:\nANALYSE([max_elements[,max_memory]])\n\nANALYSE() examines the result from a query and returns an analysis of\nthe results that suggests optimal data types for each column that may\nhelp reduce table sizes. To obtain this analysis, append PROCEDURE\nANALYSE to the end of a SELECT statement:\n\nSELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])\n\nFor example:\n\nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n\nThe results show some statistics for the values returned by the query,\nand propose an optimal data type for the columns. This can be helpful\nfor checking your existing tables, or after importing new data. You may\nneed to try different settings for the arguments so that PROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n\nThe arguments are optional and are used as follows:\n\no max_elements (default 256) is the maximum number of distinct values\n that ANALYSE() notices per column. This is used by ANALYSE() to check\n whether the optimal data type should be of type ENUM; if there are\n more than max_elements distinct values, then ENUM is not a suggested\n type.\n\no max_memory (default 8192) is the maximum amount of memory that\n ANALYSE() should allocate per column while trying to find all\n distinct values.\n\nURL: https://mariadb.com/kb/en/procedure-analyse/\n\n','','https://mariadb.com/kb/en/procedure-analyse/'),(190,'HELP_VERSION',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25 (revision: 31914)\n\nThis information applies to MySQL 5.5 through 5.5.29.\n','',''),(191,'CHARACTER_LENGTH',37,'Syntax:\nCHARACTER_LENGTH(str)\n\nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n\nURL: https://mariadb.com/kb/en/character_length/\n\n','','https://mariadb.com/kb/en/character_length/'),(192,'SHOW GRANTS',26,'Syntax:\nSHOW GRANTS [FOR user]\n\nThis statement lists the GRANT statement or statements that must be\nissued to duplicate the privileges that are granted to a MySQL user\naccount. The account is named using the same format as for the GRANT\nstatement; for example, \'jeffrey\'@\'localhost\'. If you specify only the\nuser name part of the account name, a host name part of \'%\' is used.\nFor additional information about specifying account names, see [HELP\nGRANT].\n\nMariaDB> SHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION |\n+---------------------------------------------------------------------+\n\nTo list the privileges granted to the account that you are using to\nconnect to the server, you can use any of the following statements:\n\nSHOW GRANTS;\nSHOW GRANTS FOR CURRENT_USER;\nSHOW GRANTS FOR CURRENT_USER();\n\nIf SHOW GRANTS FOR CURRENT_USER (or any of the equivalent syntaxes) is\nused in DEFINER context, such as within a stored procedure that is\ndefined with SQL SECURITY DEFINER), the grants displayed are those of\nthe definer and not the invoker.\n\nURL: https://mariadb.com/kb/en/show-grants/\n\n','','https://mariadb.com/kb/en/show-grants/'),(193,'SHOW PRIVILEGES',26,'Syntax:\nSHOW PRIVILEGES\n\nSHOW PRIVILEGES shows the list of system privileges that the MySQL\nserver supports. The exact list of privileges depends on the version of\nyour server.\n\nURL: https://mariadb.com/kb/en/show-privileges/\n\n','','https://mariadb.com/kb/en/show-privileges/'),(194,'CREATE TABLESPACE',39,'Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n USE LOGFILE GROUP logfile_group\n [EXTENT_SIZE [=] extent_size]\n [INITIAL_SIZE [=] initial_size]\n [AUTOEXTEND_SIZE [=] autoextend_size]\n [MAX_SIZE [=] max_size]\n [NODEGROUP [=] nodegroup_id]\n [WAIT]\n [COMMENT [=] comment_text]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.','','https://mariadb.com/kb/en/create-tablespace/'),(195,'INSERT FUNCTION',37,'Syntax:\nINSERT(str,pos,len,newstr)\n\nReturns the string str, with the substring beginning at position pos\nand len characters long replaced by the string newstr. Returns the\noriginal string if pos is not within the length of the string. Replaces\nthe rest of the string from position pos if len is not within the\nlength of the rest of the string. Returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/insert-function/\n\n','MariaDB> SELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n -> \'QuWhattic\'\nMariaDB> SELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n -> \'Quadratic\'\nMariaDB> SELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n -> \'QuWhat\'\n','https://mariadb.com/kb/en/insert-function/'),(196,'CRC32',4,'Syntax:\nCRC32(expr)\n\nComputes a cyclic redundancy check value and returns a 32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The argument is\nexpected to be a string and (if possible) is treated as one if it is\nnot.\n\nURL: https://mariadb.com/kb/en/crc32/\n\n','MariaDB> SELECT CRC32(\'MySQL\');\n -> 3259397556\nMariaDB> SELECT CRC32(\'mysql\');\n -> 2501908538\n','https://mariadb.com/kb/en/crc32/'),(197,'XOR',15,'Syntax:\nXOR\n\nLogical XOR. Returns NULL if either operand is NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is nonzero,\notherwise 0 is returned.\n\nURL: https://mariadb.com/kb/en/xor/\n\n','MariaDB> SELECT 1 XOR 1;\n -> 0\nMariaDB> SELECT 1 XOR 0;\n -> 1\nMariaDB> SELECT 1 XOR NULL;\n -> NULL\nMariaDB> SELECT 1 XOR 1 XOR 1;\n -> 1\n','https://mariadb.com/kb/en/xor/'),(198,'STARTPOINT',13,'StartPoint(ls)\n\nReturns the Point that is the start point of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/startpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(StartPoint(GeomFromText(@ls)));\n+---------------------------------------+\n| AsText(StartPoint(GeomFromText(@ls))) |\n+---------------------------------------+\n| POINT(1 1) |\n+---------------------------------------+\n','https://mariadb.com/kb/en/startpoint/'),(199,'GRANT',10,'Syntax:\nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [, user_specification] ...\n [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]\n [WITH with_option ...]\n\nGRANT PROXY ON user_specification\n TO user_specification [, user_specification] ...\n [WITH GRANT OPTION]\n\nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n\npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nssl_option:\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n\nwith_option:\n GRANT OPTION\n | MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n\nThe GRANT statement grants privileges to MySQL user accounts. GRANT\nalso serves to specify other account characteristics such as use of\nsecure connections and limits on access to server resources. To use\nGRANT, you must have the GRANT OPTION privilege, and you must have the\nprivileges that you are granting.\n\nNormally, a database administrator first uses CREATE USER to create an\naccount, then GRANT to define its privileges and characteristics. For\nexample:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\nGRANT ALL ON db1.* TO \'jeffrey\'@\'localhost\';\nGRANT SELECT ON db2.invoice TO \'jeffrey\'@\'localhost\';\nGRANT USAGE ON *.* TO \'jeffrey\'@\'localhost\' WITH MAX_QUERIES_PER_HOUR 90;\n\nHowever, if an account named in a GRANT statement does not already\nexist, GRANT may create it under the conditions described later in the\ndiscussion of the NO_AUTO_CREATE_USER SQL mode.\n\nThe REVOKE statement is related to GRANT and enables administrators to\nremove account privileges. See [HELP REVOKE].\n\nWhen successfully executed from the mysql program, GRANT responds with\nQuery OK, 0 rows affected. To determine what privileges result from the\noperation, use SHOW GRANTS. See [HELP SHOW GRANTS].\n\nURL: https://mariadb.com/kb/en/grant/\n\n','','https://mariadb.com/kb/en/grant/'),(200,'DECLARE VARIABLE',23,'Syntax:\nDECLARE var_name [, var_name] ... type [DEFAULT value]\n\nThis statement declares local variables within stored programs. To\nprovide a default value for a variable, include a DEFAULT clause. The\nvalue can be specified as an expression; it need not be a constant. If\nthe DEFAULT clause is missing, the initial value is NULL.\n\nLocal variables are treated like stored routine parameters with respect\nto data type and overflow checking. See [HELP CREATE PROCEDURE].\n\nVariable declarations must appear before cursor or handler\ndeclarations.\n\nLocal variable names are not case sensitive. Permissible characters and\nquoting rules are the same as for other identifiers, as described in\nhttps://mariadb.com/kb/en/identifier-names/.\n\nThe scope of a local variable is the BEGIN ... END block within which\nit is declared. The variable can be referred to in blocks nested within\nthe declaring block, except those blocks that declare a variable with\nthe same name.\n\nURL: https://mariadb.com/kb/en/declare-variable/\n\n','','https://mariadb.com/kb/en/declare-variable/'),(201,'MPOLYFROMTEXT',3,'MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])\n\nConstructs a MULTIPOLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromtext/\n\n','','https://mariadb.com/kb/en/mpolyfromtext/'),(202,'MBRINTERSECTS',6,'MBRIntersects(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 intersect.\n\nURL: https://mariadb.com/kb/en/mbrintersects/\n\n','','https://mariadb.com/kb/en/mbrintersects/'),(203,'BIT_OR',16,'Syntax:\nBIT_OR(expr)\n\nReturns the bitwise OR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_or/\n\n','','https://mariadb.com/kb/en/bit_or/'),(204,'YEARWEEK',31,'Syntax:\nYEARWEEK(date), YEARWEEK(date,mode)\n\nReturns year and week for a date. The mode argument works exactly like\nthe mode argument to WEEK(). The year in the result may be different\nfrom the year in the date argument for the first and the last week of\nthe year.\n\nURL: https://mariadb.com/kb/en/yearweek/\n\n','MariaDB> SELECT YEARWEEK(\'1987-01-01\');\n -> 198653\n','https://mariadb.com/kb/en/yearweek/'),(205,'NOT BETWEEN',18,'Syntax:\nexpr NOT BETWEEN min AND max\n\nThis is the same as NOT (expr BETWEEN min AND max).\n\nURL: https://mariadb.com/kb/en/not-between/\n\n','','https://mariadb.com/kb/en/not-between/'),(206,'IS NOT',18,'Syntax:\nIS NOT boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is-not/\n\n','MariaDB> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not/'),(207,'LOG10',4,'Syntax:\nLOG10(X)\n\nReturns the base-10 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log10/\n\n','MariaDB> SELECT LOG10(2);\n -> 0.30102999566398\nMariaDB> SELECT LOG10(100);\n -> 2\nMariaDB> SELECT LOG10(-100);\n -> NULL\n','https://mariadb.com/kb/en/log10/'),(208,'SQRT',4,'Syntax:\nSQRT(X)\n\nReturns the square root of a nonnegative number X.\n\nURL: https://mariadb.com/kb/en/sqrt/\n\n','MariaDB> SELECT SQRT(4);\n -> 2\nMariaDB> SELECT SQRT(20);\n -> 4.4721359549996\nMariaDB> SELECT SQRT(-16);\n -> NULL\n','https://mariadb.com/kb/en/sqrt/'),(209,'DECIMAL',22,'DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nA packed \"exact\" fixed-point number. M is the total number of digits\n(the precision) and D is the number of digits after the decimal point\n(the scale). The decimal point and (for negative numbers) the \"-\" sign\nare not counted in M. If D is 0, values have no decimal point or\nfractional part. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30. If D is omitted,\nthe default is 0. If M is omitted, the default is 10.\n\nUNSIGNED, if specified, disallows negative values.\n\nAll basic calculations (+, -, *, /) with DECIMAL columns are done with\na precision of 65 digits.\n\nURL: https://mariadb.com/kb/en/decimal/\n\n','','https://mariadb.com/kb/en/decimal/'),(210,'CREATE INDEX',39,'Syntax:\nCREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [index_option] ...\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nCREATE INDEX is mapped to an ALTER TABLE statement to create indexes.\nSee [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY\nKEY; use ALTER TABLE instead. For more information about indexes, see\nhttps://mariadb.com/kb/en/optimization-and-indexes/.\n\nURL: https://mariadb.com/kb/en/create-index/\n\n','','https://mariadb.com/kb/en/create-index/'),(211,'CREATE FUNCTION',39,'The CREATE FUNCTION statement is used to create stored functions and\nuser-defined functions (UDFs):\n\no For information about creating stored functions, see [HELP CREATE\n PROCEDURE].\n\no For information about creating user-defined functions, see [HELP\n CREATE FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/create-function/\n\n','','https://mariadb.com/kb/en/create-function/'),(212,'ALTER DATABASE',39,'Syntax:\nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n\nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nALTER DATABASE enables you to change the overall characteristics of a\ndatabase. These characteristics are stored in the db.opt file in the\ndatabase directory. To use ALTER DATABASE, you need the ALTER privilege\non the database. ALTER SCHEMA is a synonym for ALTER DATABASE.\n\nThe database name can be omitted from the first syntax, in which case\nthe statement applies to the default database.\n\nNational Language Characteristics\n\nThe CHARACTER SET clause changes the default database character set.\nThe COLLATE clause changes the default database collation.\nhttps://mariadb.com/kb/en/data-types-character-sets-and-collations/, discusses\ncharacter set and collation names.\n\nYou can see what character sets and collations are available using,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION statements. See\n[HELP SHOW CHARACTER SET], and [HELP SHOW COLLATION], for more\ninformation.\n\nIf you change the default character set or collation for a database,\nstored routines that use the database defaults must be dropped and\nrecreated so that they use the new defaults. (In a stored routine,\nvariables with character data types use the database defaults if the\ncharacter set or collation are not specified explicitly. See [HELP\nCREATE PROCEDURE].)\n\nUpgrading from Versions Older than MySQL 5.1\n\nThe syntax that includes the UPGRADE DATA DIRECTORY NAME clause updates\nthe name of the directory associated with the database to use the\nencoding implemented in MySQL 5.1 for mapping database names to\ndatabase directory names (see\nhttps://mariadb.com/kb/en/identifier-to-file-name-mapping/). This\nclause is for use under these conditions:\n\no It is intended when upgrading MySQL to 5.1 or later from older\n versions.\n\no It is intended to update a database directory name to the current\n encoding format if the name contains special characters that need\n encoding.\n\no The statement is used by mysqlcheck (as invoked by mysql_upgrade).\n\nFor example, if a database in MySQL 5.0 has the name a-b-c, the name\ncontains instances of the - (dash) character. In MySQL 5.0, the\ndatabase directory is also named a-b-c, which is not necessarily safe\nfor all file systems. In MySQL 5.1 and later, the same database name is\nencoded as a@002db@002dc to produce a file system-neutral directory\nname.\n\nWhen a MySQL installation is upgraded to MySQL 5.1 or later from an\nolder version,the server displays a name such as a-b-c (which is in the\nold format) as #mysql50#a-b-c, and you must refer to the name using the\n#mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME in this case to\nexplicitly tell the server to re-encode the database directory name to\nthe current encoding format:\n\nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n\nAfter executing this statement, you can refer to the database as a-b-c\nwithout the special #mysql50# prefix.\n\nURL: https://mariadb.com/kb/en/alter-database/\n\n','','https://mariadb.com/kb/en/alter-database/'),(213,'GEOMETRYN',25,'GeometryN(gc,N)\n\nReturns the N-th geometry in the GeometryCollection value gc.\nGeometries are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/geometryn/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n','https://mariadb.com/kb/en/geometryn/'),(214,'<<',19,'Syntax:\n<<\n\nShifts a longlong (BIGINT) number to the left.\n\nURL: https://mariadb.com/kb/en/shift-left/\n\n','MariaDB> SELECT 1 << 2;\n -> 4\n','https://mariadb.com/kb/en/shift-left/'),(215,'SHOW TABLE STATUS',26,'Syntax:\nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLE STATUS works likes SHOW TABLES, but provides a lot of\ninformation about each non-TEMPORARY table. You can also get this list\nusing the mysqlshow --status db_name command. The LIKE clause, if\npresent, indicates which table names to match. The WHERE clause can be\ngiven to select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-table-status/\n\n','','https://mariadb.com/kb/en/show-table-status/'),(216,'MD5',12,'Syntax:\nMD5(str)\n\nCalculates an MD5 128-bit checksum for the string. The value is\nreturned as a string of 32 hex digits, or NULL if the argument was\nNULL. The return value can, for example, be used as a hash key. See the\nnotes at the beginning of this section about storing hash values\nefficiently.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/md5/\n\n','MariaDB> SELECT MD5(\'testing\');\n -> \'ae2b1fca515949e5d54fb22b8ed95575\'\n','https://mariadb.com/kb/en/md5/'),(217,'<',18,'Syntax:\n<\n\nLess than:\n\nURL: https://mariadb.com/kb/en/less-than/\n\n','MariaDB> SELECT 2 < 2;\n -> 0\n','https://mariadb.com/kb/en/less-than/'),(218,'UNIX_TIMESTAMP',31,'Syntax:\nUNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)\n\nIf called with no argument, returns a Unix timestamp (seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If UNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the argument as\nseconds since \'1970-01-01 00:00:00\' UTC. date may be a DATE string, a\nDATETIME string, a TIMESTAMP, or a number in the format YYMMDD or\nYYYYMMDD. The server interprets date as a value in the current time\nzone and converts it to an internal value in UTC. Clients can set their\ntime zone as described in\nhttps://mariadb.com/kb/en/time-zones/.\n\nURL: https://mariadb.com/kb/en/unix_timestamp/\n\n','MariaDB> SELECT UNIX_TIMESTAMP();\n -> 1196440210\nMariaDB> SELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n -> 1196440219\n','https://mariadb.com/kb/en/unix_timestamp/'),(219,'DAYOFMONTH',31,'Syntax:\nDAYOFMONTH(date)\n\nReturns the day of the month for date, in the range 1 to 31, or 0 for\ndates such as \'0000-00-00\' or \'2008-00-00\' that have a zero day part.\n\nURL: https://mariadb.com/kb/en/dayofmonth/\n\n','MariaDB> SELECT DAYOFMONTH(\'2007-02-03\');\n -> 3\n','https://mariadb.com/kb/en/dayofmonth/'),(220,'ASCII',37,'Syntax:\nASCII(str)\n\nReturns the numeric value of the leftmost character of the string str.\nReturns 0 if str is the empty string. Returns NULL if str is NULL.\nASCII() works for 8-bit characters.\n\nURL: https://mariadb.com/kb/en/ascii/\n\n','MariaDB> SELECT ASCII(\'2\');\n -> 50\nMariaDB> SELECT ASCII(2);\n -> 50\nMariaDB> SELECT ASCII(\'dx\');\n -> 100\n','https://mariadb.com/kb/en/ascii/'),(221,'DIV',4,'Syntax:\nDIV\n\nInteger division. Similar to FLOOR(), but is safe with BIGINT values.\n\nAs of MySQL 5.5.3, if either operand has a noninteger type, the\noperands are converted to DECIMAL and divided using DECIMAL arithmetic\nbefore converting the result to BIGINT. If the result exceeds BIGINT\nrange, an error occurs. Before MySQL 5.5.3, incorrect results may occur\nfor noninteger operands that exceed BIGINT range.\n\nURL: https://mariadb.com/kb/en/div/\n\n','MariaDB> SELECT 5 DIV 2;\n -> 2\n','https://mariadb.com/kb/en/div/'),(222,'RENAME USER',10,'Syntax:\nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n\nThe RENAME USER statement renames existing MySQL accounts. To use it,\nyou must have the global CREATE USER privilege or the UPDATE privilege\nfor the mysql database. An error occurs if any old account does not\nexist or any new account exists. Each account name uses the format\ndescribed in https://mariadb.com/kb/en/create-user/#account-names.\nFor example:\n\nRENAME USER \'jeffrey\'@\'localhost\' TO \'jeff\'@\'127.0.0.1\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nRENAME USER causes the privileges held by the old user to be those held\nby the new user. However, RENAME USER does not automatically drop or\ninvalidate databases or objects within them that the old user created.\nThis includes stored programs or views for which the DEFINER attribute\nnames the old user. Attempts to access such objects may produce an\nerror if they execute in definer security context. (For information\nabout security context, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.)\n\nThe privilege changes take effect as indicated in\nhttp://dev.mysql.com/doc/refman/5.5/en/privilege-changes.html.\n\nURL: https://mariadb.com/kb/en/rename-user/\n\n','','https://mariadb.com/kb/en/rename-user/'),(223,'SHOW SLAVE STATUS',26,'Syntax:\nSHOW SLAVE STATUS\n\nThis statement provides status information on essential parameters of\nthe slave threads. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nIf you issue this statement using the mysql client, you can use a \\G\nstatement terminator rather than a semicolon to obtain a more readable\nvertical layout:\n\nMariaDB> SHOW SLAVE STATUS\\G\n*************************** 1. row ***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: localhost\n Master_User: root\n Master_Port: 3306\n Connect_Retry: 3\n Master_Log_File: gbichot-bin.005\n Read_Master_Log_Pos: 79\n Relay_Log_File: gbichot-relay-bin.005\n Relay_Log_Pos: 548\n Relay_Master_Log_File: gbichot-bin.005\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB:\n Replicate_Ignore_DB:\n Replicate_Do_Table:\n Replicate_Ignore_Table:\n Replicate_Wild_Do_Table:\n Replicate_Wild_Ignore_Table:\n Last_Errno: 0\n Last_Error:\n Skip_Counter: 0\n Exec_Master_Log_Pos: 79\n Relay_Log_Space: 552\n Until_Condition: None\n Until_Log_File:\n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File:\n Master_SSL_CA_Path:\n Master_SSL_Cert:\n Master_SSL_Cipher:\n Master_SSL_Key:\n Seconds_Behind_Master: 8\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error:\n Last_SQL_Errno: 0\n Last_SQL_Error:\n Replicate_Ignore_Server_Ids: 0\n Master_Server_Id: 1\n\nURL: https://mariadb.com/kb/en/show-slave-status/\n\n','','https://mariadb.com/kb/en/show-slave-status/'),(224,'GEOMETRY',34,'MySQL provides a standard way of creating spatial columns for geometry\ntypes, for example, with CREATE TABLE or ALTER TABLE. Currently,\nspatial columns are supported for MyISAM, Aria, InnoDB and ARCHIVE\ntables. See also the annotations about spatial indexes under [HELP\nSPATIAL].\n\nURL: https://mariadb.com/kb/en/gis-functionality/\n\n','CREATE TABLE geom (g GEOMETRY);\n','https://mariadb.com/kb/en/gis-functionality/'),(225,'NUMPOINTS',13,'NumPoints(ls)\n\nReturns the number of Point objects in the LineString value ls.\n\nURL: https://mariadb.com/kb/en/numpoints/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n','https://mariadb.com/kb/en/numpoints/'),(226,'ALTER LOGFILE GROUP',39,'Syntax:\nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n','','https://mariadb.com/kb/en/alter-logfile-group/'),(227,'&',19,'Syntax:\n&\n\nBitwise AND:\n\nURL: https://mariadb.com/kb/en/bitwise_and/\n\n','MariaDB> SELECT 29 & 15;\n -> 13\n','https://mariadb.com/kb/en/bitwise_and/'),(228,'LOCALTIMESTAMP',31,'Syntax:\nLOCALTIMESTAMP, LOCALTIMESTAMP()\n\nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtimestamp/\n\n','','https://mariadb.com/kb/en/localtimestamp/'),(229,'ASSIGN-EQUAL',15,'Syntax:\n=\n\nThis operator is used to perform value assignments in two cases,\ndescribed in the next two paragraphs.\n\nWithin a SET statement, = is treated as an assignment operator that\ncauses the user variable on the left hand side of the operator to take\non the value to its right. (In other words, when used in a SET\nstatement, = is treated identically to :=.) The value on the right hand\nside may be a literal value, another variable storing a value, or any\nlegal expression that yields a scalar value, including the result of a\nquery (provided that this value is a scalar value). You can perform\nmultiple assignments in the same SET statement.\n\nIn the SET clause of an UPDATE statement, = also acts as an assignment\noperator; in this case, however, it causes the column named on the left\nhand side of the operator to assume the value given to the right,\nprovided any WHERE conditions that are part of the UPDATE are met. You\ncan make multiple assignments in the same SET clause of an UPDATE\nstatement.\n\nIn any other context, = is treated as a comparison operator.\n\nURL: https://mariadb.com/kb/en/assignment-operators-assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n','https://mariadb.com/kb/en/assignment-operators-assignment-operator/'),(230,'CONVERT',37,'Syntax:\nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n\nThe CONVERT() and CAST() functions take an expression of any type and\nproduce a result value of a specified type.\n\nThe type for the result can be one of the following values:\n\no BINARY[(N)]\n\no CHAR[(N)]\n\no DATE\n\no DATETIME\n\no DECIMAL[(M[,D])]\n\no SIGNED [INTEGER]\n\no TIME\n\no UNSIGNED [INTEGER]\n\nBINARY produces a string with the BINARY data type. See\nhttps://mariadb.com/kb/en/binary/ for a\ndescription of how this affects comparisons. If the optional length N\nis given, BINARY(N) causes the cast to use no more than N bytes of the\nargument. Values shorter than N bytes are padded with 0x00 bytes to a\nlength of N.\n\nCHAR(N) causes the cast to use no more than N characters of the\nargument.\n\nCAST() and CONVERT(... USING ...) are standard SQL syntax. The\nnon-USING form of CONVERT() is ODBC syntax.\n\nCONVERT() with USING is used to convert data between different\ncharacter sets. In MySQL, transcoding names are the same as the\ncorresponding character set names. For example, this statement converts\nthe string \'abc\' in the default character set to the corresponding\nstring in the utf8 character set:\n\nSELECT CONVERT(\'abc\' USING utf8);\n\nURL: https://mariadb.com/kb/en/convert/\n\n','SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);\n','https://mariadb.com/kb/en/convert/'),(231,'ADDDATE',31,'Syntax:\nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, ADDDATE()\nis a synonym for DATE_ADD(). The related function SUBDATE() is a\nsynonym for DATE_SUB(). For information on the INTERVAL unit argument,\nsee the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\nMariaDB> SELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\n\nWhen invoked with the days form of the second argument, MySQL treats it\nas an integer number of days to be added to expr.\n\nURL: https://mariadb.com/kb/en/adddate/\n\n','MariaDB> SELECT ADDDATE(\'2008-01-02\', 31);\n -> \'2008-02-02\'\n','https://mariadb.com/kb/en/adddate/'),(232,'REPEAT LOOP',23,'Syntax:\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\nThe statement list within a REPEAT statement is repeated until the\nsearch_condition expression is true. Thus, a REPEAT always enters the\nloop at least once. statement_list consists of one or more statements,\neach terminated by a semicolon (;) statement delimiter.\n\nA REPEAT statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/repeat-loop/\n\n','MariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE dorepeat(p1 INT)\n -> BEGIN\n -> SET @x = 0;\n -> REPEAT\n -> SET @x = @x + 1;\n -> UNTIL @x > p1 END REPEAT;\n -> END\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL dorepeat(1000)//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/repeat-loop/'),(233,'ALTER FUNCTION',39,'Syntax:\nALTER FUNCTION func_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nfunction. More than one change may be specified in an ALTER FUNCTION\nstatement. However, you cannot change the parameters or body of a\nstored function using this statement; to make such changes, you must\ndrop and re-create the function using DROP FUNCTION and CREATE\nFUNCTION.\n\nYou must have the ALTER ROUTINE privilege for the function. (That\nprivilege is granted automatically to the function creator.) If binary\nlogging is enabled, the ALTER FUNCTION statement might also require the\nSUPER privilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nURL: https://mariadb.com/kb/en/alter-function/\n\n','','https://mariadb.com/kb/en/alter-function/'),(234,'SMALLINT',22,'SMALLINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA small integer. The signed range is -32768 to 32767. The unsigned\nrange is 0 to 65535.\n\nURL: https://mariadb.com/kb/en/smallint/\n\n','','https://mariadb.com/kb/en/smallint/'),(235,'DOUBLE PRECISION',22,'DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED]\n[ZEROFILL]\n\nThese types are synonyms for DOUBLE. Exception: If the REAL_AS_FLOAT\nSQL mode is enabled, REAL is a synonym for FLOAT rather than DOUBLE.\n\nURL: https://mariadb.com/kb/en/double-precision/\n\n','','https://mariadb.com/kb/en/double-precision/'),(236,'ORD',37,'Syntax:\nORD(str)\n\nIf the leftmost character of the string str is a multi-byte character,\nreturns the code for that character, calculated from the numeric values\nof its constituent bytes using this formula:\n\n (1st byte code)\n+ (2nd byte code * 256)\n+ (3rd byte code * 2562) ...\n\nIf the leftmost character is not a multi-byte character, ORD() returns\nthe same value as the ASCII() function.\n\nURL: https://mariadb.com/kb/en/ord/\n\n','MariaDB> SELECT ORD(\'2\');\n -> 50\n','https://mariadb.com/kb/en/ord/'),(237,'DEALLOCATE PREPARE',8,'Syntax:\n{DEALLOCATE | DROP} PREPARE stmt_name\n\nTo deallocate a prepared statement produced with PREPARE, use a\nDEALLOCATE PREPARE statement that refers to the prepared statement\nname. Attempting to execute a prepared statement after deallocating it\nresults in an error.\n\nURL: https://mariadb.com/kb/en/deallocate-drop-prepared-statement/\n\n','','https://mariadb.com/kb/en/deallocate-drop-prepared-statement/'),(238,'ENVELOPE',36,'Envelope(g)\n\nReturns the Minimum Bounding Rectangle (MBR) for the geometry value g.\nThe result is returned as a Polygon value.\n\nThe polygon is defined by the corner points of the bounding box:\n\nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n\nURL: https://mariadb.com/kb/en/envelope/\n\n','MariaDB> SELECT AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\')));\n+-------------------------------------------------------+\n| AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\'))) |\n+-------------------------------------------------------+\n| POLYGON((1 1,2 1,2 2,1 2,1 1)) |\n+-------------------------------------------------------+\n','https://mariadb.com/kb/en/envelope/'),(239,'IS_FREE_LOCK',14,'Syntax:\nIS_FREE_LOCK(str)\n\nChecks whether the lock named str is free to use (that is, not locked).\nReturns 1 if the lock is free (no one is using the lock), 0 if the lock\nis in use, and NULL if an error occurs (such as an incorrect argument).\n\nURL: https://mariadb.com/kb/en/is_free_lock/\n\n','','https://mariadb.com/kb/en/is_free_lock/'),(240,'TOUCHES',30,'Touches(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially touches g2. Two\ngeometries spatially touch if the interiors of the geometries do not\nintersect, but the boundary of one of the geometries intersects either\nthe boundary or the interior of the other.\n\nURL: https://mariadb.com/kb/en/touches/\n\n','','https://mariadb.com/kb/en/touches/'),(241,'INET_ATON',14,'Syntax:\nINET_ATON(expr)\n\nGiven the dotted-quad representation of an IPv4 network address as a\nstring, returns an integer that represents the numeric value of the\naddress in network byte order (big endian). INET_ATON() returns NULL if\nit does not understand its argument.\n\nURL: https://mariadb.com/kb/en/inet_aton/\n\n','MariaDB> SELECT INET_ATON(\'10.0.5.9\');\n -> 167773449\n','https://mariadb.com/kb/en/inet_aton/'),(242,'UNCOMPRESS',12,'Syntax:\nUNCOMPRESS(string_to_uncompress)\n\nUncompresses a string compressed by the COMPRESS() function. If the\nargument is not a compressed value, the result is NULL. This function\nrequires MySQL to have been compiled with a compression library such as\nzlib. Otherwise, the return value is always NULL.\n\nURL: https://mariadb.com/kb/en/uncompress/\n\n','MariaDB> SELECT UNCOMPRESS(COMPRESS(\'any string\'));\n -> \'any string\'\nMariaDB> SELECT UNCOMPRESS(\'any string\');\n -> NULL\n','https://mariadb.com/kb/en/uncompress/'),(243,'AUTO_INCREMENT',22,'The AUTO_INCREMENT attribute can be used to generate a unique identity\nfor new rows:\n\nURL: https://mariadb.com/kb/en/auto_increment/\n\n','CREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n);\n\nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'lax\'),(\'whale\'),(\'ostrich\');\n\nSELECT * FROM animals;\n','https://mariadb.com/kb/en/auto_increment/'),(244,'ISSIMPLE',36,'IsSimple(g)\n\nCurrently, this function is a placeholder and should not be used. If\nimplemented, its behavior will be as described in the next paragraph.\n\nReturns 1 if the geometry value g has no anomalous geometric points,\nsuch as self-intersection or self-tangency. IsSimple() returns 0 if the\nargument is not simple, and -1 if it is NULL.\n\nThe description of each instantiable geometric class given earlier in\nthe chapter includes the specific conditions that cause an instance of\nthat class to be classified as not simple. (See [HELP Geometry\nhierarchy].)\n\nURL: https://mariadb.com/kb/en/issimple/\n\n','','https://mariadb.com/kb/en/issimple/'),(245,'- BINARY',4,'Syntax:\n-\n\nSubtraction:\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT 3-5;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(246,'GEOMCOLLFROMTEXT',3,'GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromtext/\n\n','','https://mariadb.com/kb/en/geomcollfromtext/'),(247,'WKT DEFINITION',3,'The Well-Known Text (WKT) representation of Geometry is designed to\nexchange geometry data in ASCII form. For a Backus-Naur grammar that\nspecifies the formal production rules for writing WKT values, see the\nOpenGIS specification document referenced in\nhttps://mariadb.com/kb/en/gis-resources/.\n\nURL: https://mariadb.com/kb/en/wkt-definition/\n\n','','https://mariadb.com/kb/en/wkt-definition/'),(248,'CURRENT_TIME',31,'Syntax:\nCURRENT_TIME, CURRENT_TIME()\n\nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n\nURL: https://mariadb.com/kb/en/current_time/\n\n','','https://mariadb.com/kb/en/current_time/'),(249,'REVOKE',10,'Syntax:\nREVOKE\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n\nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n\nREVOKE PROXY ON user\n FROM user [, user] ...\n\nThe REVOKE statement enables system administrators to revoke privileges\nfrom MySQL accounts. Each account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nREVOKE INSERT ON *.* FROM \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nFor details on the levels at which privileges exist, the permissible\npriv_type and priv_level values, and the syntax for specifying users\nand passwords, see [HELP GRANT]\n\nTo use the first REVOKE syntax, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are revoking.\n\nTo revoke all privileges, use the second syntax, which drops all\nglobal, database, table, column, and routine privileges for the named\nuser or users:\n\nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n\nTo use this REVOKE syntax, you must have the global CREATE USER\nprivilege or the UPDATE privilege for the mysql database.\n\nURL: https://mariadb.com/kb/en/revoke/\n\n','','https://mariadb.com/kb/en/revoke/'),(250,'LAST_INSERT_ID',17,'Syntax:\nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n\nLAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value\nrepresenting the first automatically generated value successfully\ninserted for an AUTO_INCREMENT column as a result of the most recently\nexecuted INSERT statement. The value of LAST_INSERT_ID() remains\nunchanged if no rows are successfully inserted.\n\nFor example, after inserting a row that generates an AUTO_INCREMENT\nvalue, you can get the value like this:\n\nMariaDB> SELECT LAST_INSERT_ID();\n -> 195\n\nThe currently executing statement does not affect the value of\nLAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table with its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain\nstable in the second statement; its value for the second and later rows\nis not affected by the earlier row insertions. (However, if you mix\nreferences to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is\nundefined.)\n\nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if the\nstatement is rolled back due to an error, the value of LAST_INSERT_ID()\nis left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID()\nis not restored to that before the transaction; it remains as it was at\nthe point of the ROLLBACK.\n\nWithin the body of a stored routine (procedure or function) or a\ntrigger, the value of LAST_INSERT_ID() changes the same way as for\nstatements executed outside the body of these kinds of objects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements depends on the\nkind of routine:\n\no If a stored procedure executes statements that change the value of\n LAST_INSERT_ID(), the changed value is seen by statements that follow\n the procedure call.\n\no For stored functions and triggers that change the value, the value is\n restored when the function or trigger ends, so following statements\n will not see a changed value.\n\nURL: https://mariadb.com/kb/en/last_insert_id/\n\n','','https://mariadb.com/kb/en/last_insert_id/'),(251,'LAST_DAY',31,'Syntax:\nLAST_DAY(date)\n\nTakes a date or datetime value and returns the corresponding value for\nthe last day of the month. Returns NULL if the argument is invalid.\n\nURL: https://mariadb.com/kb/en/last_day/\n\n','MariaDB> SELECT LAST_DAY(\'2003-02-05\');\n -> \'2003-02-28\'\nMariaDB> SELECT LAST_DAY(\'2004-02-05\');\n -> \'2004-02-29\'\nMariaDB> SELECT LAST_DAY(\'2004-01-01 01:01:01\');\n -> \'2004-01-31\'\nMariaDB> SELECT LAST_DAY(\'2003-03-32\');\n -> NULL\n','https://mariadb.com/kb/en/last_day/'),(252,'MEDIUMINT',22,'MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA medium-sized integer. The signed range is -8388608 to 8388607. The\nunsigned range is 0 to 16777215.\n\nURL: https://mariadb.com/kb/en/mediumint/\n\n','','https://mariadb.com/kb/en/mediumint/'),(253,'FLOOR',4,'Syntax:\nFLOOR(X)\n\nReturns the largest integer value not greater than X.\n\nURL: https://mariadb.com/kb/en/floor/\n\n','MariaDB> SELECT FLOOR(1.23);\n -> 1\nMariaDB> SELECT FLOOR(-1.23);\n -> -2\n','https://mariadb.com/kb/en/floor/'),(254,'RTRIM',37,'Syntax:\nRTRIM(str)\n\nReturns the string str with trailing space characters removed.\n\nURL: https://mariadb.com/kb/en/rtrim/\n\n','MariaDB> SELECT RTRIM(\'barbar \');\n -> \'barbar\'\n','https://mariadb.com/kb/en/rtrim/'),(255,'EXPLAIN',28,'Syntax:\nEXPLAIN [explain_type] SELECT select_options\n\nexplain_type:\n EXTENDED\n | PARTITIONS\n\nOr:\n\nEXPLAIN tbl_name\n\nThe EXPLAIN statement can be used either as a way to obtain information\nabout how MySQL executes a statement, or as a synonym for DESCRIBE:\n\no When you precede a SELECT statement with the keyword EXPLAIN, MySQL\n displays information from the optimizer about the query execution\n plan. That is, MySQL explains how it would process the statement,\n including information about how tables are joined and in which order.\n EXPLAIN EXTENDED can be used to obtain additional information.\n\n For information about using EXPLAIN and EXPLAIN EXTENDED to obtain\n query execution plan information, see\n https://mariadb.com/kb/en/explain/.\n\no EXPLAIN PARTITIONS is useful only when examining queries involving\n partitioned tables. For details, see\n http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.\n\no EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS\n FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see\n [HELP DESCRIBE], and [HELP SHOW COLUMNS].\n\nURL: https://mariadb.com/kb/en/explain/\n\n','','https://mariadb.com/kb/en/explain/'),(256,'DEGREES',4,'Syntax:\nDEGREES(X)\n\nReturns the argument X, converted from radians to degrees.\n\nURL: https://mariadb.com/kb/en/degrees/\n\n','MariaDB> SELECT DEGREES(PI());\n -> 180\nMariaDB> SELECT DEGREES(PI() / 2);\n -> 90\n','https://mariadb.com/kb/en/degrees/'),(257,'VARCHAR',22,'[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA variable-length string. M represents the maximum column length in\ncharacters. The range of M is 0 to 65,535. The effective maximum length\nof a VARCHAR is subject to the maximum row size (65,535 bytes, which is\nshared among all columns) and the character set used. For example, utf8\ncharacters can require up to three bytes per character, so a VARCHAR\ncolumn that uses the utf8 character set can be declared to be a maximum\nof 21,844 characters. See\nhttp://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html.\n\nMySQL stores VARCHAR values as a 1-byte or 2-byte length prefix plus\ndata. The length prefix indicates the number of bytes in the value. A\nVARCHAR column uses one length byte if values require no more than 255\nbytes, two length bytes if values may require more than 255 bytes.\n\n*Note*: MySQL 5.5 follows the standard SQL specification, and does not\nremove trailing spaces from VARCHAR values.\n\nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR is the\nstandard SQL way to define that a VARCHAR column should use some\npredefined character set. MySQL 4.1 and up uses utf8 as this predefined\ncharacter set.\nhttps://mariadb.com/kb/en/varchar/. NVARCHAR\nis shorthand for NATIONAL VARCHAR.\n\nURL: https://mariadb.com/kb/en/varchar/\n\n','','https://mariadb.com/kb/en/varchar/'),(258,'UNHEX',37,'Syntax:\n\nUNHEX(str)\n\nFor a string argument str, UNHEX(str) performs the inverse operation of\nHEX(str). That is, it interprets each pair of characters in the\nargument as a hexadecimal number and converts it to the character\nrepresented by the number. The return value is a binary string.\n\nURL: https://mariadb.com/kb/en/unhex/\n\n','MariaDB> SELECT UNHEX(\'4D7953514C\');\n -> \'MySQL\'\nMariaDB> SELECT 0x4D7953514C;\n -> \'MySQL\'\nMariaDB> SELECT UNHEX(HEX(\'string\'));\n -> \'string\'\nMariaDB> SELECT HEX(UNHEX(\'1267\'));\n -> \'1267\'\n','https://mariadb.com/kb/en/unhex/'),(259,'- UNARY',4,'Syntax:\n-\n\nUnary minus. This operator changes the sign of the operand.\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT - 2;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(260,'STD',16,'Syntax:\nSTD(expr)\n\nReturns the population standard deviation of expr. This is an extension\nto standard SQL. The standard SQL function STDDEV_POP() can be used\ninstead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/std/\n\n','','https://mariadb.com/kb/en/std/'),(261,'COS',4,'Syntax:\nCOS(X)\n\nReturns the cosine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/cos/\n\n','MariaDB> SELECT COS(PI());\n -> -1\n','https://mariadb.com/kb/en/cos/'),(262,'DATE FUNCTION',31,'Syntax:\nDATE(expr)\n\nExtracts the date part of the date or datetime expression expr.\n\nURL: https://mariadb.com/kb/en/date-function/\n\n','MariaDB> SELECT DATE(\'2003-12-31 01:02:03\');\n -> \'2003-12-31\'\n','https://mariadb.com/kb/en/date-function/'),(263,'DROP TRIGGER',39,'Syntax:\nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n\nThis statement drops a trigger. The schema (database) name is optional.\nIf the schema is omitted, the trigger is dropped from the default\nschema. DROP TRIGGER requires the TRIGGER privilege for the table\nassociated with the trigger.\n\nUse IF EXISTS to prevent an error from occurring for a trigger that\ndoes not exist. A NOTE is generated for a nonexistent trigger when\nusing IF EXISTS. See [HELP SHOW WARNINGS].\n\nTriggers for a table are also dropped if you drop the table.\n\nURL: https://mariadb.com/kb/en/drop-trigger/\n\n','','https://mariadb.com/kb/en/drop-trigger/'),(264,'RESET MASTER',8,'Syntax:\nRESET MASTER\n\nDeletes all binary log files listed in the index file, resets the\nbinary log index file to be empty, and creates a new binary log file.\nThis statement is intended to be used only when the master is started\nfor the first time.\n\nURL: https://mariadb.com/kb/en/reset-master/\n\n','','https://mariadb.com/kb/en/reset-master/'),(265,'TAN',4,'Syntax:\nTAN(X)\n\nReturns the tangent of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/tan/\n\n','MariaDB> SELECT TAN(PI());\n -> -1.2246063538224e-16\nMariaDB> SELECT TAN(PI()+1);\n -> 1.5574077246549\n','https://mariadb.com/kb/en/tan/'),(266,'PI',4,'Syntax:\nPI()\n\nReturns the value of π (pi). The default number of decimal places\ndisplayed is seven, but MySQL uses the full double-precision value\ninternally.\n\nURL: https://mariadb.com/kb/en/pi/\n\n','MariaDB> SELECT PI();\n -> 3.141593\nMariaDB> SELECT PI()+0.000000000000000000;\n -> 3.141592653589793116\n','https://mariadb.com/kb/en/pi/'),(267,'WEEKOFYEAR',31,'Syntax:\nWEEKOFYEAR(date)\n\nReturns the calendar week of the date as a number in the range from 1\nto 53. WEEKOFYEAR() is a compatibility function that is equivalent to\nWEEK(date,3).\n\nURL: https://mariadb.com/kb/en/weekofyear/\n\n','MariaDB> SELECT WEEKOFYEAR(\'2008-02-20\');\n -> 8\n','https://mariadb.com/kb/en/weekofyear/'),(268,'/',4,'Syntax:\n/\n\nDivision:\n\nURL: https://mariadb.com/kb/en/division-operator/\n\n','MariaDB> SELECT 3/5;\n -> 0.60\n','https://mariadb.com/kb/en/division-operator/'),(269,'PURGE BINARY LOGS',8,'Syntax:\nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n\nThe binary log is a set of files that contain information about data\nmodifications made by the MySQL server. The log consists of a set of\nbinary log files, plus an index file (see\nhttps://mariadb.com/kb/en/overview-of-the-binary-log/).\n\nThe PURGE BINARY LOGS statement deletes all the binary log files listed\nin the log index file prior to the specified log file name or date.\nBINARY and MASTER are synonyms. Deleted log files also are removed from\nthe list recorded in the index file, so that the given log file becomes\nthe first in the list.\n\nThis statement has no effect if the server was not started with the\n--log-bin option to enable binary logging.\n\nURL: https://mariadb.com/kb/en/sql-commands-purge-logs/\n\n','PURGE BINARY LOGS TO \'mysql-bin.010\';\nPURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\';\n','https://mariadb.com/kb/en/sql-commands-purge-logs/'),(270,'STDDEV_SAMP',16,'Syntax:\nSTDDEV_SAMP(expr)\n\nReturns the sample standard deviation of expr (the square root of\nVAR_SAMP().\n\nSTDDEV_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_samp/\n\n','','https://mariadb.com/kb/en/stddev_samp/'),(271,'SCHEMA',17,'Syntax:\nSCHEMA()\n\nThis function is a synonym for DATABASE().\n\nURL: https://mariadb.com/kb/en/schema/\n\n','','https://mariadb.com/kb/en/schema/'),(272,'MLINEFROMWKB',32,'MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])\n\nConstructs a MULTILINESTRING value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromwkb/\n\n','','https://mariadb.com/kb/en/mlinefromwkb/'),(273,'LOG2',4,'Syntax:\nLOG2(X)\n\nReturns the base-2 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log2/\n\n','MariaDB> SELECT LOG2(65536);\n -> 16\nMariaDB> SELECT LOG2(-100);\n -> NULL\n','https://mariadb.com/kb/en/log2/'),(274,'SUBTIME',31,'Syntax:\nSUBTIME(expr1,expr2)\n\nSUBTIME() returns expr1 - expr2 expressed as a value in the same format\nas expr1. expr1 is a time or datetime expression, and expr2 is a time\nexpression.\n\nURL: https://mariadb.com/kb/en/subtime/\n\n','MariaDB> SELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\');\n -> \'2007-12-30 22:58:58.999997\'\nMariaDB> SELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'-00:59:59.999999\'\n','https://mariadb.com/kb/en/subtime/'),(275,'UNCOMPRESSED_LENGTH',12,'Syntax:\nUNCOMPRESSED_LENGTH(compressed_string)\n\nReturns the length that the compressed string had before being\ncompressed.\n\nURL: https://mariadb.com/kb/en/uncompressed_length/\n\n','MariaDB> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n -> 30\n','https://mariadb.com/kb/en/uncompressed_length/'),(276,'DROP TABLE',39,'Syntax:\nDROP [TEMPORARY] TABLE [IF EXISTS]\n tbl_name [, tbl_name] ...\n [RESTRICT | CASCADE]\n\nDROP TABLE removes one or more tables. You must have the DROP privilege\nfor each table. All table data and the table definition are removed, so\nbe careful with this statement! If any of the tables named in the\nargument list do not exist, MySQL returns an error indicating by name\nwhich nonexisting tables it was unable to drop, but it also drops all\nof the tables in the list that do exist.\n\n*Important*: When a table is dropped, user privileges on the table are\nnot automatically dropped. See [HELP GRANT].\n\nNote that for a partitioned table, DROP TABLE permanently removes the\ntable definition, all of its partitions, and all of the data which was\nstored in those partitions. It also removes the partitioning definition\n(.par) file associated with the dropped table.\n\nUse IF EXISTS to prevent an error from occurring for tables that do not\nexist. A NOTE is generated for each nonexistent table when using IF\nEXISTS. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE are permitted to make porting easier. In MySQL\n5.5, they do nothing.\n\n*Note*: DROP TABLE automatically commits the current active\ntransaction, unless you use the TEMPORARY keyword.\n\nURL: https://mariadb.com/kb/en/drop-table/\n\n','','https://mariadb.com/kb/en/drop-table/'),(277,'POW',4,'Syntax:\nPOW(X,Y)\n\nReturns the value of X raised to the power of Y.\n\nURL: https://mariadb.com/kb/en/pow/\n\n','MariaDB> SELECT POW(2,2);\n -> 4\nMariaDB> SELECT POW(2,-2);\n -> 0.25\n','https://mariadb.com/kb/en/pow/'),(278,'SHOW CREATE TABLE',26,'Syntax:\nSHOW CREATE TABLE tbl_name\n\nShows the CREATE TABLE statement that creates the given table. To use\nthis statement, you must have some privilege for the table. This\nstatement also works with views.\nSHOW CREATE TABLE quotes table and column names according to the value\nof the sql_quote_show_create option. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/show-create-table/\n\n','MariaDB> SHOW CREATE TABLE t\\G\n*************************** 1. row ***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id INT(11) default NULL auto_increment,\n s char(60) default NULL,\n PRIMARY KEY (id)\n) ENGINE=MyISAM\n','https://mariadb.com/kb/en/show-create-table/'),(279,'DUAL',27,'You are permitted to specify DUAL as a dummy table name in situations\nwhere no tables are referenced:\n\nMariaDB> SELECT 1 + 1 FROM DUAL;\n -> 2\n\nDUAL is purely for the convenience of people who require that all\nSELECT statements should have FROM and possibly other clauses. MySQL\nmay ignore the clauses. MySQL does not require FROM DUAL if no tables\nare referenced.\n\nURL: https://mariadb.com/kb/en/dual/\n\n','','https://mariadb.com/kb/en/dual/'),(280,'INSTR',37,'Syntax:\nINSTR(str,substr)\n\nReturns the position of the first occurrence of substring substr in\nstring str. This is the same as the two-argument form of LOCATE(),\nexcept that the order of the arguments is reversed.\n\nURL: https://mariadb.com/kb/en/instr/\n\n','MariaDB> SELECT INSTR(\'foobarbar\', \'bar\');\n -> 4\nMariaDB> SELECT INSTR(\'xbar\', \'foobar\');\n -> 0\n','https://mariadb.com/kb/en/instr/'),(281,'NOW',31,'Syntax:\nNOW()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed in the\ncurrent time zone.\n\nURL: https://mariadb.com/kb/en/now/\n\n','MariaDB> SELECT NOW();\n -> \'2007-12-15 23:50:26\'\nMariaDB> SELECT NOW() + 0;\n -> 20071215235026.000000\n','https://mariadb.com/kb/en/now/'),(282,'SHOW ENGINES',26,'Syntax:\nSHOW [STORAGE] ENGINES\n\nSHOW ENGINES displays status information about the server\'s storage\nengines. This is particularly useful for checking whether a storage\nengine is supported, or to see what the default engine is.\n\nURL: https://mariadb.com/kb/en/show-engines/\n\n','','https://mariadb.com/kb/en/show-engines/'),(283,'>=',18,'Syntax:\n>=\n\nGreater than or equal:\n\nURL: https://mariadb.com/kb/en/greater-than-or-equal/\n\n','MariaDB> SELECT 2 >= 2;\n -> 1\n','https://mariadb.com/kb/en/greater-than-or-equal/'),(284,'EXP',4,'Syntax:\nEXP(X)\n\nReturns the value of e (the base of natural logarithms) raised to the\npower of X. The inverse of this function is LOG() (using a single\nargument only) or LN().\n\nURL: https://mariadb.com/kb/en/exp/\n\n','MariaDB> SELECT EXP(2);\n -> 7.3890560989307\nMariaDB> SELECT EXP(-2);\n -> 0.13533528323661\nMariaDB> SELECT EXP(0);\n -> 1\n','https://mariadb.com/kb/en/exp/'),(285,'LONGBLOB',22,'LONGBLOB\n\nA BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\nbytes. The effective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol and\navailable memory. Each LONGBLOB value is stored using a 4-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longblob/\n\n','','https://mariadb.com/kb/en/longblob/'),(286,'POINTN',13,'PointN(ls,N)\n\nReturns the N-th Point in the Linestring value ls. Points are numbered\nbeginning with 1.\n\nURL: https://mariadb.com/kb/en/pointn/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/pointn/'),(287,'YEAR DATA TYPE',22,'YEAR[(2|4)]\n\nA year in two-digit or four-digit format. The default is four-digit\nformat. YEAR(2) or YEAR(4) differ in display format, but have the same\nrange of values. In four-digit format, values display as 1901 to 2155,\nand 0000. In two-digit format, values display as 70 to 69, representing\nyears from 1970 to 2069. MySQL displays YEAR values in YYYY or\nYYformat, but permits assignment of values to YEAR columns using either\nstrings or numbers.\n\n*Note*: The YEAR(2) data type has certain issues that you should\nconsider before choosing to use it. As of MySQL 5.5.27, YEAR(2) is\ndeprecated. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/migrating-to-year4.html.\n\nFor additional information about YEAR display format and inerpretation\nof input values, see https://mariadb.com/kb/en/year-data-type/.\n\nURL: https://mariadb.com/kb/en/year-data-type/\n\n','','https://mariadb.com/kb/en/year-data-type/'),(288,'SUM',16,'Syntax:\nSUM([DISTINCT] expr)\n\nReturns the sum of expr. If the return set has no rows, SUM() returns\nNULL. The DISTINCT keyword can be used to sum only the distinct values\nof expr.\n\nSUM() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/sum/\n\n','','https://mariadb.com/kb/en/sum/'),(289,'OCT',37,'Syntax:\nOCT(N)\n\nReturns a string representation of the octal value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,8). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/oct/\n\n','MariaDB> SELECT OCT(12);\n -> \'14\'\n','https://mariadb.com/kb/en/oct/'),(290,'SYSDATE',31,'Syntax:\nSYSDATE()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context.\n\nSYSDATE() returns the time at which it executes. This differs from the\nbehavior for NOW(), which returns a constant time that indicates the\ntime at which the statement began to execute. (Within a stored function\nor trigger, NOW() returns the time at which the function or triggering\nstatement began to execute.)\n\nMariaDB> SELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |\n+---------------------+----------+---------------------+\n\nMariaDB> SELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |\n+---------------------+----------+---------------------+\n\nIn addition, the SET TIMESTAMP statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp settings in the\nbinary log have no effect on invocations of SYSDATE().\n\nBecause SYSDATE() can return different values even within the same\nstatement, and is not affected by SET TIMESTAMP, it is nondeterministic\nand therefore unsafe for replication if statement-based binary logging\nis used. If that is a problem, you can use row-based logging.\n\nAlternatively, you can use the --sysdate-is-now option to cause\nSYSDATE() to be an alias for NOW(). This works if the option is used on\nboth the master and the slave.\n\nThe nondeterministic nature of SYSDATE() also means that indexes cannot\nbe used for evaluating expressions that refer to it.\n\nURL: https://mariadb.com/kb/en/sysdate/\n\n','','https://mariadb.com/kb/en/sysdate/'),(291,'UNINSTALL PLUGIN',5,'Syntax:\nUNINSTALL PLUGIN plugin_name\n\nThis statement removes an installed server plugin. It requires the\nDELETE privilege for the mysql.plugin table.\n\nplugin_name must be the name of some plugin that is listed in the\nmysql.plugin table. The server executes the plugin\'s deinitialization\nfunction and removes the row for the plugin from the mysql.plugin\ntable, so that subsequent server restarts will not load and initialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s shared\nlibrary file.\n\nURL: https://mariadb.com/kb/en/uninstall-plugin/\n\n','','https://mariadb.com/kb/en/uninstall-plugin/'),(292,'ASBINARY',32,'AsBinary(g), AsWKB(g)\n\nConverts a value in internal geometry format to its WKB representation\nand returns the binary result.\n\nURL: https://mariadb.com/kb/en/asbinary/\n\n','SELECT AsBinary(g) FROM geom;\n','https://mariadb.com/kb/en/asbinary/'),(293,'REPEAT FUNCTION',37,'Syntax:\nREPEAT(str,count)\n\nReturns a string consisting of the string str repeated count times. If\ncount is less than 1, returns an empty string. Returns NULL if str or\ncount are NULL.\n\nURL: https://mariadb.com/kb/en/repeat-function/\n\n','MariaDB> SELECT REPEAT(\'MySQL\', 3);\n -> \'MySQLMySQLMySQL\'\n','https://mariadb.com/kb/en/repeat-function/'),(294,'SHOW TABLES',26,'Syntax:\nSHOW [FULL] TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLES lists the non-TEMPORARY tables in a given database. You can\nalso get this list using the mysqlshow db_name command. The LIKE\nclause, if present, indicates which table names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\n\nThis statement also lists any views in the database. The FULL modifier\nis supported such that SHOW FULL TABLES displays a second output\ncolumn. Values for the second column are BASE TABLE for a table and\nVIEW for a view.\n\nIf you have no privileges for a base table or view, it does not show up\nin the output from SHOW TABLES or mysqlshow db_name.\n\nURL: https://mariadb.com/kb/en/show-tables/\n\n','','https://mariadb.com/kb/en/show-tables/'),(295,'MAKEDATE',31,'Syntax:\nMAKEDATE(year,dayofyear)\n\nReturns a date, given year and day-of-year values. dayofyear must be\ngreater than 0 or the result is NULL.\n\nURL: https://mariadb.com/kb/en/makedate/\n\n','MariaDB> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n -> \'2011-01-31\', \'2011-02-01\'\nMariaDB> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n -> \'2011-12-31\', \'2014-12-31\'\nMariaDB> SELECT MAKEDATE(2011,0);\n -> NULL\n','https://mariadb.com/kb/en/makedate/'),(296,'BINARY OPERATOR',37,'Syntax:\nBINARY\n\nThe BINARY operator casts the string following it to a binary string.\nThis is an easy way to force a column comparison to be done byte by\nbyte rather than character by character. This causes the comparison to\nbe case sensitive even if the column is not defined as BINARY or BLOB.\nBINARY also causes trailing spaces to be significant.\n\nURL: https://mariadb.com/kb/en/binary-operator/\n\n','MariaDB> SELECT \'a\' = \'A\';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'A\';\n -> 0\nMariaDB> SELECT \'a\' = \'a \';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'a \';\n -> 0\n','https://mariadb.com/kb/en/binary-operator/'),(297,'MBROVERLAPS',6,'MBROverlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 overlap. The term spatially overlaps is\nused if two geometries intersect and their intersection results in a\ngeometry of the same dimension but not equal to either of the given\ngeometries.\n\nURL: https://mariadb.com/kb/en/mbroverlaps/\n\n','','https://mariadb.com/kb/en/mbroverlaps/'),(298,'SOUNDEX',37,'Syntax:\nSOUNDEX(str)\n\nReturns a soundex string from str. Two strings that sound almost the\nsame should have identical soundex strings. A standard soundex string\nis four characters long, but the SOUNDEX() function returns an\narbitrarily long string. You can use SUBSTRING() on the result to get a\nstandard soundex string. All nonalphabetic characters in str are\nignored. All international alphabetic characters outside the A-Z range\nare treated as vowels.\n\n*Important*: When using SOUNDEX(), you should be aware of the following\nlimitations:\n\no This function, as currently implemented, is intended to work well\n with strings that are in the English language only. Strings in other\n languages may not produce reliable results.\n\no This function is not guaranteed to provide consistent results with\n strings that use multi-byte character sets, including utf-8.\n\n We hope to remove these limitations in a future release. See Bug\n #22638 for more information.\n\nURL: https://mariadb.com/kb/en/soundex/\n\n','MariaDB> SELECT SOUNDEX(\'Hello\');\n -> \'H400\'\nMariaDB> SELECT SOUNDEX(\'Quadratically\');\n -> \'Q36324\'\n','https://mariadb.com/kb/en/soundex/'),(299,'MBRTOUCHES',6,'MBRTouches(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially touch if\nthe interiors of the geometries do not intersect, but the boundary of\none of the geometries intersects either the boundary or the interior of\nthe other.\n\nURL: https://mariadb.com/kb/en/mbrtouches/\n\n','','https://mariadb.com/kb/en/mbrtouches/'),(300,'DROP EVENT',39,'Syntax:\nDROP EVENT [IF EXISTS] event_name\n\nThis statement drops the event named event_name. The event immediately\nceases being active, and is deleted completely from the server.\n\nIf the event does not exist, the error ERROR 1517 (HY000): Unknown\nevent \'event_name\' results. You can override this and cause the\nstatement to generate a warning for nonexistent events instead using IF\nEXISTS.\n\nThis statement requires the EVENT privilege for the schema to which the\nevent to be dropped belongs.\n\nURL: https://mariadb.com/kb/en/drop-event/\n\n','','https://mariadb.com/kb/en/drop-event/'),(301,'INSERT SELECT',27,'Syntax:\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n\nWith INSERT ... SELECT, you can quickly insert many rows into a table\nfrom one or many tables. For example:\n\nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n\nURL: https://mariadb.com/kb/en/insert-select/\n\n','','https://mariadb.com/kb/en/insert-select/'),(302,'CREATE PROCEDURE',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n FUNCTION sp_name ([func_parameter[,...]])\n RETURNS type\n [characteristic ...] routine_body\n\nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n\nfunc_parameter:\n param_name type\n\ntype:\n Any valid MySQL data type\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nroutine_body:\n Valid SQL routine statement\n\nThese statements create stored routines. By default, a routine is\nassociated with the default database. To associate the routine\nexplicitly with a given database, specify the name as db_name.sp_name\nwhen you create it.\n\nThe CREATE FUNCTION statement is also used in MySQL to support UDFs\n(user-defined functions). See\nhttps://mariadb.com/kb/en/create-function-udf/. A UDF can\nbe regarded as an external stored function. Stored functions share\ntheir namespace with UDFs. See\nhttp://dev.mysql.com/doc/refman/5.5/en/function-resolution.html, for\nthe rules describing how the server interprets references to different\nkinds of functions.\n\nTo invoke a stored procedure, use the CALL statement (see [HELP CALL]).\nTo invoke a stored function, refer to it in an expression. The function\nreturns a value during expression evaluation.\n\nCREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE\nprivilege. They might also require the SUPER privilege, depending on\nthe DEFINER value, as described later in this section. If binary\nlogging is enabled, CREATE FUNCTION might require the SUPER privilege,\nas described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nBy default, MySQL automatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the routine creator. This behavior can be changed by\ndisabling the automatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nThe DEFINER and SQL SECURITY clauses specify the security context to be\nused when checking access privileges at routine execution time, as\ndescribed later in this section.\n\nIf the routine name is the same as the name of a built-in SQL function,\na syntax error occurs unless you use a space between the name and the\nfollowing parenthesis when defining the routine or invoking it later.\nFor this reason, avoid using the names of existing SQL functions for\nyour own stored routines.\n\nThe IGNORE_SPACE SQL mode applies to built-in functions, not to stored\nroutines. It is always permissible to have spaces after a stored\nroutine name, regardless of whether IGNORE_SPACE is enabled.\n\nThe parameter list enclosed within parentheses must always be present.\nIf there are no parameters, an empty parameter list of () should be\nused. Parameter names are not case sensitive.\n\nEach parameter is an IN parameter by default. To specify otherwise for\na parameter, use the keyword OUT or INOUT before the parameter name.\n\n*Note*: Specifying a parameter as IN, OUT, or INOUT is valid only for a\nPROCEDURE. For a FUNCTION, parameters are always regarded as IN\nparameters.\n\nAn IN parameter passes a value into a procedure. The procedure might\nmodify the value, but the modification is not visible to the caller\nwhen the procedure returns. An OUT parameter passes a value from the\nprocedure back to the caller. Its initial value is NULL within the\nprocedure, and its value is visible to the caller when the procedure\nreturns. An INOUT parameter is initialized by the caller, can be\nmodified by the procedure, and any change made by the procedure is\nvisible to the caller when the procedure returns.\n\nFor each OUT or INOUT parameter, pass a user-defined variable in the\nCALL statement that invokes the procedure so that you can obtain its\nvalue when the procedure returns. If you are calling the procedure from\nwithin another stored procedure or function, you can also pass a\nroutine parameter or local routine variable as an IN or INOUT\nparameter.\n\nThe following example shows a simple stored procedure that uses an OUT\nparameter:\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE simpleproc (OUT param1 INT)\n -> BEGIN\n -> SELECT COUNT(*) INTO param1 FROM t;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter ;\n\nMariaDB> CALL simpleproc(@a);\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @a;\n+------+\n| @a |\n+------+\n| 3 |\n+------+\n1 row in set (0.00 sec)\n\nThe example uses the mysql client delimiter command to change the\nstatement delimiter from ; to // while the procedure is being defined.\nThis enables the ; delimiter used in the procedure body to be passed\nthrough to the server rather than being interpreted by mysql itself.\nSee\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nThe RETURNS clause may be specified only for a FUNCTION, for which it\nis mandatory. It indicates the return type of the function, and the\nfunction body must contain a RETURN value statement. If the RETURN\nstatement returns a value of a different type, the value is coerced to\nthe proper type. For example, if a function specifies an ENUM or SET\nvalue in the RETURNS clause, but the RETURN statement returns an\ninteger, the value returned from the function is the string for the\ncorresponding ENUM member of set of SET members.\n\nThe following example function takes a parameter, performs an operation\nusing an SQL function, and returns the result. In this case, it is\nunnecessary to use delimiter because the function definition contains\nno internal ; statement delimiters:\n\nMariaDB> CREATE FUNCTION hello (s CHAR(20))\nMariaDB> RETURNS CHAR(50) DETERMINISTIC\n -> RETURN CONCAT(\'Hello, \',s,\'!\');\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n1 row in set (0.00 sec)\n\nParameter types and function return types can be declared to use any\nvalid data type, except that the COLLATE attribute cannot be used prior\nto MySQL 5.5.3. As of 5.5.3, COLLATE can be used if preceded by the\nCHARACTER SET attribute.\n\nThe routine_body consists of a valid SQL routine statement. This can be\na simple statement such as SELECT or INSERT, or a compound statement\nwritten using BEGIN and END. Compound statements can contain\ndeclarations, loops, and other control structure statements. The syntax\nfor these statements is described in\nhttps://mariadb.com/kb/programmatic-and-compound-statements.\n\nMySQL permits routines to contain DDL statements, such as CREATE and\nDROP. MySQL also permits stored procedures (but not stored functions)\nto contain SQL transaction statements such as COMMIT. Stored functions\nmay not contain statements that perform explicit or implicit commit or\nrollback. Support for these statements is not required by the SQL\nstandard, which states that each DBMS vendor may decide whether to\npermit them.\n\nStatements that return a result set can be used within a stored\nprocedure but not within a stored function. This prohibition includes\nSELECT statements that do not have an INTO var_list clause and other\nstatements such as SHOW, EXPLAIN, and CHECK TABLE. For statements that\ncan be determined at function definition time to return a result set, a\nNot allowed to return a result set from a function error occurs\n(ER_SP_NO_RETSET). For statements that can be determined only at\nruntime to return a result set, a PROCEDURE %s can\'t return a result\nset in the given context error occurs (ER_SP_BADSELECT).\n\nUSE statements within stored routines are not permitted. When a routine\nis invoked, an implicit USE db_name is performed (and undone when the\nroutine terminates). The causes the routine to have the given default\ndatabase while it executes. References to objects in databases other\nthan the routine default database should be qualified with the\nappropriate database name.\n\nFor additional information about statements that are not permitted in\nstored routines, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/\n.\n\nFor information about invoking stored procedures from within programs\nwritten in a language that has a MySQL interface, see [HELP CALL].\n\nMySQL stores the sql_mode system variable setting that is in effect at\nthe time a routine is created, and always executes the routine with\nthis setting in force, regardless of the server SQL mode in effect when\nthe routine is invoked.\n\nThe switch from the SQL mode of the invoker to that of the routine\noccurs after evaluation of arguments and assignment of the resulting\nvalues to routine parameters. If you define a routine in strict SQL\nmode but invoke it in nonstrict mode, assignment of arguments to\nroutine parameters does not take place in strict mode. If you require\nthat expressions passed to a routine be assigned in strict SQL mode,\nyou should invoke the routine with strict mode in effect.\n\nURL: https://mariadb.com/kb/en/create-procedure/\n\n','','https://mariadb.com/kb/en/create-procedure/'),(303,'VARBINARY',22,'VARBINARY(M)\n\nThe VARBINARY type is similar to the VARCHAR type, but stores binary\nbyte strings rather than nonbinary character strings. M represents the\nmaximum column length in bytes.\n\nURL: https://mariadb.com/kb/en/varbinary/\n\n','','https://mariadb.com/kb/en/varbinary/'),(304,'LOAD INDEX',26,'Syntax:\nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n\ntbl_index_list:\n tbl_name\n [PARTITION (partition_list | ALL)]\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe LOAD INDEX INTO CACHE statement preloads a table index into the key\ncache to which it has been assigned by an explicit CACHE INDEX\nstatement, or into the default key cache otherwise.\n\nLOAD INDEX INTO CACHE is used only for MyISAM tables. In MySQL 5.5, it\nis also supported for partitioned MyISAM tables; in addition, indexes\non partitioned tables can be preloaded for one, several, or all\npartitions.\n\nThe IGNORE LEAVES modifier causes only blocks for the nonleaf nodes of\nthe index to be preloaded.\n\nIGNORE LEAVES is also supported for partitioned MyISAM tables.\n\nURL: https://mariadb.com/kb/en/load-index/\n\n','','https://mariadb.com/kb/en/load-index/'),(305,'UNION',27,'Syntax:\nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n\nUNION is used to combine the result from multiple SELECT statements\ninto a single result set.\n\nThe column names from the first SELECT statement are used as the column\nnames for the results returned. Selected columns listed in\ncorresponding positions of each SELECT statement should have the same\ndata type. (For example, the first column selected by the first\nstatement should have the same type as the first column selected by the\nother statements.)\n\nURL: https://mariadb.com/kb/en/union/\n\n','','https://mariadb.com/kb/en/union/'),(306,'TO_DAYS',31,'Syntax:\nTO_DAYS(date)\n\nGiven a date date, returns a day number (the number of days since year\n0).\n\nURL: https://mariadb.com/kb/en/to_days/\n\n','MariaDB> SELECT TO_DAYS(950501);\n -> 728779\nMariaDB> SELECT TO_DAYS(\'2007-10-07\');\n -> 733321\n','https://mariadb.com/kb/en/to_days/'),(307,'NOT REGEXP',37,'Syntax:\nexpr NOT REGEXP pat, expr NOT RLIKE pat\n\nThis is the same as NOT (expr REGEXP pat).\n\nURL: https://mariadb.com/kb/en/not-regexp/\n\n','','https://mariadb.com/kb/en/not-regexp/'),(308,'SHOW INDEX',26,'Syntax:\nSHOW {INDEX | INDEXES | KEYS}\n {FROM | IN} tbl_name\n [{FROM | IN} db_name]\n [WHERE expr]\n\nSHOW INDEX returns table index information. The format resembles that\nof the SQLStatistics call in ODBC. This statement requires some\nprivilege for any column in the table.\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. These two statements are equivalent:\n\nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n\nThe WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou can also list a table\'s indexes with the mysqlshow -k db_name\ntbl_name command.\n\nURL: https://mariadb.com/kb/en/show-index/\n\n','','https://mariadb.com/kb/en/show-index/'),(309,'SHOW CREATE DATABASE',26,'Syntax:\nSHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n\nShows the CREATE DATABASE statement that creates the given database. If\nthe SHOW statement includes an IF NOT EXISTS clause, the output too\nincludes such a clause. SHOW CREATE SCHEMA is a synonym for SHOW CREATE\nDATABASE.\n\nURL: https://mariadb.com/kb/en/show-create-database/\n\n','MariaDB> SHOW CREATE DATABASE test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n\nMariaDB> SHOW CREATE SCHEMA test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n','https://mariadb.com/kb/en/show-create-database/'),(310,'LEAVE',23,'Syntax:\nLEAVE label\n\nThis statement is used to exit the flow control construct that has the\ngiven label. If the label is for the outermost stored program block,\nLEAVE exits the program.\n\nLEAVE can be used within BEGIN ... END or loop constructs (LOOP,\nREPEAT, WHILE).\n\nURL: https://mariadb.com/kb/en/leave/\n\n','','https://mariadb.com/kb/en/leave/'),(311,'NOT IN',18,'Syntax:\nexpr NOT IN (value,...)\n\nThis is the same as NOT (expr IN (value,...)).\n\nURL: https://mariadb.com/kb/en/not-in/\n\n','','https://mariadb.com/kb/en/not-in/'),(312,'!',15,'Syntax:\nNOT, !\n\nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is\nnonzero, and NOT NULL returns NULL.\n\nURL: https://mariadb.com/kb/en/not/\n\n','MariaDB> SELECT NOT 10;\n -> 0\nMariaDB> SELECT NOT 0;\n -> 1\nMariaDB> SELECT NOT NULL;\n -> NULL\nMariaDB> SELECT ! (1+1);\n -> 0\nMariaDB> SELECT ! 1+1;\n -> 1\n','https://mariadb.com/kb/en/not/'),(313,'DECLARE HANDLER',23,'Syntax:\nDECLARE handler_action HANDLER\n FOR condition_value [, condition_value] ...\n statement\n\nhandler_action:\n CONTINUE\n | EXIT\n | UNDO\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n\nThe DECLARE ... HANDLER statement specifies a handler that deals with\none or more conditions. If one of these conditions occurs, the\nspecified statement executes. statement can be a simple statement such\nas SET var_name = value, or a compound statement written using BEGIN\nand END (see [HELP BEGIN END]).\n\nHandler declarations must appear after variable or condition\ndeclarations.\n\nThe handler_action value indicates what action the handler takes after\nexecution of the handler statement:\n\no CONTINUE: Execution of the current program continues.\n\no EXIT: Execution terminates for the BEGIN ... END compound statement\n in which the handler is declared. This is true even if the condition\n occurs in an inner block.\n\no UNDO: Not supported.\n\nThe condition_value for DECLARE ... HANDLER indicates the specific\ncondition or class of conditions that activates the handler:\n\no A MySQL error code (a number) or an SQLSTATE value (a 5-character\n string literal). You should not use MySQL error code 0 or SQLSTATE\n values that begin with \'00\', because those indicate success rather\n than an error condition. For a list of MySQL error codes and SQLSTATE\n values, see\n https://mariadb.com/kb/en/mariadb-error-codes/.\n\no A condition name previously specified with DECLARE ... CONDITION. A\n condition name can be associated with a MySQL error code or SQLSTATE\n value. See [HELP DECLARE CONDITION].\n\no SQLWARNING is shorthand for the class of SQLSTATE values that begin\n with \'01\'.\n\no NOT FOUND is shorthand for the class of SQLSTATE values that begin\n with \'02\'. This is relevant within the context of cursors and is used\n to control what happens when a cursor reaches the end of a data set.\n If no more rows are available, a No Data condition occurs with\n SQLSTATE value \'02000\'. To detect this condition, you can set up a\n handler for it (or for a NOT FOUND condition). For an example, see\n https://mariadb.com/kb/en/cursor-overview/. This condition\n also occurs for SELECT ... INTO var_list statements that retrieve no\n rows.\n\no SQLEXCEPTION is shorthand for the class of SQLSTATE values that do\n not begin with \'00\', \'01\', or \'02\'.\n\nIf a condition occurs for which no handler has been declared, the\naction taken depends on the condition class:\n\no For SQLEXCEPTION conditions, the stored program terminates at the\n statement that raised the condition, as if there were an EXIT\n handler. If the program was called by another stored program, the\n calling program handles the condition using the handler selection\n rules applied to its own handlers.\n\no For SQLWARNING conditions, the program continues executing, as if\n there were a CONTINUE handler.\n\no For NOT FOUND conditions, if the condition was raised normally, the\n action is CONTINUE. If it was raised by SIGNAL or RESIGNAL, the\n action is EXIT.\n\nURL: https://mariadb.com/kb/en/declare-handler/\n\n','MariaDB> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE handlerdemo ()\n -> BEGIN\n -> DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 = 1;\n -> SET @x = 1;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 2;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 3;\n -> END;\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL handlerdemo()//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n +------+\n | @x |\n +------+\n | 3 |\n +------+\n 1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/declare-handler/'),(314,'DOUBLE',22,'DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA normal-size (double-precision) floating-point number. Permissible\nvalues are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and\n2.2250738585072014E-308 to 1.7976931348623157E+308. These are the\ntheoretical limits, based on the IEEE standard. The actual range might\nbe slightly smaller depending on your hardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A double-precision floating-point\nnumber is accurate to approximately 15 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nURL: https://mariadb.com/kb/en/double/\n\n','','https://mariadb.com/kb/en/double/'),(315,'TIME',22,'TIME\n\nA time. The range is \'-838:59:59\' to \'838:59:59\'. MySQL displays TIME\nvalues in \'HH:MM:SS\' format, but permits assignment of values to TIME\ncolumns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/time/\n\n','','https://mariadb.com/kb/en/time/'),(316,'&&',15,'Syntax:\nAND, &&\n\nLogical AND. Evaluates to 1 if all operands are nonzero and not NULL,\nto 0 if one or more operands are 0, otherwise NULL is returned.\n\nURL: https://mariadb.com/kb/en/and/\n\n','MariaDB> SELECT 1 && 1;\n -> 1\nMariaDB> SELECT 1 && 0;\n -> 0\nMariaDB> SELECT 1 && NULL;\n -> NULL\nMariaDB> SELECT 0 && NULL;\n -> 0\nMariaDB> SELECT NULL && 0;\n -> 0\n','https://mariadb.com/kb/en/and/'),(317,'X',11,'X(p)\n\nReturns the X-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/x/\n\n','MariaDB> SELECT X(POINT(56.7, 53.34));\n+-----------------------+\n| X(POINT(56.7, 53.34)) |\n+-----------------------+\n| 56.7 |\n+-----------------------+\n','https://mariadb.com/kb/en/x/'),(318,'SYSTEM_USER',17,'Syntax:\nSYSTEM_USER()\n\nSYSTEM_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/system_user/\n\n','','https://mariadb.com/kb/en/system_user/'),(319,'FOUND_ROWS',17,'Syntax:\nFOUND_ROWS()\n\nA SELECT statement may include a LIMIT clause to restrict the number of\nrows the server returns to the client. In some cases, it is desirable\nto know how many rows the statement would have returned without the\nLIMIT, but without running the statement again. To obtain this row\ncount, include a SQL_CALC_FOUND_ROWS option in the SELECT statement,\nand then invoke FOUND_ROWS() afterward:\n\nURL: https://mariadb.com/kb/en/found_rows/\n\n','MariaDB> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name\n -> WHERE id > 100 LIMIT 10;\nMariaDB> SELECT FOUND_ROWS();\n','https://mariadb.com/kb/en/found_rows/'),(320,'CROSSES',30,'Crosses(g1,g2)\n\nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon\nor a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise,\nreturns 0.\n\nThe term spatially crosses denotes a spatial relation between two given\ngeometries that has the following properties:\n\no The two geometries intersect\n\no Their intersection results in a geometry that has a dimension that is\n one less than the maximum dimension of the two given geometries\n\no Their intersection is not equal to either of the two given geometries\n\nURL: https://mariadb.com/kb/en/crosses/\n\n','','https://mariadb.com/kb/en/crosses/'),(321,'TRUNCATE TABLE',39,'Syntax:\nTRUNCATE [TABLE] tbl_name\n\nTRUNCATE TABLE empties a table completely. It requires the DROP\nprivilege.\n\nLogically, TRUNCATE TABLE is similar to a DELETE statement that deletes\nall rows, or a sequence of DROP TABLE and CREATE TABLE statements. To\nachieve high performance, it bypasses the DML method of deleting data.\nThus, it cannot be rolled back, it does not cause ON DELETE triggers to\nfire, and it cannot be performed for InnoDB tables with parent-child\nforeign key relationships.\n\nAlthough TRUNCATE TABLE is similar to DELETE, it is classified as a DDL\nstatement rather than a DML statement. It differs from DELETE in the\nfollowing ways in MySQL 5.5:\n\no Truncate operations drop and re-create the table, which is much\n faster than deleting rows one by one, particularly for large tables.\n\no Truncate operations cause an implicit commit, and so cannot be rolled\n back.\n\no Truncation operations cannot be performed if the session holds an\n active table lock.\n\no TRUNCATE TABLE fails for an InnoDB table if there are any FOREIGN KEY\n constraints from other tables that reference the table. Foreign key\n constraints between columns of the same table are permitted.\n\no Truncation operations do not return a meaningful value for the number\n of deleted rows. The usual result is \"0 rows affected,\" which should\n be interpreted as \"no information.\"\n\no As long as the table format file tbl_name.frm is valid, the table can\n be re-created as an empty table with TRUNCATE TABLE, even if the data\n or index files have become corrupted.\n\no Any AUTO_INCREMENT value is reset to its start value. This is true\n even for MyISAM and InnoDB, which normally do not reuse sequence\n values.\n\no When used with partitioned tables, TRUNCATE TABLE preserves the\n partitioning; that is, the data and index files are dropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\n\no The TRUNCATE TABLE statement does not invoke ON DELETE triggers.\n\nURL: https://mariadb.com/kb/en/truncate-table/\n\n','','https://mariadb.com/kb/en/truncate-table/'),(322,'BIT_XOR',16,'Syntax:\nBIT_XOR(expr)\n\nReturns the bitwise XOR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_xor/\n\n','','https://mariadb.com/kb/en/bit_xor/'),(323,'CURRENT_DATE',31,'Syntax:\nCURRENT_DATE, CURRENT_DATE()\n\nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n\nURL: https://mariadb.com/kb/en/current_date/\n\n','','https://mariadb.com/kb/en/current_date/'),(324,'START SLAVE',8,'Syntax:\nSTART SLAVE [thread_types]\n\nSTART SLAVE [SQL_THREAD] UNTIL\n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\n\nSTART SLAVE [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nSTART SLAVE with no thread_type options starts both of the slave\nthreads. The I/O thread reads events from the master server and stores\nthem in the relay log. The SQL thread reads events from the relay log\nand executes them. START SLAVE requires the SUPER privilege.\n\nIf START SLAVE succeeds in starting the slave threads, it returns\nwithout any error. However, even in that case, it might be that the\nslave threads start and then later stop (for example, because they do\nnot manage to connect to the master or read its binary log, or some\nother problem). START SLAVE does not warn you about this. You must\ncheck the slave\'s error log for error messages generated by the slave\nthreads, or check that they are running satisfactorily with SHOW SLAVE\nSTATUS.\n\nURL: https://mariadb.com/kb/en/start-slave/\n\n','','https://mariadb.com/kb/en/start-slave/'),(325,'AREA',2,'Area(poly)\n\nReturns as a double-precision number the area of the Polygon value\npoly, as measured in its spatial reference system.\n\nURL: https://mariadb.com/kb/en/area/\n\n','MariaDB> SET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))\';\nMariaDB> SELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n','https://mariadb.com/kb/en/area/'),(326,'FLUSH',26,'Syntax:\nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n\nThe FLUSH statement has several variant forms that clear or reload\nvarious internal caches, flush tables, or acquire locks. To execute\nFLUSH, you must have the RELOAD privilege. Specific flush options might\nrequire additional privileges, as described later.\n\nBy default, the server writes FLUSH statements to the binary log so\nthat they replicate to replication slaves. To suppress logging, use the\noptional NO_WRITE_TO_BINLOG keyword or its alias LOCAL.\n\n*Note*: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH\nREAD LOCK (with or without a table list) are not written to the binary\nlog in any case because they would cause problems if replicated to a\nslave.\n\nThe FLUSH statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nThe RESET statement is similar to FLUSH. See [HELP RESET], for\ninformation about using the RESET statement with replication.\n\nURL: https://mariadb.com/kb/en/flush/\n\n','','https://mariadb.com/kb/en/flush/'),(327,'BEGIN END',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\nBEGIN ... END syntax is used for writing compound statements, which can\nappear within stored programs (stored procedures and functions,\ntriggers, and events). A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords. statement_list\nrepresents a list of one or more statements, each terminated by a\nsemicolon (;) statement delimiter. The statement_list itself is\noptional, so the empty compound statement (BEGIN END) is legal.\n\nBEGIN ... END blocks can be nested.\n\nUse of multiple statements requires that a client is able to send\nstatement strings containing the ; statement delimiter. In the mysql\ncommand-line client, this is handled with the delimiter command.\nChanging the ; end-of-statement delimiter (for example, to //) permit ;\nto be used in a program body. For an example, see\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nA BEGIN ... END block can be labeled. See [HELP labels].\n\nURL: https://mariadb.com/kb/en/begin-end/\n\n','','https://mariadb.com/kb/en/begin-end/'),(328,'SHOW PROCEDURE STATUS',26,'Syntax:\nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is a MySQL extension. It returns characteristics of a\nstored procedure, such as the database, name, type, creator, creation\nand modification dates, and character set information. A similar\nstatement, SHOW FUNCTION STATUS, displays information about stored\nfunctions (see [HELP SHOW FUNCTION STATUS]).\n\nThe LIKE clause, if present, indicates which procedure or function\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-procedure-status/\n\n','MariaDB> SHOW PROCEDURE STATUS LIKE \'sp1\'\\G\n*************************** 1. row ***************************\n Db: test\n Name: sp1\n Type: PROCEDURE\n Definer: testuser@localhost\n Modified: 2004-08-03 15:29:37\n Created: 2004-08-03 15:29:37\n Security_type: DEFINER\n Comment:\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-procedure-status/'),(329,'DESCRIBE',28,'Syntax:\n{DESCRIBE | DESC} tbl_name [col_name | wild]\n\nDESCRIBE provides information about the columns in a table. It is a\nshortcut for SHOW COLUMNS FROM. These statements also display\ninformation for views. (See [HELP SHOW COLUMNS].)\n\ncol_name can be a column name, or a string containing the SQL \"%\" and\n\"_\" wildcard characters to obtain output only for the columns with\nnames matching the string. There is no need to enclose the string\nwithin quotation marks unless it contains spaces or other special\ncharacters.\n\nMariaDB> DESCRIBE City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nThe description for SHOW COLUMNS provides more information about the\noutput columns (see [HELP SHOW COLUMNS]).\n\nURL: https://mariadb.com/kb/en/describe/\n\n','','https://mariadb.com/kb/en/describe/'),(330,'SHOW WARNINGS',26,'Syntax:\nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW COUNT(*) WARNINGS\n\nSHOW WARNINGS shows information about the conditions (errors, warnings,\nand notes) that resulted from the last statement in the current session\nthat generated messages. It shows nothing if the last statement used a\ntable and generated no messages. (That is, a statement that uses a\ntable but generates no messages clears the message list.) Statements\nthat do not use tables and do not generate messages have no effect on\nthe message list.\n\nWarnings are generated for DML statements such as INSERT, UPDATE, and\nLOAD DATA INFILE as well as DDL statements such as CREATE TABLE and\nALTER TABLE.\n\nSHOW WARNINGS is also used following EXPLAIN EXTENDED, to display the\nextra information generated by EXPLAIN when the EXTENDED keyword is\nused. See https://mariadb.com/kb/en/explain#explain-extended.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nA related statement, SHOW ERRORS, shows only the error conditions (it\nexcludes warnings and notes). See [HELP SHOW ERRORS].\n\nThe SHOW COUNT(*) WARNINGS statement displays the total number of\nerrors, warnings, and notes. You can also retrieve this number from the\nwarning_count system variable:\n\nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n\nURL: https://mariadb.com/kb/en/show-warnings/\n\n','','https://mariadb.com/kb/en/show-warnings/'),(331,'DROP USER',10,'Syntax:\nDROP USER user [, user] ...\n\nThe DROP USER statement removes one or more MySQL accounts and their\nprivileges. It removes privilege rows for the account from all grant\ntables. To use this statement, you must have the global CREATE USER\nprivilege or the DELETE privilege for the mysql database. Each account\nname uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nDROP USER \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nURL: https://mariadb.com/kb/en/drop-user/\n\n','','https://mariadb.com/kb/en/drop-user/'),(332,'STDDEV_POP',16,'Syntax:\nSTDDEV_POP(expr)\n\nReturns the population standard deviation of expr (the square root of\nVAR_POP()). You can also use STD() or STDDEV(), which are equivalent\nbut not standard SQL.\n\nSTDDEV_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_pop/\n\n','','https://mariadb.com/kb/en/stddev_pop/'),(333,'SHOW CHARACTER SET',26,'Syntax:\nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n\nThe SHOW CHARACTER SET statement shows all available character sets.\nThe LIKE clause, if present, indicates which character set names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n\nURL: https://mariadb.com/kb/en/show-character-set/\n\n','','https://mariadb.com/kb/en/show-character-set/'),(334,'SUBSTRING',37,'Syntax:\nSUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n\nThe forms without a len argument return a substring from string str\nstarting at position pos. The forms with a len argument return a\nsubstring len characters long from string str, starting at position\npos. The forms that use FROM are standard SQL syntax. It is also\npossible to use a negative value for pos. In this case, the beginning\nof the substring is pos characters from the end of the string, rather\nthan the beginning. A negative value may be used for pos in any of the\nforms of this function.\n\nFor all forms of SUBSTRING(), the position of the first character in\nthe string from which the substring is to be extracted is reckoned as\n1.\n\nURL: https://mariadb.com/kb/en/substring/\n\n','MariaDB> SELECT SUBSTRING(\'Quadratically\',5);\n -> \'ratically\'\nMariaDB> SELECT SUBSTRING(\'foobarbar\' FROM 4);\n -> \'barbar\'\nMariaDB> SELECT SUBSTRING(\'Quadratically\',5,6);\n -> \'ratica\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -3);\n -> \'ila\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -5, 3);\n -> \'aki\'\nMariaDB> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);\n -> \'ki\'\n','https://mariadb.com/kb/en/substring/'),(335,'ISEMPTY',36,'IsEmpty(g)\n\nReturns 1 if the geometry value g is the empty geometry, 0 if it is not\nempty, and -1 if the argument is NULL. If the geometry is empty, it\nrepresents the empty point set.\n\nURL: https://mariadb.com/kb/en/isempty/\n\n','','https://mariadb.com/kb/en/isempty/'),(336,'SHOW FUNCTION STATUS',26,'Syntax:\nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is similar to SHOW PROCEDURE STATUS but for stored\nfunctions. See [HELP SHOW PROCEDURE STATUS].\n\nURL: https://mariadb.com/kb/en/show-function-status/\n\n','','https://mariadb.com/kb/en/show-function-status/'),(337,'LTRIM',37,'Syntax:\nLTRIM(str)\n\nReturns the string str with leading space characters removed.\n\nURL: https://mariadb.com/kb/en/ltrim/\n\n','MariaDB> SELECT LTRIM(\' barbar\');\n -> \'barbar\'\n','https://mariadb.com/kb/en/ltrim/'),(338,'INTERSECTS',30,'Intersects(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially intersects g2.\n\nURL: https://mariadb.com/kb/en/intersects/\n\n','','https://mariadb.com/kb/en/intersects/'),(339,'CALL',27,'Syntax:\nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n\nThe CALL statement invokes a stored procedure that was defined\npreviously with CREATE PROCEDURE.\n\nStored procedures that take no arguments can be invoked without\nparentheses. That is, CALL p() and CALL p are equivalent.\n\nCALL can pass back values to its caller using parameters that are\ndeclared as OUT or INOUT parameters. When the procedure returns, a\nclient program can also obtain the number of rows affected for the\nfinal statement executed within the routine: At the SQL level, call the\nROW_COUNT() function; from the C API, call the mysql_affected_rows()\nfunction.\n\nURL: https://mariadb.com/kb/en/call/\n\n','','https://mariadb.com/kb/en/call/'),(340,'MBRDISJOINT',6,'MBRDisjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are disjoint (do not intersect).\n\nURL: https://mariadb.com/kb/en/mbrdisjoint/\n\n','','https://mariadb.com/kb/en/mbrdisjoint/'),(341,'VALUES',14,'Syntax:\nVALUES(col_name)\n\nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the\nVALUES(col_name) function in the UPDATE clause to refer to column\nvalues from the INSERT portion of the statement. In other words,\nVALUES(col_name) in the UPDATE clause refers to the value of col_name\nthat would be inserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts. The VALUES()\nfunction is meaningful only in the ON DUPLICATE KEY UPDATE clause of\nINSERT statements and returns NULL otherwise. See\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nURL: https://mariadb.com/kb/en/values/\n\n','MariaDB> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n','https://mariadb.com/kb/en/values/'),(342,'SUBSTRING_INDEX',37,'Syntax:\nSUBSTRING_INDEX(str,delim,count)\n\nReturns the substring from string str before count occurrences of the\ndelimiter delim. If count is positive, everything to the left of the\nfinal delimiter (counting from the left) is returned. If count is\nnegative, everything to the right of the final delimiter (counting from\nthe right) is returned. SUBSTRING_INDEX() performs a case-sensitive\nmatch when searching for delim.\n\nURL: https://mariadb.com/kb/en/substring_index/\n\n','MariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2);\n -> \'www.mariadb\'\nMariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2);\n -> \'mariadb.org\'\n','https://mariadb.com/kb/en/substring_index/'),(343,'ENCODE',12,'Syntax:\nENCODE(str,pass_str)\n\nEncrypt str using pass_str as the password. To decrypt the result, use\nDECODE().\n\nThe result is a binary string of the same length as str.\n\nThe strength of the encryption is based on how good the random\ngenerator is. It should suffice for short strings.\n\nURL: https://mariadb.com/kb/en/encode/\n\n','','https://mariadb.com/kb/en/encode/'),(344,'LOOP',23,'Syntax:\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\nLOOP implements a simple loop construct, enabling repeated execution of\nthe statement list, which consists of one or more statements, each\nterminated by a semicolon (;) statement delimiter. The statements\nwithin the loop are repeated until the loop is terminated. Usually,\nthis is accomplished with a LEAVE statement. Within a stored function,\nRETURN can also be used, which exits the function entirely.\n\nNeglecting to include a loop-termination statement results in an\ninfinite loop.\n\nA LOOP statement can be labeled. For the rules regarding label use, see\n[HELP labels].\n\nURL: https://mariadb.com/kb/en/loop/\n\n','CREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN\n ITERATE label1;\n END IF;\n LEAVE label1;\n END LOOP label1;\n SET @x = p1;\nEND;\n','https://mariadb.com/kb/en/loop/'),(345,'TRUNCATE',4,'Syntax:\nTRUNCATE(X,D)\n\nReturns the number X, truncated to D decimal places. If D is 0, the\nresult has no decimal point or fractional part. D can be negative to\ncause D digits left of the decimal point of the value X to become zero.\n\nURL: https://mariadb.com/kb/en/truncate/\n\n','MariaDB> SELECT TRUNCATE(1.223,1);\n -> 1.2\nMariaDB> SELECT TRUNCATE(1.999,1);\n -> 1.9\nMariaDB> SELECT TRUNCATE(1.999,0);\n -> 1\nMariaDB> SELECT TRUNCATE(-1.999,1);\n -> -1.9\nMariaDB> SELECT TRUNCATE(122,-2);\n -> 100\nMariaDB> SELECT TRUNCATE(10.28*100,0);\n -> 1028\n','https://mariadb.com/kb/en/truncate/'),(346,'TIMESTAMPADD',31,'Syntax:\nTIMESTAMPADD(unit,interval,datetime_expr)\n\nAdds the integer expression interval to the date or datetime expression\ndatetime_expr. The unit for interval is given by the unit argument,\nwhich should be one of the following values: MICROSECOND\n(microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or\nYEAR.\n\nIt is possible to use FRAC_SECOND in place of MICROSECOND, but\nFRAC_SECOND is deprecated. FRAC_SECOND was removed in MySQL 5.5.3.\n\nThe unit value may be specified using one of keywords as shown, or with\na prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY both are legal.\n\nURL: https://mariadb.com/kb/en/timestampadd/\n\n','MariaDB> SELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n -> \'2003-01-02 00:01:00\'\nMariaDB> SELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n -> \'2003-01-09\'\n','https://mariadb.com/kb/en/timestampadd/'),(347,'SHOW',26,'SHOW has many forms that provide information about databases, tables,\ncolumns, or status information about the server. This section describes\nthose following:\n\nSHOW AUTHORS\nSHOW {BINARY | MASTER} LOGS\nSHOW BINLOG EVENTS [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE FUNCTION func_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW MASTER STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW SLAVE HOSTS\nSHOW SLAVE STATUS\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW [FULL] TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n\nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n\nIf the syntax for a given SHOW statement includes a LIKE \'pattern\'\npart, \'pattern\' is a string that can contain the SQL \"%\" and \"_\"\nwildcard characters. The pattern is useful for restricting statement\noutput to matching values.\n\nSeveral SHOW statements also accept a WHERE clause that provides more\nflexibility in specifying which rows to display. See\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show/\n\n','','https://mariadb.com/kb/en/show/'),(348,'GREATEST',18,'Syntax:\nGREATEST(value1,value2,...)\n\nWith two or more arguments, returns the largest (maximum-valued)\nargument. The arguments are compared using the same rules as for\nLEAST().\n\nURL: https://mariadb.com/kb/en/greatest/\n\n','MariaDB> SELECT GREATEST(2,0);\n -> 2\nMariaDB> SELECT GREATEST(34.0,3.0,5.0,767.0);\n -> 767.0\nMariaDB> SELECT GREATEST(\'B\',\'A\',\'C\');\n -> \'C\'\n','https://mariadb.com/kb/en/greatest/'),(349,'SHOW VARIABLES',26,'Syntax:\nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW VARIABLES shows the values of MySQL system variables. This\ninformation also can be obtained using the mysqladmin variables\ncommand. The LIKE clause, if present, indicates which variable names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. This\nstatement does not require any privilege. It requires only the ability\nto connect to the server.\n\nWith the GLOBAL modifier, SHOW VARIABLES displays the values that are\nused for new connections to MySQL. As of MySQL 5.5.3, if a variable has\nno global value, no value is displayed. Before 5.5.3, the session value\nis displayed. With SESSION, SHOW VARIABLES displays the values that are\nin effect for the current connection. If no modifier is present, the\ndefault is SESSION. LOCAL is a synonym for SESSION.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern. To obtain the row for a\nspecific variable, use a LIKE clause as shown:\n\nSHOW VARIABLES LIKE \'max_join_size\';\nSHOW SESSION VARIABLES LIKE \'max_join_size\';\n\nTo get a list of variables whose name match a pattern, use the \"%\"\nwildcard character in a LIKE clause:\n\nSHOW VARIABLES LIKE \'%size%\';\nSHOW GLOBAL VARIABLES LIKE \'%size%\';\n\nWildcard characters can be used in any position within the pattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard that matches\nany single character, you should escape it as \"\\_\" to match it\nliterally. In practice, this is rarely necessary.\n\nURL: https://mariadb.com/kb/en/show-variables/\n\n','','https://mariadb.com/kb/en/show-variables/'),(350,'BINLOG',26,'Syntax:\nBINLOG \'str\'\n\nBINLOG is an internal-use statement. It is generated by the mysqlbinlog\nprogram as the printable representation of certain events in binary log\nfiles. (See https://mariadb.com/kb/en/mysqlbinlog/.)\nThe \'str\' value is a base 64-encoded string the that server decodes to\ndetermine the data change indicated by the corresponding event. This\nstatement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/binlog/\n\n','','https://mariadb.com/kb/en/binlog/'),(351,'BIT_AND',16,'Syntax:\nBIT_AND(expr)\n\nReturns the bitwise AND of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_and/\n\n','','https://mariadb.com/kb/en/bit_and/'),(352,'SECOND',31,'Syntax:\nSECOND(time)\n\nReturns the second for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/second/\n\n','MariaDB> SELECT SECOND(\'10:05:03\');\n -> 3\n','https://mariadb.com/kb/en/second/'),(353,'ATAN2',4,'Syntax:\nATAN(Y,X), ATAN2(Y,X)\n\nReturns the arc tangent of the two variables X and Y. It is similar to\ncalculating the arc tangent of Y / X, except that the signs of both\narguments are used to determine the quadrant of the result.\n\nURL: https://mariadb.com/kb/en/atan2/\n\n','MariaDB> SELECT ATAN(-2,2);\n -> -0.78539816339745\nMariaDB> SELECT ATAN2(PI(),0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/atan2/'),(354,'MBRCONTAINS',6,'MBRContains(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\ncontains the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRWithin().\n\nURL: https://mariadb.com/kb/en/mbrcontains/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Point(1 1)\');\nMariaDB> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n','https://mariadb.com/kb/en/mbrcontains/'),(355,'HOUR',31,'Syntax:\nHOUR(time)\n\nReturns the hour for time. The range of the return value is 0 to 23 for\ntime-of-day values. However, the range of TIME values actually is much\nlarger, so HOUR can return values greater than 23.\n\nURL: https://mariadb.com/kb/en/hour/\n\n','MariaDB> SELECT HOUR(\'10:05:03\');\n -> 10\nMariaDB> SELECT HOUR(\'272:59:59\');\n -> 272\n','https://mariadb.com/kb/en/hour/'),(356,'SELECT',27,'Syntax:\nSELECT\n [ALL | DISTINCT | DISTINCTROW ]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position}\n [ASC | DESC], ... [WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position}\n [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n [PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n export_options\n | INTO DUMPFILE \'file_name\'\n | INTO var_name [, var_name]]\n [FOR UPDATE | LOCK IN SHARE MODE]]\n\nSELECT is used to retrieve rows selected from one or more tables, and\ncan include UNION statements and subqueries. See [HELP UNION], and\nhttps://mariadb.com/kb/en/subqueries/.\n\nThe most commonly used clauses of SELECT statements are these:\n\no Each select_expr indicates a column that you want to retrieve. There\n must be at least one select_expr.\n\no table_references indicates the table or tables from which to retrieve\n rows. Its syntax is described in [HELP JOIN].\n\no The WHERE clause, if given, indicates the condition or conditions\n that rows must satisfy to be selected. where_condition is an\n expression that evaluates to true for each row to be selected. The\n statement selects all rows if there is no WHERE clause.\n\n In the WHERE expression, you can use any of the functions and\n operators that MySQL supports, except for aggregate (summary)\n functions. See\n https://mariadb.com/kb/en/select#select-expressions, and\n https://mariadb.com/kb/en/functions-and-operators/.\n\nSELECT can also be used to retrieve rows computed without reference to\nany table.\n\nURL: https://mariadb.com/kb/en/select/\n\n','','https://mariadb.com/kb/en/select/'),(357,'COT',4,'Syntax:\nCOT(X)\n\nReturns the cotangent of X.\n\nURL: https://mariadb.com/kb/en/cot/\n\n','MariaDB> SELECT COT(12);\n -> -1.5726734063977\nMariaDB> SELECT COT(0);\n -> NULL\n','https://mariadb.com/kb/en/cot/'),(358,'SHOW CREATE EVENT',26,'Syntax:\nSHOW CREATE EVENT event_name\n\nThis statement displays the CREATE EVENT statement needed to re-create\na given event. It requires the EVENT privilege for the database from\nwhich the event is to be shown. For example (using the same event\ne_daily defined and then altered in [HELP SHOW EVENTS]):\n\nURL: https://mariadb.com/kb/en/show-create-event/\n\n','MariaDB> SHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row ***************************\n Event: e_daily\n sql_mode:\n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*)\n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-event/'),(359,'LOAD_FILE',37,'Syntax:\nLOAD_FILE(file_name)\n\nReads the file and returns the file contents as a string. To use this\nfunction, the file must be located on the server host, you must specify\nthe full path name to the file, and you must have the FILE privilege.\nThe file must be readable by all and its size less than\nmax_allowed_packet bytes. If the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nIf the file does not exist or cannot be read because one of the\npreceding conditions is not satisfied, the function returns NULL.\n\nThe character_set_filesystem system variable controls interpretation of\nfile names that are given as literal strings.\n\nURL: https://mariadb.com/kb/en/load_file/\n\n','MariaDB> UPDATE t\n SET blob_col=LOAD_FILE(\'/tmp/picture\')\n WHERE id=1;\n','https://mariadb.com/kb/en/load_file/'),(360,'POINTFROMTEXT',3,'PointFromText(wkt[,srid])\n\nConstructs a POINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromtext/\n\n','','https://mariadb.com/kb/en/pointfromtext/'),(361,'GROUP_CONCAT',16,'Syntax:\nGROUP_CONCAT(expr)\n\nThis function returns a string result with the concatenated non-NULL\nvalues from a group. It returns NULL if there are no non-NULL values.\nThe full syntax is as follows:\n\nGROUP_CONCAT([DISTINCT] expr [,expr ...]\n [ORDER BY {unsigned_integer | col_name | expr}\n [ASC | DESC] [,col_name ...]]\n [SEPARATOR str_val])\n\nURL: https://mariadb.com/kb/en/group_concat/\n\n','MariaDB> SELECT student_name,\n -> GROUP_CONCAT(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/group_concat/'),(362,'DATE_FORMAT',31,'Syntax:\nDATE_FORMAT(date,format)\n\nFormats the date value according to the format string.\n\nURL: https://mariadb.com/kb/en/date_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n -> \'Sunday October 2009\'\nMariaDB> SELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n -> \'22:23:00\'\nMariaDB> SELECT DATE_FORMAT(\'1900-10-04 22:23:00\',\n -> \'%D %y %a %d %m %b %j\');\n -> \'4th 00 Thu 04 10 Oct 277\'\nMariaDB> SELECT DATE_FORMAT(\'1997-10-04 22:23:00\',\n -> \'%H %k %I %r %T %S %w\');\n -> \'22 22 10 10:23:00 PM 22:23:00 00 6\'\nMariaDB> SELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n -> \'1998 52\'\nMariaDB> SELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n -> \'00\'\n','https://mariadb.com/kb/en/date_format/'),(363,'BENCHMARK',17,'Syntax:\nBENCHMARK(count,expr)\n\nThe BENCHMARK() function executes the expression expr repeatedly count\ntimes. It may be used to time how quickly MySQL processes the\nexpression. The result value is always 0. The intended use is from\nwithin the mysql client, which reports query execution times:\n\nURL: https://mariadb.com/kb/en/benchmark/\n\n','MariaDB> SELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (4.74 sec)\n','https://mariadb.com/kb/en/benchmark/'),(364,'YEAR',31,'Syntax:\nYEAR(date)\n\nReturns the year for date, in the range 1000 to 9999, or 0 for the\n\"zero\" date.\n\nURL: https://mariadb.com/kb/en/year/\n\n','MariaDB> SELECT YEAR(\'1987-01-01\');\n -> 1987\n','https://mariadb.com/kb/en/year/'),(365,'SHOW ENGINE',26,'Syntax:\nSHOW ENGINE engine_name {STATUS | MUTEX}\n\nSHOW ENGINE displays operational information about a storage engine.\nThe following statements currently are supported:\n\nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n\nSHOW ENGINE INNODB STATUS displays extensive information from the\nstandard InnoDB Monitor about the state of the InnoDB storage engine.\nFor information about the standard monitor and other InnoDB Monitors\nthat provide information about InnoDB processing, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-monitors.html.\n\nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics. The\nstatement displays the following fields:\n\no Type\n\n Always InnoDB.\n\no Name\n\n The source file where the mutex is implemented, and the line number\n in the file where the mutex is created. The line number may change\n depending on your version of MySQL.\n\no Status\n\n The mutex status. This field displays several values if UNIV_DEBUG\n was defined at MySQL compilation time (for example, in include/univ.i\n in the InnoDB part of the MySQL source tree). If UNIV_DEBUG was not\n defined, the statement displays only the os_waits value. In the\n latter case (without UNIV_DEBUG), the information on which the output\n is based is insufficient to distinguish regular mutexes and mutexes\n that protect rw-locks (which permit multiple readers or a single\n writer). Consequently, the output may appear to contain multiple rows\n for the same mutex.\n\n o count indicates how many times the mutex was requested.\n\n o spin_waits indicates how many times the spinlock had to run.\n\n o spin_rounds indicates the number of spinlock rounds. (spin_rounds\n divided by spin_waits provides the average round count.)\n\n o os_waits indicates the number of operating system waits. This\n occurs when the spinlock did not work (the mutex was not locked\n during the spinlock and it was necessary to yield to the operating\n system and wait).\n\n o os_yields indicates the number of times a the thread trying to lock\n a mutex gave up its timeslice and yielded to the operating system\n (on the presumption that permitting other threads to run will free\n the mutex so that it can be locked).\n\n o os_wait_times indicates the amount of time (in ms) spent in\n operating system waits, if the timed_mutexes system variable is 1\n (ON). If timed_mutexes is 0 (OFF), timing is disabled, so\n os_wait_times is 0. timed_mutexes is off by default.\n\nInformation from this statement can be used to diagnose system\nproblems. For example, large values of spin_waits and spin_rounds may\nindicate scalability problems.\n\nUse SHOW ENGINE PERFORMANCE_SCHEMA STATUS to inspect the internal\noperation of the Performance Schema code:\n\nMariaDB> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\\G\n...\n*************************** 3. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_size\nStatus: 76\n*************************** 4. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_count\nStatus: 10000\n*************************** 5. row ***************************\n Type: performance_schema\n Name: events_waits_history.memory\nStatus: 760000\n...\n*************************** 57. row ***************************\n Type: performance_schema\n Name: performance_schema.memory\nStatus: 26459600\n...\n\nThe intent of this statement is to help the DBA to understand the\neffects that different options have on memory requirements.\n\nName values consist of two parts, which name an internal buffer and an\nattribute of the buffer, respectively:\n\no Internal buffers that are exposed as a table in the\n performance_schema database are named after the table. Examples:\n events_waits_history.row_size, mutex_instances.row_count.\n\no Internal buffers that are not exposed as a table are named within\n parentheses. Examples: (pfs_cond_class).row_size,\n (pfs_mutex_class).memory.\n\no Values that apply to the Performance Schema as a whole begin with\n performance_schema. Example: performance_schema.memory.\n\nAttributes have these meanings:\n\no row_size cannot be changed. It is the size of the internal record\n used by the implementation.\n\no row_count can be changed depending on the configuration options.\n\no For a table, tbl_name.memory is the product of row_size multiplied by\n row_count. For the Performance Schema as a whole,\n performance_schema.memory is the sum of all the memory used (the sum\n of all other memory values).\n\nIn some cases, there is a direct relationship between a configuration\nparameter and a SHOW ENGINE value. For example,\nevents_waits_history_long.row_count corresponds to\nperformance_schema_events_waits_history_long_size. In other cases, the\nrelationship is more complex. For example,\nevents_waits_history.row_count corresponds to\nperformance_schema_events_waits_history_size (the number of rows per\nthread) multiplied by performance_schema_max_thread_instances ( the\nnumber of threads).\n\nURL: https://mariadb.com/kb/en/show-engine/\n\n','','https://mariadb.com/kb/en/show-engine/'),(366,'NAME_CONST',14,'Syntax:\nNAME_CONST(name,value)\n\nReturns the given value. When used to produce a result set column,\nNAME_CONST() causes the column to have the given name. The arguments\nshould be constants.\n\nMariaDB> SELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n\nURL: https://mariadb.com/kb/en/name_const/\n\n','','https://mariadb.com/kb/en/name_const/'),(367,'RELEASE_LOCK',14,'Syntax:\nRELEASE_LOCK(str)\n\nReleases the lock named by the string str that was obtained with\nGET_LOCK(). Returns 1 if the lock was released, 0 if the lock was not\nestablished by this thread (in which case the lock is not released),\nand NULL if the named lock did not exist. The lock does not exist if it\nwas never obtained by a call to GET_LOCK() or if it has previously been\nreleased.\n\nThe DO statement is convenient to use with RELEASE_LOCK(). See [HELP\nDO].\n\nURL: https://mariadb.com/kb/en/release_lock/\n\n','','https://mariadb.com/kb/en/release_lock/'),(368,'IS NULL',18,'Syntax:\nIS NULL\n\nTests whether a value is NULL.\n\nURL: https://mariadb.com/kb/en/is-null/\n\n','MariaDB> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n -> 0, 0, 1\n','https://mariadb.com/kb/en/is-null/'),(369,'CONVERT_TZ',31,'Syntax:\nCONVERT_TZ(dt,from_tz,to_tz)\n\nCONVERT_TZ() converts a datetime value dt from the time zone given by\nfrom_tz to the time zone given by to_tz and returns the resulting\nvalue. Time zones are specified as described in\nhttps://mariadb.com/kb/en/time-zones/. This\nfunction returns NULL if the arguments are invalid.\n\nURL: https://mariadb.com/kb/en/convert_tz/\n\n','MariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'GMT\',\'MET\');\n -> \'2004-01-01 13:00:00\'\nMariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'+00:00\',\'+10:00\');\n -> \'2004-01-01 22:00:00\'\n','https://mariadb.com/kb/en/convert_tz/'),(370,'TIME_TO_SEC',31,'Syntax:\nTIME_TO_SEC(time)\n\nReturns the time argument, converted to seconds.\n\nURL: https://mariadb.com/kb/en/time_to_sec/\n\n','MariaDB> SELECT TIME_TO_SEC(\'22:23:00\');\n -> 80580\nMariaDB> SELECT TIME_TO_SEC(\'00:39:38\');\n -> 2378\n','https://mariadb.com/kb/en/time_to_sec/'),(371,'WEEKDAY',31,'Syntax:\nWEEKDAY(date)\n\nReturns the weekday index for date (0 = Monday, 1 = Tuesday, ... 6 =\nSunday).\n\nURL: https://mariadb.com/kb/en/weekday/\n\n','MariaDB> SELECT WEEKDAY(\'2008-02-03 22:23:00\');\n -> 6\nMariaDB> SELECT WEEKDAY(\'2007-11-06\');\n -> 1\n','https://mariadb.com/kb/en/weekday/'),(372,'EXPORT_SET',37,'Syntax:\nEXPORT_SET(bits,on,off[,separator[,number_of_bits]])\n\nReturns a string such that for every bit set in the value bits, you get\nan on string and for every bit not set in the value, you get an off\nstring. Bits in bits are examined from right to left (from low-order to\nhigh-order bits). Strings are added to the result from left to right,\nseparated by the separator string (the default being the comma\ncharacter \",\"). The number of bits examined is given by number_of_bits,\nwhich has a default of 64 if not specified. number_of_bits is silently\nclipped to 64 if larger than 64. It is treated as an unsigned integer,\nso a value of -1 is effectively the same as 64.\n\nURL: https://mariadb.com/kb/en/export_set/\n\n','MariaDB> SELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n -> \'Y,N,Y,N\'\nMariaDB> SELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n -> \'0,1,1,0,0,0,0,0,0,0\'\n','https://mariadb.com/kb/en/export_set/'),(373,'ALTER SERVER',39,'Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. See [HELP CREATE\nSERVER]. The corresponding fields in the mysql.servers table are\nupdated accordingly. This statement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/alter-server/\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','https://mariadb.com/kb/en/alter-server/'),(374,'RESIGNAL',23,'Syntax:\nRESIGNAL [condition_value]\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nRESIGNAL passes on the error condition information that is available\nduring execution of a condition handler within a compound statement\ninside a stored procedure or function, trigger, or event. RESIGNAL may\nchange some or all information before passing it on. RESIGNAL is\nrelated to SIGNAL, but instead of originating a condition as SIGNAL\ndoes, RESIGNAL relays existing condition information, possibly after\nmodifying it.\n\nRESIGNAL makes it possible to both handle an error and return the error\ninformation. Otherwise, by executing an SQL statement within the\nhandler, information that caused the handler\'s activation is destroyed.\nRESIGNAL also can make some procedures shorter if a given handler can\nhandle part of a situation, then pass the condition \"up the line\" to\nanother handler.\n\nNo special privileges are required to execute the RESIGNAL statement.\n\nFor condition_value and signal_information_item, the definitions and\nrules are the same for RESIGNAL as for SIGNAL (see [HELP SIGNAL]).\n\nThe RESIGNAL statement takes condition_value and SET clauses, both of\nwhich are optional. This leads to several possible uses:\n\no RESIGNAL alone:\n\nRESIGNAL;\n\no RESIGNAL with new signal information:\n\nRESIGNAL SET signal_information_item [, signal_information_item] ...;\n\no RESIGNAL with a condition value and possibly new signal information:\n\nRESIGNAL condition_value\n [SET signal_information_item [, signal_information_item] ...];\n\nURL: https://mariadb.com/kb/en/resignal/\n\n','','https://mariadb.com/kb/en/resignal/'),(375,'TIME FUNCTION',31,'Syntax:\nTIME(expr)\n\nExtracts the time part of the time or datetime expression expr and\nreturns it as a string.\n\nURL: https://mariadb.com/kb/en/time-function/\n\n','MariaDB> SELECT TIME(\'2003-12-31 01:02:03\');\n -> \'01:02:03\'\nMariaDB> SELECT TIME(\'2003-12-31 01:02:03.000123\');\n -> \'01:02:03.000123\'\n','https://mariadb.com/kb/en/time-function/'),(376,'DATE_ADD',31,'Syntax:\nDATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)\n\nThese functions perform date arithmetic. The date argument specifies\nthe starting date or datetime value. expr is an expression specifying\nthe interval value to be added or subtracted from the starting date.\nexpr is a string; it may start with a \"-\" for negative intervals. unit\nis a keyword indicating the units in which the expression should be\ninterpreted.\n\nURL: https://mariadb.com/kb/en/date_add/\n\n','MariaDB> SELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n -> \'2009-01-01 00:00:00\'\nMariaDB> SELECT INTERVAL 1 DAY + \'2008-12-31\';\n -> \'2009-01-01\'\nMariaDB> SELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n -> \'2004-12-31 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2000-12-31 23:59:59\',\n -> INTERVAL 1 SECOND);\n -> \'2001-01-01 00:00:00\'\nMariaDB> SELECT DATE_ADD(\'2010-12-31 23:59:59\',\n -> INTERVAL 1 DAY);\n -> \'2011-01-01 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2100-12-31 23:59:59\',\n -> INTERVAL \'1:1\' MINUTE_SECOND);\n -> \'2101-01-01 00:01:00\'\nMariaDB> SELECT DATE_SUB(\'2005-01-01 00:00:00\',\n -> INTERVAL \'1 1:1:1\' DAY_SECOND);\n -> \'2004-12-30 22:58:59\'\nMariaDB> SELECT DATE_ADD(\'1900-01-01 00:00:00\',\n -> INTERVAL \'-1 10\' DAY_HOUR);\n -> \'1899-12-30 14:00:00\'\nMariaDB> SELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n -> \'1997-12-02\'\nMariaDB> SELECT DATE_ADD(\'1992-12-31 23:59:59.000002\',\n -> INTERVAL \'1.999999\' SECOND_MICROSECOND);\n -> \'1993-01-01 00:00:01.000001\'\n','https://mariadb.com/kb/en/date_add/'),(377,'CAST',37,'Syntax:\nCAST(expr AS type)\n\nThe CAST() function takes an expression of any type and produces a\nresult value of a specified type, similar to CONVERT(). See the\ndescription of CONVERT() for more information.\n\nURL: https://mariadb.com/kb/en/cast/\n\n','','https://mariadb.com/kb/en/cast/'),(378,'SOUNDS LIKE',37,'Syntax:\nexpr1 SOUNDS LIKE expr2\n\nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n\nURL: https://mariadb.com/kb/en/sounds-like/\n\n','','https://mariadb.com/kb/en/sounds-like/'),(379,'PERIOD_DIFF',31,'Syntax:\nPERIOD_DIFF(P1,P2)\n\nReturns the number of months between periods P1 and P2. P1 and P2\nshould be in the format YYMM or YYYYMM. Note that the period arguments\nP1 and P2 are not date values.\n\nURL: https://mariadb.com/kb/en/period_diff/\n\n','MariaDB> SELECT PERIOD_DIFF(200802,200703);\n -> 11\n','https://mariadb.com/kb/en/period_diff/'),(380,'LIKE',37,'Syntax:\nexpr LIKE pat [ESCAPE \'escape_char\']\n\nPattern matching using SQL simple regular expression comparison.\nReturns 1 (TRUE) or 0 (FALSE). If either expr or pat is NULL, the\nresult is NULL.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\nURL: https://mariadb.com/kb/en/like/\n\n','MariaDB> SELECT \'David!\' LIKE \'David_\';\n -> 1\nMariaDB> SELECT \'David!\' LIKE \'%D%v%\';\n -> 1\n','https://mariadb.com/kb/en/like/'),(381,'MULTIPOINT',24,'MultiPoint(pt1,pt2,...)\n\nConstructs a MultiPoint value using Point or WKB Point arguments.\n\nURL: https://mariadb.com/kb/en/multipoint/\n\n','','https://mariadb.com/kb/en/multipoint/'),(382,'>>',19,'Syntax:\n>>\n\nShifts a longlong (BIGINT) number to the right.\n\nURL: https://mariadb.com/kb/en/shift-right/\n\n','MariaDB> SELECT 4 >> 2;\n -> 1\n','https://mariadb.com/kb/en/shift-right/'),(383,'FETCH',23,'Syntax:\nFETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...\n\nThis statement fetches the next row for the SELECT statement associated\nwith the specified cursor (which must be open), and advances the cursor\npointer. If a row exists, the fetched columns are stored in the named\nvariables. The number of columns retrieved by the SELECT statement must\nmatch the number of output variables specified in the FETCH statement.\n\nIf no more rows are available, a No Data condition occurs with SQLSTATE\nvalue \'02000\'. To detect this condition, you can set up a handler for\nit (or for a NOT FOUND condition). For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/fetch/\n\n','','https://mariadb.com/kb/en/fetch/'),(384,'AVG',16,'Syntax:\nAVG([DISTINCT] expr)\n\nReturns the average value of expr. The DISTINCT option can be used to\nreturn the average of the distinct values of expr.\n\nAVG() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/avg/\n\n','MariaDB> SELECT student_name, AVG(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/avg/'),(385,'TRUE FALSE',29,'The constants TRUE and FALSE evaluate to 1 and 0, respectively. The\nconstant names can be written in any lettercase.\n\nMariaDB> SELECT TRUE, true, FALSE, false;\n -> 1, 1, 0, 0\n\nURL: https://mariadb.com/kb/en/true-false/\n\n','','https://mariadb.com/kb/en/true-false/'),(386,'MBRWITHIN',6,'MBRWithin(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\nis within the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRContains().\n\nURL: https://mariadb.com/kb/en/mbrwithin/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nMariaDB> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n','https://mariadb.com/kb/en/mbrwithin/'),(387,'SESSION_USER',17,'Syntax:\nSESSION_USER()\n\nSESSION_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/session_user/\n\n','','https://mariadb.com/kb/en/session_user/'),(388,'IN',18,'Syntax:\nexpr IN (value,...)\n\nReturns 1 if expr is equal to any of the values in the IN list, else\nreturns 0. If all values are constants, they are evaluated according to\nthe type of expr and sorted. The search for the item then is done using\na binary search. This means IN is very quick if the IN value list\nconsists entirely of constants. Otherwise, type conversion takes place\naccording to the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the arguments.\n\nURL: https://mariadb.com/kb/en/in/\n\n','MariaDB> SELECT 2 IN (0,3,5,7);\n -> 0\nMariaDB> SELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n -> 1\n','https://mariadb.com/kb/en/in/'),(389,'QUOTE',37,'Syntax:\nQUOTE(str)\n\nQuotes a string to produce a result that can be used as a properly\nescaped data value in an SQL statement. The string is returned enclosed\nby single quotation marks and with each instance of backslash (\"\\\"),\nsingle quote (\"\'\"), ASCII NUL, and Control+Z preceded by a backslash.\nIf the argument is NULL, the return value is the word \"NULL\" without\nenclosing single quotation marks.\n\nURL: https://mariadb.com/kb/en/quote/\n\n','MariaDB> SELECT QUOTE(\'Don\\\'t!\');\n -> \'Don\\\'t!\'\nMariaDB> SELECT QUOTE(NULL);\n -> NULL\n','https://mariadb.com/kb/en/quote/'),(390,'HELP COMMAND',26,'Syntax:\nMariaDB> help search_string\n\nIf you provide an argument to the help command, mysql uses it as a\nsearch string to access server-side help from the contents of the MySQL\nReference Manual. The proper operation of this command requires that\nthe help tables in the mysql database be initialized with help topic\ninformation .\n\nIf there is no match for the search string, the search fails:\n\nMariaDB> help me\n\nNothing found\nPlease try to run \'help contents\' for a list of all accessible topics\n\nUse help contents to see a list of the help categories:\n\nMariaDB> help contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing categories:\n Account Management\n Administration\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Language Structure\n Plugins\n Storage Engines\n Stored Routines\n Table Maintenance\n Transactions\n Triggers\n\nIf the search string matches multiple items, mysql shows a list of\nmatching topics:\n\nMariaDB> help logs\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following topics:\n SHOW\n SHOW BINARY LOGS\n SHOW ENGINE\n SHOW LOGS\n\nUse a topic as the search string to see the help entry for that topic:\n\nMariaDB> help show binary logs\nName: \'SHOW BINARY LOGS\'\nDescription:\nSyntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [purge-binary-logs], that shows how\nto determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(391,'QUARTER',31,'Syntax:\nQUARTER(date)\n\nReturns the quarter of the year for date, in the range 1 to 4.\n\nURL: https://mariadb.com/kb/en/quarter/\n\n','MariaDB> SELECT QUARTER(\'2008-04-01\');\n -> 2\n','https://mariadb.com/kb/en/quarter/'),(392,'POSITION',37,'Syntax:\nPOSITION(substr IN str)\n\nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n\nURL: https://mariadb.com/kb/en/position/\n\n','','https://mariadb.com/kb/en/position/'),(393,'SHOW CREATE FUNCTION',26,'Syntax:\nSHOW CREATE FUNCTION func_name\n\nThis statement is similar to SHOW CREATE PROCEDURE but for stored\nfunctions. See [HELP SHOW CREATE PROCEDURE].\n\nURL: https://mariadb.com/kb/en/show-create-function/\n\n','','https://mariadb.com/kb/en/show-create-function/'),(394,'IS_USED_LOCK',14,'Syntax:\nIS_USED_LOCK(str)\n\nChecks whether the lock named str is in use (that is, locked). If so,\nit returns the connection identifier of the client that holds the lock.\nOtherwise, it returns NULL.\n\nURL: https://mariadb.com/kb/en/is_used_lock/\n\n','','https://mariadb.com/kb/en/is_used_lock/'),(395,'POLYFROMTEXT',3,'PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])\n\nConstructs a POLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromtext/\n\n','','https://mariadb.com/kb/en/polyfromtext/'),(396,'DES_ENCRYPT',12,'Syntax:\nDES_ENCRYPT(str[,{key_num|key_str}])\n\nEncrypts the string with the given key using the Triple-DES algorithm.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nThe encryption key to use is chosen based on the second argument to\nDES_ENCRYPT(), if one was given. With no argument, the first key from\nthe DES key file is used. With a key_num argument, the given key number\n(0 to 9) from the DES key file is used. With a key_str argument, the\ngiven key string is used to encrypt str.\n\nThe key file can be specified with the --des-key-file server option.\n\nThe return string is a binary string where the first character is\nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT() returns NULL.\n\nThe 128 is added to make it easier to recognize an encrypted key. If\nyou use a string key, key_num is 127.\n\nThe string length for the result is given by this formula:\n\nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n\nEach line in the DES key file has the following format:\n\nkey_num des_key_str\n\nEach key_num value must be a number in the range from 0 to 9. Lines in\nthe file may be in any order. des_key_str is the string that is used to\nencrypt the message. There should be at least one space between the\nnumber and the key. The first key is the default key that is used if\nyou do not specify any key argument to DES_ENCRYPT().\n\nYou can tell MySQL to read new key values from the key file with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD privilege.\n\nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted column\nvalues, without giving the end user the right to decrypt those values.\n\nURL: https://mariadb.com/kb/en/des_encrypt/\n\n','MariaDB> SELECT customer_address FROM customer_table \n > WHERE crypted_credit_card = DES_ENCRYPT(\'credit_card_number\');\n','https://mariadb.com/kb/en/des_encrypt/'),(397,'CEIL',4,'Syntax:\nCEIL(X)\n\nCEIL() is a synonym for CEILING().\n\nURL: https://mariadb.com/kb/en/ceil/\n\n','','https://mariadb.com/kb/en/ceil/'),(398,'LENGTH',37,'Syntax:\nLENGTH(str)\n\nReturns the length of the string str, measured in bytes. A multi-byte\ncharacter counts as multiple bytes. This means that for a string\ncontaining five 2-byte characters, LENGTH() returns 10, whereas\nCHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/length/\n\n','MariaDB> SELECT LENGTH(\'text\');\n -> 4\n','https://mariadb.com/kb/en/length/'),(399,'STR_TO_DATE',31,'Syntax:\nSTR_TO_DATE(str,format)\n\nThis is the inverse of the DATE_FORMAT() function. It takes a string\nstr and a format string format. STR_TO_DATE() returns a DATETIME value\nif the format string contains both date and time parts, or a DATE or\nTIME value if the string contains only date or time parts. If the date,\ntime, or datetime value extracted from str is illegal, STR_TO_DATE()\nreturns NULL and produces a warning.\n\nThe server scans str attempting to match format to it. The format\nstring can contain literal characters and format specifiers beginning\nwith %. Literal characters in format must match literally in str.\nFormat specifiers in format must match a date or time part in str. For\nthe specifiers that can be used in format, see the DATE_FORMAT()\nfunction description.\n\nMariaDB> SELECT STR_TO_DATE(\'01,5,2013\',\'%d,%m,%Y\');\n -> \'2013-05-01\'\nMariaDB> SELECT STR_TO_DATE(\'May 1, 2013\',\'%M %d,%Y\');\n -> \'2013-05-01\'\n\nScanning starts at the beginning of str and fails if format is found\nnot to match. Extra characters at the end of str are ignored.\n\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'a%h:%i:%s\');\n -> \'09:30:17\'\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'%h:%i:%s\');\n -> NULL\nMariaDB> SELECT STR_TO_DATE(\'09:30:17a\',\'%h:%i:%s\');\n -> \'09:30:17\'\n\nUnspecified date or time parts have a value of 0, so incompletely\nspecified values in str produce a result with some or all parts set to\n0:\n\nMariaDB> SELECT STR_TO_DATE(\'abc\',\'abc\');\n -> \'0000-00-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%m\');\n -> \'0000-09-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%s\');\n -> \'00:00:09\'\n\nURL: https://mariadb.com/kb/en/str_to_date/\n\n','','https://mariadb.com/kb/en/str_to_date/'),(400,'Y',11,'Y(p)\n\nReturns the Y-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/y/\n\n','MariaDB> SELECT Y(POINT(56.7, 53.34));\n+-----------------------+\n| Y(POINT(56.7, 53.34)) |\n+-----------------------+\n| 53.34 |\n+-----------------------+\n','https://mariadb.com/kb/en/y/'),(401,'CHECKSUM TABLE',20,'Syntax:\nCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]\n\nCHECKSUM TABLE reports a table checksum. This statement requires the\nSELECT privilege for the table.\n\nWith QUICK, the live table checksum is reported if it is available, or\nNULL otherwise. This is very fast. A live checksum is enabled by\nspecifying the CHECKSUM=1 table option when you create the table;\ncurrently, this is supported only for MyISAM tables. See [HELP CREATE\nTABLE].\n\nWith EXTENDED, the entire table is read row by row and the checksum is\ncalculated. This can be very slow for large tables.\n\nIf neither QUICK nor EXTENDED is specified, MySQL returns a live\nchecksum if the table storage engine supports it and scans the table\notherwise.\n\nFor a nonexistent table, CHECKSUM TABLE returns NULL and generates a\nwarning.\n\nIn MySQL 5.5, CHECKSUM TABLE returns 0 for partitioned tables unless\nyou include the EXTENDED option. This issue is resolved in MySQL 5.6.\n(Bug #11933226, Bug #60681)\n\nThe checksum value depends on the table row format. If the row format\nchanges, the checksum also changes. For example, the storage format for\nVARCHAR changed between MySQL 4.1 and 5.0, so if a 4.1 table is\nupgraded to MySQL 5.0, the checksum value may change.\n\nURL: https://mariadb.com/kb/en/checksum-table/\n\n','','https://mariadb.com/kb/en/checksum-table/'),(402,'NUMINTERIORRINGS',2,'NumInteriorRings(poly)\n\nReturns the number of interior rings in the Polygon value poly.\n\nURL: https://mariadb.com/kb/en/numinteriorrings/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n','https://mariadb.com/kb/en/numinteriorrings/'),(403,'INTERIORRINGN',2,'InteriorRingN(poly,N)\n\nReturns the N-th interior ring for the Polygon value poly as a\nLineString. Rings are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/interiorringn/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n','https://mariadb.com/kb/en/interiorringn/'),(404,'UTC_TIME',31,'Syntax:\nUTC_TIME, UTC_TIME()\n\nReturns the current UTC time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_time/\n\n','MariaDB> SELECT UTC_TIME(), UTC_TIME() + 0;\n -> \'18:07:53\', 180753.000000\n','https://mariadb.com/kb/en/utc_time/'),(405,'DROP FUNCTION',39,'The DROP FUNCTION statement is used to drop stored functions and\nuser-defined functions (UDFs):\n\no For information about dropping stored functions, see [HELP DROP\n PROCEDURE].\n\no For information about dropping user-defined functions, see [HELP DROP\n FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/drop-function/\n\n','','https://mariadb.com/kb/en/drop-function/'),(406,'ALTER EVENT',39,'Syntax:\nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO event_body]\n\nThe ALTER EVENT statement changes one or more of the characteristics of\nan existing event without the need to drop and recreate it. The syntax\nfor each of the DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE /\nDISABLE, and DO clauses is exactly the same as when used with CREATE\nEVENT. (See [HELP CREATE EVENT].)\n\nAny user can alter an event defined on a database for which that user\nhas the EVENT privilege. When a user executes a successful ALTER EVENT\nstatement, that user becomes the definer for the affected event.\n\nALTER EVENT works only with an existing event:\n\nMariaDB> ALTER EVENT no_such_event \n > ON SCHEDULE \n > EVERY \'2:3\' DAY_HOUR;\nERROR 1517 (HY000): Unknown event \'no_such_event\'\n\nURL: https://mariadb.com/kb/en/alter-event/\n\n','','https://mariadb.com/kb/en/alter-event/'),(407,'STDDEV',16,'Syntax:\nSTDDEV(expr)\n\nReturns the population standard deviation of expr. This function is\nprovided for compatibility with Oracle. The standard SQL function\nSTDDEV_POP() can be used instead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev/\n\n','','https://mariadb.com/kb/en/stddev/'),(408,'DATE_SUB',31,'Syntax:\nDATE_SUB(date,INTERVAL expr unit)\n\nSee the description for DATE_ADD().\n\nURL: https://mariadb.com/kb/en/date_sub/\n\n','','https://mariadb.com/kb/en/date_sub/'),(409,'PERIOD_ADD',31,'Syntax:\nPERIOD_ADD(P,N)\n\nAdds N months to period P (in the format YYMM or YYYYMM). Returns a\nvalue in the format YYYYMM. Note that the period argument P is not a\ndate value.\n\nURL: https://mariadb.com/kb/en/period_add/\n\n','MariaDB> SELECT PERIOD_ADD(200801,2);\n -> 200803\n','https://mariadb.com/kb/en/period_add/'),(410,'|',19,'Syntax:\n|\n\nBitwise OR:\n\nURL: https://mariadb.com/kb/en/bitwise-or/\n\n','MariaDB> SELECT 29 | 15;\n -> 31\n','https://mariadb.com/kb/en/bitwise-or/'),(411,'GEOMFROMTEXT',3,'GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])\n\nConstructs a geometry value of any type using its WKT representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromtext/\n\n','','https://mariadb.com/kb/en/geomfromtext/'),(412,'UUID_SHORT',14,'Syntax:\nUUID_SHORT()\n\nReturns a \"short\" universal identifier as a 64-bit unsigned integer\n(rather than a string-form 128-bit identifier as returned by the UUID()\nfunction).\n\nThe value of UUID_SHORT() is guaranteed to be unique if the following\nconditions hold:\n\no The server_id of the current host is unique among your set of master\n and slave servers\n\no server_id is between 0 and 255\n\no You do not set back your system time for your server between mysqld\n restarts\n\no You do not invoke UUID_SHORT() on average more than 16 million times\n per second between mysqld restarts\n\nThe UUID_SHORT() return value is constructed this way:\n\n (server_id & 255) << 56\n+ (server_startup_time_in_seconds << 24)\n+ incremented_variable++;\n\nURL: https://mariadb.com/kb/en/uuid_short/\n\n','MariaDB> SELECT UUID_SHORT();\n -> 92395783831158784\n','https://mariadb.com/kb/en/uuid_short/'),(413,'RIGHT',37,'Syntax:\nRIGHT(str,len)\n\nReturns the rightmost len characters from the string str, or NULL if\nany argument is NULL.\n\nURL: https://mariadb.com/kb/en/right/\n\n','MariaDB> SELECT RIGHT(\'foobarbar\', 4);\n -> \'rbar\'\n','https://mariadb.com/kb/en/right/'),(414,'DATEDIFF',31,'Syntax:\nDATEDIFF(expr1,expr2)\n\nDATEDIFF() returns expr1 - expr2 expressed as a value in days from one\ndate to the other. expr1 and expr2 are date or date-and-time\nexpressions. Only the date parts of the values are used in the\ncalculation.\n\nURL: https://mariadb.com/kb/en/datediff/\n\n','MariaDB> SELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n -> 1\nMariaDB> SELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n -> -31\n','https://mariadb.com/kb/en/datediff/'),(415,'DROP TABLESPACE',39,'Syntax:\nDROP TABLESPACE tablespace_name\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/drop-tablespace/\n\n','','https://mariadb.com/kb/en/drop-tablespace/'),(416,'DROP PROCEDURE',39,'Syntax:\nDROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name\n\nThis statement is used to drop a stored procedure or function. That is,\nthe specified routine is removed from the server. You must have the\nALTER ROUTINE privilege for the routine. (If the\nautomatic_sp_privileges system variable is enabled, that privilege and\nEXECUTE are granted automatically to the routine creator when the\nroutine is created and dropped from the creator when the routine is\ndropped. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n)\n\nThe IF EXISTS clause is a MySQL extension. It prevents an error from\noccurring if the procedure or function does not exist. A warning is\nproduced that can be viewed with SHOW WARNINGS.\n\nURL: https://mariadb.com/kb/en/drop-procedure/\n\n','','https://mariadb.com/kb/en/drop-procedure/'),(417,'CHECK TABLE',20,'Syntax:\nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n\noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED}\n\nCHECK TABLE checks a table or tables for errors. CHECK TABLE works for\nInnoDB, MyISAM, ARCHIVE, and CSV tables. For MyISAM tables, the key\nstatistics are updated as well.\n\nTo check a table, you must have some privilege for it.\n\nCHECK TABLE can also check views for problems, such as tables that are\nreferenced in the view definition that no longer exist.\n\nCHECK TABLE is supported for partitioned tables, and you can use ALTER\nTABLE ... CHECK PARTITION to check one or more partitions; for more\ninformation, see [HELP ALTER TABLE].\n\nURL: https://mariadb.com/kb/en/sql-commands-check-table/\n\n','','https://mariadb.com/kb/en/sql-commands-check-table/'),(418,'BIN',37,'Syntax:\nBIN(N)\n\nReturns a string representation of the binary value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,2). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/bin/\n\n','MariaDB> SELECT BIN(12);\n -> \'1100\'\n','https://mariadb.com/kb/en/bin/'),(419,'INSTALL PLUGIN',5,'Syntax:\nINSTALL PLUGIN plugin_name SONAME \'shared_library_name\'\n\nThis statement installs a server plugin. It requires the INSERT\nprivilege for the mysql.plugin table.\n\nplugin_name is the name of the plugin as defined in the plugin\ndescriptor structure contained in the library file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/plugin-data-structures.html).\nPlugin names are not case sensitive. For maximal compatibility, plugin\nnames should be limited to ASCII letters, digits, and underscore\nbecause they are used in C source files, shell command lines, M4 and\nBourne shell scripts, and SQL environments.\n\nshared_library_name is the name of the shared library that contains the\nplugin code. The name includes the file name extension (for example,\nlibmyplugin.so, libmyplugin.dll, or libmyplugin.dylib).\n\nThe shared library must be located in the plugin directory (the\ndirectory named by the plugin_dir system variable). The library must be\nin the plugin directory itself, not in a subdirectory. By default,\nplugin_dir is the plugin directory under the directory named by the\npkglibdir configuration variable, but it can be changed by setting the\nvalue of plugin_dir at server startup. For example, set its value in a\nmy.cnf file:\n\n[mysqld]\nplugin_dir=/path/to/plugin/directory\n\nIf the value of plugin_dir is a relative path name, it is taken to be\nrelative to the MySQL base directory (the value of the basedir system\nvariable).\n\nINSTALL PLUGIN loads and initializes the plugin code to make the plugin\navailable for use. A plugin is initialized by executing its\ninitialization function, which handles any setup that the plugin must\nperform before it can be used. When the server shuts down, it executes\nthe deinitialization function for each plugin that is loaded so that\nthe plugin has a change to perform any final cleanup.\n\nINSTALL PLUGIN also registers the plugin by adding a line that\nindicates the plugin name and library file name to the mysql.plugin\ntable. At server startup, the server loads and initializes any plugin\nthat is listed in the mysql.plugin table. This means that a plugin is\ninstalled with INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the server is\nstarted with the --skip-grant-tables option.\n\nA plugin library can contain multiple plugins. For each of them to be\ninstalled, use a separate INSTALL PLUGIN statement. Each statement\nnames a different plugin, but all of them specify the same library\nname.\n\nURL: https://mariadb.com/kb/en/install-plugin/\n\n','','https://mariadb.com/kb/en/install-plugin/'),(420,'DECLARE CURSOR',23,'Syntax:\nDECLARE cursor_name CURSOR FOR select_statement\n\nThis statement declares a cursor and associates it with a SELECT\nstatement that retrieves the rows to be traversed by the cursor. To\nfetch the rows later, use a FETCH statement. The number of columns\nretrieved by the SELECT statement must match the number of output\nvariables specified in the FETCH statement.\n\nThe SELECT statement cannot have an INTO clause.\n\nCursor declarations must appear before handler declarations and after\nvariable and condition declarations.\n\nA stored program may contain multiple cursor declarations, but each\ncursor declared in a given block must have a unique name. For an\nexample, see https://mariadb.com/kb/en/programmatic-and-compound-statements-cursors/.\n\nFor information available through SHOW statements, it is possible in\nmany cases to obtain equivalent information by using a cursor with an\nINFORMATION_SCHEMA table.\n\nURL: https://mariadb.com/kb/en/declare-cursor/\n\n','','https://mariadb.com/kb/en/declare-cursor/'),(421,'LOAD DATA',27,'Syntax:\nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number {LINES | ROWS}]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD DATA INFILE statement reads rows from a text file into a table\nat a very high speed. The file name must be given as a literal string.\n\nLOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. (See\nhttps://mariadb.com/kb/en/select-into/.) To write data\nfrom a table to a file, use SELECT ... INTO OUTFILE. To read the file\nback into a table, use LOAD DATA INFILE. The syntax of the FIELDS and\nLINES clauses is the same for both statements. Both clauses are\noptional, but FIELDS must precede LINES if both are specified.\n\nFor more information about the efficiency of INSERT versus LOAD DATA\nINFILE and speeding up LOAD DATA INFILE, see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-speed.html.\n\nThe character set indicated by the character_set_database system\nvariable is used to interpret the information in the file. SET NAMES\nand the setting of character_set_client do not affect interpretation of\ninput. If the contents of the input file use a character set that\ndiffers from the default, it is usually preferable to specify the\ncharacter set of the file by using the CHARACTER SET clause. A\ncharacter set of binary specifies \"no conversion.\"\n\nLOAD DATA INFILE interprets all fields in the file as having the same\ncharacter set, regardless of the data types of the columns into which\nfield values are loaded. For proper interpretation of file contents,\nyou must ensure that it was written with the correct character set. For\nexample, if you write a data file with mysqldump -T or by issuing a\nSELECT ... INTO OUTFILE statement in mysql, be sure to use a\n--default-character-set option with mysqldump or mysql so that output\nis written in the character set to be used when the file is loaded with\nLOAD DATA INFILE.\n\n*Note*: It is not possible to load data files that use the ucs2, utf16,\nor utf32 character set.\n\nThe character_set_filesystem system variable controls the\ninterpretation of the file name.\n\nYou can also load data files by using the mysqlimport utility; it\noperates by sending a LOAD DATA INFILE statement to the server. The\n--local option causes mysqlimport to read data files from the client\nhost. You can specify the --compress option to get better performance\nover slow networks if the client and server support the compressed\nprotocol. See https://mariadb.com/kb/en/mysqlimport/.\n\nIf you use LOW_PRIORITY, execution of the LOAD DATA statement is\ndelayed until no other clients are reading from the table. This affects\nonly storage engines that use only table-level locking (such as MyISAM,\nMEMORY, and MERGE).\n\nIf you specify CONCURRENT with a MyISAM table that satisfies the\ncondition for concurrent inserts (that is, it contains no free blocks\nin the middle), other threads can retrieve data from the table while\nLOAD DATA is executing. Using this option affects the performance of\nLOAD DATA a bit, even if no other thread is using the table at the same\ntime.\n\nPrior to MySQL 5.5.1, CONCURRENT was not replicated when using\nstatement-based replication (see Bug #34628). However, it is replicated\nwhen using row-based replication, regardless of the version. See\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-features-load-data.h\ntml, for more information.\n\nThe LOCAL keyword, if specified, is interpreted with respect to the\nclient end of the connection:\n\no If LOCAL is specified, the file is read by the client program on the\n client host and sent to the server. The file can be given as a full\n path name to specify its exact location. If given as a relative path\n name, the name is interpreted relative to the directory in which the\n client program was started.\n\n When using LOCAL with LOAD DATA, a copy of the file is created in the\n server\'s temporary directory. This is not the directory determined by\n the value of tmpdir or slave_load_tmpdir, but rather the operating\n system\'s temporary directory, and is not configurable in the MySQL\n Server. (Typically the system temporary directory is /tmp on Linux\n systems and C:\\WINDOWS\\TEMP on Windows.) Lack of sufficient space for\n the copy in this directory can cause the LOAD DATA LOCAL statement to\n fail.\n\no If LOCAL is not specified, the file must be located on the server\n host and is read directly by the server. The server uses the\n following rules to locate the file:\n\n o If the file name is an absolute path name, the server uses it as\n given.\n\n o If the file name is a relative path name with one or more leading\n components, the server searches for the file relative to the\n server\'s data directory.\n\n o If a file name with no leading components is given, the server\n looks for the file in the database directory of the default\n database.\n\nNote that, in the non-LOCAL case, these rules mean that a file named as\n./myfile.txt is read from the server\'s data directory, whereas the file\nnamed as myfile.txt is read from the database directory of the default\ndatabase. For example, if db1 is the default database, the following\nLOAD DATA statement reads the file data.txt from the database directory\nfor db1, even though the statement explicitly loads the file into a\ntable in the db2 database:\n\nLOAD DATA INFILE \'data.txt\' INTO TABLE db2.my_table;\n\nWindows path names are specified using forward slashes rather than\nbackslashes. If you do use backslashes, you must double them.\n\nFor security reasons, when reading text files located on the server,\nthe files must either reside in the database directory or be readable\nby all. Also, to use LOAD DATA INFILE on server files, you must have\nthe FILE privilege. See\nhttps://mariadb.com/kb/en/grant/. For\nnon-LOCAL load operations, if the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nURL: https://mariadb.com/kb/en/load-data-infile/\n\n','','https://mariadb.com/kb/en/load-data-infile/'),(422,'MULTILINESTRING',24,'MultiLineString(ls1,ls2,...)\n\nConstructs a MultiLineString value using LineString or WKB LineString\narguments.\n\nURL: https://mariadb.com/kb/en/multilinestring/\n\n','','https://mariadb.com/kb/en/multilinestring/'),(423,'LOCALTIME',31,'Syntax:\nLOCALTIME, LOCALTIME()\n\nLOCALTIME and LOCALTIME() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtime/\n\n','','https://mariadb.com/kb/en/localtime/'),(424,'SHOW RELAYLOG EVENTS',26,'Syntax:\nSHOW RELAYLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the relay log of a replication slave. If you do not\nspecify \'log_name\', the first relay log is displayed. This statement\nhas no effect on the master.\n\nURL: https://mariadb.com/kb/en/show-relaylog-events/\n\n','','https://mariadb.com/kb/en/show-relaylog-events/'),(425,'MPOINTFROMTEXT',3,'MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])\n\nConstructs a MULTIPOINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromtext/\n\n','','https://mariadb.com/kb/en/mpointfromtext/'),(426,'BLOB',22,'BLOB[(M)]\n\nA BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each\nBLOB value is stored using a 2-byte length prefix that indicates the\nnumber of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest BLOB type large enough to hold\nvalues M bytes long.\n\nURL: https://mariadb.com/kb/en/blob/\n\n','','https://mariadb.com/kb/en/blob/'),(427,'SHA1',12,'Syntax:\nSHA1(str), SHA(str)\n\nCalculates an SHA-1 160-bit checksum for the string, as described in\nRFC 3174 (Secure Hash Algorithm). The value is returned as a string of\n40 hex digits, or NULL if the argument was NULL. One of the possible\nuses for this function is as a hash key. See the notes at the beginning\nof this section about storing hash values efficiently. You can also use\nSHA1() as a cryptographic function for storing passwords. SHA() is\nsynonymous with SHA1().\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha1/\n\n','MariaDB> SELECT SHA1(\'abc\');\n -> \'a9993e364706816aba3e25717850c26c9cd0d89d\'\n','https://mariadb.com/kb/en/sha1/'),(428,'SUBSTR',37,'Syntax:\nSUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str\nFROM pos FOR len)\n\nSUBSTR() is a synonym for SUBSTRING().\n\nURL: https://mariadb.com/kb/en/substr/\n\n','','https://mariadb.com/kb/en/substr/'),(429,'PASSWORD',12,'Syntax:\nPASSWORD(str)\n\nCalculates and returns a hashed password string from the plaintext\npassword str and returns a nonbinary string in the connection character\nset (a binary string before MySQL 5.5.3), or NULL if the argument is\nNULL. This function is the SQL interface to the algorithm used by the\nserver to encrypt MySQL passwords for storage in the mysql.user grant\ntable.\n\nThe password hashing method used by PASSWORD() depends on the value of\nthe old_passwords system variable:\n\nURL: https://mariadb.com/kb/en/password/\n\n','MariaDB> SET old_passwords = 0;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+-------------------------------------------+\n| PASSWORD(\'mypass\') |\n+-------------------------------------------+\n| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |\n+-------------------------------------------+\n\nMariaDB> SET old_passwords = 1;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+--------------------+\n| PASSWORD(\'mypass\') |\n+--------------------+\n| 6f8c114b58f2ce9e |\n+--------------------+\n','https://mariadb.com/kb/en/password/'),(430,'CHAR',22,'[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA fixed-length string that is always right-padded with spaces to the\nspecified length when stored. M represents the column length in\ncharacters. The range of M is 0 to 255. If M is omitted, the length is\n1.\n\n*Note*: Trailing spaces are removed when CHAR values are retrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n\nURL: https://mariadb.com/kb/en/char/\n\n','','https://mariadb.com/kb/en/char/'),(431,'UTC_DATE',31,'Syntax:\nUTC_DATE, UTC_DATE()\n\nReturns the current UTC date as a value in \'YYYY-MM-DD\' or YYYYMMDD\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_date/\n\n','MariaDB> SELECT UTC_DATE(), UTC_DATE() + 0;\n -> \'2003-08-14\', 20030814\n','https://mariadb.com/kb/en/utc_date/'),(432,'DIMENSION',36,'Dimension(g)\n\nReturns the inherent dimension of the geometry value g. The result can\nbe -1, 0, 1, or 2. The meaning of these values is given in\nhttps://mariadb.com/kb/en/dimension/.\n\nURL: https://mariadb.com/kb/en/dimension/\n\n','MariaDB> SELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n','https://mariadb.com/kb/en/dimension/'),(433,'COUNT DISTINCT',16,'Syntax:\nCOUNT(DISTINCT expr,[expr...])\n\nReturns a count of the number of rows with different non-NULL expr\nvalues.\n\nCOUNT(DISTINCT) returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count-distinct/\n\n','MariaDB> SELECT COUNT(DISTINCT results) FROM student;\n','https://mariadb.com/kb/en/count-distinct/'),(434,'BIT',22,'BIT[(M)]\n\nA bit-field type. M indicates the number of bits per value, from 1 to\n64. The default is 1 if M is omitted.\n\nURL: https://mariadb.com/kb/en/bit/\n\n','','https://mariadb.com/kb/en/bit/'),(435,'EQUALS',30,'Equals(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially equal to g2.\n\nURL: https://mariadb.com/kb/en/equals/\n\n','','https://mariadb.com/kb/en/equals/'),(436,'SHOW CREATE VIEW',26,'Syntax:\nSHOW CREATE VIEW view_name\n\nThis statement shows a CREATE VIEW statement that creates the given\nview.\n\nURL: https://mariadb.com/kb/en/show-create-view/\n\n','','https://mariadb.com/kb/en/show-create-view/'),(437,'INTERVAL',18,'Syntax:\nINTERVAL(N,N1,N2,N3,...)\n\nReturns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All\narguments are treated as integers. It is required that N1 < N2 < N3 <\n... < Nn for this function to work correctly. This is because a binary\nsearch is used (very fast).\n\nURL: https://mariadb.com/kb/en/interval/\n\n','MariaDB> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\n -> 3\nMariaDB> SELECT INTERVAL(10, 1, 10, 100, 1000);\n -> 2\nMariaDB> SELECT INTERVAL(22, 23, 30, 44, 200);\n -> 0\n','https://mariadb.com/kb/en/interval/'),(438,'FROM_DAYS',31,'Syntax:\nFROM_DAYS(N)\n\nGiven a day number N, returns a DATE value.\n\nURL: https://mariadb.com/kb/en/from_days/\n\n','MariaDB> SELECT FROM_DAYS(730669);\n -> \'2007-07-03\'\n','https://mariadb.com/kb/en/from_days/'),(439,'ALTER PROCEDURE',39,'Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nURL: https://mariadb.com/kb/en/alter-procedure/\n\n','','https://mariadb.com/kb/en/alter-procedure/'),(440,'BIT_COUNT',19,'Syntax:\nBIT_COUNT(N)\n\nReturns the number of bits that are set in the argument N.\n\nURL: https://mariadb.com/kb/en/bit_count/\n\n','MariaDB> SELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n -> 4, 3\n','https://mariadb.com/kb/en/bit_count/'),(441,'OCTET_LENGTH',37,'Syntax:\nOCTET_LENGTH(str)\n\nOCTET_LENGTH() is a synonym for LENGTH().\n\nURL: https://mariadb.com/kb/en/octet_length/\n\n','','https://mariadb.com/kb/en/octet_length/'),(442,'UTC_TIMESTAMP',31,'Syntax:\nUTC_TIMESTAMP, UTC_TIMESTAMP()\n\nReturns the current UTC date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is used in a string or numeric context.\n\nURL: https://mariadb.com/kb/en/utc_timestamp/\n\n','MariaDB> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n -> \'2003-08-14 18:08:04\', 20030814180804.000000\n','https://mariadb.com/kb/en/utc_timestamp/'),(443,'AES_ENCRYPT',12,'Syntax:\nAES_ENCRYPT(str,key_str)\n\nAES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of\ndata using the official AES (Advanced Encryption Standard) algorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit key length is\nused, but you can extend it up to 256 bits by modifying the source. We\nchose 128 bits because it is much faster and it is secure enough for\nmost purposes.\n\nAES_ENCRYPT() encrypts a string and returns a binary string.\nAES_DECRYPT() decrypts the encrypted string and returns the original\nstring. The input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n\nBecause AES is a block-level algorithm, padding is used to encode\nuneven length strings and so the result string length may be calculated\nusing this formula:\n\n16 * (trunc(string_length / 16) + 1)\n\nIf AES_DECRYPT() detects invalid data or incorrect padding, it returns\nNULL. However, it is possible for AES_DECRYPT() to return a non-NULL\nvalue (possibly garbage) if the input data or the key is invalid.\n\nYou can use the AES functions to store data in an encrypted form by\nmodifying your queries:\n\nURL: https://mariadb.com/kb/en/aes_encrypt/\n\n','INSERT INTO t VALUES (1,AES_ENCRYPT(\'text\',\'password\'));\n','https://mariadb.com/kb/en/aes_encrypt/'),(444,'+',4,'Syntax:\n+\n\nAddition:\n\nURL: https://mariadb.com/kb/en/addition-operator/\n\n','MariaDB> SELECT 3+5;\n -> 8\n','https://mariadb.com/kb/en/addition-operator/'),(445,'INET_NTOA',14,'Syntax:\nINET_NTOA(expr)\n\nGiven a numeric IPv4 network address in network byte order, returns the\ndotted-quad representation of the address as a string. INET_NTOA()\nreturns NULL if it does not understand its argument.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/inet_ntoa/\n\n','MariaDB> SELECT INET_NTOA(167773449);\n -> \'10.0.5.9\'\n','https://mariadb.com/kb/en/inet_ntoa/'),(446,'ACOS',4,'Syntax:\nACOS(X)\n\nReturns the arc cosine of X, that is, the value whose cosine is X.\nReturns NULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/acos/\n\n','MariaDB> SELECT ACOS(1);\n -> 0\nMariaDB> SELECT ACOS(1.0001);\n -> NULL\nMariaDB> SELECT ACOS(0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/acos/'),(447,'ISOLATION',8,'Syntax:\nSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL\n {\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n }\n\nThis statement sets the transaction isolation level, used for\noperations on InnoDB tables.\n\nScope of the Isolation Level\n\nYou can set the isolation level globally, for the current session, or\nfor the next transaction:\n\no With the GLOBAL keyword, the statement sets the default transaction\n level globally for all subsequent sessions. Existing sessions are\n unaffected.\n\no With the SESSION keyword, the statement sets the default transaction\n level for all subsequent transactions performed within the current\n session.\n\no Without any SESSION or GLOBAL keyword, the statement sets the\n isolation level for the next (not started) transaction performed\n within the current session.\n\nA change to the global default isolation level requires the SUPER\nprivilege. Any session is free to change its session isolation level\n(even in the middle of a transaction), or the isolation level for its\nnext transaction.\n\nSET TRANSACTION ISOLATION LEVEL without GLOBAL or SESSION is not\npermitted while there is an active transaction:\n\nMariaDB> START TRANSACTION;\nQuery OK, 0 rows affected (0.02 sec)\n\nMariaDB> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction isolation level can\'t be changed\nwhile a transaction is in progress\n\nTo set the global default isolation level at server startup, use the\n--transaction-isolation=level option to mysqld on the command line or\nin an option file. Values of level for this option use dashes rather\nthan spaces, so the permissible values are READ-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example, to set\nthe default isolation level to REPEATABLE READ, use these lines in the\n[mysqld] section of an option file:\n\n[mysqld]\ntransaction-isolation = REPEATABLE-READ\n\nIt is possible to check or set the global and session transaction\nisolation levels at runtime by using the tx_isolation system variable:\n\nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\nSET GLOBAL tx_isolation=\'REPEATABLE-READ\';\nSET SESSION tx_isolation=\'SERIALIZABLE\';\n\nDetails and Usage of Isolation Levels\n\nInnoDB supports each of the transaction isolation levels described here\nusing different locking strategies. You can enforce a high degree of\nconsistency with the default REPEATABLE READ level, for operations on\ncrucial data where ACID compliance is important. Or you can relax the\nconsistency rules with READ COMMITTED or even READ UNCOMMITTED, in\nsituations such as bulk reporting where precise consistency and\nrepeatable results are less important than minimizing the amount of\noverhead for locking. SERIALIZABLE enforces even stricter rules than\nREPEATABLE READ, and is used mainly in specialized situations, such as\nwith XA transactions and for troubleshooting issues with concurrency\nand deadlocks.\n\nFor full information about how these isolation levels work with InnoDB\ntransactions, see\nhttp://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html.\nIn particular, for additional information about InnoDB record-level\nlocks and how it uses them to execute various types of statements, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html\nand http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html.\n\nThe following list describes how MySQL supports the different\ntransaction levels. The list goes from the most commonly used level to\nthe least used.\n\no REPEATABLE READ\n\n This is the default isolation level for InnoDB. For consistent reads,\n there is an important difference from the READ COMMITTED isolation\n level: All consistent reads within the same transaction read the\n snapshot established by the first read. This convention means that if\n you issue several plain (nonlocking) SELECT statements within the\n same transaction, these SELECT statements are consistent also with\n respect to each other. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n UPDATE, and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition, or a\n range-type search condition. For a unique index with a unique search\n condition, InnoDB locks only the index record found, not the gap\n before it. For other search conditions, InnoDB locks the index range\n scanned, using gap locks or next-key (gap plus index-record) locks to\n block insertions by other sessions into the gaps covered by the\n range.\n\no READ COMMITTED\n\n A somewhat Oracle-like isolation level with respect to consistent\n (nonlocking) reads: Each consistent read, even within the same\n transaction, sets and reads its own fresh snapshot. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n InnoDB locks only index records, not the gaps before them, and thus\n permits the free insertion of new records next to locked records. For\n UPDATE and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition (such as\n WHERE id = 100), or a range-type search condition (such as WHERE id >\n 100). For a unique index with a unique search condition, InnoDB locks\n only the index record found, not the gap before it. For range-type\n searches, InnoDB locks the index range scanned, using gap locks or\n next-key (gap plus index-record) locks to block insertions by other\n sessions into the gaps covered by the range. This is necessary\n because \"phantom rows\" must be blocked for MySQL replication and\n recovery to work.\n\n *Note*: In MySQL 5.5, if the READ COMMITTED isolation level is used\n or the innodb_locks_unsafe_for_binlog system variable is enabled,\n there is no InnoDB gap locking except for foreign-key constraint\n checking and duplicate-key checking. Also, record locks for\n nonmatching rows are released after MySQL has evaluated the WHERE\n condition. If you use READ COMMITTED or enable\n innodb_locks_unsafe_for_binlog, you must use row-based binary\n logging.\n\no READ UNCOMMITTED\n\n SELECT statements are performed in a nonlocking fashion, but a\n possible earlier version of a row might be used. Thus, using this\n isolation level, such reads are not consistent. This is also called a\n \"dirty read.\" Otherwise, this isolation level works like READ\n COMMITTED.\n\no SERIALIZABLE\n\n This level is like REPEATABLE READ, but InnoDB implicitly converts\n all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if\n autocommit is disabled. If autocommit is enabled, the SELECT is its\n own transaction. It therefore is known to be read only and can be\n serialized if performed as a consistent (nonlocking) read and need\n not block for other transactions. (To force a plain SELECT to block\n if other transactions have modified the selected rows, disable\n autocommit.)\n\nURL: https://mariadb.com/kb/en/set-transaction-isolation-level/\n\n','','https://mariadb.com/kb/en/set-transaction-isolation-level/'),(448,'CEILING',4,'Syntax:\nCEILING(X)\n\nReturns the smallest integer value not less than X.\n\nURL: https://mariadb.com/kb/en/ceiling/\n\n','MariaDB> SELECT CEILING(1.23);\n -> 2\nMariaDB> SELECT CEILING(-1.23);\n -> -1\n','https://mariadb.com/kb/en/ceiling/'),(449,'SIN',4,'Syntax:\nSIN(X)\n\nReturns the sine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/sin/\n\n','MariaDB> SELECT SIN(PI());\n -> 1.2246063538224e-16\nMariaDB> SELECT ROUND(SIN(PI()));\n -> 0\n','https://mariadb.com/kb/en/sin/'),(450,'DAYOFWEEK',31,'Syntax:\nDAYOFWEEK(date)\n\nReturns the weekday index for date (1 = Sunday, 2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC standard.\n\nURL: https://mariadb.com/kb/en/dayofweek/\n\n','MariaDB> SELECT DAYOFWEEK(\'2007-02-03\');\n -> 7\n','https://mariadb.com/kb/en/dayofweek/'),(451,'SHOW PROCESSLIST',26,'Syntax:\nSHOW [FULL] PROCESSLIST\n\nSHOW PROCESSLIST shows you which threads are running. You can also get\nthis information from the INFORMATION_SCHEMA PROCESSLIST table or the\nmysqladmin processlist command. If you have the PROCESS privilege, you\ncan see all threads. Otherwise, you can see only your own threads (that\nis, threads associated with the MySQL account that you are using). If\nyou do not use the FULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n\nURL: https://mariadb.com/kb/en/show-processlist/\n\n','','https://mariadb.com/kb/en/show-processlist/'),(452,'LINEFROMWKB',32,'LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])\n\nConstructs a LINESTRING value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromwkb/\n\n','','https://mariadb.com/kb/en/linefromwkb/'),(453,'GEOMETRYTYPE',36,'GeometryType(g)\n\nReturns as a binary string the name of the geometry type of which the\ngeometry instance g is a member. The name corresponds to one of the\ninstantiable Geometry subclasses.\n\nURL: https://mariadb.com/kb/en/geometrytype/\n\n','MariaDB> SELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n','https://mariadb.com/kb/en/geometrytype/'),(454,'CREATE VIEW',39,'Syntax:\nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThe CREATE VIEW statement creates a new view, or replaces an existing\none if the OR REPLACE clause is given. If the view does not exist,\nCREATE OR REPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR REPLACE VIEW is the same as ALTER VIEW.\n\nThe select_statement is a SELECT statement that provides the definition\nof the view. (When you select from the view, you select in effect using\nthe SELECT statement.) select_statement can select from base tables or\nother views.\n\nThe view definition is \"frozen\" at creation time, so changes to the\nunderlying tables afterward do not affect the view definition. For\nexample, if a view is defined as SELECT * on a table, new columns added\nto the table later do not become part of the view.\n\nThe ALGORITHM clause affects how MySQL processes the view. The DEFINER\nand SQL SECURITY clauses specify the security context to be used when\nchecking access privileges at view invocation time. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates to rows in\ntables referenced by the view. These clauses are described later in\nthis section.\n\nThe CREATE VIEW statement requires the CREATE VIEW privilege for the\nview, and some privilege for each column selected by the SELECT\nstatement. For columns used elsewhere in the SELECT statement you must\nhave the SELECT privilege. If the OR REPLACE clause is present, you\nmust also have the DROP privilege for the view. CREATE VIEW might also\nrequire the SUPER privilege, depending on the DEFINER value, as\ndescribed later in this section.\n\nWhen a view is referenced, privilege checking occurs as described later\nin this section.\n\nA view belongs to a database. By default, a new view is created in the\ndefault database. To create the view explicitly in a given database,\nspecify the name as db_name.view_name when you create it:\n\nMariaDB> CREATE VIEW test.v AS SELECT * FROM t;\n\nWithin a database, base tables and views share the same namespace, so a\nbase table and a view cannot have the same name.\n\nColumns retrieved by the SELECT statement can be simple references to\ntable columns. They can also be expressions that use functions,\nconstant values, operators, and so forth.\n\nViews must have unique column names with no duplicates, just like base\ntables. By default, the names of the columns retrieved by the SELECT\nstatement are used for the view column names. To define explicit names\nfor the view columns, the optional column_list clause can be given as a\nlist of comma-separated identifiers. The number of names in column_list\nmust be the same as the number of columns retrieved by the SELECT\nstatement.\n\nUnqualified table or view names in the SELECT statement are interpreted\nwith respect to the default database. A view can refer to tables or\nviews in other databases by qualifying the table or view name with the\nproper database name.\n\nA view can be created from many kinds of SELECT statements. It can\nrefer to base tables or other views. It can use joins, UNION, and\nsubqueries. The SELECT need not even refer to any tables. The following\nexample defines a view that selects two columns from another table, as\nwell as an expression calculated from those columns:\n\nMariaDB> CREATE TABLE t (qty INT, price INT);\nMariaDB> INSERT INTO t VALUES(3, 50);\nMariaDB> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;\nMariaDB> SELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n\nA view definition is subject to the following restrictions:\n\no The SELECT statement cannot contain a subquery in the FROM clause.\n\no The SELECT statement cannot refer to system or user variables.\n\no Within a stored program, the definition cannot refer to program\n parameters or local variables.\n\no The SELECT statement cannot refer to prepared statement parameters.\n\no Any table or view referred to in the definition must exist. However,\n after a view has been created, it is possible to drop a table or view\n that the definition refers to. In this case, use of the view results\n in an error. To check a view definition for problems of this kind,\n use the CHECK TABLE statement.\n\no The definition cannot refer to a TEMPORARY table, and you cannot\n create a TEMPORARY view.\n\no Any tables named in the view definition must exist at definition\n time.\n\no You cannot associate a trigger with a view.\n\no Aliases for column names in the SELECT statement are checked against\n the maximum column length of 64 characters (not the maximum alias\n length of 256 characters).\n\nORDER BY is permitted in a view definition, but it is ignored if you\nselect from a view using a statement that has its own ORDER BY.\n\nFor other options or clauses in the definition, they are added to the\noptions or clauses of the statement that references the view, but the\neffect is undefined. For example, if a view definition includes a LIMIT\nclause, and you select from the view using a statement that has its own\nLIMIT clause, it is undefined which limit applies. This same principle\napplies to options such as ALL, DISTINCT, or SQL_SMALL_RESULT that\nfollow the SELECT keyword, and to clauses such as INTO, FOR UPDATE,\nLOCK IN SHARE MODE, and PROCEDURE.\n\nIf you create a view and then change the query processing environment\nby changing system variables, that may affect the results that you get\nfrom the view:\n\nMariaDB> CREATE VIEW v (mycol) AS SELECT \'abc\';\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SET sql_mode = \'\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol |\n+-------+\n1 row in set (0.01 sec)\n\nMariaDB> SET sql_mode = \'ANSI_QUOTES\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc |\n+-------+\n1 row in set (0.00 sec)\n\nThe DEFINER and SQL SECURITY clauses determine which MySQL account to\nuse when checking access privileges for the view when a statement is\nexecuted that references the view. The valid SQL SECURITY\ncharacteristic values are DEFINER and INVOKER. These indicate that the\nrequired privileges must be held by the user who defined or invoked the\nview, respectively. The default SQL SECURITY value is DEFINER.\n\nIf a user value is given for the DEFINER clause, it should be a MySQL\naccount specified as \'user_name\'@\'host_name\' (the same format used in\nthe GRANT statement), CURRENT_USER, or CURRENT_USER(). The default\nDEFINER value is the user who executes the CREATE VIEW statement. This\nis the same as specifying DEFINER = CURRENT_USER explicitly.\n\nIf you specify the DEFINER clause, these rules determine the valid\nDEFINER user values:\n\no If you do not have the SUPER privilege, the only valid user value is\n your own account, either specified literally or by using\n CURRENT_USER. You cannot set the definer to some other account.\n\no If you have the SUPER privilege, you can specify any syntactically\n valid account name. If the account does not actually exist, a warning\n is generated.\n\no Although it is possible to create a view with a nonexistent DEFINER\n account, an error occurs when the view is referenced if the SQL\n SECURITY value is DEFINER but the definer account does not exist.\n\nFor more information about view security, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nWithin a view definition, CURRENT_USER returns the view\'s DEFINER value\nby default. For views defined with the SQL SECURITY INVOKER\ncharacteristic, CURRENT_USER returns the account for the view\'s\ninvoker. For information about user auditing within views, see\nhttp://dev.mysql.com/doc/refman/5.5/en/account-activity-auditing.html.\n\nWithin a stored routine that is defined with the SQL SECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER value. This\nalso affects a view defined within such a routine, if the view\ndefinition contains a DEFINER value of CURRENT_USER.\n\nView privileges are checked like this:\n\no At view definition time, the view creator must have the privileges\n needed to use the top-level objects accessed by the view. For\n example, if the view definition refers to table columns, the creator\n must have some privilege for each column in the select list of the\n definition, and the SELECT privilege for each column used elsewhere\n in the definition. If the definition refers to a stored function,\n only the privileges needed to invoke the function can be checked. The\n privileges required at function invocation time can be checked only\n as it executes: For different invocations, different execution paths\n within the function might be taken.\n\no The user who references a view must have appropriate privileges to\n access it (SELECT to select from it, INSERT to insert into it, and so\n forth.)\n\no When a view has been referenced, privileges for objects accessed by\n the view are checked against the privileges held by the view DEFINER\n account or invoker, depending on whether the SQL SECURITY\n characteristic is DEFINER or INVOKER, respectively.\n\no If reference to a view causes execution of a stored function,\n privilege checking for statements executed within the function depend\n on whether the function SQL SECURITY characteristic is DEFINER or\n INVOKER. If the security characteristic is DEFINER, the function runs\n with the privileges of the DEFINER account. If the characteristic is\n INVOKER, the function runs with the privileges determined by the\n view\'s SQL SECURITY characteristic.\n\nExample: A view might depend on a stored function, and that function\nmight invoke other stored routines. For example, the following view\ninvokes a stored function f():\n\nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n\nSuppose that f() contains a statement such as this:\n\nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n\nThe privileges required for executing statements within f() need to be\nchecked when f() executes. This might mean that privileges are needed\nfor p1() or p2(), depending on the execution path within f(). Those\nprivileges must be checked at runtime, and the user who must possess\nthe privileges is determined by the SQL SECURITY values of the view v\nand the function f().\n\nThe DEFINER and SQL SECURITY clauses for views are extensions to\nstandard SQL. In standard SQL, views are handled using the rules for\nSQL SECURITY DEFINER. The standard says that the definer of the view,\nwhich is the same as the owner of the view\'s schema, gets applicable\nprivileges on the view (for example, SELECT) and may grant them. MySQL\nhas no concept of a schema \"owner\", so MySQL adds a clause to identify\nthe definer. The DEFINER clause is an extension where the intent is to\nhave what the standard has; that is, a permanent record of who defined\nthe view. This is why the default DEFINER value is the account of the\nview creator.\n\nThe optional ALGORITHM clause is a MySQL extension to standard SQL. It\naffects how MySQL processes the view. ALGORITHM takes three values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is UNDEFINED if\nno ALGORITHM clause is present. For more information, see\nhttps://mariadb.com/kb/en/view-algorithms/.\n\nSome views are updatable. That is, you can use them in statements such\nas UPDATE, DELETE, or INSERT to update the contents of the underlying\ntable. For a view to be updatable, there must be a one-to-one\nrelationship between the rows in the view and the rows in the\nunderlying table. There are also certain other constructs that make a\nview nonupdatable.\n\nThe WITH CHECK OPTION clause can be given for an updatable view to\nprevent inserts or updates to rows except those for which the WHERE\nclause in the select_statement is true.\n\nIn a WITH CHECK OPTION clause for an updatable view, the LOCAL and\nCASCADED keywords determine the scope of check testing when the view is\ndefined in terms of another view. The LOCAL keyword restricts the CHECK\nOPTION only to the view being defined. CASCADED causes the checks for\nunderlying views to be evaluated as well. When neither keyword is\ngiven, the default is CASCADED.\n\nFor more information about updatable views and the WITH CHECK OPTION\nclause, see\nhttps://mariadb.com/kb/en/inserting-and-updating-with-views/.\n\nURL: https://mariadb.com/kb/en/create-view/\n\n','','https://mariadb.com/kb/en/create-view/'),(455,'TRIM',37,'Syntax:\nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr\nFROM] str)\n\nReturns the string str with all remstr prefixes or suffixes removed. If\nnone of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is\nassumed. remstr is optional and, if not specified, spaces are removed.\n\nURL: https://mariadb.com/kb/en/trim/\n\n','MariaDB> SELECT TRIM(\' bar \');\n -> \'bar\'\nMariaDB> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');\n -> \'barxxx\'\nMariaDB> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');\n -> \'bar\'\nMariaDB> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');\n -> \'barx\'\n','https://mariadb.com/kb/en/trim/'),(456,'IS',18,'Syntax:\nIS boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is/\n\n','MariaDB> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n -> 1, 1, 1\n','https://mariadb.com/kb/en/is/'),(457,'GET_FORMAT',31,'Syntax:\nGET_FORMAT({DATE|TIME|DATETIME}, {\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n\nReturns a format string. This function is useful in combination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n\nURL: https://mariadb.com/kb/en/get_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n -> \'03.10.2003\'\nMariaDB> SELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n -> \'2003-10-31\'\n','https://mariadb.com/kb/en/get_format/'),(458,'TINYBLOB',22,'TINYBLOB\n\nA BLOB column with a maximum length of 255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a 1-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinyblob/\n\n','','https://mariadb.com/kb/en/tinyblob/'),(459,'SIGNAL',23,'Syntax:\nSIGNAL condition_value\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nSIGNAL is the way to \"return\" an error. SIGNAL provides error\ninformation to a handler, to an outer portion of the application, or to\nthe client. Also, it provides control over the error\'s characteristics\n(error number, SQLSTATE value, message). Without SIGNAL, it is\nnecessary to resort to workarounds such as deliberately referring to a\nnonexistent table to cause a routine to return an error.\n\nNo special privileges are required to execute the SIGNAL statement.\n\nThe condition_value in a SIGNAL statement indicates the error value to\nbe returned. It can be an SQLSTATE value (a 5-character string literal)\nor a condition_name that refers to a named condition previously defined\nwith DECLARE ... CONDITION (see [HELP DECLARE CONDITION]).\n\nAn SQLSTATE value can indicate errors, warnings, or \"not found.\" The\nfirst two characters of the value indicate its error class, as\ndiscussed in\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items. Some signal values cause statement termination; see\nhttps://mariadb.com/kb/en/signal/#signal-effects.\n\nThe SQLSTATE value for a SIGNAL statement should not start with \'00\'\nbecause such values indicate success and are not valid for signaling an\nerror. This is true whether the SQLSTATE value is specified directly in\nthe SIGNAL statement or in a named condition referred to in the\nstatement. If the value is invalid, a Bad SQLSTATE error occurs.\n\nTo signal a generic SQLSTATE value, use \'45000\', which means \"unhandled\nuser-defined exception.\"\n\nThe SIGNAL statement optionally includes a SET clause that contains\nmultiple signal items, in a comma-separated list of\ncondition_information_item_name = simple_value_specification\nassignments.\n\nEach condition_information_item_name may be specified only once in the\nSET clause. Otherwise, a Duplicate condition information item error\noccurs.\n\nValid simple_value_specification designators can be specified using\nstored procedure or function parameters, stored program local variables\ndeclared with DECLARE, user-defined variables, system variables, or\nliterals. A character literal may include a _charset introducer.\n\nFor information about permissible condition_information_item_name\nvalues, see\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items.\n\nURL: https://mariadb.com/kb/en/signal/\n\n','CREATE PROCEDURE p (pval INT)\nBEGIN\n DECLARE specialty CONDITION FOR SQLSTATE \'45000\';\n IF pval = 0 THEN\n SIGNAL SQLSTATE \'01000\';\n ELSEIF pval = 1 THEN\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSEIF pval = 2 THEN\n SIGNAL specialty\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSE\n SIGNAL SQLSTATE \'01000\'\n SET MESSAGE_TEXT = \'A warning occurred\', MYSQL_ERRNO = 1000;\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\', MYSQL_ERRNO = 1001;\n END IF;\nEND;\n','https://mariadb.com/kb/en/signal/'),(460,'SAVEPOINT',8,'Syntax:\nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n\nInnoDB supports the SQL statements SAVEPOINT, ROLLBACK TO SAVEPOINT,\nRELEASE SAVEPOINT and the optional WORK keyword for ROLLBACK.\n\nURL: https://mariadb.com/kb/en/savepoint/\n\n','','https://mariadb.com/kb/en/savepoint/'),(461,'USER',17,'Syntax:\nUSER()\n\nReturns the current MySQL user name and host name as a string in the\nutf8 character set.\n\nURL: https://mariadb.com/kb/en/user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\n','https://mariadb.com/kb/en/user/'),(462,'LABELS',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nLabels are permitted for BEGIN ... END blocks and for the LOOP, REPEAT,\nand WHILE statements. Label use for those statements follows these\nrules:\n\no begin_label must be followed by a colon.\n\no begin_label can be given without end_label. If end_label is present,\n it must be the same as begin_label.\n\no end_label cannot be given without begin_label.\n\no Labels at the same nesting level must be distinct.\n\no Labels can be up to 16 characters long.\n\nTo refer to a label within the labeled construct, use an ITERATE or\nLEAVE statement. The following example uses those statements to\ncontinue iterating or terminate the loop:\n\nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN ITERATE label1; END IF;\n LEAVE label1;\n END LOOP label1;\nEND;\n\nThe scope of a block label does not include the code for handlers\ndeclared within the block. For details, see [HELP DECLARE HANDLER].\n\nURL: https://mariadb.com/kb/en/labels/\n\n','','https://mariadb.com/kb/en/labels/'),(463,'ALTER TABLE',39,'Syntax:\nALTER [ONLINE | OFFLINE] [IGNORE] TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (index_col_name,...)\n reference_definition\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] col_name\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} index_name\n | DROP FOREIGN KEY fk_symbol\n | MAX_ROWS = rows\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO|AS] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | FORCE\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO (partition_definitions)]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | PARTITION BY partitioning_expression\n | REMOVE PARTITIONING\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\ntable_options:\n table_option [[,] table_option] ... (see CREATE TABLE options)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\nPartitioning-related clauses for ALTER TABLE can be used with\npartitioned tables for repartitioning, for adding, dropping, merging,\nand splitting partitions, and for performing partitioning maintenance.\nFor more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations\n.html.\n\nFollowing the table name, specify the alterations to be made. If none\nare given, ALTER TABLE does nothing.\n\nURL: https://mariadb.com/kb/en/alter-table/\n\n','','https://mariadb.com/kb/en/alter-table/'),(464,'MPOINTFROMWKB',32,'MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])\n\nConstructs a MULTIPOINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromwkb/\n\n','','https://mariadb.com/kb/en/mpointfromwkb/'),(465,'CHAR BYTE',22,'The CHAR BYTE data type is an alias for the BINARY data type. This is a\ncompatibility feature.\n\nURL: https://mariadb.com/kb/en/char-byte/\n\n','','https://mariadb.com/kb/en/char-byte/'),(466,'REPAIR TABLE',20,'Syntax:\nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n\nREPAIR TABLE repairs a possibly corrupted table. By default, it has the\nsame effect as myisamchk --recover tbl_name. REPAIR TABLE works for\nMyISAM, ARCHIVE, and CSV tables. See\nhttps://mariadb.com/kb/en/myisam-storage-engine/, and\nhttps://mariadb.com/kb/en/archive/, and\nhttps://mariadb.com/kb/en/csv/\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nREPAIR TABLE is supported for partitioned tables. However, the USE_FRM\noption cannot be used with this statement on a partitioned table.\n\nYou can use ALTER TABLE ... REPAIR PARTITION to repair one or more\npartitions; for more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/repair-table/\n\n','','https://mariadb.com/kb/en/repair-table/'),(467,'MERGE',39,'The MERGE storage engine, also known as the MRG_MyISAM engine, is a\ncollection of identical MyISAM tables that can be used as one.\n\"Identical\" means that all tables have identical column and index\ninformation. You cannot merge MyISAM tables in which the columns are\nlisted in a different order, do not have exactly the same columns, or\nhave the indexes in different order. However, any or all of the MyISAM\ntables can be compressed with myisampack. See\nhttps://mariadb.com/kb/en/myisampack/. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS do not\nmatter.\n\nURL: https://mariadb.com/kb/en/merge/\n\n','MariaDB> CREATE TABLE t1 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> CREATE TABLE t2 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> INSERT INTO t1 (message) VALUES (\'Testing\'),(\'table\'),(\'t1\');\nMariaDB> INSERT INTO t2 (message) VALUES (\'Testing\'),(\'table\'),(\'t2\');\nMariaDB> CREATE TABLE total (\n -> a INT NOT NULL AUTO_INCREMENT,\n -> message CHAR(20), INDEX(a))\n -> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n','https://mariadb.com/kb/en/merge/'),(468,'CREATE TABLE',39,'Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n select_statement\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT default_value]\n [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [STORAGE {DISK|MEMORY|DEFAULT}]\n [reference_definition]\n\ndata_type:\n BIT[(length)]\n | TINYINT[(length)] [UNSIGNED] [ZEROFILL]\n | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]\n | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]\n | INT[(length)] [UNSIGNED] [ZEROFILL]\n | INTEGER[(length)] [UNSIGNED] [ZEROFILL]\n | BIGINT[(length)] [UNSIGNED] [ZEROFILL]\n | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | DATE\n | TIME\n | TIMESTAMP\n | DATETIME\n | YEAR\n | CHAR[(length)]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | VARCHAR(length)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | BINARY[(length)]\n | VARBINARY(length)\n | TINYBLOB\n | BLOB\n | MEDIUMBLOB\n | LONGBLOB\n | TINYTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | TEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | MEDIUMTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | LONGTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | ENUM(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | SET(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | spatial_type\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES \n {LESS THAN {(expr | value_list) | MAXVALUE} \n | \n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n\nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some valid select statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nRules for permissible table names are given in\nhttps://mariadb.com/kb/en/identifier-names/. By default,\nthe table is created in the default database, using the InnoDB storage\nengine. An error occurs if the table exists, if there is no default\ndatabase, or if the database does not exist.\n\nURL: https://mariadb.com/kb/en/create-table/\n\n','','https://mariadb.com/kb/en/create-table/'),(469,'>',18,'Syntax:\n>\n\nGreater than:\n\nURL: https://mariadb.com/kb/en/greater-than/\n\n','MariaDB> SELECT 2 > 2;\n -> 0\n','https://mariadb.com/kb/en/greater-than/'),(470,'ANALYZE TABLE',20,'Syntax:\nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nANALYZE TABLE analyzes and stores the key distribution for a table.\nDuring the analysis, the table is locked with a read lock for InnoDB\nand MyISAM. This statement works with InnoDB, Aria and MyISAM tables.\nFor MyISAM tables, this statement is equivalent to using myisamchk\n--analyze.\n\nFor more information on how the analysis works within InnoDB, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html.\n\nMySQL uses the stored key distribution to decide the order in which\ntables should be joined when you perform a join on something other than\na constant. In addition, key distributions can be used when deciding\nwhich indexes to use for a specific table within a query.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nANALYZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... ANALYZE PARTITION to analyze one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/analyze-table/\n\n','','https://mariadb.com/kb/en/analyze-table/'),(471,'MICROSECOND',31,'Syntax:\nMICROSECOND(expr)\n\nReturns the microseconds from the time or datetime expression expr as a\nnumber in the range from 0 to 999999.\n\nURL: https://mariadb.com/kb/en/microsecond/\n\n','MariaDB> SELECT MICROSECOND(\'12:00:00.123456\');\n -> 123456\nMariaDB> SELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n -> 10\n','https://mariadb.com/kb/en/microsecond/'),(472,'CONSTRAINT',39,'InnoDB supports foreign keys, which let you cross-reference related\ndata across tables, and foreign key constraints, which help keep this\nspread-out data consistent. The syntax for an InnoDB foreign key\nconstraint definition in the CREATE TABLE or ALTER TABLE statement\nlooks like this:\n\n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\nURL: https://mariadb.com/kb/en/constraint/\n\n','CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n','https://mariadb.com/kb/en/constraint/'),(473,'CREATE SERVER',39,'Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nwithin the servers table within the mysql database. This statement\nrequires the SUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name should be mysql, and may be quoted with single\nquotation marks. Other values for wrapper_name are not currently\nsupported.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*: Note that the OWNER option is currently not applied, and has no\neffect on the ownership or operation of the server connection that is\ncreated.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: https://mariadb.com/kb/en/create-server/\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE \'test\');\n','https://mariadb.com/kb/en/create-server/'),(474,'FIELD',37,'Syntax:\nFIELD(str,str1,str2,str3,...)\n\nReturns the index (position) of str in the str1, str2, str3, ... list.\nReturns 0 if str is not found.\n\nIf all arguments to FIELD() are strings, all arguments are compared as\nstrings. If all arguments are numbers, they are compared as numbers.\nOtherwise, the arguments are compared as double.\n\nIf str is NULL, the return value is 0 because NULL fails equality\ncomparison with any value. FIELD() is the complement of ELT().\n\nURL: https://mariadb.com/kb/en/field/\n\n','MariaDB> SELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 2\nMariaDB> SELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 0\n','https://mariadb.com/kb/en/field/'),(475,'MAKETIME',31,'Syntax:\nMAKETIME(hour,minute,second)\n\nReturns a time value calculated from the hour, minute, and second\narguments.\n\nURL: https://mariadb.com/kb/en/maketime/\n\n','MariaDB> SELECT MAKETIME(12,15,30);\n -> \'12:15:30\'\n','https://mariadb.com/kb/en/maketime/'),(476,'CURDATE',31,'Syntax:\nCURDATE()\n\nReturns the current date as a value in \'YYYY-MM-DD\' or YYYYMMDD format,\ndepending on whether the function is used in a string or numeric\ncontext.\n\nURL: https://mariadb.com/kb/en/curdate/\n\n','MariaDB> SELECT CURDATE();\n -> \'2008-06-13\'\nMariaDB> SELECT CURDATE() + 0;\n -> 20080613\n','https://mariadb.com/kb/en/curdate/'),(477,'SET PASSWORD',10,'Syntax:\nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'cleartext password\')\n | OLD_PASSWORD(\'cleartext password\')\n | \'encrypted password\'\n }\n\nThe SET PASSWORD statement assigns a password to an existing MySQL user\naccount. When the read_only system variable is enabled, the SUPER\nprivilege is required to use SET PASSWORD, in addition to whatever\nother privileges might be required.\n\nIf the password is specified using the PASSWORD() or OLD_PASSWORD()\nfunction, the cleartext (unencrypted) password should be given as the\nargument to the function, which hashes the password and returns the\nencrypted password string. If the password is specified without using\neither function, it should be the already encrypted password value as a\nliteral string. In all cases, the encrypted password string must be in\nthe format required by the authentication method used for the account.\n\nThe old_passwords system variable value determines the hashing method\nused by PASSWORD(). If you specify the password using that function and\nSET PASSWORD rejects the password as not being in the correct format,\nit may be necessary to set old_passwords to change the hashing method.\nFor descriptions of the permitted values, see\nhttps://mariadb.com/kb/en/server-system-variables#old_passwords.\n\nWith no FOR user clause, this statement sets the password for the\ncurrent user. (To see which account the server authenticated you as,\ninvoke the CURRENT_USER() function.) Any client who successfully\nconnects to the server using a nonanonymous account can change the\npassword for that account.\n\nWith a FOR user clause, this statement sets the password for the named\nuser. You must have the UPDATE privilege for the mysql database to do\nthis. The user account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. The user\nvalue should be given as \'user_name\'@\'host_name\', where \'user_name\' and\n\'host_name\' are exactly as listed in the User and Host columns of the\nmysql.user table row. (If you specify only a user name, a host name of\n\'%\' is used.) For example, to set the password for an account with User\nand Host column values of \'bob\' and \'%.example.org\', write the\nstatement like this:\n\nSET PASSWORD FOR \'bob\'@\'%.example.org\' = PASSWORD(\'cleartext password\');\n\nURL: https://mariadb.com/kb/en/set-password/\n\n','','https://mariadb.com/kb/en/set-password/'),(478,'ALTER TABLESPACE',39,'Syntax:\nALTER TABLESPACE tablespace_name\n {ADD|DROP} DATAFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/alter-tablespace/\n\n','','https://mariadb.com/kb/en/alter-tablespace/'),(479,'IF FUNCTION',7,'Syntax:\nIF(expr1,expr2,expr3)\n\nIf expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns\nexpr2; otherwise it returns expr3. IF() returns a numeric or string\nvalue, depending on the context in which it is used.\n\nURL: https://mariadb.com/kb/en/if-function/\n\n','MariaDB> SELECT IF(1>2,2,3);\n -> 3\nMariaDB> SELECT IF(1<2,\'yes\',\'no\');\n -> \'yes\'\nMariaDB> SELECT IF(STRCMP(\'test\',\'test1\'),\'no\',\'yes\');\n -> \'no\'\n','https://mariadb.com/kb/en/if-function/'),(480,'ENUM',22,'ENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nAn enumeration. A string object that can have only one value, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or the special \'\'\nerror value. An ENUM column can have a maximum of 65,535 distinct\nvalues. ENUM values are represented internally as integers.\n\nURL: https://mariadb.com/kb/en/enum/\n\n','','https://mariadb.com/kb/en/enum/'),(481,'DATABASE',17,'Syntax:\nDATABASE()\n\nReturns the default (current) database name as a string in the utf8\ncharacter set. If there is no default database, DATABASE() returns\nNULL. Within a stored routine, the default database is the database\nthat the routine is associated with, which is not necessarily the same\nas the database that is the default in the calling context.\n\nURL: https://mariadb.com/kb/en/database/\n\n','MariaDB> SELECT DATABASE();\n -> \'test\'\n','https://mariadb.com/kb/en/database/'),(482,'POINTFROMWKB',32,'PointFromWKB(wkb[,srid])\n\nConstructs a POINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromwkb/\n\n','','https://mariadb.com/kb/en/pointfromwkb/'),(483,'POWER',4,'Syntax:\nPOWER(X,Y)\n\nThis is a synonym for POW().\n\nURL: https://mariadb.com/kb/en/power/\n\n','','https://mariadb.com/kb/en/power/'),(484,'ATAN',4,'Syntax:\nATAN(X)\n\nReturns the arc tangent of X, that is, the value whose tangent is X.\n\nURL: https://mariadb.com/kb/en/atan/\n\n','MariaDB> SELECT ATAN(2);\n -> 1.1071487177941\nMariaDB> SELECT ATAN(-2);\n -> -1.1071487177941\n','https://mariadb.com/kb/en/atan/'),(485,'STRCMP',37,'Syntax:\nSTRCMP(expr1,expr2)\n\nSTRCMP() returns 0 if the strings are the same, -1 if the first\nargument is smaller than the second according to the current sort\norder, and 1 otherwise.\n\nURL: https://mariadb.com/kb/en/strcmp/\n\n','MariaDB> SELECT STRCMP(\'text\', \'text2\');\n -> -1\nMariaDB> SELECT STRCMP(\'text2\', \'text\');\n -> 1\nMariaDB> SELECT STRCMP(\'text\', \'text\');\n -> 0\n','https://mariadb.com/kb/en/strcmp/'),(486,'INSERT DELAYED',27,'Syntax:\nINSERT DELAYED ...\n\nThe DELAYED option for the INSERT statement is a MySQL extension to\nstandard SQL that is very useful if you have clients that cannot or\nneed not wait for the INSERT to complete. This is a common situation\nwhen you use MySQL for logging and you also periodically run SELECT and\nUPDATE statements that take a long time to complete.\n\nWhen a client uses INSERT DELAYED, it gets an okay from the server at\nonce, and the row is queued to be inserted when the table is not in use\nby any other thread.\n\nAnother major benefit of using INSERT DELAYED is that inserts from many\nclients are bundled together and written in one block. This is much\nfaster than performing many separate inserts.\n\nNote that INSERT DELAYED is slower than a normal INSERT if the table is\nnot otherwise in use. There is also the additional overhead for the\nserver to handle a separate thread for each table for which there are\ndelayed rows. This means that you should use INSERT DELAYED only when\nyou are really sure that you need it.\n\nThe queued rows are held only in memory until they are inserted into\nthe table. This means that if you terminate mysqld forcibly (for\nexample, with kill -9) or if mysqld dies unexpectedly, any queued rows\nthat have not been written to disk are lost.\n\nThere are some constraints on the use of DELAYED:\n\no INSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE, and BLACKHOLE\n tables. For engines that do not support DELAYED, an error occurs.\n\no An error occurs for INSERT DELAYED if used with a table that has been\n locked with LOCK TABLES because the insert must be handled by a\n separate thread, not by the session that holds the lock.\n\no For MyISAM tables, if there are no free blocks in the middle of the\n data file, concurrent SELECT and INSERT statements are supported.\n Under these circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\n\no INSERT DELAYED should be used only for INSERT statements that specify\n value lists. The server ignores DELAYED for INSERT ... SELECT or\n INSERT ... ON DUPLICATE KEY UPDATE statements.\n\no Because the INSERT DELAYED statement returns immediately, before the\n rows are inserted, you cannot use LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\n\no DELAYED rows are not visible to SELECT statements until they actually\n have been inserted.\n\no Prior to MySQL 5.5.7, INSERT DELAYED was treated as a normal INSERT\n if the statement inserted multiple rows, binary logging was enabled,\n and the global logging format was statement-based (that is, whenever\n binlog_format was set to STATEMENT). Beginning with MySQL 5.5.7,\n INSERT DELAYED is always handled as a simple INSERT (that is, without\n the DELAYED option) whenever the value of binlog_format is STATEMENT\n or MIXED. (In the latter case, the statement no longer triggers a\n switch to row-based logging, and so is logged using the\n statement-based format.)\n\n This does not apply when using row-based binary logging mode\n (binlog_format set to ROW), in which INSERT DELAYED statements are\n always executed using the DELAYED option as specified, and logged as\n row-update events.\n\no DELAYED is ignored on slave replication servers, so that INSERT\n DELAYED is treated as a normal INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than the master.\n\no Pending INSERT DELAYED statements are lost if a table is write locked\n and ALTER TABLE is used to modify the table structure.\n\no INSERT DELAYED is not supported for views.\n\no INSERT DELAYED is not supported for partitioned tables.\n\nURL: https://mariadb.com/kb/en/insert-delayed/\n\n','','https://mariadb.com/kb/en/insert-delayed/'),(487,'SHOW PROFILE',26,'Syntax:\nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n\ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n\nThe SHOW PROFILE and SHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements executed\nduring the course of the current session.\n\nProfiling is controlled by the profiling session variable, which has a\ndefault value of 0 (OFF). Profiling is enabled by setting profiling to\n1 or ON:\n\nMariaDB> SET profiling = 1;\n\nSHOW PROFILES displays a list of the most recent statements sent to the\nserver. The size of the list is controlled by the\nprofiling_history_size session variable, which has a default value of\n15. The maximum value is 100. Setting the value to 0 has the practical\neffect of disabling profiling.\n\nAll statements are profiled except SHOW PROFILE and SHOW PROFILES, so\nyou will find neither of those statements in the profile list.\nMalformed statements are profiled. For example, SHOW PROFILING is an\nillegal statement, and a syntax error occurs if you try to execute it,\nbut it will show up in the profiling list.\n\nSHOW PROFILE displays detailed information about a single statement.\nWithout the FOR QUERY n clause, the output pertains to the most\nrecently executed statement. If FOR QUERY n is included, SHOW PROFILE\ndisplays information for statement n. The values of n correspond to the\nQuery_ID values displayed by SHOW PROFILES.\n\nThe LIMIT row_count clause may be given to limit the output to\nrow_count rows. If LIMIT is given, OFFSET offset may be added to begin\nthe output offset rows into the full set of rows.\n\nBy default, SHOW PROFILE displays Status and Duration columns. The\nStatus values are like the State values displayed by SHOW PROCESSLIST,\nalthough there might be some minor differences in interpretion for the\ntwo statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.5/en/thread-information.html).\n\nOptional type values may be specified to display specific additional\ntypes of information:\n\no ALL displays all information\n\no BLOCK IO displays counts for block input and output operations\n\no CONTEXT SWITCHES displays counts for voluntary and involuntary\n context switches\n\no CPU displays user and system CPU usage times\n\no IPC displays counts for messages sent and received\n\no MEMORY is not currently implemented\n\no PAGE FAULTS displays counts for major and minor page faults\n\no SOURCE displays the names of functions from the source code, together\n with the name and line number of the file in which the function\n occurs\n\no SWAPS displays swap counts\n\nProfiling is enabled per session. When a session ends, its profiling\ninformation is lost.\n\nURL: https://mariadb.com/kb/en/show-profile/\n\n','MariaDB> SELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> SET profiling = 1;\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> DROP TABLE IF EXISTS t1;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nMariaDB> CREATE TABLE T1 (id INT);\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SHOW PROFILES;\n+----------+----------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+----------+--------------------------+\n| 0 | 0.000088 | SET PROFILING = 1 |\n| 1 | 0.000136 | DROP TABLE IF EXISTS t1 |\n| 2 | 0.011947 | CREATE TABLE t1 (id INT) |\n+----------+----------+--------------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| checking permissions | 0.000040 |\n| creating table | 0.000056 |\n| After create | 0.011363 |\n| query end | 0.000375 |\n| freeing items | 0.000089 |\n| logging slow query | 0.000019 |\n| cleaning up | 0.000005 |\n+----------------------+----------+\n7 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE FOR QUERY 1;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| query end | 0.000107 |\n| freeing items | 0.000008 |\n| logging slow query | 0.000015 |\n| cleaning up | 0.000006 |\n+--------------------+----------+\n4 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE CPU FOR QUERY 2;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| checking permissions | 0.000040 | 0.000038 | 0.000002 |\n| creating table | 0.000056 | 0.000028 | 0.000028 |\n| After create | 0.011363 | 0.000217 | 0.001571 |\n| query end | 0.000375 | 0.000013 | 0.000028 |\n| freeing items | 0.000089 | 0.000010 | 0.000014 |\n| logging slow query | 0.000019 | 0.000009 | 0.000010 |\n| cleaning up | 0.000005 | 0.000003 | 0.000002 |\n+----------------------+----------+----------+------------+\n7 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-profile/'),(488,'SHOW PROCEDURE CODE',26,'Syntax:\nSHOW PROCEDURE CODE proc_name\n\nThis statement is a MySQL extension that is available only for servers\nthat have been built with debugging support. It displays a\nrepresentation of the internal implementation of the named stored\nprocedure. A similar statement, SHOW FUNCTION CODE, displays\ninformation about stored functions (see [HELP SHOW FUNCTION CODE]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table.\n\nIf the named routine is available, each statement produces a result\nset. Each row in the result set corresponds to one \"instruction\" in the\nroutine. The first column is Pos, which is an ordinal number beginning\nwith 0. The second column is Instruction, which contains an SQL\nstatement (usually changed from the original source), or a directive\nwhich has meaning only to the stored-routine handler.\n\nURL: https://mariadb.com/kb/en/show-procedure-code/\n\n','MariaDB> DELIMITER //\nMariaDB> CREATE PROCEDURE p1 ()\n -> BEGIN\n -> DECLARE fanta INT DEFAULT 55;\n -> DROP TABLE t2;\n -> LOOP\n -> INSERT INTO t3 VALUES (fanta);\n -> END LOOP;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n4 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-procedure-code/'),(489,'MEDIUMTEXT',22,'MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 16,777,215 (224 - 1) characters.\nThe effective maximum length is less if the value contains multi-byte\ncharacters. Each MEDIUMTEXT value is stored using a 3-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumtext/\n\n','','https://mariadb.com/kb/en/mediumtext/'),(490,'LN',4,'Syntax:\nLN(X)\n\nReturns the natural logarithm of X; that is, the base-e logarithm of X.\nIf X is less than or equal to 0, then NULL is returned.\n\nURL: https://mariadb.com/kb/en/ln/\n\n','MariaDB> SELECT LN(2);\n -> 0.69314718055995\nMariaDB> SELECT LN(-2);\n -> NULL\n','https://mariadb.com/kb/en/ln/'),(491,'RETURN',23,'Syntax:\nRETURN expr\n\nThe RETURN statement terminates execution of a stored function and\nreturns the value expr to the function caller. There must be at least\none RETURN statement in a stored function. There may be more than one\nif the function has multiple exit points.\n\nThis statement is not used in stored procedures, triggers, or events.\nThe LEAVE statement can be used to exit a stored program of those\ntypes.\n\nURL: https://mariadb.com/kb/en/return/\n\n','','https://mariadb.com/kb/en/return/'),(492,'SHOW COLLATION',26,'Syntax:\nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement lists collations supported by the server. By default,\nthe output from SHOW COLLATION includes all available collations. The\nLIKE clause, if present, indicates which collation names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | | 0 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |\n| latin1_danish_ci | latin1 | 15 | | | 0 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 0 |\n| latin1_general_ci | latin1 | 48 | | | 0 |\n| latin1_general_cs | latin1 | 49 | | | 0 |\n| latin1_spanish_ci | latin1 | 94 | | | 0 |\n+-------------------+---------+----+---------+----------+---------+\n\nURL: https://mariadb.com/kb/en/show-collation/\n\n','','https://mariadb.com/kb/en/show-collation/'),(493,'LOG',4,'Syntax:\nLOG(X), LOG(B,X)\n\nIf called with one parameter, this function returns the natural\nlogarithm of X. If X is less than or equal to 0, then NULL is returned.\n\nThe inverse of this function (when called with a single argument) is\nthe EXP() function.\n\nURL: https://mariadb.com/kb/en/log/\n\n','MariaDB> SELECT LOG(2);\n -> 0.69314718055995\nMariaDB> SELECT LOG(-2);\n -> NULL\n','https://mariadb.com/kb/en/log/'),(494,'SET SQL_LOG_BIN',8,'Syntax:\nSET sql_log_bin = {0|1}\n\nThe sql_log_bin variable controls whether logging to the binary log is\ndone. The default value is 1 (do logging). To change logging for the\ncurrent session, change the session value of this variable. The session\nuser must have the SUPER privilege to set this variable.\n\nBeginning with MySQL 5.5.5, it is no longer possible to set\n@@session.sql_log_bin within a transaction or subquery. (Bug #53437)\n\nURL: https://mariadb.com/kb/en/set-sql_log_bin/\n\n','','https://mariadb.com/kb/en/set-sql_log_bin/'),(495,'!=',18,'Syntax:\n<>, !=\n\nNot equal:\n\nURL: https://mariadb.com/kb/en/not-equal/\n\n','MariaDB> SELECT \'.01\' <> \'0.01\';\n -> 1\nMariaDB> SELECT .01 <> \'0.01\';\n -> 0\nMariaDB> SELECT \'zapp\' <> \'zappp\';\n -> 1\n','https://mariadb.com/kb/en/not-equal/'),(496,'WHILE',23,'Syntax:\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nThe statement list within a WHILE statement is repeated as long as the\nsearch_condition expression is true. statement_list consists of one or\nmore SQL statements, each terminated by a semicolon (;) statement\ndelimiter.\n\nA WHILE statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/while/\n\n','CREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n\n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n END WHILE;\nEND;\n','https://mariadb.com/kb/en/while/'),(497,'AES_DECRYPT',12,'Syntax:\nAES_DECRYPT(crypt_str,key_str)\n\nThis function decrypts data using the official AES (Advanced Encryption\nStandard) algorithm. For more information, see the description of\nAES_ENCRYPT().\n\nURL: https://mariadb.com/kb/en/aes_decrypt/\n\n','','https://mariadb.com/kb/en/aes_decrypt/'),(498,'DAYNAME',31,'Syntax:\nDAYNAME(date)\n\nReturns the name of the weekday for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-system-variables#lc_time_names).\n\nURL: https://mariadb.com/kb/en/dayname/\n\n','MariaDB> SELECT DAYNAME(\'2007-02-03\');\n -> \'Saturday\'\n','https://mariadb.com/kb/en/dayname/'),(499,'COERCIBILITY',17,'Syntax:\nCOERCIBILITY(str)\n\nReturns the collation coercibility value of the string argument.\n\nURL: https://mariadb.com/kb/en/coercibility/\n\n','MariaDB> SELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n -> 0\nMariaDB> SELECT COERCIBILITY(USER());\n -> 3\nMariaDB> SELECT COERCIBILITY(\'abc\');\n -> 4\n','https://mariadb.com/kb/en/coercibility/'),(500,'INT',22,'INT[(M)] [UNSIGNED] [ZEROFILL]\n\nA normal-size integer. The signed range is -2147483648 to 2147483647.\nThe unsigned range is 0 to 4294967295.\n\nURL: https://mariadb.com/kb/en/int/\n\n','','https://mariadb.com/kb/en/int/'),(501,'GLENGTH',13,'GLength(ls)\n\nReturns as a double-precision number the length of the LineString value\nls in its associated spatial reference.\n\nURL: https://mariadb.com/kb/en/glength/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.8284271247462 |\n+----------------------------+\n','https://mariadb.com/kb/en/glength/'),(502,'RADIANS',4,'Syntax:\nRADIANS(X)\n\nReturns the argument X, converted from degrees to radians. (Note that\nπ radians equals 180 degrees.)\n\nURL: https://mariadb.com/kb/en/radians/\n\n','MariaDB> SELECT RADIANS(90);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/radians/'),(503,'COLLATION',17,'Syntax:\nCOLLATION(str)\n\nReturns the collation of the string argument.\n\nURL: https://mariadb.com/kb/en/collation/\n\n','MariaDB> SELECT COLLATION(\'abc\');\n -> \'latin1_swedish_ci\'\nMariaDB> SELECT COLLATION(_utf8\'abc\');\n -> \'utf8_general_ci\'\n','https://mariadb.com/kb/en/collation/'),(504,'COALESCE',18,'Syntax:\nCOALESCE(value,...)\n\nReturns the first non-NULL value in the list, or NULL if there are no\nnon-NULL values.\n\nURL: https://mariadb.com/kb/en/coalesce/\n\n','MariaDB> SELECT COALESCE(NULL,1);\n -> 1\nMariaDB> SELECT COALESCE(NULL,NULL,NULL);\n -> NULL\n','https://mariadb.com/kb/en/coalesce/'),(505,'VERSION',17,'Syntax:\nVERSION()\n\nReturns a string that indicates the MySQL server version. The string\nuses the utf8 character set. The value might have a suffix in addition\nto the version number. See the description of the version system\nvariable in\nhttps://mariadb.com/kb/en/server-system-variables#version.\n\nURL: https://mariadb.com/kb/en/version/\n\n','MariaDB> SELECT VERSION();\n -> \'5.5.29-standard\'\n','https://mariadb.com/kb/en/version/'),(506,'MAKE_SET',37,'Syntax:\nMAKE_SET(bits,str1,str2,...)\n\nReturns a set value (a string containing substrings separated by \",\"\ncharacters) consisting of the strings that have the corresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL\nvalues in str1, str2, ... are not appended to the result.\n\nURL: https://mariadb.com/kb/en/make_set/\n\n','MariaDB> SELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n -> \'a\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n -> \'hello,world\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n -> \'hello\'\nMariaDB> SELECT MAKE_SET(0,\'a\',\'b\',\'c\');\n -> \'\'\n','https://mariadb.com/kb/en/make_set/'),(507,'FIND_IN_SET',37,'Syntax:\nFIND_IN_SET(str,strlist)\n\nReturns a value in the range of 1 to N if the string str is in the\nstring list strlist consisting of N substrings. A string list is a\nstring composed of substrings separated by \",\" characters. If the first\nargument is a constant string and the second is a column of type SET,\nthe FIND_IN_SET() function is optimized to use bit arithmetic. Returns\n0 if str is not in strlist or if strlist is the empty string. Returns\nNULL if either argument is NULL. This function does not work properly\nif the first argument contains a comma (\",\") character.\n\nURL: https://mariadb.com/kb/en/find_in_set/\n\n','MariaDB> SELECT FIND_IN_SET(\'b\',\'a,b,c,d\');\n -> 2\n','https://mariadb.com/kb/en/find_in_set/'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `host` +-- + +DROP TABLE IF EXISTS `host`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `host` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `host` +-- + +LOCK TABLES `host` WRITE; +/*!40000 ALTER TABLE `host` DISABLE KEYS */; +/*!40000 ALTER TABLE `host` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `index_stats` +-- + +DROP TABLE IF EXISTS `index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `index_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `prefix_arity` int(11) unsigned NOT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `index_stats` +-- + +LOCK TABLES `index_stats` WRITE; +/*!40000 ALTER TABLE `index_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_index_stats` +-- + +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_index_stats` +-- + +LOCK TABLES `innodb_index_stats` WRITE; +/*!40000 ALTER TABLE `innodb_index_stats` DISABLE KEYS */; +INSERT INTO `innodb_index_stats` VALUES ('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:12:54','n_diff_pfx01',0,1,'domain_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:12:54','n_diff_pfx02',0,1,'domain_id,sub_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:12:54','n_leaf_pages',1,NULL,'Number of leaf pages in the index'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:12:54','size',1,NULL,'Number of pages in the index'); +/*!40000 ALTER TABLE `innodb_index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_table_stats` +-- + +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_table_stats` +-- + +LOCK TABLES `innodb_table_stats` WRITE; +/*!40000 ALTER TABLE `innodb_table_stats` DISABLE KEYS */; +INSERT INTO `innodb_table_stats` VALUES ('mysql','gtid_slave_pos','2020-05-31 16:12:54',0,1,0); +/*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +INSERT INTO `proc` VALUES ('mysql','AddGeometryColumn','PROCEDURE','AddGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64), t_srid int','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:13:00','2020-05-31 16:13:00','','','latin1','latin1_swedish_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end'),('mysql','DropGeometryColumn','PROCEDURE','DropGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64)','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:13:00','2020-05-31 16:13:00','','','latin1','latin1_swedish_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end'); +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT '0', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 16:12:54'),('asus','root','','',1,'','2020-05-31 16:12:54'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_mapping` +-- + +DROP TABLE IF EXISTS `roles_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_mapping` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Admin_option` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + UNIQUE KEY `Host` (`Host`,`User`,`Role`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Granted roles'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_mapping` +-- + +LOCK TABLES `roles_mapping` WRITE; +/*!40000 ALTER TABLE `roles_mapping` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_mapping` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` char(64) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(80) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT '0', + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` char(64) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `table_stats` +-- + +DROP TABLE IF EXISTS `table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `table_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `cardinality` bigint(21) unsigned DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `table_stats` +-- + +LOCK TABLES `table_stats` WRITE; +/*!40000 ALTER TABLE `table_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT '0', + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', + `ssl_cipher` blob NOT NULL, + `x509_issuer` blob NOT NULL, + `x509_subject` blob NOT NULL, + `max_questions` int(11) unsigned NOT NULL DEFAULT '0', + `max_updates` int(11) unsigned NOT NULL DEFAULT '0', + `max_connections` int(11) unsigned NOT NULL DEFAULT '0', + `max_user_connections` int(11) NOT NULL DEFAULT '0', + `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, + `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000', + PRIMARY KEY (`Host`,`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 19:13:29 diff --git a/mysql-test/std_data/mysql_database_10.2.dump b/mysql-test/std_data/mysql_database_10.2.dump new file mode 100644 index 00000000000..0321955edbe --- /dev/null +++ b/mysql-test/std_data/mysql_database_10.2.dump @@ -0,0 +1,906 @@ +-- MySQL dump 10.16 Distrib 10.2.32-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 10.2.32-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `column_stats` +-- + +DROP TABLE IF EXISTS `column_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, + `nulls_ratio` decimal(12,4) DEFAULT NULL, + `avg_length` decimal(12,4) DEFAULT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + `hist_size` tinyint(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `column_stats` +-- + +LOCK TABLES `column_stats` WRITE; +/*!40000 ALTER TABLE `column_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `column_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + PRIMARY KEY (`db`,`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT 0, + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gtid_slave_pos` +-- + +DROP TABLE IF EXISTS `gtid_slave_pos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gtid_slave_pos` ( + `domain_id` int(10) unsigned NOT NULL, + `sub_id` bigint(20) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `seq_no` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`domain_id`,`sub_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Replication slave GTID position'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gtid_slave_pos` +-- + +LOCK TABLES `gtid_slave_pos` WRITE; +/*!40000 ALTER TABLE `gtid_slave_pos` DISABLE KEYS */; +/*!40000 ALTER TABLE `gtid_slave_pos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control flow functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry constructors',34,''),(25,'GeometryCollection properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (0,'JOIN'),(1,'HOST'),(2,'REPEAT'),(3,'SERIALIZABLE'),(4,'REPLACE'),(5,'AT'),(6,'SCHEDULE'),(7,'RETURNS'),(8,'STARTS'),(9,'MASTER_SSL_CA'),(10,'NCHAR'),(11,'COLUMNS'),(12,'COMPLETION'),(13,'WORK'),(14,'DATETIME'),(15,'MODE'),(16,'OPEN'),(17,'INTEGER'),(18,'ESCAPE'),(19,'VALUE'),(20,'MASTER_SSL_VERIFY_SERVER_CERT'),(21,'SQL_BIG_RESULT'),(22,'DROP'),(23,'GEOMETRYCOLLECTIONFROMWKB'),(24,'EVENTS'),(25,'MONTH'),(26,'PROFILES'),(27,'DUPLICATE'),(28,'REPLICATION'),(29,'UNLOCK'),(30,'INNODB'),(31,'YEAR_MONTH'),(32,'SUBJECT'),(33,'PREPARE'),(34,'LOCK'),(35,'NDB'),(36,'CHECK'),(37,'FULL'),(38,'INT4'),(39,'BY'),(40,'NO'),(41,'MINUTE'),(42,'PARTITION'),(43,'DATA'),(44,'DAY'),(45,'SHARE'),(46,'REAL'),(47,'SEPARATOR'),(48,'MESSAGE_TEXT'),(49,'MASTER_HEARTBEAT_PERIOD'),(50,'DELETE'),(51,'ON'),(52,'COLUMN_NAME'),(53,'CONNECTION'),(54,'CLOSE'),(55,'X509'),(56,'USE'),(57,'SUBCLASS_ORIGIN'),(58,'WHERE'),(59,'PRIVILEGES'),(60,'SPATIAL'),(61,'EVENT'),(62,'SUPER'),(63,'SQL_BUFFER_RESULT'),(64,'IGNORE'),(65,'SHA2'),(66,'QUICK'),(67,'SIGNED'),(68,'OFFLINE'),(69,'SECURITY'),(70,'AUTOEXTEND_SIZE'),(71,'NDBCLUSTER'),(72,'POLYGONFROMWKB'),(73,'FALSE'),(74,'LEVEL'),(75,'FORCE'),(76,'BINARY'),(77,'TO'),(78,'CHANGE'),(79,'CURRENT_USER'),(80,'HOUR_MINUTE'),(81,'UPDATE'),(82,'PRESERVE'),(83,'TABLE_NAME'),(84,'INTO'),(85,'FEDERATED'),(86,'VARYING'),(87,'MAX_SIZE'),(88,'HOUR_SECOND'),(89,'VARIABLE'),(90,'ROLLBACK'),(91,'PROCEDURE'),(92,'TIMESTAMP'),(93,'IMPORT'),(94,'AGAINST'),(95,'CHECKSUM'),(96,'COUNT'),(97,'LONGBINARY'),(98,'THEN'),(99,'INSERT'),(100,'ENGINES'),(101,'HANDLER'),(102,'PORT'),(103,'DAY_SECOND'),(104,'EXISTS'),(105,'MUTEX'),(106,'HELP_DATE'),(107,'RELEASE'),(108,'BOOLEAN'),(109,'MOD'),(110,'DEFAULT'),(111,'TYPE'),(112,'NO_WRITE_TO_BINLOG'),(113,'OPTIMIZE'),(114,'SQLSTATE'),(115,'RESET'),(116,'CLASS_ORIGIN'),(117,'INSTALL'),(118,'ITERATE'),(119,'DO'),(120,'BIGINT'),(121,'SET'),(122,'ISSUER'),(123,'DATE'),(124,'STATUS'),(125,'FULLTEXT'),(126,'COMMENT'),(127,'MASTER_CONNECT_RETRY'),(128,'INNER'),(129,'RELAYLOG'),(130,'STOP'),(131,'MASTER_LOG_FILE'),(132,'MRG_MYISAM'),(133,'PRECISION'),(134,'REQUIRE'),(135,'TRAILING'),(136,'PARTITIONS'),(137,'LONG'),(138,'OPTION'),(139,'REORGANIZE'),(140,'ELSE'),(141,'DEALLOCATE'),(142,'IO_THREAD'),(143,'CASE'),(144,'CIPHER'),(145,'CONTINUE'),(146,'FROM'),(147,'READ'),(148,'LEFT'),(149,'ELSEIF'),(150,'MINUTE_SECOND'),(151,'COMPACT'),(152,'DEC'),(153,'FOR'),(154,'WARNINGS'),(155,'MIN_ROWS'),(156,'STRING'),(157,'CONDITION'),(158,'ENCLOSED'),(159,'FUNCTION'),(160,'AGGREGATE'),(161,'FIELDS'),(162,'INT3'),(163,'ARCHIVE'),(164,'AVG_ROW_LENGTH'),(165,'ADD'),(166,'KILL'),(167,'FLOAT4'),(168,'TABLESPACE'),(169,'VIEW'),(170,'REPEATABLE'),(171,'INFILE'),(172,'HELP_VERSION'),(173,'ORDER'),(174,'USING'),(175,'CONSTRAINT_CATALOG'),(176,'MIDDLEINT'),(177,'GRANT'),(178,'UNSIGNED'),(179,'DECIMAL'),(180,'GEOMETRYFROMTEXT'),(181,'INDEXES'),(182,'FOREIGN'),(183,'CACHE'),(184,'HOSTS'),(185,'MYSQL_ERRNO'),(186,'COMMIT'),(187,'SCHEMAS'),(188,'LEADING'),(189,'SNAPSHOT'),(190,'CONSTRAINT_NAME'),(191,'DECLARE'),(192,'LOAD'),(193,'SQL_CACHE'),(194,'CONVERT'),(195,'DYNAMIC'),(196,'COLLATE'),(197,'POLYGONFROMTEXT'),(198,'BYTE'),(199,'GLOBAL'),(200,'LINESTRINGFROMWKB'),(201,'WHEN'),(202,'HAVING'),(203,'AS'),(204,'STARTING'),(205,'RELOAD'),(206,'AUTOCOMMIT'),(207,'REVOKE'),(208,'GRANTS'),(209,'OUTER'),(210,'CURSOR_NAME'),(211,'FLOOR'),(212,'EXPLAIN'),(213,'WITH'),(214,'AFTER'),(215,'STD'),(216,'CSV'),(217,'DISABLE'),(218,'UNINSTALL'),(219,'OUTFILE'),(220,'LOW_PRIORITY'),(221,'FILE'),(222,'NODEGROUP'),(223,'SCHEMA'),(224,'SONAME'),(225,'POW'),(226,'DUAL'),(227,'MULTIPOINTFROMWKB'),(228,'INDEX'),(229,'MULTIPOINTFROMTEXT'),(230,'DEFINER'),(231,'MASTER_BIND'),(232,'REMOVE'),(233,'EXTENDED'),(234,'MULTILINESTRINGFROMWKB'),(235,'CROSS'),(236,'CONTRIBUTORS'),(237,'NATIONAL'),(238,'GROUP'),(239,'SHA'),(240,'ONLINE'),(241,'UNDO'),(242,'IGNORE_SERVER_IDS'),(243,'ZEROFILL'),(244,'CLIENT'),(245,'MASTER_PASSWORD'),(246,'OWNER'),(247,'RELAY_LOG_FILE'),(248,'TRUE'),(249,'CHARACTER'),(250,'MASTER_USER'),(251,'SCHEMA_NAME'),(252,'TABLE'),(253,'ENGINE'),(254,'INSERT_METHOD'),(255,'CASCADE'),(256,'RELAY_LOG_POS'),(257,'SQL_CALC_FOUND_ROWS'),(258,'UNION'),(259,'MYISAM'),(260,'LEAVE'),(261,'MODIFY'),(262,'MATCH'),(263,'MASTER_LOG_POS'),(264,'DISTINCTROW'),(265,'DESC'),(266,'TIME'),(267,'NUMERIC'),(268,'EXPANSION'),(269,'CODE'),(270,'CURSOR'),(271,'GEOMETRYCOLLECTIONFROMTEXT'),(272,'CHAIN'),(273,'LOGFILE'),(274,'FLUSH'),(275,'CREATE'),(276,'DESCRIBE'),(277,'EXTENT_SIZE'),(278,'MAX_UPDATES_PER_HOUR'),(279,'INT2'),(280,'PROCESSLIST'),(281,'ENDS'),(282,'LOGS'),(283,'DISCARD'),(284,'HEAP'),(285,'SOUNDS'),(286,'BETWEEN'),(287,'MULTILINESTRINGFROMTEXT'),(288,'REPAIR'),(289,'PACK_KEYS'),(290,'FAST'),(291,'VALUES'),(292,'CALL'),(293,'LOOP'),(294,'VARCHARACTER'),(295,'BEFORE'),(296,'TRUNCATE'),(297,'SHOW'),(298,'ALL'),(299,'REDUNDANT'),(300,'USER_RESOURCES'),(301,'PARTIAL'),(302,'BINLOG'),(303,'END'),(304,'SECOND'),(305,'AND'),(306,'FLOAT8'),(307,'PREV'),(308,'HOUR'),(309,'SELECT'),(310,'DATABASES'),(311,'OR'),(312,'IDENTIFIED'),(313,'WRAPPER'),(314,'MASTER_SSL_CIPHER'),(315,'SQL_SLAVE_SKIP_COUNTER'),(316,'BOTH'),(317,'BOOL'),(318,'YEAR'),(319,'MASTER_PORT'),(320,'CONCURRENT'),(321,'HELP'),(322,'UNIQUE'),(323,'TRIGGERS'),(324,'PROCESS'),(325,'OPTIONS'),(326,'RESIGNAL'),(327,'CONSISTENT'),(328,'MASTER_SSL'),(329,'DATE_ADD'),(330,'MAX_CONNECTIONS_PER_HOUR'),(331,'LIKE'),(332,'PLUGIN'),(333,'FETCH'),(334,'IN'),(335,'COLUMN'),(336,'DUMPFILE'),(337,'USAGE'),(338,'EXECUTE'),(339,'MEMORY'),(340,'CEIL'),(341,'QUERY'),(342,'MASTER_HOST'),(343,'LINES'),(344,'SQL_THREAD'),(345,'SERVER'),(346,'MAX_QUERIES_PER_HOUR'),(347,'MASTER_SSL_CERT'),(348,'MULTIPOLYGONFROMWKB'),(349,'TRANSACTION'),(350,'DAY_MINUTE'),(351,'STDDEV'),(352,'DATE_SUB'),(353,'REBUILD'),(354,'GEOMETRYFROMWKB'),(355,'INT1'),(356,'RENAME'),(357,'PARSER'),(358,'RIGHT'),(359,'ALTER'),(360,'MAX_ROWS'),(361,'SOCKET'),(362,'STRAIGHT_JOIN'),(363,'NATURAL'),(364,'VARIABLES'),(365,'ESCAPED'),(366,'SHA1'),(367,'KEY_BLOCK_SIZE'),(368,'PASSWORD'),(369,'OFFSET'),(370,'CHAR'),(371,'NEXT'),(372,'ERRORS'),(373,'SQL_LOG_BIN'),(374,'TEMPORARY'),(375,'COMMITTED'),(376,'SQL_SMALL_RESULT'),(377,'UPGRADE'),(378,'BEGIN'),(379,'DELAY_KEY_WRITE'),(380,'PROFILE'),(381,'MEDIUM'),(382,'INTERVAL'),(383,'SSL'),(384,'DAY_HOUR'),(385,'NAME'),(386,'REFERENCES'),(387,'AES_ENCRYPT'),(388,'STORAGE'),(389,'ISOLATION'),(390,'CEILING'),(391,'EVERY'),(392,'INT8'),(393,'AUTHORS'),(394,'RESTRICT'),(395,'UNCOMMITTED'),(396,'LINESTRINGFROMTEXT'),(397,'IS'),(398,'NOT'),(399,'ANALYSE'),(400,'DATAFILE'),(401,'DES_KEY_FILE'),(402,'SIGNAL'),(403,'COMPRESSED'),(404,'START'),(405,'PLUGINS'),(406,'SAVEPOINT'),(407,'IF'),(408,'ROWS'),(409,'PRIMARY'),(410,'PURGE'),(411,'LAST'),(412,'USER'),(413,'EXIT'),(414,'KEYS'),(415,'LIMIT'),(416,'KEY'),(417,'MERGE'),(418,'UNTIL'),(419,'SQL_NO_CACHE'),(420,'DELAYED'),(421,'CONSTRAINT_SCHEMA'),(422,'ANALYZE'),(423,'CONSTRAINT'),(424,'SERIAL'),(425,'ACTION'),(426,'WRITE'),(427,'INITIAL_SIZE'),(428,'SESSION'),(429,'DATABASE'),(430,'NULL'),(431,'POWER'),(432,'USE_FRM'),(433,'TERMINATED'),(434,'SLAVE'),(435,'NVARCHAR'),(436,'ASC'),(437,'RETURN'),(438,'OPTIONALLY'),(439,'ENABLE'),(440,'DIRECTORY'),(441,'MAX_USER_CONNECTIONS'),(442,'WHILE'),(443,'LOCAL'),(444,'DISTINCT'),(445,'AES_DECRYPT'),(446,'MASTER_SSL_KEY'),(447,'NONE'),(448,'TABLES'),(449,'<>'),(450,'RLIKE'),(451,'TRIGGER'),(452,'COLLATION'),(453,'SHUTDOWN'),(454,'HIGH_PRIORITY'),(455,'BTREE'),(456,'FIRST'),(457,'COALESCE'),(458,'WAIT'),(459,'CATALOG_NAME'),(460,'MASTER'),(461,'FIXED'),(462,'MULTIPOLYGONFROMTEXT'),(463,'ROW_FORMAT'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (1,0),(356,0),(473,1),(232,2),(447,3),(3,4),(130,4),(421,4),(89,5),(89,6),(406,6),(97,7),(89,8),(185,9),(430,10),(21,11),(347,11),(421,11),(463,11),(468,11),(89,12),(406,12),(146,13),(230,14),(88,15),(356,15),(18,16),(106,16),(134,16),(347,16),(97,17),(500,17),(380,18),(3,19),(104,19),(243,19),(374,19),(459,19),(185,20),(356,21),(9,22),(30,22),(34,22),(87,22),(186,22),(237,22),(263,22),(276,22),(300,22),(331,22),(405,22),(415,22),(416,22),(463,22),(478,22),(108,23),(122,24),(170,24),(424,24),(376,25),(82,26),(104,27),(199,28),(36,29),(347,30),(468,30),(376,31),(199,32),(35,33),(237,33),(36,34),(356,34),(468,35),(417,36),(463,36),(468,36),(21,37),(294,37),(347,37),(451,37),(468,37),(500,38),(48,39),(77,39),(83,39),(130,39),(199,39),(356,39),(361,39),(421,39),(463,39),(468,39),(468,40),(472,40),(376,41),(463,42),(468,42),(212,43),(421,43),(468,43),(473,43),(376,44),(356,45),(97,46),(314,46),(361,47),(374,48),(459,48),(185,49),(48,50),(468,50),(472,50),(1,51),(89,51),(406,51),(472,51),(374,52),(459,52),(176,53),(468,53),(51,54),(106,54),(199,55),(1,56),(55,56),(194,56),(374,57),(459,57),(48,58),(83,58),(106,58),(193,59),(199,59),(249,59),(210,60),(463,60),(89,61),(300,61),(358,61),(406,61),(199,62),(356,63),(1,64),(83,64),(104,64),(130,64),(356,64),(421,64),(463,64),(66,65),(48,66),(417,66),(466,66),(230,67),(87,68),(210,68),(463,68),(199,69),(194,70),(468,71),(91,72),(482,72),(385,73),(447,74),(1,75),(39,76),(230,76),(269,76),(185,77),(269,77),(460,77),(185,78),(463,78),(89,79),(406,79),(376,80),(83,81),(104,81),(356,81),(472,81),(89,82),(406,82),(374,83),(459,83),(3,84),(104,84),(304,84),(356,84),(468,85),(257,86),(194,87),(376,88),(129,89),(146,90),(460,90),(17,91),(189,91),(302,91),(328,91),(347,91),(356,91),(416,91),(439,91),(488,91),(99,92),(188,92),(421,93),(463,93),(88,94),(401,95),(468,95),(69,96),(330,96),(433,96),(285,97),(28,98),(57,98),(85,98),(104,99),(195,99),(301,99),(486,99),(282,100),(347,100),(106,101),(313,101),(473,102),(376,103),(9,104),(30,104),(89,104),(155,104),(186,104),(276,104),(300,104),(347,105),(365,105),(109,106),(146,107),(460,107),(24,108),(88,108),(113,109),(174,109),(3,110),(104,110),(155,110),(200,110),(212,110),(243,110),(463,110),(468,110),(463,111),(115,112),(326,112),(466,112),(470,112),(115,113),(463,113),(374,114),(459,114),(38,115),(119,115),(151,115),(264,115),(374,116),(459,116),(419,117),(124,118),(89,119),(125,119),(406,119),(496,119),(221,120),(3,121),(83,121),(104,121),(129,121),(130,121),(146,121),(155,121),(182,121),(212,121),(333,121),(347,121),(356,121),(374,121),(421,121),(459,121),(463,121),(468,121),(472,121),(477,121),(494,121),(199,122),(132,123),(230,123),(262,123),(376,123),(58,124),(137,124),(215,124),(223,124),(328,124),(336,124),(347,124),(365,124),(210,125),(463,125),(468,125),(89,126),(194,126),(210,126),(406,126),(468,126),(185,127),(1,128),(424,129),(52,130),(185,131),(468,132),(314,133),(199,134),(455,135),(255,136),(285,137),(199,138),(249,138),(463,139),(57,140),(85,140),(237,141),(52,142),(324,142),(57,143),(85,143),(199,144),(313,145),(48,146),(122,146),(347,146),(356,146),(424,146),(455,146),(36,147),(106,147),(447,147),(1,148),(28,149),(376,150),(468,151),(209,152),(180,153),(313,153),(347,153),(356,153),(420,153),(330,154),(347,154),(468,155),(97,156),(180,157),(421,158),(34,159),(68,159),(97,159),(211,159),(233,159),(302,159),(336,159),(347,159),(393,159),(405,159),(416,159),(97,160),(347,161),(421,161),(252,162),(468,163),(463,164),(468,164),(60,165),(194,165),(463,165),(478,165),(176,166),(168,167),(194,168),(415,168),(463,168),(478,168),(30,169),(159,169),(454,169),(447,170),(130,171),(421,171),(190,172),(48,173),(83,173),(356,173),(361,173),(463,173),(1,174),(48,174),(86,174),(374,175),(459,175),(252,176),(199,177),(249,177),(24,178),(128,178),(168,178),(209,178),(230,178),(314,178),(500,178),(97,179),(156,179),(230,179),(411,180),(347,181),(463,182),(468,182),(472,182),(473,182),(101,183),(151,183),(304,183),(145,184),(347,184),(374,185),(459,185),(146,186),(160,187),(347,187),(455,188),(146,189),(374,190),(459,190),(180,191),(200,191),(313,191),(420,191),(304,192),(421,192),(356,193),(230,194),(377,194),(468,195),(155,196),(212,196),(468,196),(395,197),(465,198),(129,199),(137,199),(182,199),(349,199),(447,199),(452,200),(57,201),(85,201),(356,202),(1,203),(36,203),(356,203),(421,204),(199,205),(146,206),(249,207),(192,208),(347,208),(1,209),(374,210),(459,210),(221,211),(255,212),(88,213),(199,213),(210,213),(463,213),(468,213),(463,214),(260,215),(421,216),(468,216),(89,217),(406,217),(463,217),(291,218),(356,219),(3,220),(36,220),(48,220),(83,220),(104,220),(130,220),(421,220),(199,221),(194,222),(155,223),(186,223),(212,223),(309,223),(347,223),(97,224),(277,225),(279,226),(464,227),(1,228),(60,228),(87,228),(101,228),(210,228),(304,228),(308,228),(347,228),(463,228),(468,228),(425,229),(89,230),(406,230),(185,231),(463,232),(255,233),(466,233),(272,234),(1,235),(7,236),(347,236),(257,237),(430,237),(194,238),(226,238),(356,238),(427,239),(87,240),(210,240),(463,240),(313,241),(185,242),(24,243),(128,243),(168,243),(209,243),(314,243),(500,243),(199,244),(185,245),(473,246),(185,247),(385,248),(130,249),(155,249),(212,249),(257,249),(333,249),(347,249),(356,249),(421,249),(430,249),(468,249),(185,250),(374,251),(459,251),(60,252),(110,252),(115,252),(215,252),(276,252),(278,252),(321,252),(347,252),(401,252),(417,252),(463,252),(466,252),(468,252),(470,252),(194,253),(347,253),(365,253),(415,253),(463,253),(468,253),(478,253),(468,254),(30,255),(276,255),(468,255),(472,255),(185,256),(356,257),(305,258),(468,259),(310,260),(463,261),(88,262),(185,263),(356,264),(329,265),(356,265),(361,265),(230,266),(315,266),(375,266),(209,267),(88,268),(68,269),(488,269),(420,270),(246,271),(146,272),(194,273),(226,273),(151,274),(326,274),(17,275),(22,275),(60,275),(77,275),(89,275),(97,275),(155,275),(194,275),(210,275),(211,275),(278,275),(302,275),(309,275),(347,275),(358,275),(393,275),(454,275),(468,275),(473,275),(329,276),(194,277),(199,278),(234,279),(347,280),(451,280),(89,281),(39,282),(269,282),(347,282),(463,283),(468,284),(378,285),(147,286),(107,287),(463,288),(466,288),(468,289),(417,290),(3,291),(104,291),(339,292),(344,293),(257,294),(269,295),(321,296),(463,296),(7,297),(10,297),(17,297),(21,297),(25,297),(33,297),(39,297),(58,297),(68,297),(69,297),(82,297),(122,297),(134,297),(137,297),(145,297),(160,297),(170,297),(192,297),(193,297),(215,297),(223,297),(278,297),(282,297),(294,297),(308,297),(309,297),(328,297),(330,297),(333,297),(336,297),(347,297),(349,297),(358,297),(365,297),(393,297),(424,297),(451,297),(487,297),(488,297),(492,297),(38,298),(199,298),(249,298),(305,298),(356,298),(468,299),(326,300),(468,301),(122,302),(350,302),(28,303),(57,303),(85,303),(232,303),(327,303),(344,303),(496,303),(376,304),(147,305),(316,305),(314,306),(106,307),(376,308),(3,309),(104,309),(255,309),(301,309),(356,309),(160,310),(347,310),(141,311),(77,312),(130,312),(199,312),(473,313),(185,314),(182,315),(455,316),(24,317),(111,317),(376,318),(185,319),(130,320),(421,320),(118,321),(390,321),(463,322),(25,323),(347,323),(199,324),(373,325),(473,325),(374,326),(146,327),(185,328),(376,329),(199,330),(347,331),(378,331),(291,332),(347,332),(419,332),(383,333),(88,334),(122,334),(356,334),(424,334),(463,335),(356,336),(199,337),(86,338),(199,338),(356,339),(397,340),(88,341),(151,341),(176,341),(185,342),(130,343),(421,343),(52,344),(324,344),(9,345),(373,345),(473,345),(199,346),(185,347),(123,348),(146,349),(447,349),(376,350),(407,351),(376,352),(463,353),(144,354),(24,355),(110,356),(222,356),(406,356),(463,356),(210,357),(463,357),(468,357),(1,358),(60,359),(159,359),(199,359),(212,359),(226,359),(233,359),(373,359),(406,359),(439,359),(463,359),(478,359),(463,360),(468,360),(473,361),(1,362),(356,362),(1,363),(347,364),(349,364),(421,365),(427,366),(468,367),(77,368),(199,368),(473,368),(477,368),(356,369),(230,370),(465,370),(106,371),(69,372),(347,372),(494,373),(276,374),(447,375),(356,376),(212,377),(417,377),(146,378),(327,378),(468,379),(487,380),(417,381),(89,382),(376,382),(199,383),(376,384),(212,385),(199,386),(468,386),(472,386),(443,387),(282,388),(447,389),(448,390),(89,391),(128,392),(10,393),(347,393),(30,394),(276,394),(472,394),(447,395),(56,396),(84,397),(206,397),(368,397),(456,397),(84,398),(89,398),(155,398),(206,398),(312,398),(189,399),(194,400),(478,400),(326,401),(459,402),(468,403),(146,404),(324,404),(33,405),(460,406),(9,407),(28,407),(30,407),(89,407),(155,407),(186,407),(276,407),(300,407),(479,407),(130,408),(463,409),(269,410),(106,411),(77,412),(222,412),(331,412),(473,412),(313,413),(308,414),(347,414),(463,414),(48,415),(83,415),(106,415),(122,415),(356,415),(424,415),(60,416),(104,416),(463,416),(468,416),(472,416),(468,417),(232,418),(356,419),(3,420),(104,420),(486,420),(374,421),(459,421),(463,422),(470,422),(463,423),(468,423),(243,424),(468,424),(468,425),(472,425),(36,426),(194,427),(478,427),(129,428),(137,428),(349,428),(447,428),(155,429),(186,429),(212,429),(309,429),(347,429),(473,429),(84,430),(368,430),(472,430),(483,431),(466,432),(421,433),(38,434),(52,434),(89,434),(145,434),(223,434),(324,434),(406,434),(257,435),(356,436),(361,436),(491,437),(421,438),(89,439),(406,439),(463,439),(212,440),(468,440),(199,441),(496,442),(36,443),(115,443),(130,443),(326,443),(421,443),(466,443),(470,443),(0,444),(96,444),(288,444),(305,444),(356,444),(361,444),(384,444),(433,444),(497,445),(185,446),(199,447),(36,448),(134,448),(294,448),(347,448),(495,449),(27,450),(22,451),(263,451),(347,451),(347,452),(492,452),(199,453),(104,454),(356,454),(210,455),(106,456),(463,456),(468,456),(463,457),(194,458),(478,458),(374,459),(459,459),(39,460),(58,460),(185,460),(264,460),(269,460),(209,461),(468,461),(201,462),(468,463); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (0,'MIN',16,'Syntax:\nMIN([DISTINCT] expr)\n\nReturns the minimum value of expr. MIN() may take a string argument; in\nsuch cases, it returns the minimum string value.\nThe DISTINCT keyword can be used to find the minimum of the distinct values\nof expr, however, this produces the same result as omitting DISTINCT.\n\nMIN() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/min/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/min/'),(1,'JOIN',27,'MySQL supports the following JOIN syntaxes for the table_references\npart of SELECT statements and multiple-table DELETE and UPDATE\nstatements:\n\ntable_references:\n table_reference [, table_reference] ...\n\ntable_reference:\n table_factor\n | join_table\n\ntable_factor:\n tbl_name [[AS] alias] [index_hint_list]\n | table_subquery [AS] alias\n | ( table_references )\n | { OJ table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n\njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor [join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON conditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor\n\njoin_condition:\n ON conditional_expr\n | USING (column_list)\n\nindex_hint_list:\n index_hint [, index_hint] ...\n\nindex_hint:\n USE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n\nindex_list:\n index_name [, index_name] ...\n\nA table reference is also known as a join expression.\n\nThe syntax of table_factor is extended in comparison with the SQL\nStandard. The latter accepts only table_reference, not a list of them\ninside a pair of parentheses.\n\nThis is a conservative extension if we consider each comma in a list of\ntable_reference items as equivalent to an inner join. For example:\n\nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nis equivalent to:\n\nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nIn MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents\n(they can replace each other). In standard SQL, they are not\nequivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used\notherwise.\n\nIn general, parentheses can be ignored in join expressions containing\nonly inner join operations.\n\nIndex hints can be specified to affect how the MySQL optimizer makes\nuse of indexes. For more information, see\nhttps://mariadb.com/kb/en/how-to-force-query-plans/.\n\nURL: https://mariadb.com/kb/en/join-syntax/\n\n','SELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id\n WHERE right_tbl.id IS NULL;\n','https://mariadb.com/kb/en/join-syntax/'),(2,'HEX',37,'Syntax:\nHEX(str), HEX(N)\n\nFor a string argument str, HEX() returns a hexadecimal string\nrepresentation of str where each character in str is converted to two\nhexadecimal digits. The inverse of this operation is performed by the\nUNHEX() function.\n\nFor a numeric argument N, HEX() returns a hexadecimal string\nrepresentation of the value of N treated as a longlong (BIGINT) number.\nThis is equivalent to CONV(N,10,16). The inverse of this operation is\nperformed by CONV(HEX(N),16,10).\n\nURL: https://mariadb.com/kb/en/hex/\n\n','MariaDB> SELECT 0x616263, HEX(\'abc\'), UNHEX(HEX(\'abc\'));\n -> \'abc\', 616263, \'abc\'\nMariaDB> SELECT HEX(255), CONV(HEX(255),16,10);\n -> \'FF\', 255\n','https://mariadb.com/kb/en/hex/'),(3,'REPLACE',27,'Syntax:\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n\nREPLACE works exactly like INSERT, except that if an old row in the\ntable has the same value as a new row for a PRIMARY KEY or a UNIQUE\nindex, the old row is deleted before the new row is inserted. See [HELP\nINSERT].\n\nREPLACE is a MySQL extension to the SQL standard. It either inserts, or\ndeletes and inserts. For another MySQL extension to standard SQL---that\neither inserts or updates---see\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nNote that unless the table has a PRIMARY KEY or UNIQUE index, using a\nREPLACE statement makes no sense. It becomes equivalent to INSERT,\nbecause there is no index to be used to determine whether a new row\nduplicates another.\n\nValues for all columns are taken from the values specified in the\nREPLACE statement. Any missing columns are set to their default values,\njust as happens for INSERT. You cannot refer to values from the current\nrow and use them in the new row. If you use an assignment such as SET\ncol_name = col_name + 1, the reference to the column name on the right\nhand side is treated as DEFAULT(col_name), so the assignment is\nequivalent to SET col_name = DEFAULT(col_name) + 1.\n\nTo use REPLACE, you must have both the INSERT and DELETE privileges for\nthe table.\n\nURL: https://mariadb.com/kb/en/replace/\n\n','','https://mariadb.com/kb/en/replace/'),(4,'CONTAINS',30,'Contains(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 completely contains g2. This\ntests the opposite relationship as Within().\n\nURL: https://mariadb.com/kb/en/contains/\n\n','','https://mariadb.com/kb/en/contains/'),(5,'SRID',36,'SRID(g)\n\nReturns an integer indicating the Spatial Reference System ID for the\ngeometry value g.\n\nIn MySQL, the SRID value is just an integer associated with the\ngeometry value. All calculations are done assuming Euclidean (planar)\ngeometry.\n\nURL: https://mariadb.com/kb/en/srid/\n\n','MariaDB> SELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n','https://mariadb.com/kb/en/srid/'),(6,'CURRENT_TIMESTAMP',31,'Syntax:\nCURRENT_TIMESTAMP, CURRENT_TIMESTAMP()\n\nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/current_timestamp/\n\n','','https://mariadb.com/kb/en/current_timestamp/'),(7,'SHOW CONTRIBUTORS',26,'Syntax:\nSHOW CONTRIBUTORS\n\nThe SHOW CONTRIBUTORS statement displays information about the people\nwho contribute to MySQL source or to causes that we support. For each\ncontributor, it displays Name, Location, and Comment values.\n\nURL: https://mariadb.com/kb/en/show-contributors/\n\n','','https://mariadb.com/kb/en/show-contributors/'),(8,'VARIANCE',16,'Syntax:\nVARIANCE(expr)\n\nReturns the population standard variance of expr. This is an extension\nto standard SQL. The standard SQL function VAR_POP() can be used\ninstead.\n\nVARIANCE() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/variance/\n\n','','https://mariadb.com/kb/en/variance/'),(9,'DROP SERVER',39,'Syntax:\nDROP SERVER [ IF EXISTS ] server_name\n\nDrops the server definition for the server named server_name. The\ncorresponding row within the mysql.servers table will be deleted. This\nstatement requires the SUPER privilege.\n\nDropping a server for a table does not affect any FEDERATED tables that\nused this connection information when they were created. See [HELP\nCREATE SERVER].\n\nURL: https://mariadb.com/kb/en/drop-server/\n\n','','https://mariadb.com/kb/en/drop-server/'),(10,'SHOW AUTHORS',26,'Syntax:\nSHOW AUTHORS\n\nThe SHOW AUTHORS statement displays information about the people who\nwork on MySQL. For each author, it displays Name, Location, and Comment\nvalues.\n\nURL: https://mariadb.com/kb/en/show-authors/\n\n','','https://mariadb.com/kb/en/show-authors/'),(11,'VAR_SAMP',16,'Syntax:\nVAR_SAMP(expr)\n\nReturns the sample variance of expr. That is, the denominator is the\nnumber of rows minus one.\n\nVAR_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_samp/\n\n','','https://mariadb.com/kb/en/var_samp/'),(12,'CONCAT',37,'Syntax:\nCONCAT(str1,str2,...)\n\nReturns the string that results from concatenating the arguments. May\nhave one or more arguments. If all arguments are nonbinary strings, the\nresult is a nonbinary string. If the arguments include any binary\nstrings, the result is a binary string. A numeric argument is converted\nto its equivalent string form. This is a nonbinary string as of MySQL\n5.5.3. Before 5.5.3, it is a binary string; to to avoid that and\nproduce a nonbinary string, you can use an explicit type cast, as in\nthis example:\n\nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n\nCONCAT() returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/concat/\n\n','MariaDB> SELECT CONCAT(\'My\', \'S\', \'QL\');\n -> \'MySQL\'\nMariaDB> SELECT CONCAT(\'My\', NULL, \'QL\');\n -> NULL\nMariaDB> SELECT CONCAT(14.3);\n -> \'14.3\'\n','https://mariadb.com/kb/en/concat/'),(13,'GEOMETRY HIERARCHY',34,'Geometry is the base class. It is an abstract class. The instantiable\nsubclasses of Geometry are restricted to zero-, one-, and\ntwo-dimensional geometric objects that exist in two-dimensional\ncoordinate space. All instantiable geometry classes are defined so that\nvalid instances of a geometry class are topologically closed (that is,\nall defined geometries include their boundary).\n\nThe base Geometry class has subclasses for Point, Curve, Surface, and\nGeometryCollection:\n\no Point represents zero-dimensional objects.\n\no Curve represents one-dimensional objects, and has subclass\n LineString, with sub-subclasses Line and LinearRing.\n\no Surface is designed for two-dimensional objects and has subclass\n Polygon.\n\no GeometryCollection has specialized zero-, one-, and two-dimensional\n collection classes named MultiPoint, MultiLineString, and\n MultiPolygon for modeling geometries corresponding to collections of\n Points, LineStrings, and Polygons, respectively. MultiCurve and\n MultiSurface are introduced as abstract superclasses that generalize\n the collection interfaces to handle Curves and Surfaces.\n\nGeometry, Curve, Surface, MultiCurve, and MultiSurface are defined as\nnoninstantiable classes. They define a common set of methods for their\nsubclasses and are included for extensibility.\n\nPoint, LineString, Polygon, GeometryCollection, MultiPoint,\nMultiLineString, and MultiPolygon are instantiable classes.\n\nURL: https://mariadb.com/kb/en/geometry-hierarchy/\n\n','','https://mariadb.com/kb/en/geometry-hierarchy/'),(14,'CHAR FUNCTION',37,'Syntax:\nCHAR(N,... [USING charset_name])\n\nCHAR() interprets each argument N as an integer and returns a string\nconsisting of the characters given by the code values of those\nintegers. NULL values are skipped.\nBy default, CHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n\nMariaDB> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n\nIf USING is given and the result string is illegal for the given\ncharacter set, a warning is issued. Also, if strict SQL mode is\nenabled, the result from CHAR() becomes NULL.\n\nURL: https://mariadb.com/kb/en/char-function/\n\n','MariaDB> SELECT CHAR(77,121,83,81,\'76\');\n -> \'MySQL\'\nMariaDB> SELECT CHAR(77,77.3,\'77.3\');\n -> \'MMM\'\n','https://mariadb.com/kb/en/char-function/'),(15,'DATETIME',22,'DATETIME\n\nA date and time combination. The supported range is \'1000-01-01\n00:00:00\' to \'9999-12-31 23:59:59\'. MySQL displays DATETIME values in\n\'YYYY-MM-DD HH:MM:SS\' format, but permits assignment of values to\nDATETIME columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/datetime/\n\n','','https://mariadb.com/kb/en/datetime/'),(16,'SHOW CREATE TRIGGER',26,'Syntax:\nSHOW CREATE TRIGGER trigger_name\n\nThis statement shows a CREATE TRIGGER statement that creates the given\ntrigger.\n\nURL: https://mariadb.com/kb/en/show-create-trigger/\n\n','','https://mariadb.com/kb/en/show-create-trigger/'),(17,'SHOW CREATE PROCEDURE',26,'Syntax:\nSHOW CREATE PROCEDURE proc_name\n\nThis statement is a MySQL extension. It returns the exact string that\ncan be used to re-create the named stored procedure. A similar\nstatement, SHOW CREATE FUNCTION, displays information about stored\nfunctions (see [HELP SHOW CREATE FUNCTION]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table. If you do not have privileges\nfor the routine itself, the value displayed for the Create Procedure or\nCreate Function field will be NULL.\n\nURL: https://mariadb.com/kb/en/show-create-procedure/\n\n','MariaDB> SHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row ***************************\n Procedure: simpleproc\n sql_mode:\n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nMariaDB> SHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row ***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-procedure/'),(18,'OPEN',23,'Syntax:\nOPEN cursor_name\n\nThis statement opens a previously declared cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/open/\n\n','','https://mariadb.com/kb/en/open/'),(19,'INTEGER',22,'INTEGER[(M)] [UNSIGNED] [ZEROFILL]\n\nThis type is a synonym for INT.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-int\n\n','','https://mariadb.com/kb/en/sql_language-data_types-int'),(20,'LOWER',37,'Syntax:\nLOWER(str)\n\nReturns the string str with all characters changed to lowercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT LOWER(\'QUADRATICALLY\');\n -> \'quadratically\'\n\nLOWER() (and UPPER()) are ineffective when applied to binary strings\n(BINARY, VARBINARY, BLOB). To perform lettercase conversion, convert\nthe string to a nonbinary string:\n\nMariaDB> SET @str = BINARY \'New York\';\nMariaDB> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+-------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+-------------+-----------------------------------+\n| New York | new york |\n+-------------+-----------------------------------+\n\nURL: https://mariadb.com/kb/en/lower/\n\n','','https://mariadb.com/kb/en/lower/'),(21,'SHOW COLUMNS',26,'Syntax:\nSHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW COLUMNS displays information about the columns in a given table.\nIt also works for views. The LIKE clause, if present, indicates which\ncolumn names to match. The WHERE clause can be given to select rows\nusing more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nSHOW COLUMNS displays information only for those columns for which you\nhave some privilege.\n\nMariaDB> SHOW COLUMNS FROM City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nIf the data types differ from what you expect them to be based on a\nCREATE TABLE statement, note that MySQL sometimes changes data types\nwhen you create or alter a table. The conditions under which this\noccurs are described in\nhttps://mariadb.com/kb/en/silent-column-changes/.\n\nThe FULL keyword causes the output to include the column collation and\ncomments, as well as the privileges you have for each column.\n\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. In other words, these two statements are equivalent:\n\nMariaDB> SHOW COLUMNS FROM mytable FROM mydb;\nMariaDB> SHOW COLUMNS FROM mydb.mytable;\n\nSHOW COLUMNS displays the following values for each table column:\n\nField indicates the column name.\n\nType indicates the column data type.\n\nCollation indicates the collation for nonbinary string columns, or NULL\nfor other columns. This value is displayed only if you use the FULL\nkeyword.\n\nThe Null field contains YES if NULL values can be stored in the column,\nNO if not.\n\nThe Key field indicates whether the column is indexed:\n\no If Key is empty, the column either is not indexed or is indexed only\n as a secondary column in a multiple-column, nonunique index.\n\no If Key is PRI, the column is a PRIMARY KEY or is one of the columns\n in a multiple-column PRIMARY KEY.\n\no If Key is UNI, the column is the first column of a UNIQUE index. (A\n UNIQUE index permits multiple NULL values, but you can tell whether\n the column permits NULL by checking the Null field.)\n\no If Key is MUL, the column is the first column of a nonunique index in\n which multiple occurrences of a given value are permitted within the\n column.\n\nIf more than one of the Key values applies to a given column of a\ntable, Key displays the one with the highest priority, in the order\nPRI, UNI, MUL.\n\nA UNIQUE index may be displayed as PRI if it cannot contain NULL values\nand there is no PRIMARY KEY in the table. A UNIQUE index may display as\nMUL if several columns form a composite UNIQUE index; although the\ncombination of the columns is unique, each column can still hold\nmultiple occurrences of a given value.\n\nThe Default field indicates the default value that is assigned to the\ncolumn. This is NULL if the column has an explicit default of NULL, or\nif the column definition has no DEFAULT clause.\n\nThe Extra field contains any additional information that is available\nabout a given column. The value is nonempty in these cases:\nauto_increment for columns that have the AUTO_INCREMENT attribute; on\nupdate CURRENT_TIMESTAMP for TIMESTAMP columns that have the ON UPDATE\nCURRENT_TIMESTAMP attribute.\n\nPrivileges indicates the privileges you have for the column. This value\nis displayed only if you use the FULL keyword.\n\nComment indicates any comment the column has. This value is displayed\nonly if you use the FULL keyword.\n\nSHOW FIELDS is a synonym for SHOW COLUMNS. You can also list a table\'s\ncolumns with the mysqlshow db_name tbl_name command.\n\nThe DESCRIBE statement provides information similar to SHOW COLUMNS.\nSee [HELP DESCRIBE].\n\nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX statements\nalso provide information about tables. See [HELP SHOW].\n\nURL: https://mariadb.com/kb/en/show-columns/\n\n','','https://mariadb.com/kb/en/show-columns/'),(22,'CREATE TRIGGER',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name trigger_time trigger_event\n ON tbl_name FOR EACH ROW trigger_body\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section. If\nbinary logging is enabled, CREATE TRIGGER might require the SUPER\nprivilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time. See later in\nthis section for more information.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\ntrigger_event indicates the kind of statement that activates the\ntrigger. The trigger_event can be one of the following:\n\no INSERT: The trigger is activated whenever a new row is inserted into\n the table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger is activated whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger is activated whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. However,\n DROP TABLE and TRUNCATE TABLE statements on the table do not activate\n this trigger, because they do not use DELETE. Dropping a partition\n does not activate DELETE triggers, either. See [HELP TRUNCATE TABLE].\n\nURL: https://mariadb.com/kb/en/create-trigger/\n\n','','https://mariadb.com/kb/en/create-trigger/'),(23,'MONTH',31,'Syntax:\nMONTH(date)\n\nReturns the month for date, in the range 1 to 12 for January to\nDecember, or 0 for dates such as \'0000-00-00\' or \'2008-00-00\' that have\na zero month part.\n\nURL: https://mariadb.com/kb/en/month/\n\n','MariaDB> SELECT MONTH(\'2008-02-03\');\n -> 2\n','https://mariadb.com/kb/en/month/'),(24,'TINYINT',22,'TINYINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA very small integer. The signed range is -128 to 127. The unsigned\nrange is 0 to 255.\n\nURL: https://mariadb.com/kb/en/tinyint/\n\n','','https://mariadb.com/kb/en/tinyint/'),(25,'SHOW TRIGGERS',26,'Syntax:\nSHOW TRIGGERS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TRIGGERS lists the triggers currently defined for tables in a\ndatabase (the default database unless a FROM clause is given). This\nstatement returns results only for databases and tables for which you\nhave the TRIGGER privilege. The LIKE clause, if present, indicates\nwhich table names to match and causes the statement to display triggers\nfor those tables. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nFor the trigger ins_sum as defined in\nhttps://mariadb.com/kb/en/triggers/, the output of\nthis statement is as shown here:\n\nMariaDB> SHOW TRIGGERS LIKE \'acc%\'\\G\n*************************** 1. row ***************************\n Trigger: ins_sum\n Event: INSERT\n Table: account\n Statement: SET @sum = @sum + NEW.amount\n Timing: BEFORE\n Created: NULL\n sql_mode:\n Definer: myname@localhost\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\ncharacter_set_client is the session value of the character_set_client\nsystem variable when the trigger was created. collation_connection is\nthe session value of the collation_connection system variable when the\ntrigger was created. Database Collation is the collation of the\ndatabase with which the trigger is associated.\n\nURL: https://mariadb.com/kb/en/show-triggers/\n\n','','https://mariadb.com/kb/en/show-triggers/'),(26,'MASTER_POS_WAIT',14,'Syntax:\nMASTER_POS_WAIT(log_name,log_pos[,timeout])\n\nThis function is useful for control of master/slave synchronization. It\nblocks until the slave has read and applied all updates up to the\nspecified position in the master log. The return value is the number of\nlog events the slave had to wait for to advance to the specified\nposition. The function returns NULL if the slave SQL thread is not\nstarted, the slave\'s master information is not initialized, the\narguments are incorrect, or an error occurs. It returns -1 if the\ntimeout has been exceeded. If the slave SQL thread stops while\nMASTER_POS_WAIT() is waiting, the function returns NULL. If the slave\nis past the specified position, the function returns immediately.\n\nIf a timeout value is specified, MASTER_POS_WAIT() stops waiting when\ntimeout seconds have elapsed. timeout must be greater than 0; a zero or\nnegative timeout means no timeout.\n\nURL: https://mariadb.com/kb/en/master_pos_wait/\n\n','','https://mariadb.com/kb/en/master_pos_wait/'),(27,'REGEXP',37,'Syntax:\nexpr REGEXP pat, expr RLIKE pat\n\nPerforms a pattern match of a string expression expr against a pattern\npat. The pattern can be an extended regular expression. The syntax for\nregular expressions is discussed in\nhttps://mariadb.com/kb/en/regexp/. Returns 1 if expr\nmatches pat; otherwise it returns 0. If either expr or pat is NULL, the\nresult is NULL. RLIKE is a synonym for REGEXP, provided for mSQL\ncompatibility.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\n*Note*: Because MySQL uses the C escape syntax in strings (for example,\n\"\\n\" to represent the newline character), you must double any \"\\\" that\nyou use in your REGEXP strings.\n\nREGEXP is not case sensitive, except when used with binary strings.\n\nURL: https://mariadb.com/kb/en/regexp/\n\n','MariaDB> SELECT \'Monty!\' REGEXP \'.*\';\n -> 1\nMariaDB> SELECT \'new*\\n*line\' REGEXP \'new\\\\*.\\\\*line\';\n -> 1\nMariaDB> SELECT \'a\' REGEXP \'A\', \'a\' REGEXP BINARY \'A\';\n -> 1 0\nMariaDB> SELECT \'a\' REGEXP \'^[a-d]\';\n -> 1\n','https://mariadb.com/kb/en/regexp/'),(28,'IF STATEMENT',23,'Syntax:\nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF\n\nThe IF statement for stored programs implements a basic conditional\nconstruct.\n\n*Note*: There is also an IF() function, which differs from the IF\nstatement described here. See\nhttps://mariadb.com/kb/en/if-function/. The\nIF statement can have THEN, ELSE, and ELSEIF clauses, and it is\nterminated with END IF.\n\nIf the search_condition evaluates to true, the corresponding THEN or\nELSEIF clause statement_list executes. If no search_condition matches,\nthe ELSE clause statement_list executes.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nURL: https://mariadb.com/kb/en/if-statement/\n\n','','https://mariadb.com/kb/en/if-statement/'),(29,'^',19,'Syntax:\n^\n\nBitwise XOR:\n\nURL: https://mariadb.com/kb/en/bitwise-xor/\n\n','MariaDB> SELECT 1 ^ 1;\n -> 0\nMariaDB> SELECT 1 ^ 0;\n -> 1\nMariaDB> SELECT 11 ^ 3;\n -> 8\n','https://mariadb.com/kb/en/bitwise-xor/'),(30,'DROP VIEW',39,'Syntax:\nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n\nDROP VIEW removes one or more views. You must have the DROP privilege\nfor each view. If any of the views named in the argument list do not\nexist, MySQL returns an error indicating by name which nonexisting\nviews it was unable to drop, but it also drops all of the views in the\nlist that do exist.\n\nThe IF EXISTS clause prevents an error from occurring for views that\ndon\'t exist. When this clause is given, a NOTE is generated for each\nnonexistent view. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE, if given, are parsed and ignored.\n\nURL: https://mariadb.com/kb/en/drop-view/\n\n','','https://mariadb.com/kb/en/drop-view/'),(31,'WITHIN',30,'Within(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially within g2. This\ntests the opposite relationship as Contains().\n\nURL: https://mariadb.com/kb/en/within/\n\n','','https://mariadb.com/kb/en/within/'),(32,'WEEK',31,'Syntax:\nWEEK(date[,mode])\n\nThis function returns the week number for date. The two-argument form\nof WEEK() enables you to specify whether the week starts on Sunday or\nMonday and whether the return value should be in the range from 0 to 53\nor from 1 to 53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/week/\n\n','MariaDB> SELECT WEEK(\'2008-02-20\');\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',0);\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',1);\n -> 8\nMariaDB> SELECT WEEK(\'2008-12-31\',1);\n -> 53\n','https://mariadb.com/kb/en/week/'),(33,'SHOW PLUGINS',26,'Syntax:\nSHOW PLUGINS\n\nSHOW PLUGINS displays information about server plugins. Plugin\ninformation is also available in the INFORMATION_SCHEMA.PLUGINS table.\nSee https://mariadb.com/kb/en/information_schemaplugins-table/.\n\nExample of SHOW PLUGINS output:\n\nMariaDB> SHOW PLUGINS\\G\n*************************** 1. row ***************************\n Name: binlog\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 2. row ***************************\n Name: CSV\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 3. row ***************************\n Name: MEMORY\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 4. row ***************************\n Name: MyISAM\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n...\n\nURL: https://mariadb.com/kb/en/show-plugins/\n\n','','https://mariadb.com/kb/en/show-plugins/'),(34,'DROP FUNCTION UDF',21,'Syntax:\nDROP FUNCTION function_name\n\nThis statement drops the user-defined function (UDF) named\nfunction_name.\n\nTo drop a function, you must have the DELETE privilege for the mysql\ndatabase. This is because DROP FUNCTION removes a row from the\nmysql.func system table that records the function\'s name, type, and\nshared library name.\n\nURL: https://mariadb.com/kb/en/drop-function-udf/\n\n','','https://mariadb.com/kb/en/drop-function-udf/'),(35,'PREPARE',8,'Syntax:\nPREPARE stmt_name FROM preparable_stmt\n\nThe PREPARE statement prepares a statement and assigns it a name,\nstmt_name, by which to refer to the statement later. Statement names\nare not case sensitive. preparable_stmt is either a string literal or a\nuser variable that contains the text of the statement. The text must\nrepresent a single SQL statement, not multiple statements. Within the\nstatement, \"?\" characters can be used as parameter markers to indicate\nwhere data values are to be bound to the query later when you execute\nit. The \"?\" characters should not be enclosed within quotation marks,\neven if you intend to bind them to string values. Parameter markers can\nbe used only where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n\nIf a prepared statement with the given name already exists, it is\ndeallocated implicitly before the new statement is prepared. This means\nthat if the new statement contains an error and cannot be prepared, an\nerror is returned and no statement with the given name exists.\n\nA prepared statement is executed with EXECUTE and released with\nDEALLOCATE PREPARE.\n\nThe scope of a prepared statement is the session within which it is\ncreated. Other sessions cannot see it.\n\nURL: https://mariadb.com/kb/en/prepare-statement/\n\n','','https://mariadb.com/kb/en/prepare-statement/'),(36,'LOCK',8,'Syntax:\nLOCK TABLES\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n\nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n\nUNLOCK TABLES\n\nMySQL enables client sessions to acquire table locks explicitly for the\npurpose of cooperating with other sessions for access to tables, or to\nprevent other sessions from modifying tables during periods when a\nsession requires exclusive access to them. A session can acquire or\nrelease locks only for itself. One session cannot acquire locks for\nanother session or release locks held by another session.\n\nLocks may be used to emulate transactions or to get more speed when\nupdating tables. This is explained in more detail later in this\nsection.\n\nLOCK TABLES explicitly acquires table locks for the current client\nsession. Table locks can be acquired for base tables or views. You must\nhave the LOCK TABLES privilege, and the SELECT privilege for each\nobject to be locked.\n\nFor view locking, LOCK TABLES adds all base tables used in the view to\nthe set of tables to be locked and locks them automatically. If you\nlock a table explicitly with LOCK TABLES, any tables used in triggers\nare also locked implicitly, as described in\nhttps://mariadb.com/kb/en/triggers-and-implicit-locks/.\n\nUNLOCK TABLES explicitly releases any table locks held by the current\nsession. LOCK TABLES implicitly releases any table locks held by the\ncurrent session before acquiring new locks.\n\nAnother use for UNLOCK TABLES is to release the global read lock\nacquired with the FLUSH TABLES WITH READ LOCK statement, which enables\nyou to lock all tables in all databases. See [HELP FLUSH]. (This is a\nvery convenient way to get backups if you have a file system such as\nVeritas that can take snapshots in time.)\n\nURL: https://mariadb.com/kb/en/transactions-lock/\n\n','','https://mariadb.com/kb/en/transactions-lock/'),(37,'UPDATEXML',37,'Syntax:\nUpdateXML(xml_target, xpath_expr, new_xml)\n\nThis function replaces a single portion of a given fragment of XML\nmarkup xml_target with a new XML fragment new_xml, and then returns the\nchanged XML. The portion of xml_target that is replaced matches an\nXPath expression xpath_expr supplied by the user. In MySQL 5.5, the\nXPath expression can contain at most 127 characters. (This limitation\nis lifted in MySQL 5.6.)\n\nIf no expression matching xpath_expr is found, or if multiple matches\nare found, the function returns the original xml_target XML fragment.\nAll three arguments should be strings.\n\nURL: https://mariadb.com/kb/en/updatexml/\n\n','MariaDB> SELECT\n -> UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n -> UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n -> UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n -> \\G\n\n*************************** 1. row ***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n','https://mariadb.com/kb/en/updatexml/'),(38,'RESET SLAVE',8,'Syntax:\nRESET SLAVE [ALL]\n\nRESET SLAVE makes the slave forget its replication position in the\nmaster\'s binary log. This statement is meant to be used for a clean\nstart: It deletes the master.info and relay-log.info files, all the\nrelay log files, and starts a new relay log file. To use RESET SLAVE,\nthe slave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\n*Note*: All relay log files are deleted, even if they have not been\ncompletely executed by the slave SQL thread. (This is a condition\nlikely to exist on a replication slave if you have issued a STOP SLAVE\nstatement or if the slave is highly loaded.)\n\nIn MySQL 5.5 (unlike the case in MySQL 5.1 and earlier), RESET SLAVE\ndoes not change any replication connection parameters such as master\nhost, master port, master user, or master password, which are retained\nin memory. This means that START SLAVE can be issued without requiring\na CHANGE MASTER TO statement following RESET SLAVE.\n\nIn MySQL 5.5.16 and later, you can use RESET SLAVE ALL to reset these\nconnection parameters (Bug #11809016). Connection parameters are also\nreset if the slave mysqld is shut down.\n\nIf the slave SQL thread was in the middle of replicating temporary\ntables when it was stopped, and RESET SLAVE is issued, these replicated\ntemporary tables are deleted on the slave.\n\nURL: https://mariadb.com/kb/en/reset-slave-connection_name/\n\n','','https://mariadb.com/kb/en/reset-slave-connection_name/'),(39,'SHOW BINARY LOGS',26,'Syntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [HELP PURGE BINARY LOGS], that shows\nhow to determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/show-binary-logs/\n\n','','https://mariadb.com/kb/en/show-binary-logs/'),(40,'POLYGON',24,'Polygon(ls1,ls2,...)\n\nConstructs a Polygon value from a number of LineString or WKB\nLineString arguments. If any argument does not represent a LinearRing\n(that is, not a closed and simple LineString), the return value is\nNULL.\n\nURL: https://mariadb.com/kb/en/polygon/\n\n','','https://mariadb.com/kb/en/polygon/'),(41,'MINUTE',31,'Syntax:\nMINUTE(time)\n\nReturns the minute for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/minute/\n\n','MariaDB> SELECT MINUTE(\'2008-02-03 10:05:03\');\n -> 5\n','https://mariadb.com/kb/en/minute/'),(42,'DAY',31,'Syntax:\nDAY(date)\n\nDAY() is a synonym for DAYOFMONTH().\n\nURL: https://mariadb.com/kb/en/day/\n\n','','https://mariadb.com/kb/en/day/'),(43,'MID',37,'Syntax:\nMID(str,pos,len)\n\nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n\nURL: https://mariadb.com/kb/en/mid/\n\n','','https://mariadb.com/kb/en/mid/'),(44,'UUID',14,'Syntax:\nUUID()\n\nReturns a Universal Unique Identifier (UUID) generated according to\n\"DCE 1.1: Remote Procedure Call\" (Appendix A) CAE (Common Applications\nEnvironment) Specifications published by The Open Group in October 1997\n(Document Number C706,\nhttp://www.opengroup.org/public/pubs/catalog/c706.htm).\n\nA UUID is designed as a number that is globally unique in space and\ntime. Two calls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate computers\nthat are not connected to each other.\n\nA UUID is a 128-bit number represented by a utf8 string of five\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format:\n\no The first three numbers are generated from a timestamp.\n\no The fourth number preserves temporal uniqueness in case the timestamp\n value loses monotonicity (for example, due to daylight saving time).\n\no The fifth number is an IEEE 802 node number that provides spatial\n uniqueness. A random number is substituted if the latter is not\n available (for example, because the host computer has no Ethernet\n card, or we do not know how to find the hardware address of an\n interface on your operating system). In this case, spatial uniqueness\n cannot be guaranteed. Nevertheless, a collision should have very low\n probability.\n\n Currently, the MAC address of an interface is taken into account only\n on FreeBSD and Linux. On other operating systems, MySQL uses a\n randomly generated 48-bit number.\n\nURL: https://mariadb.com/kb/en/uuid/\n\n','MariaDB> SELECT UUID();\n -> \'6ccd780c-baba-1026-9564-0040f4311e29\'\n','https://mariadb.com/kb/en/uuid/'),(45,'LINESTRING',24,'LineString(pt1,pt2,...)\n\nConstructs a LineString value from a number of Point or WKB Point\narguments. If the number of arguments is less than two, the return\nvalue is NULL.\n\nURL: https://mariadb.com/kb/en/linestring/\n\n','','https://mariadb.com/kb/en/linestring/'),(46,'SLEEP',14,'Syntax:\nSLEEP(duration)\n\nSleeps (pauses) for the number of seconds given by the duration\nargument, then returns 0. If SLEEP() is interrupted, it returns 1. The\nduration may have a fractional part given in microseconds.\n\nURL: https://mariadb.com/kb/en/sleep/\n\n','','https://mariadb.com/kb/en/sleep/'),(47,'CONNECTION_ID',17,'Syntax:\nCONNECTION_ID()\n\nReturns the connection ID (thread ID) for the connection. Every\nconnection has an ID that is unique among the set of currently\nconnected clients.\n\nURL: https://mariadb.com/kb/en/connection_id/\n\n','MariaDB> SELECT CONNECTION_ID();\n -> 23786\n','https://mariadb.com/kb/en/connection_id/'),(48,'DELETE',27,'Syntax:\nSingle-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n\nOr:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n\nFor the single-table syntax, the DELETE statement deletes rows from\ntbl_name and returns a count of the number of deleted rows. This count\ncan be obtained by calling the ROW_COUNT() function (see\nhttps://mariadb.com/kb/en/information-functions-row_count/). The\nWHERE clause, if given, specifies the conditions that identify which\nrows to delete. With no WHERE clause, all rows are deleted. If the\nORDER BY clause is specified, the rows are deleted in the order that is\nspecified. The LIMIT clause places a limit on the number of rows that\ncan be deleted.\n\nFor the multiple-table syntax, DELETE deletes from each tbl_name the\nrows that satisfy the conditions. In this case, ORDER BY and LIMIT\ncannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe deleted. It is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nCurrently, you cannot delete from a table and select from the same\ntable in a subquery.\n\nYou need the DELETE privilege on a table to delete rows from it. You\nneed only the SELECT privilege for any columns that are only read, such\nas those named in the WHERE clause.\n\nAs stated, a DELETE statement with no WHERE clause deletes all rows. A\nfaster way to do this, when you do not need to know the number of\ndeleted rows, is to use TRUNCATE TABLE. However, within a transaction\nor if you have a lock on the table, TRUNCATE TABLE cannot be used\nwhereas DELETE can. See [HELP TRUNCATE TABLE], and [HELP LOCK].\n\nURL: https://mariadb.com/kb/en/delete/\n\n','','https://mariadb.com/kb/en/delete/'),(49,'ROUND',4,'Syntax:\nROUND(X), ROUND(X,D)\n\nRounds the argument X to D decimal places. The rounding algorithm\ndepends on the data type of X. D defaults to 0 if not specified. D can\nbe negative to cause D digits left of the decimal point of the value X\nto become zero.\n\nURL: https://mariadb.com/kb/en/round/\n\n','MariaDB> SELECT ROUND(-1.23);\n -> -1\nMariaDB> SELECT ROUND(-1.58);\n -> -2\nMariaDB> SELECT ROUND(1.58);\n -> 2\nMariaDB> SELECT ROUND(1.298, 1);\n -> 1.3\nMariaDB> SELECT ROUND(1.298, 0);\n -> 1\nMariaDB> SELECT ROUND(23.298, -1);\n -> 20\n','https://mariadb.com/kb/en/round/'),(50,'NULLIF',7,'Syntax:\nNULLIF(expr1,expr2)\n\nReturns NULL if expr1 = expr2 is true, otherwise returns expr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.\n\nURL: https://mariadb.com/kb/en/nullif/\n\n','MariaDB> SELECT NULLIF(1,1);\n -> NULL\nMariaDB> SELECT NULLIF(1,2);\n -> 1\n','https://mariadb.com/kb/en/nullif/'),(51,'CLOSE',23,'Syntax:\nCLOSE cursor_name\n\nThis statement closes a previously opened cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nAn error occurs if the cursor is not open.\n\nIf not closed explicitly, a cursor is closed at the end of the BEGIN\n... END block in which it was declared.\n\nURL: https://mariadb.com/kb/en/close/\n\n','','https://mariadb.com/kb/en/close/'),(52,'STOP SLAVE',8,'Syntax:\nSTOP SLAVE [thread_types]\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nStops the slave threads. STOP SLAVE requires the SUPER privilege.\nRecommended best practice is to execute STOP SLAVE on the slave before\nstopping the slave server (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-shutdown.html, for more\ninformation).\n\nWhen using the row-based logging format: You should execute STOP SLAVE\non the slave prior to shutting down the slave server if you are\nreplicating any tables that use a nontransactional storage engine (see\nthe Note later in this section). In MySQL 5.5.9 and later, you can also\nuse STOP SLAVE SQL_THREAD for this purpose.\n\nLike START SLAVE, this statement may be used with the IO_THREAD and\nSQL_THREAD options to name the thread or threads to be stopped.\n\n*Note*: In MySQL 5.5, STOP SLAVE waits until the current replication\nevent group affecting one or more non-transactional tables has finished\nexecuting (if there is any such replication group), or until the user\nissues a KILL QUERY or KILL CONNECTION statement. (Bug #319, Bug\n#38205)\n\nURL: https://mariadb.com/kb/en/stop-slave/\n\n','','https://mariadb.com/kb/en/stop-slave/'),(53,'TIMEDIFF',31,'Syntax:\nTIMEDIFF(expr1,expr2)\n\nTIMEDIFF() returns expr1 - expr2 expressed as a time value. expr1 and\nexpr2 are time or date-and-time expressions, but both must be of the\nsame type.\n\nThe result returned by TIMEDIFF() is limited to the range allowed for\nTIME values. Alternatively, you can use either of the functions\nTIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.\n\nURL: https://mariadb.com/kb/en/timediff/\n\n','MariaDB> SELECT TIMEDIFF(\'2000:01:01 00:00:00\',\n -> \'2000:01:01 00:00:00.000001\');\n -> \'-00:00:00.000001\'\nMariaDB> SELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\',\n -> \'2008-12-30 01:01:01.000002\');\n -> \'46:58:57.999999\'\n','https://mariadb.com/kb/en/timediff/'),(54,'REPLACE FUNCTION',37,'Syntax:\nREPLACE(str,from_str,to_str)\n\nReturns the string str with all occurrences of the string from_str\nreplaced by the string to_str. REPLACE() performs a case-sensitive\nmatch when searching for from_str.\n\nURL: https://mariadb.com/kb/en/replace-function/\n\n','MariaDB> SELECT REPLACE(\'www.mariadb.org\', \'w\', \'Ww\');\n -> \'WwWwWw.mariadb.org\'\n','https://mariadb.com/kb/en/replace-function/'),(55,'USE',28,'Syntax:\nUSE db_name\n\nThe USE db_name statement tells MySQL to use the db_name database as\nthe default (current) database for subsequent statements. The database\nremains the default until the end of the session or another USE\nstatement is issued:\n\nUSE db1;\nSELECT COUNT(*) FROM mytable; # selects from db1.mytable\nUSE db2;\nSELECT COUNT(*) FROM mytable; # selects from db2.mytable\n\nURL: https://mariadb.com/kb/en/use/\n\n','','https://mariadb.com/kb/en/use/'),(56,'LINEFROMTEXT',3,'LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])\n\nConstructs a LINESTRING value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromtext/\n\n','','https://mariadb.com/kb/en/linefromtext/'),(57,'CASE OPERATOR',7,'Syntax:\nCASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN\nresult ...] [ELSE result] END\n\nCASE WHEN [condition] THEN result [WHEN [condition] THEN result ...]\n[ELSE result] END\n\nThe first version returns the result where value=compare_value. The\nsecond version returns the result for the first condition that is true.\nIf there was no matching result value, the result after ELSE is\nreturned, or NULL if there is no ELSE part.\n\nURL: https://mariadb.com/kb/en/case-operator/\n\n','MariaDB> SELECT CASE 1 WHEN 1 THEN \'one\'\n -> WHEN 2 THEN \'two\' ELSE \'more\' END;\n -> \'one\'\nMariaDB> SELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n -> \'true\'\nMariaDB> SELECT CASE BINARY \'B\'\n -> WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END;\n -> NULL\n','https://mariadb.com/kb/en/case-operator/'),(58,'SHOW MASTER STATUS',26,'Syntax:\nSHOW MASTER STATUS\n\nThis statement provides status information about the binary log files\nof the master. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nExample:\n\nMariaDB> SHOW MASTER STATUS;\n+---------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+---------------+----------+--------------+------------------+\n| mysql-bin.003 | 73 | test | manual,mysql |\n+---------------+----------+--------------+------------------+\n\nURL: https://mariadb.com/kb/en/show-master-status/\n\n','','https://mariadb.com/kb/en/show-master-status/'),(59,'ADDTIME',31,'Syntax:\nADDTIME(expr1,expr2)\n\nADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time\nor datetime expression, and expr2 is a time expression.\n\nURL: https://mariadb.com/kb/en/addtime/\n\n','MariaDB> SELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1 1:1:1.000002\');\n -> \'2008-01-02 01:01:01.000001\'\nMariaDB> SELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'03:00:01.999997\'\n','https://mariadb.com/kb/en/addtime/'),(60,'SPATIAL',34,'For MyISAM tables, MySQL can create spatial indexes using syntax\nsimilar to that for creating regular indexes, but extended with the\nSPATIAL keyword. Currently, columns in spatial indexes must be declared\nNOT NULL. The following examples demonstrate how to create spatial\nindexes:\n\no With CREATE TABLE:\n\nCREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;\n\no With ALTER TABLE:\n\nALTER TABLE geom ADD SPATIAL INDEX(g);\n\no With CREATE INDEX:\n\nCREATE SPATIAL INDEX sp_index ON geom (g);\n\nFor MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage\nengines that support nonspatial indexing of spatial columns, the engine\ncreates a B-tree index. A B-tree index on spatial values will be useful\nfor exact-value lookups, but not for range scans.\n\nFor more information on indexing spatial columns, see [HELP CREATE\nINDEX].\n\nTo drop spatial indexes, use ALTER TABLE or DROP INDEX:\n\no With ALTER TABLE:\n\nALTER TABLE geom DROP INDEX g;\n\no With DROP INDEX:\n\nDROP INDEX sp_index ON geom;\n\nExample: Suppose that a table geom contains more than 32,000\ngeometries, which are stored in the column g of type GEOMETRY. The\ntable also has an AUTO_INCREMENT column fid for storing object ID\nvalues.\n\nURL: https://mariadb.com/kb/en/spatial/\n\n','','https://mariadb.com/kb/en/spatial/'),(61,'TO_SECONDS',31,'Syntax:\nTO_SECONDS(expr)\n\nGiven a date or datetime expr, returns a the number of seconds since\nthe year 0. If expr is not a valid date or datetime value, returns\nNULL.\n\nURL: https://mariadb.com/kb/en/to_seconds/\n\n','MariaDB> SELECT TO_SECONDS(950501);\n -> 62966505600\nMariaDB> SELECT TO_SECONDS(\'2009-11-29\');\n -> 63426672000\nMariaDB> SELECT TO_SECONDS(\'2009-11-29 13:43:32\');\n -> 63426721412\nMariaDB> SELECT TO_SECONDS( NOW() );\n -> 63426721458\n','https://mariadb.com/kb/en/to_seconds/'),(62,'TIMESTAMPDIFF',31,'Syntax:\nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n\nReturns datetime_expr2 - datetime_expr1, where datetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One expression may be\na date and the other a datetime; a date value is treated as a datetime\nhaving the time part \'00:00:00\' where necessary. The unit for the\nresult (an integer) is given by the unit argument. The legal values for\nunit are the same as those listed in the description of the\nTIMESTAMPADD() function.\n\nURL: https://mariadb.com/kb/en/timestampdiff/\n\n','MariaDB> SELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n -> 3\nMariaDB> SELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n -> -1\nMariaDB> SELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01 12:05:55\');\n -> 128885\n','https://mariadb.com/kb/en/timestampdiff/'),(63,'UPPER',37,'Syntax:\nUPPER(str)\n\nReturns the string str with all characters changed to uppercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT UPPER(\'Hej\');\n -> \'HEJ\'\n\nSee the description of LOWER() for information that also applies to\nUPPER(), such as information about how to perform lettercase conversion\nof binary strings (BINARY, VARBINARY, BLOB) for which these functions\nare ineffective.\n\nURL: https://mariadb.com/kb/en/upper/\n\n','','https://mariadb.com/kb/en/upper/'),(64,'FROM_UNIXTIME',31,'Syntax:\nFROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)\n\nReturns a representation of the unix_timestamp argument as a value in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the function is used in a string or numeric context. The value\nis expressed in the current time zone. unix_timestamp is an internal\ntimestamp value such as is produced by the UNIX_TIMESTAMP() function.\n\nIf format is given, the result is formatted according to the format\nstring, which is used the same way as listed in the entry for the\nDATE_FORMAT() function.\n\nURL: https://mariadb.com/kb/en/from_unixtime/\n\n','MariaDB> SELECT FROM_UNIXTIME(1196440219);\n -> \'2007-11-30 10:30:19\'\nMariaDB> SELECT FROM_UNIXTIME(1196440219) + 0;\n -> 20071130103019.000000\nMariaDB> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),\n -> \'%Y %D %M %h:%i:%s %x\');\n -> \'2007 30th November 10:30:59 2007\'\n','https://mariadb.com/kb/en/from_unixtime/'),(65,'MEDIUMBLOB',22,'MEDIUMBLOB\n\nA BLOB column with a maximum length of 16,777,215 (224 - 1) bytes. Each\nMEDIUMBLOB value is stored using a 3-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumblob/\n\n','','https://mariadb.com/kb/en/mediumblob/'),(66,'SHA2',12,'Syntax:\nSHA2(str, hash_length)\n\nCalculates the SHA-2 family of hash functions (SHA-224, SHA-256,\nSHA-384, and SHA-512). The first argument is the cleartext string to be\nhashed. The second argument indicates the desired bit length of the\nresult, which must have a value of 224, 256, 384, 512, or 0 (which is\nequivalent to 256). If either argument is NULL or the hash length is\nnot one of the permitted values, the return value is NULL. Otherwise,\nthe function result is a hash value containing the desired number of\nbits. See the notes at the beginning of this section about storing hash\nvalues efficiently.\n\nAs of MySQL 5.5.6, the return value is a nonbinary string in the\nconnection character set. Before 5.5.6, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha2/\n\n','MariaDB> SELECT SHA2(\'abc\', 224);\n -> \'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\'\n','https://mariadb.com/kb/en/sha2/'),(67,'IFNULL',7,'Syntax:\nIFNULL(expr1,expr2)\n\nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it returns\nexpr2. IFNULL() returns a numeric or string value, depending on the\ncontext in which it is used.\n\nURL: https://mariadb.com/kb/en/ifnull/\n\n','MariaDB> SELECT IFNULL(1,0);\n -> 1\nMariaDB> SELECT IFNULL(NULL,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,\'yes\');\n -> \'yes\'\n','https://mariadb.com/kb/en/ifnull/'),(68,'SHOW FUNCTION CODE',26,'Syntax:\nSHOW FUNCTION CODE func_name\n\nThis statement is similar to SHOW PROCEDURE CODE but for stored\nfunctions. See [HELP SHOW PROCEDURE CODE].\n\nURL: https://mariadb.com/kb/en/show-function-code/\n\n','','https://mariadb.com/kb/en/show-function-code/'),(69,'SHOW ERRORS',26,'Syntax:\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW COUNT(*) ERRORS\n\nThis statement is similar to SHOW WARNINGS, except that it displays\ninformation only for errors, rather than for errors, warnings, and\nnotes.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nThe SHOW COUNT(*) ERRORS statement displays the number of errors. You\ncan also retrieve this number from the error_count variable:\n\nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n\nSHOW ERRORS and error_count apply only to errors, not warnings or\nnotes. In other respects, they are similar to SHOW WARNINGS and\nwarning_count. In particular, SHOW ERRORS cannot display information\nfor more than max_error_count messages, and error_count can exceed the\nvalue of max_error_count if the number of errors exceeds\nmax_error_count.\n\nURL: https://mariadb.com/kb/en/show-errors/\n\n','','https://mariadb.com/kb/en/show-errors/'),(70,'LEAST',18,'Syntax:\nLEAST(value1,value2,...)\n\nWith two or more arguments, returns the smallest (minimum-valued)\nargument. The arguments are compared using the following rules:\n\no If any argument is NULL, the result is NULL. No comparison is needed.\n\no If the return value is used in an INTEGER context or all arguments\n are integer-valued, they are compared as integers.\n\no If the return value is used in a REAL context or all arguments are\n real-valued, they are compared as reals.\n\no If the arguments comprise a mix of numbers and strings, they are\n compared as numbers.\n\no If any argument is a nonbinary (character) string, the arguments are\n compared as nonbinary strings.\n\no In all other cases, the arguments are compared as binary strings.\n\nURL: https://mariadb.com/kb/en/least/\n\n','MariaDB> SELECT LEAST(2,0);\n -> 0\nMariaDB> SELECT LEAST(34.0,3.0,5.0,767.0);\n -> 3.0\nMariaDB> SELECT LEAST(\'B\',\'A\',\'C\');\n -> \'A\'\n','https://mariadb.com/kb/en/least/'),(71,'=',18,'=\n\nEqual:\n\nURL: https://mariadb.com/kb/en/equal/\n\n','MariaDB> SELECT 1 = 0;\n -> 0\nMariaDB> SELECT \'0\' = 0;\n -> 1\nMariaDB> SELECT \'0.0\' = 0;\n -> 1\nMariaDB> SELECT \'0.01\' = 0;\n -> 0\nMariaDB> SELECT \'.01\' = 0.01;\n -> 1\n','https://mariadb.com/kb/en/equal/'),(72,'REVERSE',37,'Syntax:\nREVERSE(str)\n\nReturns the string str with the order of the characters reversed.\n\nURL: https://mariadb.com/kb/en/reverse/\n\n','MariaDB> SELECT REVERSE(\'abc\');\n -> \'cba\'\n','https://mariadb.com/kb/en/reverse/'),(73,'ISNULL',18,'Syntax:\nISNULL(expr)\n\nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n\nURL: https://mariadb.com/kb/en/isnull/\n\n','MariaDB> SELECT ISNULL(1+1);\n -> 0\nMariaDB> SELECT ISNULL(1/0);\n -> 1\n','https://mariadb.com/kb/en/isnull/'),(74,'BINARY',22,'BINARY(M)\n\nThe BINARY type is similar to the CHAR type, but stores binary byte\nstrings rather than nonbinary character strings. M represents the\ncolumn length in bytes.\n\nURL: https://mariadb.com/kb/en/binary/\n\n','','https://mariadb.com/kb/en/binary/'),(75,'BLOB DATA TYPE',22,'A BLOB is a binary large object that can hold a variable amount of\ndata. The four BLOB types are TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB.\nThese differ only in the maximum length of the values they can hold.\nThe four TEXT types are TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. These\ncorrespond to the four BLOB types and have the same maximum lengths and\nstorage requirements. See\nhttps://mariadb.com/kb/en/data-type-storage-requirements/.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-blob/\n\n','','https://mariadb.com/kb/en/sql_language-data_types-blob/'),(76,'BOUNDARY',36,'Boundary(g)\n\nReturns a geometry that is the closure of the combinatorial boundary of\nthe geometry value g.\n\nURL: https://mariadb.com/kb/en/boundary/\n\n','','https://mariadb.com/kb/en/boundary/'),(77,'CREATE USER',10,'Syntax:\nCREATE USER user_specification\n [, user_specification] ...\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nThe CREATE USER statement creates new MySQL accounts. To use it, you\nmust have the global CREATE USER privilege or the INSERT privilege for\nthe mysql database. For each account, CREATE USER creates a new row in\nthe mysql.user table and assigns the account no privileges. An error\noccurs if the account already exists.\n\nEach account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nThe user specification may indicate how the user should authenticate\nwhen connecting to the server:\n\no To enable the user to connect with no password (which is insecure),\n include no IDENTIFIED BY clause:\n\nCREATE USER \'jeffrey\'@\'localhost\';\n\n In this case, the account uses built-in authentication and clients\n must provide no password.\n\no To assign a password, use IDENTIFIED BY with the literal plaintext\n password value:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To avoid specifying the plaintext password if you know its hash value\n (the value that PASSWORD() would return for the password), specify\n the hash value preceded by the keyword PASSWORD:\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED BY PASSWORD \'*90E462C37378CED12064BB3388827D2BA3A9B689\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To authenticate the account using a specific authentication plugin,\n use IDENTIFIED WITH, where auth_plugin is the plugin name. It can be\n an unquoted name or a quoted string literal. \'auth_string\' is an\n optional quoted string literal to pass to the plugin. The plugin\n interprets the meaning of the string, so its format is plugin\n specific. Consult the documentation for a given plugin for\n information about the authentication string values it accepts.\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED WITH my_auth_plugin;\n\n For connections that use this account, the server invokes the named\n plugin and clients must provide credentials as required for the\n authentication method that the plugin implements. If the server\n cannot find the plugin, either at account-creation time or connect\n time, an error occurs. IDENTIFIED WITH can be used as of MySQL 5.5.7.\n\nThe IDENTIFIED BY and IDENTIFIED WITH clauses are mutually exclusive,\nso at most one of them can be specified for a given user.\n\nFor additional information about setting passwords, see\nhttps://mariadb.com/kb/en/create-user/.\n\nURL: https://mariadb.com/kb/en/create-user/\n\n','','https://mariadb.com/kb/en/create-user/'),(78,'POINT',24,'Point(x,y)\n\nConstructs a Point using its coordinates.\n\nURL: https://mariadb.com/kb/en/point/\n\n','','https://mariadb.com/kb/en/point/'),(79,'CURRENT_USER',17,'Syntax:\nCURRENT_USER, CURRENT_USER()\n\nReturns the user name and host name combination for the MySQL account\nthat the server used to authenticate the current client. This account\ndetermines your access privileges. The return value is a string in the\nutf8 character set.\n\nThe value of CURRENT_USER() can differ from the value of USER().\n\nURL: https://mariadb.com/kb/en/current_user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\nMariaDB> SELECT * FROM mysql.user;\nERROR 1044: Access denied for user \'\'@\'localhost\' to\ndatabase \'mysql\'\nMariaDB> SELECT CURRENT_USER();\n -> \'@localhost\'\n','https://mariadb.com/kb/en/current_user/'),(80,'LCASE',37,'Syntax:\nLCASE(str)\n\nLCASE() is a synonym for LOWER().\n\nURL: https://mariadb.com/kb/en/lcase/\n\n','','https://mariadb.com/kb/en/lcase/'),(81,'<=',18,'Syntax:\n<=\n\nLess than or equal:\n\nURL: https://mariadb.com/kb/en/less-than-or-equal/\n\n','MariaDB> SELECT 0.1 <= 2;\n -> 1\n','https://mariadb.com/kb/en/less-than-or-equal/'),(82,'SHOW PROFILES',26,'Syntax:\nSHOW PROFILES\n\nThe SHOW PROFILES statement, together with SHOW PROFILE, displays\nprofiling information that indicates resource usage for statements\nexecuted during the course of the current session. For more\ninformation, see [HELP SHOW PROFILE].\n\nURL: https://mariadb.com/kb/en/show-profiles/\n\n','','https://mariadb.com/kb/en/show-profiles/'),(83,'UPDATE',27,'Syntax:\nSingle-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_reference\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n\nFor the single-table syntax, the UPDATE statement updates columns of\nexisting rows in the named table with new values. The SET clause\nindicates which columns to modify and the values they should be given.\nEach value can be given as an expression, or the keyword DEFAULT to set\na column explicitly to its default value. The WHERE clause, if given,\nspecifies the conditions that identify which rows to update. With no\nWHERE clause, all rows are updated. If the ORDER BY clause is\nspecified, the rows are updated in the order that is specified. The\nLIMIT clause places a limit on the number of rows that can be updated.\n\nFor the multiple-table syntax, UPDATE updates rows in each table named\nin table_references that satisfy the conditions. In this case, ORDER BY\nand LIMIT cannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe updated. For expression syntax, see\nhttp://dev.mysql.com/doc/refman/5.5/en/expressions.html.\n\ntable_references and where_condition are is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nYou need the UPDATE privilege only for columns referenced in an UPDATE\nthat are actually updated. You need only the SELECT privilege for any\ncolumns that are read but not modified.\n\nThe UPDATE statement supports the following modifiers:\n\no With the LOW_PRIORITY keyword, execution of the UPDATE is delayed\n until no other clients are reading from the table. This affects only\n storage engines that use only table-level locking (such as MyISAM,\n MEMORY, and MERGE).\n\no With the IGNORE keyword, the update statement does not abort even if\n errors occur during the update. Rows for which duplicate-key\n conflicts occur are not updated. Rows for which columns are updated\n to values that would cause data conversion errors are updated to the\n closest valid values instead.\n\nURL: https://mariadb.com/kb/en/update/\n\n','','https://mariadb.com/kb/en/update/'),(84,'IS NOT NULL',18,'Syntax:\nIS NOT NULL\n\nTests whether a value is not NULL.\n\nURL: https://mariadb.com/kb/en/is-not-null/\n\n','MariaDB> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not-null/'),(85,'CASE STATEMENT',23,'Syntax:\nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nOr:\n\nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nThe CASE statement for stored programs implements a complex conditional\nconstruct.\n\n*Note*: There is also a CASE expression, which differs from the CASE\nstatement described here. See\nhttps://mariadb.com/kb/en/case-operator/. The\nCASE statement cannot have an ELSE NULL clause, and it is terminated\nwith END CASE instead of END.\n\nFor the first syntax, case_value is an expression. This value is\ncompared to the when_value expression in each WHEN clause until one of\nthem is equal. When an equal when_value is found, the corresponding\nTHEN clause statement_list executes. If no when_value is equal, the\nELSE clause statement_list executes, if there is one.\n\nThis syntax cannot be used to test for equality with NULL because NULL\n= NULL is false. See\nhttps://mariadb.com/kb/en/null-values/.\n\nFor the second syntax, each WHEN clause search_condition expression is\nevaluated until one is true, at which point its corresponding THEN\nclause statement_list executes. If no search_condition is equal, the\nELSE clause statement_list executes, if there is one.\n\nIf no when_value or search_condition matches the value tested and the\nCASE statement contains no ELSE clause, a Case not found for CASE\nstatement error results.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nTo handle situations where no value is matched by any WHEN clause, use\nan ELSE containing an empty BEGIN ... END block, as shown in this\nexample. (The indentation used here in the ELSE clause is for purposes\nof clarity only, and is not otherwise significant.)\n\nDELIMITER |\n\nCREATE PROCEDURE p()\n BEGIN\n DECLARE v INT DEFAULT 1;\n\n CASE v\n WHEN 2 THEN SELECT v;\n WHEN 3 THEN SELECT 0;\n ELSE\n BEGIN\n END;\n END CASE;\n END;\n |\n\nURL: https://mariadb.com/kb/en/case-statement/\n\n','','https://mariadb.com/kb/en/case-statement/'),(86,'EXECUTE STATEMENT',8,'Syntax:\nEXECUTE stmt_name\n [USING @var_name [, @var_name] ...]\n\nAfter preparing a statement with PREPARE, you execute it with an\nEXECUTE statement that refers to the prepared statement name. If the\nprepared statement contains any parameter markers, you must supply a\nUSING clause that lists user variables containing the values to be\nbound to the parameters. Parameter values can be supplied only by user\nvariables, and the USING clause must name exactly as many variables as\nthe number of parameter markers in the statement.\n\nYou can execute a given prepared statement multiple times, passing\ndifferent variables to it or setting the variables to different values\nbefore each execution.\n\nURL: https://mariadb.com/kb/en/execute-statement/\n\n','','https://mariadb.com/kb/en/execute-statement/'),(87,'DROP INDEX',39,'Syntax:\nDROP [ONLINE|OFFLINE] INDEX index_name ON tbl_name\n\nDROP INDEX drops the index named index_name from the table tbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop the index.\nSee [HELP ALTER TABLE].\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: https://mariadb.com/kb/en/drop-index/\n\n','','https://mariadb.com/kb/en/drop-index/'),(88,'MATCH AGAINST',37,'Syntax:\nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n\nMySQL has support for full-text indexing and searching:\n\no A full-text index in MySQL is an index of type FULLTEXT.\n\no Full-text indexes can be used only with MyISAM tables, and can be\n created only for CHAR, VARCHAR, or TEXT columns.\n\no A FULLTEXT index definition can be given in the CREATE TABLE\n statement when a table is created, or added later using ALTER TABLE\n or CREATE INDEX.\n\no For large data sets, it is much faster to load your data into a table\n that has no FULLTEXT index and then create the index after that, than\n to load data into a table that has an existing FULLTEXT index.\n\nFull-text searching is performed using MATCH() ... AGAINST syntax.\nMATCH() takes a comma-separated list that names the columns to be\nsearched. AGAINST takes a string to search for, and an optional\nmodifier that indicates what type of search to perform. The search\nstring must be a literal string, not a variable or a column name. There\nare three types of full-text searches:\n\no A natural language search interprets the search string as a phrase in\n natural human language (a phrase in free text). There are no special\n operators. The stopword list applies. In addition, words that are\n present in 50% or more of the rows are considered common and do not\n match.\n\n Full-text searches are natural language searches if the IN NATURAL\n LANGUAGE MODE modifier is given or if no modifier is given. For more\n information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-natural-language-mode\n .\n\no A boolean search interprets the search string using the rules of a\n special query language. The string contains the words to search for.\n It can also contain operators that specify requirements such that a\n word must be present or absent in matching rows, or that it should be\n weighted higher or lower than usual. Common words such as \"some\" or\n \"then\" are stopwords and do not match if present in the search\n string. The IN BOOLEAN MODE modifier specifies a boolean search. For\n more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-boolean-mode.\n\no A query expansion search is a modification of a natural language\n search. The search string is used to perform a natural language\n search. Then words from the most relevant rows returned by the search\n are added to the search string and the search is done again. The\n query returns the rows from the second search. The IN NATURAL\n LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier\n specifies a query expansion search. For more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#with-query-expansion.\n\nURL: https://mariadb.com/kb/en/match-against/\n\n','MariaDB> SELECT id, body, MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE) AS score\n -> FROM articles WHERE MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |\n| 6 | When configured properly, MySQL ... | 1.3114095926285 |\n+----+-------------------------------------+-----------------+\n2 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/match-against/'),(89,'CREATE EVENT',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n EVENT\n [IF NOT EXISTS]\n event_name\n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO event_body;\n\nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval\n [STARTS timestamp [+ INTERVAL interval] ...]\n [ENDS timestamp [+ INTERVAL interval] ...]\n\ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n\nThis statement creates and schedules a new event. The event will not\nrun unless the Event Scheduler is enabled. For information about\nchecking Event Scheduler status and enabling it if necessary, see\nhttps://mariadb.com/kb/en/events/.\n\nCREATE EVENT requires the EVENT privilege for the schema in which the\nevent is to be created. It might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section.\n\nThe minimum requirements for a valid CREATE EVENT statement are as\nfollows:\n\no The keywords CREATE EVENT plus an event name, which uniquely\n identifies the event in a database schema.\n\no An ON SCHEDULE clause, which determines when and how often the event\n executes.\n\no A DO clause, which contains the SQL statement to be executed by an\n event.\n\nThis is an example of a minimal CREATE EVENT statement:\n\nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n\nThe previous statement creates an event named myevent. This event\nexecutes once---one hour following its creation---by running an SQL\nstatement that increments the value of the myschema.mytable table\'s\nmycol column by 1.\n\nThe event_name must be a valid MySQL identifier with a maximum length\nof 64 characters. Event names are not case sensitive, so you cannot\nhave two events named myevent and MyEvent in the same schema. In\ngeneral, the rules governing event names are the same as those for\nnames of stored routines. See\nhttps://mariadb.com/kb/en/identifier-names/.\n\nAn event is associated with a schema. If no schema is indicated as part\nof event_name, the default (current) schema is assumed. To create an\nevent in a specific schema, qualify the event name with a schema using\nschema_name.event_name syntax.\n\nURL: https://mariadb.com/kb/en/create-event/\n\n','','https://mariadb.com/kb/en/create-event/'),(90,'ABS',4,'Syntax:\nABS(X)\n\nReturns the absolute value of X.\n\nURL: https://mariadb.com/kb/en/abs/\n\n','MariaDB> SELECT ABS(2);\n -> 2\nMariaDB> SELECT ABS(-32);\n -> 32\n','https://mariadb.com/kb/en/abs/'),(91,'POLYFROMWKB',32,'PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])\n\nConstructs a POLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromwkb/\n\n','','https://mariadb.com/kb/en/polyfromwkb/'),(92,'NOT LIKE',37,'Syntax:\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n\nThis is the same as NOT (expr LIKE pat [ESCAPE \'escape_char\']).\n\nURL: https://mariadb.com/kb/en/not-like/\n\n','','https://mariadb.com/kb/en/not-like/'),(93,'SPACE',37,'Syntax:\nSPACE(N)\n\nReturns a string consisting of N space characters.\n\nURL: https://mariadb.com/kb/en/space/\n\n','MariaDB> SELECT SPACE(6);\n -> \' \'\n','https://mariadb.com/kb/en/space/'),(94,'MBR DEFINITION',6,'Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding\ngeometry, formed by the minimum and maximum (X,Y) coordinates:\n\nURL: https://mariadb.com/kb/en/mbr-definition/\n\n','((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n','https://mariadb.com/kb/en/mbr-definition/'),(95,'GEOMETRYCOLLECTION',24,'GeometryCollection(g1,g2,...)\n\nConstructs a GeometryCollection.\n\nURL: https://mariadb.com/kb/en/geometrycollection/\n\n','','https://mariadb.com/kb/en/geometrycollection/'),(96,'MAX',16,'Syntax:\nMAX([DISTINCT] expr)\n\nReturns the maximum value of expr. MAX() may take a string argument; in\nsuch cases, it returns the maximum string value. See\nhttps://mariadb.com/kb/en/max/. The DISTINCT\nkeyword can be used to find the maximum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMAX() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/max/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/max/'),(97,'CREATE FUNCTION UDF',21,'Syntax:\nCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n\nA user-defined function (UDF) is a way to extend MySQL with a new\nfunction that works like a native (built-in) MySQL function such as\nABS() or CONCAT().\n\nfunction_name is the name that should be used in SQL statements to\ninvoke the function. The RETURNS clause indicates the type of the\nfunction\'s return value. DECIMAL is a legal value after RETURNS, but\ncurrently DECIMAL functions return string values and should be written\nlike STRING functions.\n\nshared_library_name is the basename of the shared object file that\ncontains the code that implements the function. The file must be\nlocated in the plugin directory. This directory is given by the value\nof the plugin_dir system variable. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/udf-compiling.html.\n\nTo create a function, you must have the INSERT privilege for the mysql\ndatabase. This is necessary because CREATE FUNCTION adds a row to the\nmysql.func system table that records the function\'s name, type, and\nshared library name. If you do not have this table, you should run the\nmysql_upgrade command to create it. See\nhttps://mariadb.com/kb/en/mysql_upgrade/.\n\nURL: https://mariadb.com/kb/en/create-function-udf/\n\n','','https://mariadb.com/kb/en/create-function-udf/'),(98,'*',4,'Syntax:\n*\n\nMultiplication:\n\nURL: https://mariadb.com/kb/en/multiplication-operator/\n\n','MariaDB> SELECT 3*5;\n -> 15\nMariaDB> SELECT 18014398509481984*18014398509481984.0;\n -> 324518553658426726783156020576256.0\nMariaDB> SELECT 18014398509481984*18014398509481984;\n -> 0\n','https://mariadb.com/kb/en/multiplication-operator/'),(99,'TIMESTAMP',22,'TIMESTAMP\n\nA timestamp. The range is \'1970-01-01 00:00:01\' UTC to \'2038-01-19\n03:14:07\' UTC. TIMESTAMP values are stored as the number of seconds\nsince the epoch (\'1970-01-01 00:00:00\' UTC). A TIMESTAMP cannot\nrepresent the value \'1970-01-01 00:00:00\' because that is equivalent to\n0 seconds from the epoch and the value 0 is reserved for representing\n\'0000-00-00 00:00:00\', the \"zero\" TIMESTAMP value.\n\nUnless specified otherwise, the first TIMESTAMP column in a table is\ndefined to be automatically set to the date and time of the most recent\nmodification if not explicitly assigned a value. This makes TIMESTAMP\nuseful for recording the timestamp of an INSERT or UPDATE operation.\nYou can also set any TIMESTAMP column to the current date and time by\nassigning it a NULL value, unless it has been defined with the NULL\nattribute to permit NULL values. The automatic initialization and\nupdating to the current date and time can be specified using DEFAULT\nCURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, as described\nin\nhttps://mariadb.com/kb/en/timestamp/.\n\n*Note*: The TIMESTAMP format that was used prior to MySQL 4.1 is not\nsupported in MySQL 5.5; see MySQL 3.23, 4.0, 4.1 Reference Manual for\ninformation regarding the old format.\n\nURL: https://mariadb.com/kb/en/timestamp/\n\n','','https://mariadb.com/kb/en/timestamp/'),(100,'DES_DECRYPT',12,'Syntax:\nDES_DECRYPT(crypt_str[,key_str])\n\nDecrypts a string encrypted with DES_ENCRYPT(). If an error occurs,\nthis function returns NULL.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nIf no key_str argument is given, DES_DECRYPT() examines the first byte\nof the encrypted string to determine the DES key number that was used\nto encrypt the original string, and then reads the key from the DES key\nfile to decrypt the message. For this to work, the user must have the\nSUPER privilege. The key file can be specified with the --des-key-file\nserver option.\n\nIf you pass this function a key_str argument, that string is used as\nthe key for decrypting the message.\n\nIf the crypt_str argument does not appear to be an encrypted string,\nMySQL returns the given crypt_str.\n\nURL: https://mariadb.com/kb/en/des_decrypt/\n\n','','https://mariadb.com/kb/en/des_decrypt/'),(101,'CACHE INDEX',26,'Syntax:\nCACHE INDEX\n tbl_index_list [, tbl_index_list] ...\n [PARTITION (partition_list | ALL)]\n IN key_cache_name\n\ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe CACHE INDEX statement assigns table indexes to a specific key\ncache. It is used only for MyISAM tables. After the indexes have been\nassigned, they can be preloaded into the cache if desired with LOAD\nINDEX INTO CACHE.\n\nThe following statement assigns indexes from the tables t1, t2, and t3\nto the key cache named hot_cache:\n\nMariaDB> CACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n\nURL: https://mariadb.com/kb/en/cache-index/\n\n','','https://mariadb.com/kb/en/cache-index/'),(102,'ENDPOINT',13,'EndPoint(ls)\n\nReturns the Point that is the endpoint of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/endpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/endpoint/'),(103,'COMPRESS',12,'Syntax:\nCOMPRESS(string_to_compress)\n\nCompresses a string and returns the result as a binary string. This\nfunction requires MySQL to have been compiled with a compression\nlibrary such as zlib. Otherwise, the return value is always NULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n\nURL: https://mariadb.com/kb/en/compress/\n\n','MariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n -> 21\nMariaDB> SELECT LENGTH(COMPRESS(\'\'));\n -> 0\nMariaDB> SELECT LENGTH(COMPRESS(\'a\'));\n -> 13\nMariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n -> 15\n','https://mariadb.com/kb/en/compress/'),(104,'INSERT',27,'Syntax:\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nINSERT inserts new rows into an existing table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based on\nexplicitly specified values. The INSERT ... SELECT form inserts rows\nselected from another table or tables. INSERT ... SELECT is discussed\nfurther in [HELP INSERT SELECT].\n\nURL: https://mariadb.com/kb/en/insert/\n\n','','https://mariadb.com/kb/en/insert/'),(105,'COUNT',16,'Syntax:\nCOUNT(expr)\n\nReturns a count of the number of non-NULL values of expr in the rows\nretrieved by a SELECT statement. The result is a BIGINT value.\n\nCOUNT() returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count/\n\n','MariaDB> SELECT student.student_name,COUNT(*)\n -> FROM student,course\n -> WHERE student.student_id=course.student_id\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/count/'),(106,'HANDLER',27,'Syntax:\nHANDLER tbl_name OPEN [ [AS] alias]\n\nHANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ { FIRST | NEXT }\n [ WHERE where_condition ] [LIMIT ... ]\n\nHANDLER tbl_name CLOSE\n\nThe HANDLER statement provides direct access to table storage engine\ninterfaces. It is available for MyISAM and InnoDB tables.\n\nURL: https://mariadb.com/kb/en/handler-commands/\n\n','','https://mariadb.com/kb/en/handler-commands/'),(107,'MLINEFROMTEXT',3,'MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])\n\nConstructs a MULTILINESTRING value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromtext/\n\n','','https://mariadb.com/kb/en/mlinefromtext/'),(108,'GEOMCOLLFROMWKB',32,'GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkb[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromwkb/\n\n','','https://mariadb.com/kb/en/geomcollfromwkb/'),(109,'HELP_DATE',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25\n','',''),(110,'RENAME TABLE',39,'Syntax:\nRENAME TABLE tbl_name TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n\nThis statement renames one or more tables.\n\nThe rename operation is done atomically, which means that no other\nsession can access any of the tables while the rename is running. For\nexample, if you have an existing table old_table, you can create\nanother table new_table that has the same structure but is empty, and\nthen replace the existing table with the empty one as follows (assuming\nthat backup_table does not already exist):\n\nURL: https://mariadb.com/kb/en/rename-table/\n\n','CREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO old_table;\n','https://mariadb.com/kb/en/rename-table/'),(111,'BOOLEAN',22,'BOOL, BOOLEAN\n\nThese types are synonyms for TINYINT(1). A value of zero is considered\nfalse. Nonzero values are considered true:\n\nMariaDB> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n\nMariaDB> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nMariaDB> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nHowever, the values TRUE and FALSE are merely aliases for 1 and 0,\nrespectively, as shown here:\n\nMariaDB> SELECT IF(0 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n\nMariaDB> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n\nThe last two statements display the results shown because 2 is equal to\nneither 1 nor 0.\n\nURL: https://mariadb.com/kb/en/boolean/\n\n','','https://mariadb.com/kb/en/boolean/'),(112,'DEFAULT',14,'Syntax:\nDEFAULT(col_name)\n\nReturns the default value for a table column. An error results if the\ncolumn has no default value.\n\nURL: https://mariadb.com/kb/en/default/\n\n','MariaDB> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\n','https://mariadb.com/kb/en/default/'),(113,'MOD',4,'Syntax:\nMOD(N,M), N % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M.\n\nURL: https://mariadb.com/kb/en/mod/\n\n','MariaDB> SELECT MOD(234, 10);\n -> 4\nMariaDB> SELECT 253 % 7;\n -> 1\nMariaDB> SELECT MOD(29,9);\n -> 2\nMariaDB> SELECT 29 MOD 9;\n -> 2\n','https://mariadb.com/kb/en/mod/'),(114,'TINYTEXT',22,'TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 255 (28 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TINYTEXT value is stored using a 1-byte length prefix\nthat indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinytext/\n\n','','https://mariadb.com/kb/en/tinytext/'),(115,'OPTIMIZE TABLE',20,'Syntax:\nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nOPTIMIZE TABLE should be used if you have deleted a large part of a\ntable or if you have made many changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT columns).\nDeleted rows are maintained in a linked list and subsequent INSERT\noperations reuse old row positions. You can use OPTIMIZE TABLE to\nreclaim the unused space and to defragment the data file. After\nextensive changes to a table, this statement may also improve\nperformance of statements that use the table, sometimes significantly.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nOPTIMIZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... OPTIMIZE PARTITION to optimize one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/optimize-table/\n\n','','https://mariadb.com/kb/en/optimize-table/'),(116,'DECODE',12,'Syntax:\nDECODE(crypt_str,pass_str)\n\nDecrypts the encrypted string crypt_str using pass_str as the password.\ncrypt_str should be a string returned from ENCODE().\n\nURL: https://mariadb.com/kb/en/decode/\n\n','','https://mariadb.com/kb/en/decode/'),(117,'<=>',18,'Syntax:\n<=>\n\nNULL-safe equal. This operator performs an equality comparison like the\n= operator, but returns 1 rather than NULL if both operands are NULL,\nand 0 rather than NULL if one operand is NULL.\n\nURL: https://mariadb.com/kb/en/null-safe-equal/\n\n','MariaDB> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\n -> 1, 1, 0\nMariaDB> SELECT 1 = 1, NULL = NULL, 1 = NULL;\n -> 1, NULL, NULL\n','https://mariadb.com/kb/en/null-safe-equal/'),(118,'HELP STATEMENT',28,'Syntax:\nHELP \'search_string\'\n\nThe HELP statement returns online information from the MySQL Reference\nmanual. Its proper operation requires that the help tables in the mysql\ndatabase be initialized with help topic information.\n\nThe HELP statement searches the help tables for the given search string\nand displays the result of the search. The search string is not case\nsensitive.\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(119,'RESET',26,'Syntax:\nRESET reset_option [, reset_option] ...\n\nThe RESET statement is used to clear the state of various server\noperations. You must have the RELOAD privilege to execute RESET.\n\nRESET acts as a stronger version of the FLUSH statement. See [HELP\nFLUSH].\n\nThe RESET statement causes an implicit commit. See\nhttps://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/.\n\nURL: https://mariadb.com/kb/en/reset/\n\n','','https://mariadb.com/kb/en/reset/'),(120,'GET_LOCK',14,'Syntax:\nGET_LOCK(str,timeout)\n\nTries to obtain a lock with a name given by the string str, using a\ntimeout of timeout seconds. Returns 1 if the lock was obtained\nsuccessfully, 0 if the attempt timed out (for example, because another\nclient has previously locked the name), or NULL if an error occurred\n(such as running out of memory or the thread was killed with mysqladmin\nkill). If you have a lock obtained with GET_LOCK(), it is released when\nyou execute RELEASE_LOCK(), execute a new GET_LOCK(), or your\nconnection terminates (either normally or abnormally). Locks obtained\nwith GET_LOCK() do not interact with transactions. That is, committing\na transaction does not release any such locks obtained during the\ntransaction.\n\nThis function can be used to implement application locks or to simulate\nrecord locks. Names are locked on a server-wide basis. If a name has\nbeen locked by one client, GET_LOCK() blocks any request by another\nclient for a lock with the same name. This enables clients that agree\non a given lock name to use the name to perform cooperative advisory\nlocking. But be aware that it also enables a client that is not among\nthe set of cooperating clients to lock a name, either inadvertently or\ndeliberately, and thus prevent any of the cooperating clients from\nlocking that name. One way to reduce the likelihood of this is to use\nlock names that are database-specific or application-specific. For\nexample, use lock names of the form db_name.str or app_name.str.\n\nURL: https://mariadb.com/kb/en/get_lock/\n\n','MariaDB> SELECT GET_LOCK(\'lock1\',10);\n -> 1\nMariaDB> SELECT IS_FREE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT GET_LOCK(\'lock2\',10);\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock1\');\n -> NULL\n','https://mariadb.com/kb/en/get_lock/'),(121,'UCASE',37,'Syntax:\nUCASE(str)\n\nUCASE() is a synonym for UPPER().\n\nURL: https://mariadb.com/kb/en/ucase/\n\n','','https://mariadb.com/kb/en/ucase/'),(122,'SHOW BINLOG EVENTS',26,'Syntax:\nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the binary log. If you do not specify \'log_name\',\nthe first binary log is displayed.\n\nURL: https://mariadb.com/kb/en/show-binlog-events/\n\n','','https://mariadb.com/kb/en/show-binlog-events/'),(123,'MPOLYFROMWKB',32,'MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])\n\nConstructs a MULTIPOLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromwkb/\n\n','','https://mariadb.com/kb/en/mpolyfromwkb/'),(124,'ITERATE',23,'Syntax:\nITERATE label\n\nITERATE can appear only within LOOP, REPEAT, and WHILE statements.\nITERATE means \"start the loop again.\"\n\nURL: https://mariadb.com/kb/en/iterate/\n\n','','https://mariadb.com/kb/en/iterate/'),(125,'DO',27,'Syntax:\nDO expr [, expr] ...\n\nDO executes the expressions but does not return any results. In most\nrespects, DO is shorthand for SELECT expr, ..., but has the advantage\nthat it is slightly faster when you do not care about the result.\n\nDO is useful primarily with functions that have side effects, such as\nRELEASE_LOCK().\n\nURL: https://mariadb.com/kb/en/do/\n\n','','https://mariadb.com/kb/en/do/'),(126,'CURTIME',31,'Syntax:\nCURTIME()\n\nReturns the current time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context. The value is expressed in the current time zone.\n\nURL: https://mariadb.com/kb/en/curtime/\n\n','MariaDB> SELECT CURTIME();\n -> \'23:50:26\'\nMariaDB> SELECT CURTIME() + 0;\n -> 235026.000000\n','https://mariadb.com/kb/en/curtime/'),(127,'CHAR_LENGTH',37,'Syntax:\nCHAR_LENGTH(str)\n\nReturns the length of the string str, measured in characters. A\nmulti-byte character counts as a single character. This means that for\na string containing five 2-byte characters, LENGTH() returns 10,\nwhereas CHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/char_length/\n\n','','https://mariadb.com/kb/en/char_length/'),(128,'BIGINT',22,'BIGINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to 18446744073709551615.\n\nSERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.\n\nURL: https://mariadb.com/kb/en/bigint/\n\n','','https://mariadb.com/kb/en/bigint/'),(129,'SET',26,'Syntax:\nSET variable_assignment [, variable_assignment] ...\n\nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n\nThe SET statement assigns values to different types of variables that\naffect the operation of the server or your client. Older versions of\nMySQL employed SET OPTION, but this syntax is deprecated in favor of\nSET without OPTION.\n\nURL: https://mariadb.com/kb/en/set/\n\n','','https://mariadb.com/kb/en/set/'),(130,'LOAD XML',27,'Syntax:\nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD XML statement reads data from an XML file into a table. The\nfile_name must be given as a literal string. The tagname in the\noptional ROWS IDENTIFIED BY clause must also be given as a literal\nstring, and must be surrounded by angle brackets (< and >).\n\nLOAD XML acts as the complement of running the mysql client in XML\noutput mode (that is, starting the client with the --xml option). To\nwrite data from a table to an XML file, use a command such as the\nfollowing one from the system shell:\n\nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n\nTo read the file back into a table, use LOAD XML INFILE. By default,\nthe element is considered to be the equivalent of a database\ntable row; this can be changed using the ROWS IDENTIFIED BY clause.\n\nThis statement supports three different XML formats:\n\no Column names as attributes and column values as attribute values:\n\n\n\no Column names as tags and column values as the content of these tags:\n\n\n value1\n value2\n\n\no Column names are the name attributes of tags, and values are\n the contents of these tags:\n\n\n value1\n value2\n\n\n This is the format used by other MySQL tools, such as mysqldump.\n\nAll 3 formats can be used in the same XML file; the import routine\nautomatically detects the format for each row and interprets it\ncorrectly. Tags are matched based on the tag or attribute name and the\ncolumn name.\n\nThe following clauses work essentially the same way for LOAD XML as\nthey do for LOAD DATA:\n\no LOW_PRIORITY or CONCURRENT\n\no LOCAL\n\no REPLACE or IGNORE\n\no CHARACTER SET\n\no (column_or_user_var,...)\n\no SET\n\nSee [HELP LOAD DATA], for more information about these clauses.\n\nThe IGNORE number LINES or IGNORE number ROWS clause causes the first\nnumber rows in the XML file to be skipped. It is analogous to the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n\nURL: https://mariadb.com/kb/en/load-xml/\n\n','','https://mariadb.com/kb/en/load-xml/'),(131,'CONV',4,'Syntax:\nCONV(N,from_base,to_base)\n\nConverts numbers between different number bases. Returns a string\nrepresentation of the number N, converted from base from_base to base\nto_base. Returns NULL if any argument is NULL. The argument N is\ninterpreted as an integer, but may be specified as an integer or a\nstring. The minimum base is 2 and the maximum base is 36. If to_base is\na negative number, N is regarded as a signed number. Otherwise, N is\ntreated as unsigned. CONV() works with 64-bit precision.\n\nURL: https://mariadb.com/kb/en/conv/\n\n','MariaDB> SELECT CONV(\'a\',16,2);\n -> \'1010\'\nMariaDB> SELECT CONV(\'6E\',18,8);\n -> \'172\'\nMariaDB> SELECT CONV(-17,10,-18);\n -> \'-H\'\nMariaDB> SELECT CONV(10+\'10\'+\'10\'+0xa,10,10);\n -> \'40\'\n','https://mariadb.com/kb/en/conv/'),(132,'DATE',22,'DATE\n\nA date. The supported range is \'1000-01-01\' to \'9999-12-31\'. MySQL\ndisplays DATE values in \'YYYY-MM-DD\' format, but permits assignment of\nvalues to DATE columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/date/\n\n','','https://mariadb.com/kb/en/date/'),(133,'ASSIGN-VALUE',15,'Syntax:\n:=\n\nAssignment operator. Causes the user variable on the left hand side of\nthe operator to take on the value to its right. The value on the right\nhand side may be a literal value, another variable storing a value, or\nany legal expression that yields a scalar value, including the result\nof a query (provided that this value is a scalar value). You can\nperform multiple assignments in the same SET statement. You can perform\nmultiple assignments in the same statement-\n\nUnlike =, the := operator is never interpreted as a comparison\noperator. This means you can use := in any valid SQL statement (not\njust in SET statements) to assign a value to a variable.\n\nURL: https://mariadb.com/kb/en/assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n\nMariaDB> SELECT @var1:=COUNT(*) FROM t1;\n -> 4\nMariaDB> SELECT @var1;\n -> 4\n','https://mariadb.com/kb/en/assignment-operator/'),(134,'SHOW OPEN TABLES',26,'Syntax:\nSHOW OPEN TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW OPEN TABLES lists the non-TEMPORARY tables that are currently open\nin the table cache. See\nhttp://dev.mysql.com/doc/refman/5.5/en/table-cache.html. The FROM\nclause, if present, restricts the tables shown to those present in the\ndb_name database. The LIKE clause, if present, indicates which table\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-open-tables/\n\n','','https://mariadb.com/kb/en/show-open-tables/'),(135,'EXTRACT',31,'Syntax:\nEXTRACT(unit FROM date)\n\nThe EXTRACT() function uses the same kinds of unit specifiers as\nDATE_ADD() or DATE_SUB(), but extracts parts from the date rather than\nperforming date arithmetic.\n\nURL: https://mariadb.com/kb/en/extract/\n\n','MariaDB> SELECT EXTRACT(YEAR FROM \'2009-07-02\');\n -> 2009\nMariaDB> SELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n -> 200907\nMariaDB> SELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n -> 20102\nMariaDB> SELECT EXTRACT(MICROSECOND\n -> FROM \'2003-01-02 10:30:00.000123\');\n -> 123\n','https://mariadb.com/kb/en/extract/'),(136,'ENCRYPT',12,'Syntax:\nENCRYPT(str[,salt])\n\nEncrypts str using the Unix crypt() system call and returns a binary\nstring. The salt argument must be a string with at least two characters\nor the result will be NULL. If no salt argument is given, a random\nvalue is used.\n\nURL: https://mariadb.com/kb/en/encrypt/\n\n','MariaDB> SELECT ENCRYPT(\'hello\');\n -> \'VxuFAJXVARROc\'\n','https://mariadb.com/kb/en/encrypt/'),(137,'SHOW STATUS',26,'Syntax:\nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW STATUS provides server status information. This information also\ncan be obtained using the mysqladmin extended-status command. The LIKE\nclause, if present, indicates which variable names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\nThis statement does not require any privilege. It requires only the\nability to connect to the server.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern:\n\nMariaDB> SHOW STATUS LIKE \'Key%\';\n+--------------------+----------+\n| Variable_name | Value |\n+--------------------+----------+\n| Key_blocks_used | 14955 |\n| Key_read_requests | 96854827 |\n| Key_reads | 162040 |\n| Key_write_requests | 7589728 |\n| Key_writes | 3813196 |\n+--------------------+----------+\n\nWith the GLOBAL modifier, SHOW STATUS displays the status values for\nall connections to MySQL. With SESSION, it displays the status values\nfor the current connection. If no modifier is present, the default is\nSESSION. LOCAL is a synonym for SESSION.\n\nSome status variables have only a global value. For these, you get the\nsame value for both GLOBAL and SESSION. The scope for each status\nvariable is listed at\nhttps://mariadb.com/kb/en/server-status-variables/.\n\nEach invocation of the SHOW STATUS statement uses an internal temporary\ntable and increments the global Created_tmp_tables value.\n\nURL: https://mariadb.com/kb/en/show-status/\n\n','','https://mariadb.com/kb/en/show-status/'),(138,'EXTRACTVALUE',37,'Syntax:\nExtractValue(xml_frag, xpath_expr)\n\nExtractValue() takes two string arguments, a fragment of XML markup\nxml_frag and an XPath expression xpath_expr (also known as a locator);\nit returns the text (CDATA) of the first text node which is a child of\nthe elements or elements matched by the XPath expression. In MySQL 5.5,\nthe XPath expression can contain at most 127 characters. (This\nlimitation is lifted in MySQL 5.6.)\n\nUsing this function is the equivalent of performing a match using the\nxpath_expr after appending /text(). In other words,\nExtractValue(\'Sakila\', \'/a/b\') and\nExtractValue(\'Sakila\', \'/a/b/text()\') produce the same\nresult.\n\nIf multiple matches are found, the content of the first child text node\nof each matching element is returned (in the order matched) as a\nsingle, space-delimited string.\n\nIf no matching text node is found for the expression (including the\nimplicit /text())---for whatever reason, as long as xpath_expr is\nvalid, and xml_frag consists of elements which are properly nested and\nclosed---an empty string is returned. No distinction is made between a\nmatch on an empty element and no match at all. This is by design.\n\nIf you need to determine whether no matching element was found in\nxml_frag or such an element was found but contained no child text\nnodes, you should test the result of an expression that uses the XPath\ncount() function. For example, both of these statements return an empty\nstring, as shown here:\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nHowever, you can determine whether there was actually a matching\nelement using the following:\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 1 |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n1 row in set (0.01 sec)\n\n*Important*: ExtractValue() returns only CDATA, and does not return any\ntags that might be contained within a matching tag, nor any of their\ncontent (see the result returned as val1 in the following example).\n\nURL: https://mariadb.com/kb/en/extractvalue/\n\n','MariaDB> SELECT\n -> ExtractValue(\'cccddd\', \'/a\') AS val1,\n -> ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n -> ExtractValue(\'cccddd\', \'//b\') AS val3,\n -> ExtractValue(\'cccddd\', \'/b\') AS val4,\n -> ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n\n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n','https://mariadb.com/kb/en/extractvalue/'),(139,'OLD_PASSWORD',12,'Syntax:\nOLD_PASSWORD(str)\n\nOLD_PASSWORD() was added when the implementation of PASSWORD() was\nchanged in MySQL 4.1 to improve security. OLD_PASSWORD() returns the\nvalue of the pre-4.1 implementation of PASSWORD() as a string, and is\nintended to permit you to reset passwords for any pre-4.1 clients that\nneed to connect to your version 5.5 MySQL server without locking them\nout. See http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/old_password/\n\n','','https://mariadb.com/kb/en/old_password/'),(140,'FORMAT',37,'Syntax:\nFORMAT(X,D[,locale])\n\nFormats the number X to a format like \'#,###,###.##\', rounded to D\ndecimal places, and returns the result as a string. If D is 0, the\nresult has no decimal point or fractional part.\n\nThe optional third parameter enables a locale to be specified to be\nused for the result number\'s decimal point, thousands separator, and\ngrouping between separators. Permissible locale values are the same as\nthe legal values for the lc_time_names system variable (see\nhttps://mariadb.com/kb/en/server-locale/). If no\nlocale is specified, the default is \'en_US\'.\n\nURL: https://mariadb.com/kb/en/format/\n\n','MariaDB> SELECT FORMAT(12332.123456, 4);\n -> \'12,332.1235\'\nMariaDB> SELECT FORMAT(12332.1,4);\n -> \'12,332.1000\'\nMariaDB> SELECT FORMAT(12332.2,0);\n -> \'12,332\'\nMariaDB> SELECT FORMAT(12332.2,2,\'de_DE\');\n -> \'12.332,20\'\n','https://mariadb.com/kb/en/format/'),(141,'||',15,'Syntax:\nOR, ||\n\nLogical OR. When both operands are non-NULL, the result is 1 if any\noperand is nonzero, and 0 otherwise. With a NULL operand, the result is\n1 if the other operand is nonzero, and NULL otherwise. If both operands\nare NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/or/\n\n','MariaDB> SELECT 1 || 1;\n -> 1\nMariaDB> SELECT 1 || 0;\n -> 1\nMariaDB> SELECT 0 || 0;\n -> 0\nMariaDB> SELECT 0 || NULL;\n -> NULL\nMariaDB> SELECT 1 || NULL;\n -> 1\n','https://mariadb.com/kb/en/or/'),(142,'BIT_LENGTH',37,'Syntax:\nBIT_LENGTH(str)\n\nReturns the length of the string str in bits.\n\nURL: https://mariadb.com/kb/en/bit_length/\n\n','MariaDB> SELECT BIT_LENGTH(\'text\');\n -> 32\n','https://mariadb.com/kb/en/bit_length/'),(143,'EXTERIORRING',2,'ExteriorRing(poly)\n\nReturns the exterior ring of the Polygon value poly as a LineString.\n\nURL: https://mariadb.com/kb/en/exteriorring/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n','https://mariadb.com/kb/en/exteriorring/'),(144,'GEOMFROMWKB',32,'GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkb[,srid])\n\nConstructs a geometry value of any type using its WKB representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromwkb/\n\n','','https://mariadb.com/kb/en/geomfromwkb/'),(145,'SHOW SLAVE HOSTS',26,'Syntax:\nSHOW SLAVE HOSTS\n\nDisplays a list of replication slaves currently registered with the\nmaster. (Before MySQL 5.5.3, only slaves started with the\n--report-host=host_name option are visible in this list.)\n\nThe list is displayed on any server (not just the master server). The\noutput looks like this:\n\nMariaDB> SHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\n\no Server_id: The unique server ID of the slave server, as configured in\n the server\'s option file, or on the command line with\n --server-id=value.\n\no Host: The host name of the slave server, as configured in the\n server\'s option file, or on the command line with\n --report-host=host_name. Note that this can differ from the machine\n name as configured in the operating system.\n\no Port: The port the slave server is listening on.\n\n In MySQL 5.5.23 and later, a zero in this column means that the slave\n port (--report-port) was not set. Prior to MySQL 5.5.23, 3306 was\n used as the default in such cases (Bug #13333431).\n\no Master_id: The unique server ID of the master server that the slave\n server is replicating from.\n\nSome MySQL versions report another variable, Rpl_recovery_rank. This\nvariable was never used, and was removed in MySQL 5.5.3. (Bug #13963)\n\nURL: https://mariadb.com/kb/en/show-slave-hosts/\n\n','','https://mariadb.com/kb/en/show-slave-hosts/'),(146,'START TRANSACTION',8,'Syntax:\nSTART TRANSACTION [WITH CONSISTENT SNAPSHOT]\nBEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n\nThese statements provide control over use of transactions:\n\no START TRANSACTION or BEGIN start a new transaction.\n\no COMMIT commits the current transaction, making its changes permanent.\n\no ROLLBACK rolls back the current transaction, canceling its changes.\n\no SET autocommit disables or enables the default autocommit mode for\n the current session.\n\nBy default, MySQL runs with autocommit mode enabled. This means that as\nsoon as you execute a statement that updates (modifies) a table, MySQL\nstores the update on disk to make it permanent. The change cannot be\nrolled back.\n\nTo disable autocommit mode implicitly for a single series of\nstatements, use the START TRANSACTION statement:\n\nSTART TRANSACTION;\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\nUPDATE table2 SET summary=@A WHERE type=1;\nCOMMIT;\n\nWith START TRANSACTION, autocommit remains disabled until you end the\ntransaction with COMMIT or ROLLBACK. The autocommit mode then reverts\nto its previous state.\n\nYou can also begin a transaction like this:\n\nSTART TRANSACTION WITH CONSISTENT SNAPSHOT;\n\nThe WITH CONSISTENT SNAPSHOT option starts a consistent read for\nstorage engines that are capable of it. This applies only to InnoDB.\nThe effect is the same as issuing a START TRANSACTION followed by a\nSELECT from any InnoDB table. See\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html. The\nWITH CONSISTENT SNAPSHOT option does not change the current transaction\nisolation level, so it provides a consistent snapshot only if the\ncurrent isolation level is one that permits consistent read (REPEATABLE\nREAD or SERIALIZABLE).\n\n*Important*: Many APIs used for writing MySQL client applications (such\nas JDBC) provide their own methods for starting transactions that can\n(and sometimes should) be used instead of sending a START TRANSACTION\nstatement from the client. See\nhttp://dev.mysql.com/doc/refman/5.5/en/connectors-apis.html, or the\ndocumentation for your API, for more information.\n\nTo disable autocommit mode explicitly, use the following statement:\n\nSET autocommit=0;\n\nAfter disabling autocommit mode by setting the autocommit variable to\nzero, changes to transaction-safe tables (such as those for InnoDB) are not made permanent immediately. You must use COMMIT to\nstore your changes to disk or ROLLBACK to ignore the changes.\n\nautocommit is a session variable and must be set for each session. To\ndisable autocommit mode for each new connection, see the description of\nthe autocommit system variable at\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nBEGIN and BEGIN WORK are supported as aliases of START TRANSACTION for\ninitiating a transaction. START TRANSACTION is standard SQL syntax and\nis the recommended way to start an ad-hoc transaction.\n\nThe BEGIN statement differs from the use of the BEGIN keyword that\nstarts a BEGIN ... END compound statement. The latter does not begin a\ntransaction. See [HELP BEGIN END].\n\n*Note*: Within all stored programs (stored procedures and functions,\ntriggers, and events), the parser treats BEGIN [WORK] as the beginning\nof a BEGIN ... END block. Begin a transaction in this context with\nSTART TRANSACTION instead.\n\nThe optional WORK keyword is supported for COMMIT and ROLLBACK, as are\nthe CHAIN and RELEASE clauses. CHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of the\ncompletion_type system variable determines the default completion\nbehavior. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nThe AND CHAIN clause causes a new transaction to begin as soon as the\ncurrent one ends, and the new transaction has the same isolation level\nas the just-terminated transaction. The RELEASE clause causes the\nserver to disconnect the current client session after terminating the\ncurrent transaction. Including the NO keyword suppresses CHAIN or\nRELEASE completion, which can be useful if the completion_type system\nvariable is set to cause chaining or release completion by default.\n\nURL: https://mariadb.com/kb/en/start-transaction/\n\n','','https://mariadb.com/kb/en/start-transaction/'),(147,'BETWEEN AND',18,'Syntax:\nexpr BETWEEN min AND max\n\nIf expr is greater than or equal to min and expr is less than or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is equivalent\nto the expression (min <= expr AND expr <= max) if all the arguments\nare of the same type. Otherwise type conversion takes place according\nto the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the three arguments.\n\nURL: https://mariadb.com/kb/en/between-and/\n\n','MariaDB> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;\n -> 1, 0\nMariaDB> SELECT 1 BETWEEN 2 AND 3;\n -> 0\nMariaDB> SELECT \'b\' BETWEEN \'a\' AND \'c\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'3\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'x-3\';\n -> 0\n','https://mariadb.com/kb/en/between-and/'),(148,'MULTIPOLYGON',24,'MultiPolygon(poly1,poly2,...)\n\nConstructs a MultiPolygon value from a set of Polygon or WKB Polygon\narguments.\n\nURL: https://mariadb.com/kb/en/multipolygon/\n\n','','https://mariadb.com/kb/en/multipolygon/'),(149,'TIME_FORMAT',31,'Syntax:\nTIME_FORMAT(time,format)\n\nThis is used like the DATE_FORMAT() function, but the format string may\ncontain format specifiers only for hours, minutes, seconds, and\nmicroseconds. Other specifiers produce a NULL value or 0.\n\nURL: https://mariadb.com/kb/en/time_format/\n\n','MariaDB> SELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n -> \'100 100 04 04 4\'\n','https://mariadb.com/kb/en/time_format/'),(150,'LEFT',37,'Syntax:\nLEFT(str,len)\n\nReturns the leftmost len characters from the string str, or NULL if any\nargument is NULL.\n\nURL: https://mariadb.com/kb/en/left/\n\n','MariaDB> SELECT LEFT(\'foobarbar\', 5);\n -> \'fooba\'\n','https://mariadb.com/kb/en/left/'),(151,'FLUSH QUERY CACHE',26,'You can defragment the query cache to better utilize its memory with\nthe FLUSH QUERY CACHE statement. The statement does not remove any\nqueries from the cache.\n\nThe RESET QUERY CACHE statement removes all query results from the\nquery cache. The FLUSH TABLES statement also does this.\n\nURL: https://mariadb.com/kb/en/flush-query-cache/\n\n','','https://mariadb.com/kb/en/flush-query-cache/'),(152,'SET DATA TYPE',22,'SET(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA set. A string object that can have zero or more values, each of which\nmust be chosen from the list of values \'value1\', \'value2\', ... A SET\ncolumn can have a maximum of 64 members. SET values are represented\ninternally as integers.\n\nURL: https://mariadb.com/kb/en/set-data-type/\n\n','','https://mariadb.com/kb/en/set-data-type/'),(153,'RAND',4,'Syntax:\nRAND(), RAND(N)\n\nReturns a random floating-point value v in the range 0 <= v < 1.0. If a\nconstant integer argument N is specified, it is used as the seed value,\nwhich produces a repeatable sequence of column values. In the following\nexample, note that the sequences of values produced by RAND(3) is the\nsame both places where it occurs.\n\nURL: https://mariadb.com/kb/en/rand/\n\n','MariaDB> CREATE TABLE t (i INT);\nQuery OK, 0 rows affected (0.42 sec)\n\nMariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.61914388706828 |\n| 2 | 0.93845168309142 |\n| 3 | 0.83482678498591 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.35877890638893 |\n| 2 | 0.28941420772058 |\n| 3 | 0.37073435016976 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.01 sec)\n','https://mariadb.com/kb/en/rand/'),(154,'RPAD',37,'Syntax:\nRPAD(str,len,padstr)\n\nReturns the string str, right-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\nURL: https://mariadb.com/kb/en/rpad/\n\n','MariaDB> SELECT RPAD(\'hi\',5,\'?\');\n -> \'hi???\'\nMariaDB> SELECT RPAD(\'hi\',1,\'?\');\n -> \'h\'\n','https://mariadb.com/kb/en/rpad/'),(155,'CREATE DATABASE',39,'Syntax:\nCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n [create_specification] ...\n\ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nCREATE DATABASE creates a database with the given name. To use this\nstatement, you need the CREATE privilege for the database. CREATE\nSCHEMA is a synonym for CREATE DATABASE.\n\nURL: https://mariadb.com/kb/en/create-database/\n\n','','https://mariadb.com/kb/en/create-database/'),(156,'DEC',22,'DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED]\n[ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nThese types are synonyms for DECIMAL. The FIXED synonym is available\nfor compatibility with other database systems.\n\nURL: https://mariadb.com/kb/en/dec-numeric-fixed/\n\n','','https://mariadb.com/kb/en/dec-numeric-fixed/'),(157,'VAR_POP',16,'Syntax:\nVAR_POP(expr)\n\nReturns the population standard variance of expr. It considers rows as\nthe whole population, not as a sample, so it has the number of rows as\nthe denominator. You can also use VARIANCE(), which is equivalent but\nis not standard SQL.\n\nVAR_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_pop/\n\n','','https://mariadb.com/kb/en/var_pop/'),(158,'ELT',37,'Syntax:\nELT(N,str1,str2,str3,...)\n\nReturns str1 if N = 1, str2 if N = 2, and so on. Returns NULL if N is\nless than 1 or greater than the number of arguments. ELT() is the\ncomplement of FIELD().\n\nURL: https://mariadb.com/kb/en/elt/.html\n\n','MariaDB> SELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'ej\'\nMariaDB> SELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'foo\'\n','https://mariadb.com/kb/en/elt/.html'),(159,'ALTER VIEW',39,'Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW and the effect is the same as\nfor CREATE OR REPLACE VIEW. See [HELP CREATE VIEW]. This statement\nrequires the CREATE VIEW and DROP privileges for the view, and some\nprivilege for each column referred to in the SELECT statement. ALTER\nVIEW is permitted only to the definer or users with the SUPER\nprivilege.\n\nURL: https://mariadb.com/kb/en/alter-view/\n\n','','https://mariadb.com/kb/en/alter-view/'),(160,'SHOW DATABASES',26,'Syntax:\nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW DATABASES lists the databases on the MySQL server host. SHOW\nSCHEMAS is a synonym for SHOW DATABASES. The LIKE clause, if present,\nindicates which database names to match. The WHERE clause can be given\nto select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou see only those databases for which you have some kind of privilege,\nunless you have the global SHOW DATABASES privilege. You can also get\nthis list using the mysqlshow command.\n\nIf the server was started with the --skip-show-database option, you\ncannot use this statement at all unless you have the SHOW DATABASES\nprivilege.\n\nURL: https://mariadb.com/kb/en/show-databases/\n\n','','https://mariadb.com/kb/en/show-databases/'),(161,'~',19,'Syntax:\n~\n\nInvert all bits.\n\nURL: https://mariadb.com/kb/en/3489/\n\n','MariaDB> SELECT 5 & ~1;\n -> 4\n','https://mariadb.com/kb/en/3489/'),(162,'TEXT',22,'TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 65,535 (216 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TEXT value is stored using a 2-byte length prefix that\nindicates the number of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest TEXT type large enough to hold\nvalues M characters long.\n\nURL: https://mariadb.com/kb/en/text/\n\n','','https://mariadb.com/kb/en/text/'),(163,'CONCAT_WS',37,'Syntax:\nCONCAT_WS(separator,str1,str2,...)\n\nCONCAT_WS() stands for Concatenate With Separator and is a special form\nof CONCAT(). The first argument is the separator for the rest of the\narguments. The separator is added between the strings to be\nconcatenated. The separator can be a string, as can the rest of the\narguments. If the separator is NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/concat_ws/\n\n','MariaDB> SELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last Name\');\n -> \'First name,Second name,Last Name\'\nMariaDB> SELECT CONCAT_WS(\',\',\'First name\',NULL,\'Last Name\');\n -> \'First name,Last Name\'\n','https://mariadb.com/kb/en/concat_ws/'),(164,'ROW_COUNT',17,'Syntax:\nROW_COUNT()\n\nBefore MySQL 5.5.5, ROW_COUNT() returns the number of rows changed,\ndeleted, or inserted by the last statement if it was an UPDATE, DELETE,\nor INSERT. For other statements, the value may not be meaningful.\n\nAs of MySQL 5.5.5, ROW_COUNT() returns a value as follows:\n\no DDL statements: 0. This applies to statements such as CREATE TABLE or\n DROP TABLE.\n\no DML statements other than SELECT: The number of affected rows. This\n applies to statements such as UPDATE, INSERT, or DELETE (as before),\n but now also to statements such as ALTER TABLE and LOAD DATA INFILE.\n\no SELECT: -1 if the statement returns a result set, or the number of\n rows \"affected\" if it does not. For example, for SELECT * FROM t1,\n ROW_COUNT() returns -1. For SELECT * FROM t1 INTO OUTFILE\n \'file_name\', ROW_COUNT() returns the number of rows written to the\n file.\n\no SIGNAL statements: 0.\n\nFor UPDATE statements, the affected-rows value by default is the number\nof rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() when connecting to mysqld, the affected-rows value\nis the number of rows \"found\"; that is, matched by the WHERE clause.\n\nFor REPLACE statements, the affected-rows value is 2 if the new row\nreplaced an old row, because in this case, one row was inserted after\nthe duplicate was deleted.\n\nFor INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows\nvalue is 1 if the row is inserted as a new row and 2 if an existing row\nis updated.\n\nThe ROW_COUNT() value is similar to the value from the\nmysql_affected_rows() C API function and the row count that the mysql\nclient displays following statement execution.\n\nURL: https://mariadb.com/kb/en/information-functions-row_count/\n\n','MariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> DELETE FROM t WHERE i IN(1,2);\nQuery OK, 2 rows affected (0.00 sec)\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/information-functions-row_count/'),(165,'ASIN',4,'Syntax:\nASIN(X)\n\nReturns the arc sine of X, that is, the value whose sine is X. Returns\nNULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/asin/\n\n','MariaDB> SELECT ASIN(0.2);\n -> 0.20135792079033\nMariaDB> SELECT ASIN(\'foo\');\n\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n1 row in set, 1 warning (0.00 sec)\n\nMariaDB> SHOW WARNINGS;\n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\' |\n+---------+------+-----------------------------------------+\n','https://mariadb.com/kb/en/asin/'),(166,'SIGN',4,'Syntax:\nSIGN(X)\n\nReturns the sign of the argument as -1, 0, or 1, depending on whether X\nis negative, zero, or positive.\n\nURL: https://mariadb.com/kb/en/sign/\n\n','MariaDB> SELECT SIGN(-32);\n -> -1\nMariaDB> SELECT SIGN(0);\n -> 0\nMariaDB> SELECT SIGN(234);\n -> 1\n','https://mariadb.com/kb/en/sign/'),(167,'SEC_TO_TIME',31,'Syntax:\nSEC_TO_TIME(seconds)\n\nReturns the seconds argument, converted to hours, minutes, and seconds,\nas a TIME value. The range of the result is constrained to that of the\nTIME data type. A warning occurs if the argument corresponds to a value\noutside that range.\n\nURL: https://mariadb.com/kb/en/sec_to_time/\n\n','MariaDB> SELECT SEC_TO_TIME(2378);\n -> \'00:39:38\'\nMariaDB> SELECT SEC_TO_TIME(2378) + 0;\n -> 3938\n','https://mariadb.com/kb/en/sec_to_time/'),(168,'FLOAT',22,'FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA small (single-precision) floating-point number. Permissible values\nare -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to\n3.402823466E+38. These are the theoretical limits, based on the IEEE\nstandard. The actual range might be slightly smaller depending on your\nhardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A single-precision floating-point\nnumber is accurate to approximately 7 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nUsing FLOAT might give you some unexpected problems because all\ncalculations in MySQL are done with double precision. See\nhttps://mariadb.com/kb/en/floating-point-accuracy/.\n\nURL: https://mariadb.com/kb/en/float/\n\n','','https://mariadb.com/kb/en/float/'),(169,'LOCATE',37,'Syntax:\nLOCATE(substr,str), LOCATE(substr,str,pos)\n\nThe first syntax returns the position of the first occurrence of\nsubstring substr in string str. The second syntax returns the position\nof the first occurrence of substring substr in string str, starting at\nposition pos. Returns 0 if substr is not in str.\n\nURL: https://mariadb.com/kb/en/locate/\n\n','MariaDB> SELECT LOCATE(\'bar\', \'foobarbar\');\n -> 4\nMariaDB> SELECT LOCATE(\'xbar\', \'foobar\');\n -> 0\nMariaDB> SELECT LOCATE(\'bar\', \'foobarbar\', 5);\n -> 7\n','https://mariadb.com/kb/en/locate/'),(170,'SHOW EVENTS',26,'Syntax:\nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement displays information about Event Manager events. It\nrequires the EVENT privilege for the database from which the events are\nto be shown.\n\nIn its simplest form, SHOW EVENTS lists all of the events in the\ncurrent schema:\n\nMariaDB> SELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n1 row in set (0.00 sec)\n\nMariaDB> SHOW EVENTS\\G\n*************************** 1. row ***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nTo see events for a specific schema, use the FROM clause. For example,\nto see events for the test schema, use the following statement:\n\nSHOW EVENTS FROM test;\n\nThe LIKE clause, if present, indicates which event names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-events/\n\n','','https://mariadb.com/kb/en/show-events/'),(171,'CHARSET',17,'Syntax:\nCHARSET(str)\n\nReturns the character set of the string argument.\n\nURL: https://mariadb.com/kb/en/charset/\n\n','MariaDB> SELECT CHARSET(\'abc\');\n -> \'latin1\'\nMariaDB> SELECT CHARSET(CONVERT(\'abc\' USING utf8));\n -> \'utf8\'\nMariaDB> SELECT CHARSET(USER());\n -> \'utf8\'\n','https://mariadb.com/kb/en/charset/'),(172,'SUBDATE',31,'Syntax:\nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, SUBDATE()\nis a synonym for DATE_SUB(). For information on the INTERVAL unit\nargument, see the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\nMariaDB> SELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\n\nThe second form enables the use of an integer value for days. In such\ncases, it is interpreted as the number of days to be subtracted from\nthe date or datetime expression expr.\n\nMariaDB> SELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n -> \'2007-12-02 12:00:00\'\n\nURL: https://mariadb.com/kb/en/subdate/\n\n','','https://mariadb.com/kb/en/subdate/'),(173,'DAYOFYEAR',31,'Syntax:\nDAYOFYEAR(date)\n\nReturns the day of the year for date, in the range 1 to 366.\n\nURL: https://mariadb.com/kb/en/dayofyear/\n\n','MariaDB> SELECT DAYOFYEAR(\'2007-02-03\');\n -> 34\n','https://mariadb.com/kb/en/dayofyear/'),(174,'%',4,'Syntax:\nN % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M. For more\ninformation, see the description for the MOD() function in\nhttps://mariadb.com/kb/en/mod/.\n\nURL: https://mariadb.com/kb/en/modulo-operator/\n\n','','https://mariadb.com/kb/en/modulo-operator/'),(175,'LONGTEXT',22,'LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\ncharacters. The effective maximum length is less if the value contains\nmulti-byte characters. The effective maximum length of LONGTEXT columns\nalso depends on the configured maximum packet size in the client/server\nprotocol and available memory. Each LONGTEXT value is stored using a\n4-byte length prefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longtext/\n\n','','https://mariadb.com/kb/en/longtext/'),(176,'KILL',26,'Syntax:\nKILL [CONNECTION | QUERY] thread_id\n\nEach connection to mysqld runs in a separate thread. You can see which\nthreads are running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement.\n\nKILL permits an optional CONNECTION or QUERY modifier:\n\no KILL CONNECTION is the same as KILL with no modifier: It terminates\n the connection associated with the given thread_id.\n\no KILL QUERY terminates the statement that the connection is currently\n executing, but leaves the connection itself intact.\n\nIf you have the PROCESS privilege, you can see all threads. If you have\nthe SUPER privilege, you can kill all threads and statements.\nOtherwise, you can see and kill only your own threads and statements.\n\nYou can also use the mysqladmin processlist and mysqladmin kill\ncommands to examine and kill threads.\n\n*Note*: You cannot use KILL with the Embedded MySQL Server library\nbecause the embedded server merely runs inside the threads of the host\napplication. It does not create any connection threads of its own.\n\nURL: https://mariadb.com/kb/en/data-manipulation-kill-connection-query/\n\n','','https://mariadb.com/kb/en/data-manipulation-kill-connection-query/'),(177,'DISJOINT',30,'Disjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially disjoint from (does\nnot intersect) g2.\n\nURL: https://mariadb.com/kb/en/disjoint/\n\n','','https://mariadb.com/kb/en/disjoint/'),(178,'ASTEXT',3,'AsText(g), AsWKT(g)\n\nConverts a value in internal geometry format to its WKT representation\nand returns the string result.\n\nURL: https://mariadb.com/kb/en/astext/\n\n','MariaDB> SET @g = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(GeomFromText(@g));\n+--------------------------+\n| AsText(GeomFromText(@g)) |\n+--------------------------+\n| LINESTRING(1 1,2 2,3 3) |\n+--------------------------+\n','https://mariadb.com/kb/en/astext/'),(179,'LPAD',37,'Syntax:\nLPAD(str,len,padstr)\n\nReturns the string str, left-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\n\nURL: https://mariadb.com/kb/en/lpad/\n\n','MariaDB> SELECT LPAD(\'hi\',4,\'??\');\n -> \'??hi\'\nMariaDB> SELECT LPAD(\'hi\',1,\'??\');\n -> \'h\'\n','https://mariadb.com/kb/en/lpad/'),(180,'DECLARE CONDITION',23,'Syntax:\nDECLARE condition_name CONDITION FOR condition_value\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n\nThe DECLARE ... CONDITION statement declares a named error condition,\nassociating a name with a condition that needs specific handling. The\nname can be referred to in a subsequent DECLARE ... HANDLER statement\n(see [HELP DECLARE HANDLER]).\n\nCondition declarations must appear before cursor or handler\ndeclarations.\n\nThe condition_value for DECLARE ... CONDITION can be a MySQL error code\n(a number) or an SQLSTATE value (a 5-character string literal). You\nshould not use MySQL error code 0 or SQLSTATE values that begin with\n\'00\', because those indicate success rather than an error condition.\nFor a list of MySQL error codes and SQLSTATE values, see\nhttps://mariadb.com/kb/en/mariadb-error-codes/.\n\nURL: https://mariadb.com/kb/en/declare-condition/\n\n','','https://mariadb.com/kb/en/declare-condition/'),(181,'OVERLAPS',30,'Overlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially overlaps g2. The term\nspatially overlaps is used if two geometries intersect and their\nintersection results in a geometry of the same dimension but not equal\nto either of the given geometries.\n\nURL: https://mariadb.com/kb/en/overlaps/\n\n','','https://mariadb.com/kb/en/overlaps/'),(182,'SET GLOBAL SQL_SLAVE_SKIP_COUNTER',8,'Syntax:\nSET GLOBAL sql_slave_skip_counter = N\n\nThis statement skips the next N events from the master. This is useful\nfor recovering from replication stops caused by a statement.\n\nThis statement is valid only when the slave threads are not running.\nOtherwise, it produces an error.\n\nURL: https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/\n\n','','https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/'),(183,'NUMGEOMETRIES',25,'NumGeometries(gc)\n\nReturns the number of geometries in the GeometryCollection value gc.\n\nURL: https://mariadb.com/kb/en/numgeometries/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT NumGeometries(GeomFromText(@gc));\n+----------------------------------+\n| NumGeometries(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n','https://mariadb.com/kb/en/numgeometries/'),(184,'MONTHNAME',31,'Syntax:\nMONTHNAME(date)\n\nReturns the full name of the month for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-locale/).\n\nURL: https://mariadb.com/kb/en/monthname/\n\n','MariaDB> SELECT MONTHNAME(\'2008-02-03\');\n -> \'February\'\n','https://mariadb.com/kb/en/monthname/'),(185,'CHANGE MASTER TO',8,'Syntax:\nCHANGE MASTER TO option [, option] ...\n\noption:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | IGNORE_SERVER_IDS = (server_id_list)\n\nserver_id_list:\n [server_id [, server_id] ... ]\n\nCHANGE MASTER TO changes the parameters that the slave server uses for\nconnecting to the master server, for reading the master binary log, and\nreading the slave relay log. It also updates the contents of the\nmaster.info and relay-log.info files. To use CHANGE MASTER TO, the\nslave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\nOptions not specified retain their value, except as indicated in the\nfollowing discussion. Thus, in most cases, there is no need to specify\noptions that do not change. For example, if the password to connect to\nyour MySQL master has changed, you just need to issue these statements\nto tell the slave about the new password:\n\nSTOP SLAVE; -- if replication was running\nCHANGE MASTER TO MASTER_PASSWORD=\'new3cret\';\nSTART SLAVE; -- if you want to restart replication\n\nMASTER_HOST, MASTER_USER, MASTER_PASSWORD, and MASTER_PORT provide\ninformation to the slave about how to connect to its master:\n\no MASTER_HOST and MASTER_PORT are the host name (or IP address) of the\n master host and its TCP/IP port.\n\n *Note*: Replication cannot use Unix socket files. You must be able to\n connect to the master MySQL server using TCP/IP.\n\n If you specify the MASTER_HOST or MASTER_PORT option, the slave\n assumes that the master server is different from before (even if the\n option value is the same as its current value.) In this case, the old\n values for the master binary log file name and position are\n considered no longer applicable, so if you do not specify\n MASTER_LOG_FILE and MASTER_LOG_POS in the statement,\n MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4 are silently appended to it.\n\n Setting MASTER_HOST=\'\' (that is, setting its value explicitly to an\n empty string) is not the same as not setting MASTER_HOST at all.\n Beginning with MySQL 5.5, trying to set MASTER_HOST to an empty\n string fails with an error. Previously, setting MASTER_HOST to an\n empty string caused START SLAVE subsequently to fail. (Bug #28796)\n\no MASTER_USER and MASTER_PASSWORD are the user name and password of the\n account to use for connecting to the master.\n\n In MySQL 5.5.20 and later, MASTER_USER cannot be made empty; setting\n MASTER_USER = \'\' or leaving it unset when setting a value for for\n MASTER_PASSWORD causes an error (Bug #13427949).\n\n Currently, a password used for a replication slave account is\n effectively limited to 32 characters in length; the password can be\n longer, but any excess characters are truncated. This is not due to\n any limit imposed by the MySQL Server generally, but rather is an\n issue specific to MySQL Replication. (For more information, see Bug\n #43439.)\n\n The text of a running CHANGE MASTER TO statement, including values\n for MASTER_USER and MASTER_PASSWORD, can be seen in the output of a\n concurrent SHOW PROCESSLIST statement.\n\nThe MASTER_SSL_xxx options provide information about using SSL for the\nconnection. They correspond to the --ssl-xxx options described in\nhttps://mariadb.com/kb/en/ssl-server-system-variables/, and\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-solutions-ssl.html.\nThese options can be changed even on slaves that are compiled without\nSSL support. They are saved to the master.info file, but are ignored if\nthe slave does not have SSL support enabled.\n\nMASTER_CONNECT_RETRY specifies how many seconds to wait between connect\nretries. The default is 60. The number of reconnection attempts is\nlimited by the --master-retry-count server option; for more\ninformation, see\nhttps://mariadb.com/kb/en/replication-and-binary-log-server-system-variables/.\n\nMASTER_HEARTBEAT_PERIOD sets the interval in seconds between\nreplication heartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is reset.\ninterval is a decimal value having the range 0 to 4294967 seconds and a\nresolution in milliseconds; the smallest nonzero value is 0.001.\nHeartbeats are sent by the master only if there are no unsent events in\nthe binary log file for a period longer than interval.\n\nSetting interval to 0 disables heartbeats altogether. The default value\nfor interval is equal to the value of slave_net_timeout divided by 2.\n\nSetting @@global.slave_net_timeout to a value less than that of the\ncurrent heartbeat interval results in a warning being issued. The\neffect of issuing RESET SLAVE on the heartbeat interval is to reset it\nto the default value.\n\nMASTER_LOG_FILE and MASTER_LOG_POS are the coordinates at which the\nslave I/O thread should begin reading from the master the next time the\nthread starts. RELAY_LOG_FILE and RELAY_LOG_POS are the coordinates at\nwhich the slave SQL thread should begin reading from the relay log the\nnext time the thread starts. If you specify either of MASTER_LOG_FILE\nor MASTER_LOG_POS, you cannot specify RELAY_LOG_FILE or RELAY_LOG_POS.\nIf neither of MASTER_LOG_FILE or MASTER_LOG_POS is specified, the slave\nuses the last coordinates of the slave SQL thread before CHANGE MASTER\nTO was issued. This ensures that there is no discontinuity in\nreplication, even if the slave SQL thread was late compared to the\nslave I/O thread, when you merely want to change, say, the password to\nuse.\n\nCHANGE MASTER TO deletes all relay log files and starts a new one,\nunless you specify RELAY_LOG_FILE or RELAY_LOG_POS. In that case, relay\nlog files are kept; the relay_log_purge global variable is set silently\nto 0.\n\nPrior to MySQL 5.5, RELAY_LOG_FILE required an absolute path. In MySQL\n5.5, the path can be relative, in which case the path is assumed to be\nrelative to the slave\'s data directory. (Bug #12190)\n\nIGNORE_SERVER_IDS was added in MySQL 5.5. This option takes a\ncomma-separated list of 0 or more server IDs. Events originating from\nthe corresponding servers are ignored, with the exception of log\nrotation and deletion events, which are still recorded in the relay\nlog.\n\nIn circular replication, the originating server normally acts as the\nterminator of its own events, so that they are not applied more than\nonce. Thus, this option is useful in circular replication when one of\nthe servers in the circle is removed. Suppose that you have a circular\nreplication setup with 4 servers, having server IDs 1, 2, 3, and 4, and\nserver 3 fails. When bridging the gap by starting replication from\nserver 2 to server 4, you can include IGNORE_SERVER_IDS = (3) in the\nCHANGE MASTER TO statement that you issue on server 4 to tell it to use\nserver 2 as its master instead of server 3. Doing so causes it to\nignore and not to propagate any statements that originated with the\nserver that is no longer in use.\n\nIf a CHANGE MASTER TO statement is issued without any IGNORE_SERVER_IDS\noption, any existing list is preserved; RESET SLAVE also has no effect\non the server ID list. To clear the list of ignored servers, it is\nnecessary to use the option with an empty list:\n\nCHANGE MASTER TO IGNORE_SERVER_IDS = ();\n\nIf IGNORE_SERVER_IDS contains the server\'s own ID and the server was\nstarted with the --replicate-same-server-id option enabled, an error\nresults.\n\nAlso beginning with MySQL 5.5, the master.info file and the output of\nSHOW SLAVE STATUS are extended to provide the list of servers that are\ncurrently ignored. For more information, see\nhttps://mariadb.com/kb/en/show-slave-status/, and\n[HELP SHOW SLAVE STATUS].\n\nBeginning with MySQL 5.5.5, invoking CHANGE MASTER TO causes the\nprevious values for MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE, and\nMASTER_LOG_POS to be written to the error log, along with other\ninformation about the slave\'s state prior to execution.\n\nCHANGE MASTER TO is useful for setting up a slave when you have the\nsnapshot of the master and have recorded the master binary log\ncoordinates corresponding to the time of the snapshot. After loading\nthe snapshot into the slave to synchronize it to the slave, you can run\nCHANGE MASTER TO MASTER_LOG_FILE=\'log_name\', MASTER_LOG_POS=log_pos on\nthe slave to specify the coordinates at which the slave should begin\nreading the master binary log.\n\nThe following example changes the master server the slave uses and\nestablishes the master binary log coordinates from which the slave\nbegins reading. This is used when you want to set up the slave to\nreplicate the master:\n\nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n\nThe next example shows an operation that is less frequently employed.\nIt is used when the slave has relay log files that you want it to\nexecute again for some reason. To do this, the master need not be\nreachable. You need only use CHANGE MASTER TO and start the SQL thread\n(START SLAVE SQL_THREAD):\n\nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n\nURL: https://mariadb.com/kb/en/change-master-to/\n\n','','https://mariadb.com/kb/en/change-master-to/'),(186,'DROP DATABASE',39,'Syntax:\nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n\nDROP DATABASE drops all tables in the database and deletes the\ndatabase. Be very careful with this statement! To use DROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is a synonym\nfor DROP DATABASE.\n\n*Important*: When a database is dropped, user privileges on the\ndatabase are not automatically dropped. See [HELP GRANT].\n\nIF EXISTS is used to prevent an error from occurring if the database\ndoes not exist.\n\nURL: https://mariadb.com/kb/en/drop-database/\n\n','','https://mariadb.com/kb/en/drop-database/'),(187,'MBREQUAL',6,'MBREqual(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are the same.\n\nURL: https://mariadb.com/kb/en/mbrequal/\n\n','','https://mariadb.com/kb/en/mbrequal/'),(188,'TIMESTAMP FUNCTION',31,'Syntax:\nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n\nWith a single argument, this function returns the date or datetime\nexpression expr as a datetime value. With two arguments, it adds the\ntime expression expr2 to the date or datetime expression expr1 and\nreturns the result as a datetime value.\n\nURL: https://mariadb.com/kb/en/timestamp-function/\n\n','MariaDB> SELECT TIMESTAMP(\'2003-12-31\');\n -> \'2003-12-31 00:00:00\'\nMariaDB> SELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'12:00:00\');\n -> \'2004-01-01 00:00:00\'\n','https://mariadb.com/kb/en/timestamp-function/'),(189,'PROCEDURE ANALYSE',33,'Syntax:\nANALYSE([max_elements[,max_memory]])\n\nANALYSE() examines the result from a query and returns an analysis of\nthe results that suggests optimal data types for each column that may\nhelp reduce table sizes. To obtain this analysis, append PROCEDURE\nANALYSE to the end of a SELECT statement:\n\nSELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])\n\nFor example:\n\nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n\nThe results show some statistics for the values returned by the query,\nand propose an optimal data type for the columns. This can be helpful\nfor checking your existing tables, or after importing new data. You may\nneed to try different settings for the arguments so that PROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n\nThe arguments are optional and are used as follows:\n\no max_elements (default 256) is the maximum number of distinct values\n that ANALYSE() notices per column. This is used by ANALYSE() to check\n whether the optimal data type should be of type ENUM; if there are\n more than max_elements distinct values, then ENUM is not a suggested\n type.\n\no max_memory (default 8192) is the maximum amount of memory that\n ANALYSE() should allocate per column while trying to find all\n distinct values.\n\nURL: https://mariadb.com/kb/en/procedure-analyse/\n\n','','https://mariadb.com/kb/en/procedure-analyse/'),(190,'HELP_VERSION',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25 (revision: 31914)\n\nThis information applies to MySQL 5.5 through 5.5.29.\n','',''),(191,'CHARACTER_LENGTH',37,'Syntax:\nCHARACTER_LENGTH(str)\n\nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n\nURL: https://mariadb.com/kb/en/character_length/\n\n','','https://mariadb.com/kb/en/character_length/'),(192,'SHOW GRANTS',26,'Syntax:\nSHOW GRANTS [FOR user]\n\nThis statement lists the GRANT statement or statements that must be\nissued to duplicate the privileges that are granted to a MySQL user\naccount. The account is named using the same format as for the GRANT\nstatement; for example, \'jeffrey\'@\'localhost\'. If you specify only the\nuser name part of the account name, a host name part of \'%\' is used.\nFor additional information about specifying account names, see [HELP\nGRANT].\n\nMariaDB> SHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION |\n+---------------------------------------------------------------------+\n\nTo list the privileges granted to the account that you are using to\nconnect to the server, you can use any of the following statements:\n\nSHOW GRANTS;\nSHOW GRANTS FOR CURRENT_USER;\nSHOW GRANTS FOR CURRENT_USER();\n\nIf SHOW GRANTS FOR CURRENT_USER (or any of the equivalent syntaxes) is\nused in DEFINER context, such as within a stored procedure that is\ndefined with SQL SECURITY DEFINER), the grants displayed are those of\nthe definer and not the invoker.\n\nURL: https://mariadb.com/kb/en/show-grants/\n\n','','https://mariadb.com/kb/en/show-grants/'),(193,'SHOW PRIVILEGES',26,'Syntax:\nSHOW PRIVILEGES\n\nSHOW PRIVILEGES shows the list of system privileges that the MySQL\nserver supports. The exact list of privileges depends on the version of\nyour server.\n\nURL: https://mariadb.com/kb/en/show-privileges/\n\n','','https://mariadb.com/kb/en/show-privileges/'),(194,'CREATE TABLESPACE',39,'Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n USE LOGFILE GROUP logfile_group\n [EXTENT_SIZE [=] extent_size]\n [INITIAL_SIZE [=] initial_size]\n [AUTOEXTEND_SIZE [=] autoextend_size]\n [MAX_SIZE [=] max_size]\n [NODEGROUP [=] nodegroup_id]\n [WAIT]\n [COMMENT [=] comment_text]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.','','https://mariadb.com/kb/en/create-tablespace/'),(195,'INSERT FUNCTION',37,'Syntax:\nINSERT(str,pos,len,newstr)\n\nReturns the string str, with the substring beginning at position pos\nand len characters long replaced by the string newstr. Returns the\noriginal string if pos is not within the length of the string. Replaces\nthe rest of the string from position pos if len is not within the\nlength of the rest of the string. Returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/insert-function/\n\n','MariaDB> SELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n -> \'QuWhattic\'\nMariaDB> SELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n -> \'Quadratic\'\nMariaDB> SELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n -> \'QuWhat\'\n','https://mariadb.com/kb/en/insert-function/'),(196,'CRC32',4,'Syntax:\nCRC32(expr)\n\nComputes a cyclic redundancy check value and returns a 32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The argument is\nexpected to be a string and (if possible) is treated as one if it is\nnot.\n\nURL: https://mariadb.com/kb/en/crc32/\n\n','MariaDB> SELECT CRC32(\'MySQL\');\n -> 3259397556\nMariaDB> SELECT CRC32(\'mysql\');\n -> 2501908538\n','https://mariadb.com/kb/en/crc32/'),(197,'XOR',15,'Syntax:\nXOR\n\nLogical XOR. Returns NULL if either operand is NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is nonzero,\notherwise 0 is returned.\n\nURL: https://mariadb.com/kb/en/xor/\n\n','MariaDB> SELECT 1 XOR 1;\n -> 0\nMariaDB> SELECT 1 XOR 0;\n -> 1\nMariaDB> SELECT 1 XOR NULL;\n -> NULL\nMariaDB> SELECT 1 XOR 1 XOR 1;\n -> 1\n','https://mariadb.com/kb/en/xor/'),(198,'STARTPOINT',13,'StartPoint(ls)\n\nReturns the Point that is the start point of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/startpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(StartPoint(GeomFromText(@ls)));\n+---------------------------------------+\n| AsText(StartPoint(GeomFromText(@ls))) |\n+---------------------------------------+\n| POINT(1 1) |\n+---------------------------------------+\n','https://mariadb.com/kb/en/startpoint/'),(199,'GRANT',10,'Syntax:\nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [, user_specification] ...\n [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]\n [WITH with_option ...]\n\nGRANT PROXY ON user_specification\n TO user_specification [, user_specification] ...\n [WITH GRANT OPTION]\n\nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n\npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nssl_option:\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n\nwith_option:\n GRANT OPTION\n | MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n\nThe GRANT statement grants privileges to MySQL user accounts. GRANT\nalso serves to specify other account characteristics such as use of\nsecure connections and limits on access to server resources. To use\nGRANT, you must have the GRANT OPTION privilege, and you must have the\nprivileges that you are granting.\n\nNormally, a database administrator first uses CREATE USER to create an\naccount, then GRANT to define its privileges and characteristics. For\nexample:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\nGRANT ALL ON db1.* TO \'jeffrey\'@\'localhost\';\nGRANT SELECT ON db2.invoice TO \'jeffrey\'@\'localhost\';\nGRANT USAGE ON *.* TO \'jeffrey\'@\'localhost\' WITH MAX_QUERIES_PER_HOUR 90;\n\nHowever, if an account named in a GRANT statement does not already\nexist, GRANT may create it under the conditions described later in the\ndiscussion of the NO_AUTO_CREATE_USER SQL mode.\n\nThe REVOKE statement is related to GRANT and enables administrators to\nremove account privileges. See [HELP REVOKE].\n\nWhen successfully executed from the mysql program, GRANT responds with\nQuery OK, 0 rows affected. To determine what privileges result from the\noperation, use SHOW GRANTS. See [HELP SHOW GRANTS].\n\nURL: https://mariadb.com/kb/en/grant/\n\n','','https://mariadb.com/kb/en/grant/'),(200,'DECLARE VARIABLE',23,'Syntax:\nDECLARE var_name [, var_name] ... type [DEFAULT value]\n\nThis statement declares local variables within stored programs. To\nprovide a default value for a variable, include a DEFAULT clause. The\nvalue can be specified as an expression; it need not be a constant. If\nthe DEFAULT clause is missing, the initial value is NULL.\n\nLocal variables are treated like stored routine parameters with respect\nto data type and overflow checking. See [HELP CREATE PROCEDURE].\n\nVariable declarations must appear before cursor or handler\ndeclarations.\n\nLocal variable names are not case sensitive. Permissible characters and\nquoting rules are the same as for other identifiers, as described in\nhttps://mariadb.com/kb/en/identifier-names/.\n\nThe scope of a local variable is the BEGIN ... END block within which\nit is declared. The variable can be referred to in blocks nested within\nthe declaring block, except those blocks that declare a variable with\nthe same name.\n\nURL: https://mariadb.com/kb/en/declare-variable/\n\n','','https://mariadb.com/kb/en/declare-variable/'),(201,'MPOLYFROMTEXT',3,'MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])\n\nConstructs a MULTIPOLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromtext/\n\n','','https://mariadb.com/kb/en/mpolyfromtext/'),(202,'MBRINTERSECTS',6,'MBRIntersects(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 intersect.\n\nURL: https://mariadb.com/kb/en/mbrintersects/\n\n','','https://mariadb.com/kb/en/mbrintersects/'),(203,'BIT_OR',16,'Syntax:\nBIT_OR(expr)\n\nReturns the bitwise OR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_or/\n\n','','https://mariadb.com/kb/en/bit_or/'),(204,'YEARWEEK',31,'Syntax:\nYEARWEEK(date), YEARWEEK(date,mode)\n\nReturns year and week for a date. The mode argument works exactly like\nthe mode argument to WEEK(). The year in the result may be different\nfrom the year in the date argument for the first and the last week of\nthe year.\n\nURL: https://mariadb.com/kb/en/yearweek/\n\n','MariaDB> SELECT YEARWEEK(\'1987-01-01\');\n -> 198653\n','https://mariadb.com/kb/en/yearweek/'),(205,'NOT BETWEEN',18,'Syntax:\nexpr NOT BETWEEN min AND max\n\nThis is the same as NOT (expr BETWEEN min AND max).\n\nURL: https://mariadb.com/kb/en/not-between/\n\n','','https://mariadb.com/kb/en/not-between/'),(206,'IS NOT',18,'Syntax:\nIS NOT boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is-not/\n\n','MariaDB> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not/'),(207,'LOG10',4,'Syntax:\nLOG10(X)\n\nReturns the base-10 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log10/\n\n','MariaDB> SELECT LOG10(2);\n -> 0.30102999566398\nMariaDB> SELECT LOG10(100);\n -> 2\nMariaDB> SELECT LOG10(-100);\n -> NULL\n','https://mariadb.com/kb/en/log10/'),(208,'SQRT',4,'Syntax:\nSQRT(X)\n\nReturns the square root of a nonnegative number X.\n\nURL: https://mariadb.com/kb/en/sqrt/\n\n','MariaDB> SELECT SQRT(4);\n -> 2\nMariaDB> SELECT SQRT(20);\n -> 4.4721359549996\nMariaDB> SELECT SQRT(-16);\n -> NULL\n','https://mariadb.com/kb/en/sqrt/'),(209,'DECIMAL',22,'DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nA packed \"exact\" fixed-point number. M is the total number of digits\n(the precision) and D is the number of digits after the decimal point\n(the scale). The decimal point and (for negative numbers) the \"-\" sign\nare not counted in M. If D is 0, values have no decimal point or\nfractional part. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30. If D is omitted,\nthe default is 0. If M is omitted, the default is 10.\n\nUNSIGNED, if specified, disallows negative values.\n\nAll basic calculations (+, -, *, /) with DECIMAL columns are done with\na precision of 65 digits.\n\nURL: https://mariadb.com/kb/en/decimal/\n\n','','https://mariadb.com/kb/en/decimal/'),(210,'CREATE INDEX',39,'Syntax:\nCREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [index_option] ...\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nCREATE INDEX is mapped to an ALTER TABLE statement to create indexes.\nSee [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY\nKEY; use ALTER TABLE instead. For more information about indexes, see\nhttps://mariadb.com/kb/en/optimization-and-indexes/.\n\nURL: https://mariadb.com/kb/en/create-index/\n\n','','https://mariadb.com/kb/en/create-index/'),(211,'CREATE FUNCTION',39,'The CREATE FUNCTION statement is used to create stored functions and\nuser-defined functions (UDFs):\n\no For information about creating stored functions, see [HELP CREATE\n PROCEDURE].\n\no For information about creating user-defined functions, see [HELP\n CREATE FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/create-function/\n\n','','https://mariadb.com/kb/en/create-function/'),(212,'ALTER DATABASE',39,'Syntax:\nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n\nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nALTER DATABASE enables you to change the overall characteristics of a\ndatabase. These characteristics are stored in the db.opt file in the\ndatabase directory. To use ALTER DATABASE, you need the ALTER privilege\non the database. ALTER SCHEMA is a synonym for ALTER DATABASE.\n\nThe database name can be omitted from the first syntax, in which case\nthe statement applies to the default database.\n\nNational Language Characteristics\n\nThe CHARACTER SET clause changes the default database character set.\nThe COLLATE clause changes the default database collation.\nhttps://mariadb.com/kb/en/data-types-character-sets-and-collations/, discusses\ncharacter set and collation names.\n\nYou can see what character sets and collations are available using,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION statements. See\n[HELP SHOW CHARACTER SET], and [HELP SHOW COLLATION], for more\ninformation.\n\nIf you change the default character set or collation for a database,\nstored routines that use the database defaults must be dropped and\nrecreated so that they use the new defaults. (In a stored routine,\nvariables with character data types use the database defaults if the\ncharacter set or collation are not specified explicitly. See [HELP\nCREATE PROCEDURE].)\n\nUpgrading from Versions Older than MySQL 5.1\n\nThe syntax that includes the UPGRADE DATA DIRECTORY NAME clause updates\nthe name of the directory associated with the database to use the\nencoding implemented in MySQL 5.1 for mapping database names to\ndatabase directory names (see\nhttps://mariadb.com/kb/en/identifier-to-file-name-mapping/). This\nclause is for use under these conditions:\n\no It is intended when upgrading MySQL to 5.1 or later from older\n versions.\n\no It is intended to update a database directory name to the current\n encoding format if the name contains special characters that need\n encoding.\n\no The statement is used by mysqlcheck (as invoked by mysql_upgrade).\n\nFor example, if a database in MySQL 5.0 has the name a-b-c, the name\ncontains instances of the - (dash) character. In MySQL 5.0, the\ndatabase directory is also named a-b-c, which is not necessarily safe\nfor all file systems. In MySQL 5.1 and later, the same database name is\nencoded as a@002db@002dc to produce a file system-neutral directory\nname.\n\nWhen a MySQL installation is upgraded to MySQL 5.1 or later from an\nolder version,the server displays a name such as a-b-c (which is in the\nold format) as #mysql50#a-b-c, and you must refer to the name using the\n#mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME in this case to\nexplicitly tell the server to re-encode the database directory name to\nthe current encoding format:\n\nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n\nAfter executing this statement, you can refer to the database as a-b-c\nwithout the special #mysql50# prefix.\n\nURL: https://mariadb.com/kb/en/alter-database/\n\n','','https://mariadb.com/kb/en/alter-database/'),(213,'GEOMETRYN',25,'GeometryN(gc,N)\n\nReturns the N-th geometry in the GeometryCollection value gc.\nGeometries are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/geometryn/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n','https://mariadb.com/kb/en/geometryn/'),(214,'<<',19,'Syntax:\n<<\n\nShifts a longlong (BIGINT) number to the left.\n\nURL: https://mariadb.com/kb/en/shift-left/\n\n','MariaDB> SELECT 1 << 2;\n -> 4\n','https://mariadb.com/kb/en/shift-left/'),(215,'SHOW TABLE STATUS',26,'Syntax:\nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLE STATUS works likes SHOW TABLES, but provides a lot of\ninformation about each non-TEMPORARY table. You can also get this list\nusing the mysqlshow --status db_name command. The LIKE clause, if\npresent, indicates which table names to match. The WHERE clause can be\ngiven to select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-table-status/\n\n','','https://mariadb.com/kb/en/show-table-status/'),(216,'MD5',12,'Syntax:\nMD5(str)\n\nCalculates an MD5 128-bit checksum for the string. The value is\nreturned as a string of 32 hex digits, or NULL if the argument was\nNULL. The return value can, for example, be used as a hash key. See the\nnotes at the beginning of this section about storing hash values\nefficiently.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/md5/\n\n','MariaDB> SELECT MD5(\'testing\');\n -> \'ae2b1fca515949e5d54fb22b8ed95575\'\n','https://mariadb.com/kb/en/md5/'),(217,'<',18,'Syntax:\n<\n\nLess than:\n\nURL: https://mariadb.com/kb/en/less-than/\n\n','MariaDB> SELECT 2 < 2;\n -> 0\n','https://mariadb.com/kb/en/less-than/'),(218,'UNIX_TIMESTAMP',31,'Syntax:\nUNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)\n\nIf called with no argument, returns a Unix timestamp (seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If UNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the argument as\nseconds since \'1970-01-01 00:00:00\' UTC. date may be a DATE string, a\nDATETIME string, a TIMESTAMP, or a number in the format YYMMDD or\nYYYYMMDD. The server interprets date as a value in the current time\nzone and converts it to an internal value in UTC. Clients can set their\ntime zone as described in\nhttps://mariadb.com/kb/en/time-zones/.\n\nURL: https://mariadb.com/kb/en/unix_timestamp/\n\n','MariaDB> SELECT UNIX_TIMESTAMP();\n -> 1196440210\nMariaDB> SELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n -> 1196440219\n','https://mariadb.com/kb/en/unix_timestamp/'),(219,'DAYOFMONTH',31,'Syntax:\nDAYOFMONTH(date)\n\nReturns the day of the month for date, in the range 1 to 31, or 0 for\ndates such as \'0000-00-00\' or \'2008-00-00\' that have a zero day part.\n\nURL: https://mariadb.com/kb/en/dayofmonth/\n\n','MariaDB> SELECT DAYOFMONTH(\'2007-02-03\');\n -> 3\n','https://mariadb.com/kb/en/dayofmonth/'),(220,'ASCII',37,'Syntax:\nASCII(str)\n\nReturns the numeric value of the leftmost character of the string str.\nReturns 0 if str is the empty string. Returns NULL if str is NULL.\nASCII() works for 8-bit characters.\n\nURL: https://mariadb.com/kb/en/ascii/\n\n','MariaDB> SELECT ASCII(\'2\');\n -> 50\nMariaDB> SELECT ASCII(2);\n -> 50\nMariaDB> SELECT ASCII(\'dx\');\n -> 100\n','https://mariadb.com/kb/en/ascii/'),(221,'DIV',4,'Syntax:\nDIV\n\nInteger division. Similar to FLOOR(), but is safe with BIGINT values.\n\nAs of MySQL 5.5.3, if either operand has a noninteger type, the\noperands are converted to DECIMAL and divided using DECIMAL arithmetic\nbefore converting the result to BIGINT. If the result exceeds BIGINT\nrange, an error occurs. Before MySQL 5.5.3, incorrect results may occur\nfor noninteger operands that exceed BIGINT range.\n\nURL: https://mariadb.com/kb/en/div/\n\n','MariaDB> SELECT 5 DIV 2;\n -> 2\n','https://mariadb.com/kb/en/div/'),(222,'RENAME USER',10,'Syntax:\nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n\nThe RENAME USER statement renames existing MySQL accounts. To use it,\nyou must have the global CREATE USER privilege or the UPDATE privilege\nfor the mysql database. An error occurs if any old account does not\nexist or any new account exists. Each account name uses the format\ndescribed in https://mariadb.com/kb/en/create-user/#account-names.\nFor example:\n\nRENAME USER \'jeffrey\'@\'localhost\' TO \'jeff\'@\'127.0.0.1\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nRENAME USER causes the privileges held by the old user to be those held\nby the new user. However, RENAME USER does not automatically drop or\ninvalidate databases or objects within them that the old user created.\nThis includes stored programs or views for which the DEFINER attribute\nnames the old user. Attempts to access such objects may produce an\nerror if they execute in definer security context. (For information\nabout security context, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.)\n\nThe privilege changes take effect as indicated in\nhttp://dev.mysql.com/doc/refman/5.5/en/privilege-changes.html.\n\nURL: https://mariadb.com/kb/en/rename-user/\n\n','','https://mariadb.com/kb/en/rename-user/'),(223,'SHOW SLAVE STATUS',26,'Syntax:\nSHOW SLAVE STATUS\n\nThis statement provides status information on essential parameters of\nthe slave threads. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nIf you issue this statement using the mysql client, you can use a \\G\nstatement terminator rather than a semicolon to obtain a more readable\nvertical layout:\n\nMariaDB> SHOW SLAVE STATUS\\G\n*************************** 1. row ***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: localhost\n Master_User: root\n Master_Port: 3306\n Connect_Retry: 3\n Master_Log_File: gbichot-bin.005\n Read_Master_Log_Pos: 79\n Relay_Log_File: gbichot-relay-bin.005\n Relay_Log_Pos: 548\n Relay_Master_Log_File: gbichot-bin.005\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB:\n Replicate_Ignore_DB:\n Replicate_Do_Table:\n Replicate_Ignore_Table:\n Replicate_Wild_Do_Table:\n Replicate_Wild_Ignore_Table:\n Last_Errno: 0\n Last_Error:\n Skip_Counter: 0\n Exec_Master_Log_Pos: 79\n Relay_Log_Space: 552\n Until_Condition: None\n Until_Log_File:\n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File:\n Master_SSL_CA_Path:\n Master_SSL_Cert:\n Master_SSL_Cipher:\n Master_SSL_Key:\n Seconds_Behind_Master: 8\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error:\n Last_SQL_Errno: 0\n Last_SQL_Error:\n Replicate_Ignore_Server_Ids: 0\n Master_Server_Id: 1\n\nURL: https://mariadb.com/kb/en/show-slave-status/\n\n','','https://mariadb.com/kb/en/show-slave-status/'),(224,'GEOMETRY',34,'MySQL provides a standard way of creating spatial columns for geometry\ntypes, for example, with CREATE TABLE or ALTER TABLE. Currently,\nspatial columns are supported for MyISAM, Aria, InnoDB and ARCHIVE\ntables. See also the annotations about spatial indexes under [HELP\nSPATIAL].\n\nURL: https://mariadb.com/kb/en/gis-functionality/\n\n','CREATE TABLE geom (g GEOMETRY);\n','https://mariadb.com/kb/en/gis-functionality/'),(225,'NUMPOINTS',13,'NumPoints(ls)\n\nReturns the number of Point objects in the LineString value ls.\n\nURL: https://mariadb.com/kb/en/numpoints/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n','https://mariadb.com/kb/en/numpoints/'),(226,'ALTER LOGFILE GROUP',39,'Syntax:\nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n','','https://mariadb.com/kb/en/alter-logfile-group/'),(227,'&',19,'Syntax:\n&\n\nBitwise AND:\n\nURL: https://mariadb.com/kb/en/bitwise_and/\n\n','MariaDB> SELECT 29 & 15;\n -> 13\n','https://mariadb.com/kb/en/bitwise_and/'),(228,'LOCALTIMESTAMP',31,'Syntax:\nLOCALTIMESTAMP, LOCALTIMESTAMP()\n\nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtimestamp/\n\n','','https://mariadb.com/kb/en/localtimestamp/'),(229,'ASSIGN-EQUAL',15,'Syntax:\n=\n\nThis operator is used to perform value assignments in two cases,\ndescribed in the next two paragraphs.\n\nWithin a SET statement, = is treated as an assignment operator that\ncauses the user variable on the left hand side of the operator to take\non the value to its right. (In other words, when used in a SET\nstatement, = is treated identically to :=.) The value on the right hand\nside may be a literal value, another variable storing a value, or any\nlegal expression that yields a scalar value, including the result of a\nquery (provided that this value is a scalar value). You can perform\nmultiple assignments in the same SET statement.\n\nIn the SET clause of an UPDATE statement, = also acts as an assignment\noperator; in this case, however, it causes the column named on the left\nhand side of the operator to assume the value given to the right,\nprovided any WHERE conditions that are part of the UPDATE are met. You\ncan make multiple assignments in the same SET clause of an UPDATE\nstatement.\n\nIn any other context, = is treated as a comparison operator.\n\nURL: https://mariadb.com/kb/en/assignment-operators-assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n','https://mariadb.com/kb/en/assignment-operators-assignment-operator/'),(230,'CONVERT',37,'Syntax:\nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n\nThe CONVERT() and CAST() functions take an expression of any type and\nproduce a result value of a specified type.\n\nThe type for the result can be one of the following values:\n\no BINARY[(N)]\n\no CHAR[(N)]\n\no DATE\n\no DATETIME\n\no DECIMAL[(M[,D])]\n\no SIGNED [INTEGER]\n\no TIME\n\no UNSIGNED [INTEGER]\n\nBINARY produces a string with the BINARY data type. See\nhttps://mariadb.com/kb/en/binary/ for a\ndescription of how this affects comparisons. If the optional length N\nis given, BINARY(N) causes the cast to use no more than N bytes of the\nargument. Values shorter than N bytes are padded with 0x00 bytes to a\nlength of N.\n\nCHAR(N) causes the cast to use no more than N characters of the\nargument.\n\nCAST() and CONVERT(... USING ...) are standard SQL syntax. The\nnon-USING form of CONVERT() is ODBC syntax.\n\nCONVERT() with USING is used to convert data between different\ncharacter sets. In MySQL, transcoding names are the same as the\ncorresponding character set names. For example, this statement converts\nthe string \'abc\' in the default character set to the corresponding\nstring in the utf8 character set:\n\nSELECT CONVERT(\'abc\' USING utf8);\n\nURL: https://mariadb.com/kb/en/convert/\n\n','SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);\n','https://mariadb.com/kb/en/convert/'),(231,'ADDDATE',31,'Syntax:\nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, ADDDATE()\nis a synonym for DATE_ADD(). The related function SUBDATE() is a\nsynonym for DATE_SUB(). For information on the INTERVAL unit argument,\nsee the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\nMariaDB> SELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\n\nWhen invoked with the days form of the second argument, MySQL treats it\nas an integer number of days to be added to expr.\n\nURL: https://mariadb.com/kb/en/adddate/\n\n','MariaDB> SELECT ADDDATE(\'2008-01-02\', 31);\n -> \'2008-02-02\'\n','https://mariadb.com/kb/en/adddate/'),(232,'REPEAT LOOP',23,'Syntax:\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\nThe statement list within a REPEAT statement is repeated until the\nsearch_condition expression is true. Thus, a REPEAT always enters the\nloop at least once. statement_list consists of one or more statements,\neach terminated by a semicolon (;) statement delimiter.\n\nA REPEAT statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/repeat-loop/\n\n','MariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE dorepeat(p1 INT)\n -> BEGIN\n -> SET @x = 0;\n -> REPEAT\n -> SET @x = @x + 1;\n -> UNTIL @x > p1 END REPEAT;\n -> END\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL dorepeat(1000)//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/repeat-loop/'),(233,'ALTER FUNCTION',39,'Syntax:\nALTER FUNCTION func_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nfunction. More than one change may be specified in an ALTER FUNCTION\nstatement. However, you cannot change the parameters or body of a\nstored function using this statement; to make such changes, you must\ndrop and re-create the function using DROP FUNCTION and CREATE\nFUNCTION.\n\nYou must have the ALTER ROUTINE privilege for the function. (That\nprivilege is granted automatically to the function creator.) If binary\nlogging is enabled, the ALTER FUNCTION statement might also require the\nSUPER privilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nURL: https://mariadb.com/kb/en/alter-function/\n\n','','https://mariadb.com/kb/en/alter-function/'),(234,'SMALLINT',22,'SMALLINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA small integer. The signed range is -32768 to 32767. The unsigned\nrange is 0 to 65535.\n\nURL: https://mariadb.com/kb/en/smallint/\n\n','','https://mariadb.com/kb/en/smallint/'),(235,'DOUBLE PRECISION',22,'DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED]\n[ZEROFILL]\n\nThese types are synonyms for DOUBLE. Exception: If the REAL_AS_FLOAT\nSQL mode is enabled, REAL is a synonym for FLOAT rather than DOUBLE.\n\nURL: https://mariadb.com/kb/en/double-precision/\n\n','','https://mariadb.com/kb/en/double-precision/'),(236,'ORD',37,'Syntax:\nORD(str)\n\nIf the leftmost character of the string str is a multi-byte character,\nreturns the code for that character, calculated from the numeric values\nof its constituent bytes using this formula:\n\n (1st byte code)\n+ (2nd byte code * 256)\n+ (3rd byte code * 2562) ...\n\nIf the leftmost character is not a multi-byte character, ORD() returns\nthe same value as the ASCII() function.\n\nURL: https://mariadb.com/kb/en/ord/\n\n','MariaDB> SELECT ORD(\'2\');\n -> 50\n','https://mariadb.com/kb/en/ord/'),(237,'DEALLOCATE PREPARE',8,'Syntax:\n{DEALLOCATE | DROP} PREPARE stmt_name\n\nTo deallocate a prepared statement produced with PREPARE, use a\nDEALLOCATE PREPARE statement that refers to the prepared statement\nname. Attempting to execute a prepared statement after deallocating it\nresults in an error.\n\nURL: https://mariadb.com/kb/en/deallocate-drop-prepared-statement/\n\n','','https://mariadb.com/kb/en/deallocate-drop-prepared-statement/'),(238,'ENVELOPE',36,'Envelope(g)\n\nReturns the Minimum Bounding Rectangle (MBR) for the geometry value g.\nThe result is returned as a Polygon value.\n\nThe polygon is defined by the corner points of the bounding box:\n\nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n\nURL: https://mariadb.com/kb/en/envelope/\n\n','MariaDB> SELECT AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\')));\n+-------------------------------------------------------+\n| AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\'))) |\n+-------------------------------------------------------+\n| POLYGON((1 1,2 1,2 2,1 2,1 1)) |\n+-------------------------------------------------------+\n','https://mariadb.com/kb/en/envelope/'),(239,'IS_FREE_LOCK',14,'Syntax:\nIS_FREE_LOCK(str)\n\nChecks whether the lock named str is free to use (that is, not locked).\nReturns 1 if the lock is free (no one is using the lock), 0 if the lock\nis in use, and NULL if an error occurs (such as an incorrect argument).\n\nURL: https://mariadb.com/kb/en/is_free_lock/\n\n','','https://mariadb.com/kb/en/is_free_lock/'),(240,'TOUCHES',30,'Touches(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially touches g2. Two\ngeometries spatially touch if the interiors of the geometries do not\nintersect, but the boundary of one of the geometries intersects either\nthe boundary or the interior of the other.\n\nURL: https://mariadb.com/kb/en/touches/\n\n','','https://mariadb.com/kb/en/touches/'),(241,'INET_ATON',14,'Syntax:\nINET_ATON(expr)\n\nGiven the dotted-quad representation of an IPv4 network address as a\nstring, returns an integer that represents the numeric value of the\naddress in network byte order (big endian). INET_ATON() returns NULL if\nit does not understand its argument.\n\nURL: https://mariadb.com/kb/en/inet_aton/\n\n','MariaDB> SELECT INET_ATON(\'10.0.5.9\');\n -> 167773449\n','https://mariadb.com/kb/en/inet_aton/'),(242,'UNCOMPRESS',12,'Syntax:\nUNCOMPRESS(string_to_uncompress)\n\nUncompresses a string compressed by the COMPRESS() function. If the\nargument is not a compressed value, the result is NULL. This function\nrequires MySQL to have been compiled with a compression library such as\nzlib. Otherwise, the return value is always NULL.\n\nURL: https://mariadb.com/kb/en/uncompress/\n\n','MariaDB> SELECT UNCOMPRESS(COMPRESS(\'any string\'));\n -> \'any string\'\nMariaDB> SELECT UNCOMPRESS(\'any string\');\n -> NULL\n','https://mariadb.com/kb/en/uncompress/'),(243,'AUTO_INCREMENT',22,'The AUTO_INCREMENT attribute can be used to generate a unique identity\nfor new rows:\n\nURL: https://mariadb.com/kb/en/auto_increment/\n\n','CREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n);\n\nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'lax\'),(\'whale\'),(\'ostrich\');\n\nSELECT * FROM animals;\n','https://mariadb.com/kb/en/auto_increment/'),(244,'ISSIMPLE',36,'IsSimple(g)\n\nCurrently, this function is a placeholder and should not be used. If\nimplemented, its behavior will be as described in the next paragraph.\n\nReturns 1 if the geometry value g has no anomalous geometric points,\nsuch as self-intersection or self-tangency. IsSimple() returns 0 if the\nargument is not simple, and -1 if it is NULL.\n\nThe description of each instantiable geometric class given earlier in\nthe chapter includes the specific conditions that cause an instance of\nthat class to be classified as not simple. (See [HELP Geometry\nhierarchy].)\n\nURL: https://mariadb.com/kb/en/issimple/\n\n','','https://mariadb.com/kb/en/issimple/'),(245,'- BINARY',4,'Syntax:\n-\n\nSubtraction:\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT 3-5;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(246,'GEOMCOLLFROMTEXT',3,'GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromtext/\n\n','','https://mariadb.com/kb/en/geomcollfromtext/'),(247,'WKT DEFINITION',3,'The Well-Known Text (WKT) representation of Geometry is designed to\nexchange geometry data in ASCII form. For a Backus-Naur grammar that\nspecifies the formal production rules for writing WKT values, see the\nOpenGIS specification document referenced in\nhttps://mariadb.com/kb/en/gis-resources/.\n\nURL: https://mariadb.com/kb/en/wkt-definition/\n\n','','https://mariadb.com/kb/en/wkt-definition/'),(248,'CURRENT_TIME',31,'Syntax:\nCURRENT_TIME, CURRENT_TIME()\n\nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n\nURL: https://mariadb.com/kb/en/current_time/\n\n','','https://mariadb.com/kb/en/current_time/'),(249,'REVOKE',10,'Syntax:\nREVOKE\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n\nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n\nREVOKE PROXY ON user\n FROM user [, user] ...\n\nThe REVOKE statement enables system administrators to revoke privileges\nfrom MySQL accounts. Each account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nREVOKE INSERT ON *.* FROM \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nFor details on the levels at which privileges exist, the permissible\npriv_type and priv_level values, and the syntax for specifying users\nand passwords, see [HELP GRANT]\n\nTo use the first REVOKE syntax, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are revoking.\n\nTo revoke all privileges, use the second syntax, which drops all\nglobal, database, table, column, and routine privileges for the named\nuser or users:\n\nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n\nTo use this REVOKE syntax, you must have the global CREATE USER\nprivilege or the UPDATE privilege for the mysql database.\n\nURL: https://mariadb.com/kb/en/revoke/\n\n','','https://mariadb.com/kb/en/revoke/'),(250,'LAST_INSERT_ID',17,'Syntax:\nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n\nLAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value\nrepresenting the first automatically generated value successfully\ninserted for an AUTO_INCREMENT column as a result of the most recently\nexecuted INSERT statement. The value of LAST_INSERT_ID() remains\nunchanged if no rows are successfully inserted.\n\nFor example, after inserting a row that generates an AUTO_INCREMENT\nvalue, you can get the value like this:\n\nMariaDB> SELECT LAST_INSERT_ID();\n -> 195\n\nThe currently executing statement does not affect the value of\nLAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table with its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain\nstable in the second statement; its value for the second and later rows\nis not affected by the earlier row insertions. (However, if you mix\nreferences to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is\nundefined.)\n\nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if the\nstatement is rolled back due to an error, the value of LAST_INSERT_ID()\nis left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID()\nis not restored to that before the transaction; it remains as it was at\nthe point of the ROLLBACK.\n\nWithin the body of a stored routine (procedure or function) or a\ntrigger, the value of LAST_INSERT_ID() changes the same way as for\nstatements executed outside the body of these kinds of objects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements depends on the\nkind of routine:\n\no If a stored procedure executes statements that change the value of\n LAST_INSERT_ID(), the changed value is seen by statements that follow\n the procedure call.\n\no For stored functions and triggers that change the value, the value is\n restored when the function or trigger ends, so following statements\n will not see a changed value.\n\nURL: https://mariadb.com/kb/en/last_insert_id/\n\n','','https://mariadb.com/kb/en/last_insert_id/'),(251,'LAST_DAY',31,'Syntax:\nLAST_DAY(date)\n\nTakes a date or datetime value and returns the corresponding value for\nthe last day of the month. Returns NULL if the argument is invalid.\n\nURL: https://mariadb.com/kb/en/last_day/\n\n','MariaDB> SELECT LAST_DAY(\'2003-02-05\');\n -> \'2003-02-28\'\nMariaDB> SELECT LAST_DAY(\'2004-02-05\');\n -> \'2004-02-29\'\nMariaDB> SELECT LAST_DAY(\'2004-01-01 01:01:01\');\n -> \'2004-01-31\'\nMariaDB> SELECT LAST_DAY(\'2003-03-32\');\n -> NULL\n','https://mariadb.com/kb/en/last_day/'),(252,'MEDIUMINT',22,'MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA medium-sized integer. The signed range is -8388608 to 8388607. The\nunsigned range is 0 to 16777215.\n\nURL: https://mariadb.com/kb/en/mediumint/\n\n','','https://mariadb.com/kb/en/mediumint/'),(253,'FLOOR',4,'Syntax:\nFLOOR(X)\n\nReturns the largest integer value not greater than X.\n\nURL: https://mariadb.com/kb/en/floor/\n\n','MariaDB> SELECT FLOOR(1.23);\n -> 1\nMariaDB> SELECT FLOOR(-1.23);\n -> -2\n','https://mariadb.com/kb/en/floor/'),(254,'RTRIM',37,'Syntax:\nRTRIM(str)\n\nReturns the string str with trailing space characters removed.\n\nURL: https://mariadb.com/kb/en/rtrim/\n\n','MariaDB> SELECT RTRIM(\'barbar \');\n -> \'barbar\'\n','https://mariadb.com/kb/en/rtrim/'),(255,'EXPLAIN',28,'Syntax:\nEXPLAIN [explain_type] SELECT select_options\n\nexplain_type:\n EXTENDED\n | PARTITIONS\n\nOr:\n\nEXPLAIN tbl_name\n\nThe EXPLAIN statement can be used either as a way to obtain information\nabout how MySQL executes a statement, or as a synonym for DESCRIBE:\n\no When you precede a SELECT statement with the keyword EXPLAIN, MySQL\n displays information from the optimizer about the query execution\n plan. That is, MySQL explains how it would process the statement,\n including information about how tables are joined and in which order.\n EXPLAIN EXTENDED can be used to obtain additional information.\n\n For information about using EXPLAIN and EXPLAIN EXTENDED to obtain\n query execution plan information, see\n https://mariadb.com/kb/en/explain/.\n\no EXPLAIN PARTITIONS is useful only when examining queries involving\n partitioned tables. For details, see\n http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.\n\no EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS\n FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see\n [HELP DESCRIBE], and [HELP SHOW COLUMNS].\n\nURL: https://mariadb.com/kb/en/explain/\n\n','','https://mariadb.com/kb/en/explain/'),(256,'DEGREES',4,'Syntax:\nDEGREES(X)\n\nReturns the argument X, converted from radians to degrees.\n\nURL: https://mariadb.com/kb/en/degrees/\n\n','MariaDB> SELECT DEGREES(PI());\n -> 180\nMariaDB> SELECT DEGREES(PI() / 2);\n -> 90\n','https://mariadb.com/kb/en/degrees/'),(257,'VARCHAR',22,'[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA variable-length string. M represents the maximum column length in\ncharacters. The range of M is 0 to 65,535. The effective maximum length\nof a VARCHAR is subject to the maximum row size (65,535 bytes, which is\nshared among all columns) and the character set used. For example, utf8\ncharacters can require up to three bytes per character, so a VARCHAR\ncolumn that uses the utf8 character set can be declared to be a maximum\nof 21,844 characters. See\nhttp://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html.\n\nMySQL stores VARCHAR values as a 1-byte or 2-byte length prefix plus\ndata. The length prefix indicates the number of bytes in the value. A\nVARCHAR column uses one length byte if values require no more than 255\nbytes, two length bytes if values may require more than 255 bytes.\n\n*Note*: MySQL 5.5 follows the standard SQL specification, and does not\nremove trailing spaces from VARCHAR values.\n\nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR is the\nstandard SQL way to define that a VARCHAR column should use some\npredefined character set. MySQL 4.1 and up uses utf8 as this predefined\ncharacter set.\nhttps://mariadb.com/kb/en/varchar/. NVARCHAR\nis shorthand for NATIONAL VARCHAR.\n\nURL: https://mariadb.com/kb/en/varchar/\n\n','','https://mariadb.com/kb/en/varchar/'),(258,'UNHEX',37,'Syntax:\n\nUNHEX(str)\n\nFor a string argument str, UNHEX(str) performs the inverse operation of\nHEX(str). That is, it interprets each pair of characters in the\nargument as a hexadecimal number and converts it to the character\nrepresented by the number. The return value is a binary string.\n\nURL: https://mariadb.com/kb/en/unhex/\n\n','MariaDB> SELECT UNHEX(\'4D7953514C\');\n -> \'MySQL\'\nMariaDB> SELECT 0x4D7953514C;\n -> \'MySQL\'\nMariaDB> SELECT UNHEX(HEX(\'string\'));\n -> \'string\'\nMariaDB> SELECT HEX(UNHEX(\'1267\'));\n -> \'1267\'\n','https://mariadb.com/kb/en/unhex/'),(259,'- UNARY',4,'Syntax:\n-\n\nUnary minus. This operator changes the sign of the operand.\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT - 2;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(260,'STD',16,'Syntax:\nSTD(expr)\n\nReturns the population standard deviation of expr. This is an extension\nto standard SQL. The standard SQL function STDDEV_POP() can be used\ninstead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/std/\n\n','','https://mariadb.com/kb/en/std/'),(261,'COS',4,'Syntax:\nCOS(X)\n\nReturns the cosine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/cos/\n\n','MariaDB> SELECT COS(PI());\n -> -1\n','https://mariadb.com/kb/en/cos/'),(262,'DATE FUNCTION',31,'Syntax:\nDATE(expr)\n\nExtracts the date part of the date or datetime expression expr.\n\nURL: https://mariadb.com/kb/en/date-function/\n\n','MariaDB> SELECT DATE(\'2003-12-31 01:02:03\');\n -> \'2003-12-31\'\n','https://mariadb.com/kb/en/date-function/'),(263,'DROP TRIGGER',39,'Syntax:\nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n\nThis statement drops a trigger. The schema (database) name is optional.\nIf the schema is omitted, the trigger is dropped from the default\nschema. DROP TRIGGER requires the TRIGGER privilege for the table\nassociated with the trigger.\n\nUse IF EXISTS to prevent an error from occurring for a trigger that\ndoes not exist. A NOTE is generated for a nonexistent trigger when\nusing IF EXISTS. See [HELP SHOW WARNINGS].\n\nTriggers for a table are also dropped if you drop the table.\n\nURL: https://mariadb.com/kb/en/drop-trigger/\n\n','','https://mariadb.com/kb/en/drop-trigger/'),(264,'RESET MASTER',8,'Syntax:\nRESET MASTER\n\nDeletes all binary log files listed in the index file, resets the\nbinary log index file to be empty, and creates a new binary log file.\nThis statement is intended to be used only when the master is started\nfor the first time.\n\nURL: https://mariadb.com/kb/en/reset-master/\n\n','','https://mariadb.com/kb/en/reset-master/'),(265,'TAN',4,'Syntax:\nTAN(X)\n\nReturns the tangent of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/tan/\n\n','MariaDB> SELECT TAN(PI());\n -> -1.2246063538224e-16\nMariaDB> SELECT TAN(PI()+1);\n -> 1.5574077246549\n','https://mariadb.com/kb/en/tan/'),(266,'PI',4,'Syntax:\nPI()\n\nReturns the value of π (pi). The default number of decimal places\ndisplayed is seven, but MySQL uses the full double-precision value\ninternally.\n\nURL: https://mariadb.com/kb/en/pi/\n\n','MariaDB> SELECT PI();\n -> 3.141593\nMariaDB> SELECT PI()+0.000000000000000000;\n -> 3.141592653589793116\n','https://mariadb.com/kb/en/pi/'),(267,'WEEKOFYEAR',31,'Syntax:\nWEEKOFYEAR(date)\n\nReturns the calendar week of the date as a number in the range from 1\nto 53. WEEKOFYEAR() is a compatibility function that is equivalent to\nWEEK(date,3).\n\nURL: https://mariadb.com/kb/en/weekofyear/\n\n','MariaDB> SELECT WEEKOFYEAR(\'2008-02-20\');\n -> 8\n','https://mariadb.com/kb/en/weekofyear/'),(268,'/',4,'Syntax:\n/\n\nDivision:\n\nURL: https://mariadb.com/kb/en/division-operator/\n\n','MariaDB> SELECT 3/5;\n -> 0.60\n','https://mariadb.com/kb/en/division-operator/'),(269,'PURGE BINARY LOGS',8,'Syntax:\nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n\nThe binary log is a set of files that contain information about data\nmodifications made by the MySQL server. The log consists of a set of\nbinary log files, plus an index file (see\nhttps://mariadb.com/kb/en/overview-of-the-binary-log/).\n\nThe PURGE BINARY LOGS statement deletes all the binary log files listed\nin the log index file prior to the specified log file name or date.\nBINARY and MASTER are synonyms. Deleted log files also are removed from\nthe list recorded in the index file, so that the given log file becomes\nthe first in the list.\n\nThis statement has no effect if the server was not started with the\n--log-bin option to enable binary logging.\n\nURL: https://mariadb.com/kb/en/sql-commands-purge-logs/\n\n','PURGE BINARY LOGS TO \'mysql-bin.010\';\nPURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\';\n','https://mariadb.com/kb/en/sql-commands-purge-logs/'),(270,'STDDEV_SAMP',16,'Syntax:\nSTDDEV_SAMP(expr)\n\nReturns the sample standard deviation of expr (the square root of\nVAR_SAMP().\n\nSTDDEV_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_samp/\n\n','','https://mariadb.com/kb/en/stddev_samp/'),(271,'SCHEMA',17,'Syntax:\nSCHEMA()\n\nThis function is a synonym for DATABASE().\n\nURL: https://mariadb.com/kb/en/schema/\n\n','','https://mariadb.com/kb/en/schema/'),(272,'MLINEFROMWKB',32,'MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])\n\nConstructs a MULTILINESTRING value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromwkb/\n\n','','https://mariadb.com/kb/en/mlinefromwkb/'),(273,'LOG2',4,'Syntax:\nLOG2(X)\n\nReturns the base-2 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log2/\n\n','MariaDB> SELECT LOG2(65536);\n -> 16\nMariaDB> SELECT LOG2(-100);\n -> NULL\n','https://mariadb.com/kb/en/log2/'),(274,'SUBTIME',31,'Syntax:\nSUBTIME(expr1,expr2)\n\nSUBTIME() returns expr1 - expr2 expressed as a value in the same format\nas expr1. expr1 is a time or datetime expression, and expr2 is a time\nexpression.\n\nURL: https://mariadb.com/kb/en/subtime/\n\n','MariaDB> SELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\');\n -> \'2007-12-30 22:58:58.999997\'\nMariaDB> SELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'-00:59:59.999999\'\n','https://mariadb.com/kb/en/subtime/'),(275,'UNCOMPRESSED_LENGTH',12,'Syntax:\nUNCOMPRESSED_LENGTH(compressed_string)\n\nReturns the length that the compressed string had before being\ncompressed.\n\nURL: https://mariadb.com/kb/en/uncompressed_length/\n\n','MariaDB> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n -> 30\n','https://mariadb.com/kb/en/uncompressed_length/'),(276,'DROP TABLE',39,'Syntax:\nDROP [TEMPORARY] TABLE [IF EXISTS]\n tbl_name [, tbl_name] ...\n [RESTRICT | CASCADE]\n\nDROP TABLE removes one or more tables. You must have the DROP privilege\nfor each table. All table data and the table definition are removed, so\nbe careful with this statement! If any of the tables named in the\nargument list do not exist, MySQL returns an error indicating by name\nwhich nonexisting tables it was unable to drop, but it also drops all\nof the tables in the list that do exist.\n\n*Important*: When a table is dropped, user privileges on the table are\nnot automatically dropped. See [HELP GRANT].\n\nNote that for a partitioned table, DROP TABLE permanently removes the\ntable definition, all of its partitions, and all of the data which was\nstored in those partitions. It also removes the partitioning definition\n(.par) file associated with the dropped table.\n\nUse IF EXISTS to prevent an error from occurring for tables that do not\nexist. A NOTE is generated for each nonexistent table when using IF\nEXISTS. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE are permitted to make porting easier. In MySQL\n5.5, they do nothing.\n\n*Note*: DROP TABLE automatically commits the current active\ntransaction, unless you use the TEMPORARY keyword.\n\nURL: https://mariadb.com/kb/en/drop-table/\n\n','','https://mariadb.com/kb/en/drop-table/'),(277,'POW',4,'Syntax:\nPOW(X,Y)\n\nReturns the value of X raised to the power of Y.\n\nURL: https://mariadb.com/kb/en/pow/\n\n','MariaDB> SELECT POW(2,2);\n -> 4\nMariaDB> SELECT POW(2,-2);\n -> 0.25\n','https://mariadb.com/kb/en/pow/'),(278,'SHOW CREATE TABLE',26,'Syntax:\nSHOW CREATE TABLE tbl_name\n\nShows the CREATE TABLE statement that creates the given table. To use\nthis statement, you must have some privilege for the table. This\nstatement also works with views.\nSHOW CREATE TABLE quotes table and column names according to the value\nof the sql_quote_show_create option. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/show-create-table/\n\n','MariaDB> SHOW CREATE TABLE t\\G\n*************************** 1. row ***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id INT(11) default NULL auto_increment,\n s char(60) default NULL,\n PRIMARY KEY (id)\n) ENGINE=MyISAM\n','https://mariadb.com/kb/en/show-create-table/'),(279,'DUAL',27,'You are permitted to specify DUAL as a dummy table name in situations\nwhere no tables are referenced:\n\nMariaDB> SELECT 1 + 1 FROM DUAL;\n -> 2\n\nDUAL is purely for the convenience of people who require that all\nSELECT statements should have FROM and possibly other clauses. MySQL\nmay ignore the clauses. MySQL does not require FROM DUAL if no tables\nare referenced.\n\nURL: https://mariadb.com/kb/en/dual/\n\n','','https://mariadb.com/kb/en/dual/'),(280,'INSTR',37,'Syntax:\nINSTR(str,substr)\n\nReturns the position of the first occurrence of substring substr in\nstring str. This is the same as the two-argument form of LOCATE(),\nexcept that the order of the arguments is reversed.\n\nURL: https://mariadb.com/kb/en/instr/\n\n','MariaDB> SELECT INSTR(\'foobarbar\', \'bar\');\n -> 4\nMariaDB> SELECT INSTR(\'xbar\', \'foobar\');\n -> 0\n','https://mariadb.com/kb/en/instr/'),(281,'NOW',31,'Syntax:\nNOW()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed in the\ncurrent time zone.\n\nURL: https://mariadb.com/kb/en/now/\n\n','MariaDB> SELECT NOW();\n -> \'2007-12-15 23:50:26\'\nMariaDB> SELECT NOW() + 0;\n -> 20071215235026.000000\n','https://mariadb.com/kb/en/now/'),(282,'SHOW ENGINES',26,'Syntax:\nSHOW [STORAGE] ENGINES\n\nSHOW ENGINES displays status information about the server\'s storage\nengines. This is particularly useful for checking whether a storage\nengine is supported, or to see what the default engine is.\n\nURL: https://mariadb.com/kb/en/show-engines/\n\n','','https://mariadb.com/kb/en/show-engines/'),(283,'>=',18,'Syntax:\n>=\n\nGreater than or equal:\n\nURL: https://mariadb.com/kb/en/greater-than-or-equal/\n\n','MariaDB> SELECT 2 >= 2;\n -> 1\n','https://mariadb.com/kb/en/greater-than-or-equal/'),(284,'EXP',4,'Syntax:\nEXP(X)\n\nReturns the value of e (the base of natural logarithms) raised to the\npower of X. The inverse of this function is LOG() (using a single\nargument only) or LN().\n\nURL: https://mariadb.com/kb/en/exp/\n\n','MariaDB> SELECT EXP(2);\n -> 7.3890560989307\nMariaDB> SELECT EXP(-2);\n -> 0.13533528323661\nMariaDB> SELECT EXP(0);\n -> 1\n','https://mariadb.com/kb/en/exp/'),(285,'LONGBLOB',22,'LONGBLOB\n\nA BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\nbytes. The effective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol and\navailable memory. Each LONGBLOB value is stored using a 4-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longblob/\n\n','','https://mariadb.com/kb/en/longblob/'),(286,'POINTN',13,'PointN(ls,N)\n\nReturns the N-th Point in the Linestring value ls. Points are numbered\nbeginning with 1.\n\nURL: https://mariadb.com/kb/en/pointn/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/pointn/'),(287,'YEAR DATA TYPE',22,'YEAR[(2|4)]\n\nA year in two-digit or four-digit format. The default is four-digit\nformat. YEAR(2) or YEAR(4) differ in display format, but have the same\nrange of values. In four-digit format, values display as 1901 to 2155,\nand 0000. In two-digit format, values display as 70 to 69, representing\nyears from 1970 to 2069. MySQL displays YEAR values in YYYY or\nYYformat, but permits assignment of values to YEAR columns using either\nstrings or numbers.\n\n*Note*: The YEAR(2) data type has certain issues that you should\nconsider before choosing to use it. As of MySQL 5.5.27, YEAR(2) is\ndeprecated. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/migrating-to-year4.html.\n\nFor additional information about YEAR display format and inerpretation\nof input values, see https://mariadb.com/kb/en/year-data-type/.\n\nURL: https://mariadb.com/kb/en/year-data-type/\n\n','','https://mariadb.com/kb/en/year-data-type/'),(288,'SUM',16,'Syntax:\nSUM([DISTINCT] expr)\n\nReturns the sum of expr. If the return set has no rows, SUM() returns\nNULL. The DISTINCT keyword can be used to sum only the distinct values\nof expr.\n\nSUM() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/sum/\n\n','','https://mariadb.com/kb/en/sum/'),(289,'OCT',37,'Syntax:\nOCT(N)\n\nReturns a string representation of the octal value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,8). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/oct/\n\n','MariaDB> SELECT OCT(12);\n -> \'14\'\n','https://mariadb.com/kb/en/oct/'),(290,'SYSDATE',31,'Syntax:\nSYSDATE()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context.\n\nSYSDATE() returns the time at which it executes. This differs from the\nbehavior for NOW(), which returns a constant time that indicates the\ntime at which the statement began to execute. (Within a stored function\nor trigger, NOW() returns the time at which the function or triggering\nstatement began to execute.)\n\nMariaDB> SELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |\n+---------------------+----------+---------------------+\n\nMariaDB> SELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |\n+---------------------+----------+---------------------+\n\nIn addition, the SET TIMESTAMP statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp settings in the\nbinary log have no effect on invocations of SYSDATE().\n\nBecause SYSDATE() can return different values even within the same\nstatement, and is not affected by SET TIMESTAMP, it is nondeterministic\nand therefore unsafe for replication if statement-based binary logging\nis used. If that is a problem, you can use row-based logging.\n\nAlternatively, you can use the --sysdate-is-now option to cause\nSYSDATE() to be an alias for NOW(). This works if the option is used on\nboth the master and the slave.\n\nThe nondeterministic nature of SYSDATE() also means that indexes cannot\nbe used for evaluating expressions that refer to it.\n\nURL: https://mariadb.com/kb/en/sysdate/\n\n','','https://mariadb.com/kb/en/sysdate/'),(291,'UNINSTALL PLUGIN',5,'Syntax:\nUNINSTALL PLUGIN plugin_name\n\nThis statement removes an installed server plugin. It requires the\nDELETE privilege for the mysql.plugin table.\n\nplugin_name must be the name of some plugin that is listed in the\nmysql.plugin table. The server executes the plugin\'s deinitialization\nfunction and removes the row for the plugin from the mysql.plugin\ntable, so that subsequent server restarts will not load and initialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s shared\nlibrary file.\n\nURL: https://mariadb.com/kb/en/uninstall-plugin/\n\n','','https://mariadb.com/kb/en/uninstall-plugin/'),(292,'ASBINARY',32,'AsBinary(g), AsWKB(g)\n\nConverts a value in internal geometry format to its WKB representation\nand returns the binary result.\n\nURL: https://mariadb.com/kb/en/asbinary/\n\n','SELECT AsBinary(g) FROM geom;\n','https://mariadb.com/kb/en/asbinary/'),(293,'REPEAT FUNCTION',37,'Syntax:\nREPEAT(str,count)\n\nReturns a string consisting of the string str repeated count times. If\ncount is less than 1, returns an empty string. Returns NULL if str or\ncount are NULL.\n\nURL: https://mariadb.com/kb/en/repeat-function/\n\n','MariaDB> SELECT REPEAT(\'MySQL\', 3);\n -> \'MySQLMySQLMySQL\'\n','https://mariadb.com/kb/en/repeat-function/'),(294,'SHOW TABLES',26,'Syntax:\nSHOW [FULL] TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLES lists the non-TEMPORARY tables in a given database. You can\nalso get this list using the mysqlshow db_name command. The LIKE\nclause, if present, indicates which table names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\n\nThis statement also lists any views in the database. The FULL modifier\nis supported such that SHOW FULL TABLES displays a second output\ncolumn. Values for the second column are BASE TABLE for a table and\nVIEW for a view.\n\nIf you have no privileges for a base table or view, it does not show up\nin the output from SHOW TABLES or mysqlshow db_name.\n\nURL: https://mariadb.com/kb/en/show-tables/\n\n','','https://mariadb.com/kb/en/show-tables/'),(295,'MAKEDATE',31,'Syntax:\nMAKEDATE(year,dayofyear)\n\nReturns a date, given year and day-of-year values. dayofyear must be\ngreater than 0 or the result is NULL.\n\nURL: https://mariadb.com/kb/en/makedate/\n\n','MariaDB> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n -> \'2011-01-31\', \'2011-02-01\'\nMariaDB> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n -> \'2011-12-31\', \'2014-12-31\'\nMariaDB> SELECT MAKEDATE(2011,0);\n -> NULL\n','https://mariadb.com/kb/en/makedate/'),(296,'BINARY OPERATOR',37,'Syntax:\nBINARY\n\nThe BINARY operator casts the string following it to a binary string.\nThis is an easy way to force a column comparison to be done byte by\nbyte rather than character by character. This causes the comparison to\nbe case sensitive even if the column is not defined as BINARY or BLOB.\nBINARY also causes trailing spaces to be significant.\n\nURL: https://mariadb.com/kb/en/binary-operator/\n\n','MariaDB> SELECT \'a\' = \'A\';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'A\';\n -> 0\nMariaDB> SELECT \'a\' = \'a \';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'a \';\n -> 0\n','https://mariadb.com/kb/en/binary-operator/'),(297,'MBROVERLAPS',6,'MBROverlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 overlap. The term spatially overlaps is\nused if two geometries intersect and their intersection results in a\ngeometry of the same dimension but not equal to either of the given\ngeometries.\n\nURL: https://mariadb.com/kb/en/mbroverlaps/\n\n','','https://mariadb.com/kb/en/mbroverlaps/'),(298,'SOUNDEX',37,'Syntax:\nSOUNDEX(str)\n\nReturns a soundex string from str. Two strings that sound almost the\nsame should have identical soundex strings. A standard soundex string\nis four characters long, but the SOUNDEX() function returns an\narbitrarily long string. You can use SUBSTRING() on the result to get a\nstandard soundex string. All nonalphabetic characters in str are\nignored. All international alphabetic characters outside the A-Z range\nare treated as vowels.\n\n*Important*: When using SOUNDEX(), you should be aware of the following\nlimitations:\n\no This function, as currently implemented, is intended to work well\n with strings that are in the English language only. Strings in other\n languages may not produce reliable results.\n\no This function is not guaranteed to provide consistent results with\n strings that use multi-byte character sets, including utf-8.\n\n We hope to remove these limitations in a future release. See Bug\n #22638 for more information.\n\nURL: https://mariadb.com/kb/en/soundex/\n\n','MariaDB> SELECT SOUNDEX(\'Hello\');\n -> \'H400\'\nMariaDB> SELECT SOUNDEX(\'Quadratically\');\n -> \'Q36324\'\n','https://mariadb.com/kb/en/soundex/'),(299,'MBRTOUCHES',6,'MBRTouches(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially touch if\nthe interiors of the geometries do not intersect, but the boundary of\none of the geometries intersects either the boundary or the interior of\nthe other.\n\nURL: https://mariadb.com/kb/en/mbrtouches/\n\n','','https://mariadb.com/kb/en/mbrtouches/'),(300,'DROP EVENT',39,'Syntax:\nDROP EVENT [IF EXISTS] event_name\n\nThis statement drops the event named event_name. The event immediately\nceases being active, and is deleted completely from the server.\n\nIf the event does not exist, the error ERROR 1517 (HY000): Unknown\nevent \'event_name\' results. You can override this and cause the\nstatement to generate a warning for nonexistent events instead using IF\nEXISTS.\n\nThis statement requires the EVENT privilege for the schema to which the\nevent to be dropped belongs.\n\nURL: https://mariadb.com/kb/en/drop-event/\n\n','','https://mariadb.com/kb/en/drop-event/'),(301,'INSERT SELECT',27,'Syntax:\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n\nWith INSERT ... SELECT, you can quickly insert many rows into a table\nfrom one or many tables. For example:\n\nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n\nURL: https://mariadb.com/kb/en/insert-select/\n\n','','https://mariadb.com/kb/en/insert-select/'),(302,'CREATE PROCEDURE',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n FUNCTION sp_name ([func_parameter[,...]])\n RETURNS type\n [characteristic ...] routine_body\n\nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n\nfunc_parameter:\n param_name type\n\ntype:\n Any valid MySQL data type\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nroutine_body:\n Valid SQL routine statement\n\nThese statements create stored routines. By default, a routine is\nassociated with the default database. To associate the routine\nexplicitly with a given database, specify the name as db_name.sp_name\nwhen you create it.\n\nThe CREATE FUNCTION statement is also used in MySQL to support UDFs\n(user-defined functions). See\nhttps://mariadb.com/kb/en/create-function-udf/. A UDF can\nbe regarded as an external stored function. Stored functions share\ntheir namespace with UDFs. See\nhttp://dev.mysql.com/doc/refman/5.5/en/function-resolution.html, for\nthe rules describing how the server interprets references to different\nkinds of functions.\n\nTo invoke a stored procedure, use the CALL statement (see [HELP CALL]).\nTo invoke a stored function, refer to it in an expression. The function\nreturns a value during expression evaluation.\n\nCREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE\nprivilege. They might also require the SUPER privilege, depending on\nthe DEFINER value, as described later in this section. If binary\nlogging is enabled, CREATE FUNCTION might require the SUPER privilege,\nas described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nBy default, MySQL automatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the routine creator. This behavior can be changed by\ndisabling the automatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nThe DEFINER and SQL SECURITY clauses specify the security context to be\nused when checking access privileges at routine execution time, as\ndescribed later in this section.\n\nIf the routine name is the same as the name of a built-in SQL function,\na syntax error occurs unless you use a space between the name and the\nfollowing parenthesis when defining the routine or invoking it later.\nFor this reason, avoid using the names of existing SQL functions for\nyour own stored routines.\n\nThe IGNORE_SPACE SQL mode applies to built-in functions, not to stored\nroutines. It is always permissible to have spaces after a stored\nroutine name, regardless of whether IGNORE_SPACE is enabled.\n\nThe parameter list enclosed within parentheses must always be present.\nIf there are no parameters, an empty parameter list of () should be\nused. Parameter names are not case sensitive.\n\nEach parameter is an IN parameter by default. To specify otherwise for\na parameter, use the keyword OUT or INOUT before the parameter name.\n\n*Note*: Specifying a parameter as IN, OUT, or INOUT is valid only for a\nPROCEDURE. For a FUNCTION, parameters are always regarded as IN\nparameters.\n\nAn IN parameter passes a value into a procedure. The procedure might\nmodify the value, but the modification is not visible to the caller\nwhen the procedure returns. An OUT parameter passes a value from the\nprocedure back to the caller. Its initial value is NULL within the\nprocedure, and its value is visible to the caller when the procedure\nreturns. An INOUT parameter is initialized by the caller, can be\nmodified by the procedure, and any change made by the procedure is\nvisible to the caller when the procedure returns.\n\nFor each OUT or INOUT parameter, pass a user-defined variable in the\nCALL statement that invokes the procedure so that you can obtain its\nvalue when the procedure returns. If you are calling the procedure from\nwithin another stored procedure or function, you can also pass a\nroutine parameter or local routine variable as an IN or INOUT\nparameter.\n\nThe following example shows a simple stored procedure that uses an OUT\nparameter:\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE simpleproc (OUT param1 INT)\n -> BEGIN\n -> SELECT COUNT(*) INTO param1 FROM t;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter ;\n\nMariaDB> CALL simpleproc(@a);\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @a;\n+------+\n| @a |\n+------+\n| 3 |\n+------+\n1 row in set (0.00 sec)\n\nThe example uses the mysql client delimiter command to change the\nstatement delimiter from ; to // while the procedure is being defined.\nThis enables the ; delimiter used in the procedure body to be passed\nthrough to the server rather than being interpreted by mysql itself.\nSee\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nThe RETURNS clause may be specified only for a FUNCTION, for which it\nis mandatory. It indicates the return type of the function, and the\nfunction body must contain a RETURN value statement. If the RETURN\nstatement returns a value of a different type, the value is coerced to\nthe proper type. For example, if a function specifies an ENUM or SET\nvalue in the RETURNS clause, but the RETURN statement returns an\ninteger, the value returned from the function is the string for the\ncorresponding ENUM member of set of SET members.\n\nThe following example function takes a parameter, performs an operation\nusing an SQL function, and returns the result. In this case, it is\nunnecessary to use delimiter because the function definition contains\nno internal ; statement delimiters:\n\nMariaDB> CREATE FUNCTION hello (s CHAR(20))\nMariaDB> RETURNS CHAR(50) DETERMINISTIC\n -> RETURN CONCAT(\'Hello, \',s,\'!\');\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n1 row in set (0.00 sec)\n\nParameter types and function return types can be declared to use any\nvalid data type, except that the COLLATE attribute cannot be used prior\nto MySQL 5.5.3. As of 5.5.3, COLLATE can be used if preceded by the\nCHARACTER SET attribute.\n\nThe routine_body consists of a valid SQL routine statement. This can be\na simple statement such as SELECT or INSERT, or a compound statement\nwritten using BEGIN and END. Compound statements can contain\ndeclarations, loops, and other control structure statements. The syntax\nfor these statements is described in\nhttps://mariadb.com/kb/programmatic-and-compound-statements.\n\nMySQL permits routines to contain DDL statements, such as CREATE and\nDROP. MySQL also permits stored procedures (but not stored functions)\nto contain SQL transaction statements such as COMMIT. Stored functions\nmay not contain statements that perform explicit or implicit commit or\nrollback. Support for these statements is not required by the SQL\nstandard, which states that each DBMS vendor may decide whether to\npermit them.\n\nStatements that return a result set can be used within a stored\nprocedure but not within a stored function. This prohibition includes\nSELECT statements that do not have an INTO var_list clause and other\nstatements such as SHOW, EXPLAIN, and CHECK TABLE. For statements that\ncan be determined at function definition time to return a result set, a\nNot allowed to return a result set from a function error occurs\n(ER_SP_NO_RETSET). For statements that can be determined only at\nruntime to return a result set, a PROCEDURE %s can\'t return a result\nset in the given context error occurs (ER_SP_BADSELECT).\n\nUSE statements within stored routines are not permitted. When a routine\nis invoked, an implicit USE db_name is performed (and undone when the\nroutine terminates). The causes the routine to have the given default\ndatabase while it executes. References to objects in databases other\nthan the routine default database should be qualified with the\nappropriate database name.\n\nFor additional information about statements that are not permitted in\nstored routines, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/\n.\n\nFor information about invoking stored procedures from within programs\nwritten in a language that has a MySQL interface, see [HELP CALL].\n\nMySQL stores the sql_mode system variable setting that is in effect at\nthe time a routine is created, and always executes the routine with\nthis setting in force, regardless of the server SQL mode in effect when\nthe routine is invoked.\n\nThe switch from the SQL mode of the invoker to that of the routine\noccurs after evaluation of arguments and assignment of the resulting\nvalues to routine parameters. If you define a routine in strict SQL\nmode but invoke it in nonstrict mode, assignment of arguments to\nroutine parameters does not take place in strict mode. If you require\nthat expressions passed to a routine be assigned in strict SQL mode,\nyou should invoke the routine with strict mode in effect.\n\nURL: https://mariadb.com/kb/en/create-procedure/\n\n','','https://mariadb.com/kb/en/create-procedure/'),(303,'VARBINARY',22,'VARBINARY(M)\n\nThe VARBINARY type is similar to the VARCHAR type, but stores binary\nbyte strings rather than nonbinary character strings. M represents the\nmaximum column length in bytes.\n\nURL: https://mariadb.com/kb/en/varbinary/\n\n','','https://mariadb.com/kb/en/varbinary/'),(304,'LOAD INDEX',26,'Syntax:\nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n\ntbl_index_list:\n tbl_name\n [PARTITION (partition_list | ALL)]\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe LOAD INDEX INTO CACHE statement preloads a table index into the key\ncache to which it has been assigned by an explicit CACHE INDEX\nstatement, or into the default key cache otherwise.\n\nLOAD INDEX INTO CACHE is used only for MyISAM tables. In MySQL 5.5, it\nis also supported for partitioned MyISAM tables; in addition, indexes\non partitioned tables can be preloaded for one, several, or all\npartitions.\n\nThe IGNORE LEAVES modifier causes only blocks for the nonleaf nodes of\nthe index to be preloaded.\n\nIGNORE LEAVES is also supported for partitioned MyISAM tables.\n\nURL: https://mariadb.com/kb/en/load-index/\n\n','','https://mariadb.com/kb/en/load-index/'),(305,'UNION',27,'Syntax:\nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n\nUNION is used to combine the result from multiple SELECT statements\ninto a single result set.\n\nThe column names from the first SELECT statement are used as the column\nnames for the results returned. Selected columns listed in\ncorresponding positions of each SELECT statement should have the same\ndata type. (For example, the first column selected by the first\nstatement should have the same type as the first column selected by the\nother statements.)\n\nURL: https://mariadb.com/kb/en/union/\n\n','','https://mariadb.com/kb/en/union/'),(306,'TO_DAYS',31,'Syntax:\nTO_DAYS(date)\n\nGiven a date date, returns a day number (the number of days since year\n0).\n\nURL: https://mariadb.com/kb/en/to_days/\n\n','MariaDB> SELECT TO_DAYS(950501);\n -> 728779\nMariaDB> SELECT TO_DAYS(\'2007-10-07\');\n -> 733321\n','https://mariadb.com/kb/en/to_days/'),(307,'NOT REGEXP',37,'Syntax:\nexpr NOT REGEXP pat, expr NOT RLIKE pat\n\nThis is the same as NOT (expr REGEXP pat).\n\nURL: https://mariadb.com/kb/en/not-regexp/\n\n','','https://mariadb.com/kb/en/not-regexp/'),(308,'SHOW INDEX',26,'Syntax:\nSHOW {INDEX | INDEXES | KEYS}\n {FROM | IN} tbl_name\n [{FROM | IN} db_name]\n [WHERE expr]\n\nSHOW INDEX returns table index information. The format resembles that\nof the SQLStatistics call in ODBC. This statement requires some\nprivilege for any column in the table.\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. These two statements are equivalent:\n\nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n\nThe WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou can also list a table\'s indexes with the mysqlshow -k db_name\ntbl_name command.\n\nURL: https://mariadb.com/kb/en/show-index/\n\n','','https://mariadb.com/kb/en/show-index/'),(309,'SHOW CREATE DATABASE',26,'Syntax:\nSHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n\nShows the CREATE DATABASE statement that creates the given database. If\nthe SHOW statement includes an IF NOT EXISTS clause, the output too\nincludes such a clause. SHOW CREATE SCHEMA is a synonym for SHOW CREATE\nDATABASE.\n\nURL: https://mariadb.com/kb/en/show-create-database/\n\n','MariaDB> SHOW CREATE DATABASE test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n\nMariaDB> SHOW CREATE SCHEMA test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n','https://mariadb.com/kb/en/show-create-database/'),(310,'LEAVE',23,'Syntax:\nLEAVE label\n\nThis statement is used to exit the flow control construct that has the\ngiven label. If the label is for the outermost stored program block,\nLEAVE exits the program.\n\nLEAVE can be used within BEGIN ... END or loop constructs (LOOP,\nREPEAT, WHILE).\n\nURL: https://mariadb.com/kb/en/leave/\n\n','','https://mariadb.com/kb/en/leave/'),(311,'NOT IN',18,'Syntax:\nexpr NOT IN (value,...)\n\nThis is the same as NOT (expr IN (value,...)).\n\nURL: https://mariadb.com/kb/en/not-in/\n\n','','https://mariadb.com/kb/en/not-in/'),(312,'!',15,'Syntax:\nNOT, !\n\nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is\nnonzero, and NOT NULL returns NULL.\n\nURL: https://mariadb.com/kb/en/not/\n\n','MariaDB> SELECT NOT 10;\n -> 0\nMariaDB> SELECT NOT 0;\n -> 1\nMariaDB> SELECT NOT NULL;\n -> NULL\nMariaDB> SELECT ! (1+1);\n -> 0\nMariaDB> SELECT ! 1+1;\n -> 1\n','https://mariadb.com/kb/en/not/'),(313,'DECLARE HANDLER',23,'Syntax:\nDECLARE handler_action HANDLER\n FOR condition_value [, condition_value] ...\n statement\n\nhandler_action:\n CONTINUE\n | EXIT\n | UNDO\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n\nThe DECLARE ... HANDLER statement specifies a handler that deals with\none or more conditions. If one of these conditions occurs, the\nspecified statement executes. statement can be a simple statement such\nas SET var_name = value, or a compound statement written using BEGIN\nand END (see [HELP BEGIN END]).\n\nHandler declarations must appear after variable or condition\ndeclarations.\n\nThe handler_action value indicates what action the handler takes after\nexecution of the handler statement:\n\no CONTINUE: Execution of the current program continues.\n\no EXIT: Execution terminates for the BEGIN ... END compound statement\n in which the handler is declared. This is true even if the condition\n occurs in an inner block.\n\no UNDO: Not supported.\n\nThe condition_value for DECLARE ... HANDLER indicates the specific\ncondition or class of conditions that activates the handler:\n\no A MySQL error code (a number) or an SQLSTATE value (a 5-character\n string literal). You should not use MySQL error code 0 or SQLSTATE\n values that begin with \'00\', because those indicate success rather\n than an error condition. For a list of MySQL error codes and SQLSTATE\n values, see\n https://mariadb.com/kb/en/mariadb-error-codes/.\n\no A condition name previously specified with DECLARE ... CONDITION. A\n condition name can be associated with a MySQL error code or SQLSTATE\n value. See [HELP DECLARE CONDITION].\n\no SQLWARNING is shorthand for the class of SQLSTATE values that begin\n with \'01\'.\n\no NOT FOUND is shorthand for the class of SQLSTATE values that begin\n with \'02\'. This is relevant within the context of cursors and is used\n to control what happens when a cursor reaches the end of a data set.\n If no more rows are available, a No Data condition occurs with\n SQLSTATE value \'02000\'. To detect this condition, you can set up a\n handler for it (or for a NOT FOUND condition). For an example, see\n https://mariadb.com/kb/en/cursor-overview/. This condition\n also occurs for SELECT ... INTO var_list statements that retrieve no\n rows.\n\no SQLEXCEPTION is shorthand for the class of SQLSTATE values that do\n not begin with \'00\', \'01\', or \'02\'.\n\nIf a condition occurs for which no handler has been declared, the\naction taken depends on the condition class:\n\no For SQLEXCEPTION conditions, the stored program terminates at the\n statement that raised the condition, as if there were an EXIT\n handler. If the program was called by another stored program, the\n calling program handles the condition using the handler selection\n rules applied to its own handlers.\n\no For SQLWARNING conditions, the program continues executing, as if\n there were a CONTINUE handler.\n\no For NOT FOUND conditions, if the condition was raised normally, the\n action is CONTINUE. If it was raised by SIGNAL or RESIGNAL, the\n action is EXIT.\n\nURL: https://mariadb.com/kb/en/declare-handler/\n\n','MariaDB> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE handlerdemo ()\n -> BEGIN\n -> DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 = 1;\n -> SET @x = 1;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 2;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 3;\n -> END;\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL handlerdemo()//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n +------+\n | @x |\n +------+\n | 3 |\n +------+\n 1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/declare-handler/'),(314,'DOUBLE',22,'DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA normal-size (double-precision) floating-point number. Permissible\nvalues are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and\n2.2250738585072014E-308 to 1.7976931348623157E+308. These are the\ntheoretical limits, based on the IEEE standard. The actual range might\nbe slightly smaller depending on your hardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A double-precision floating-point\nnumber is accurate to approximately 15 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nURL: https://mariadb.com/kb/en/double/\n\n','','https://mariadb.com/kb/en/double/'),(315,'TIME',22,'TIME\n\nA time. The range is \'-838:59:59\' to \'838:59:59\'. MySQL displays TIME\nvalues in \'HH:MM:SS\' format, but permits assignment of values to TIME\ncolumns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/time/\n\n','','https://mariadb.com/kb/en/time/'),(316,'&&',15,'Syntax:\nAND, &&\n\nLogical AND. Evaluates to 1 if all operands are nonzero and not NULL,\nto 0 if one or more operands are 0, otherwise NULL is returned.\n\nURL: https://mariadb.com/kb/en/and/\n\n','MariaDB> SELECT 1 && 1;\n -> 1\nMariaDB> SELECT 1 && 0;\n -> 0\nMariaDB> SELECT 1 && NULL;\n -> NULL\nMariaDB> SELECT 0 && NULL;\n -> 0\nMariaDB> SELECT NULL && 0;\n -> 0\n','https://mariadb.com/kb/en/and/'),(317,'X',11,'X(p)\n\nReturns the X-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/x/\n\n','MariaDB> SELECT X(POINT(56.7, 53.34));\n+-----------------------+\n| X(POINT(56.7, 53.34)) |\n+-----------------------+\n| 56.7 |\n+-----------------------+\n','https://mariadb.com/kb/en/x/'),(318,'SYSTEM_USER',17,'Syntax:\nSYSTEM_USER()\n\nSYSTEM_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/system_user/\n\n','','https://mariadb.com/kb/en/system_user/'),(319,'FOUND_ROWS',17,'Syntax:\nFOUND_ROWS()\n\nA SELECT statement may include a LIMIT clause to restrict the number of\nrows the server returns to the client. In some cases, it is desirable\nto know how many rows the statement would have returned without the\nLIMIT, but without running the statement again. To obtain this row\ncount, include a SQL_CALC_FOUND_ROWS option in the SELECT statement,\nand then invoke FOUND_ROWS() afterward:\n\nURL: https://mariadb.com/kb/en/found_rows/\n\n','MariaDB> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name\n -> WHERE id > 100 LIMIT 10;\nMariaDB> SELECT FOUND_ROWS();\n','https://mariadb.com/kb/en/found_rows/'),(320,'CROSSES',30,'Crosses(g1,g2)\n\nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon\nor a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise,\nreturns 0.\n\nThe term spatially crosses denotes a spatial relation between two given\ngeometries that has the following properties:\n\no The two geometries intersect\n\no Their intersection results in a geometry that has a dimension that is\n one less than the maximum dimension of the two given geometries\n\no Their intersection is not equal to either of the two given geometries\n\nURL: https://mariadb.com/kb/en/crosses/\n\n','','https://mariadb.com/kb/en/crosses/'),(321,'TRUNCATE TABLE',39,'Syntax:\nTRUNCATE [TABLE] tbl_name\n\nTRUNCATE TABLE empties a table completely. It requires the DROP\nprivilege.\n\nLogically, TRUNCATE TABLE is similar to a DELETE statement that deletes\nall rows, or a sequence of DROP TABLE and CREATE TABLE statements. To\nachieve high performance, it bypasses the DML method of deleting data.\nThus, it cannot be rolled back, it does not cause ON DELETE triggers to\nfire, and it cannot be performed for InnoDB tables with parent-child\nforeign key relationships.\n\nAlthough TRUNCATE TABLE is similar to DELETE, it is classified as a DDL\nstatement rather than a DML statement. It differs from DELETE in the\nfollowing ways in MySQL 5.5:\n\no Truncate operations drop and re-create the table, which is much\n faster than deleting rows one by one, particularly for large tables.\n\no Truncate operations cause an implicit commit, and so cannot be rolled\n back.\n\no Truncation operations cannot be performed if the session holds an\n active table lock.\n\no TRUNCATE TABLE fails for an InnoDB table if there are any FOREIGN KEY\n constraints from other tables that reference the table. Foreign key\n constraints between columns of the same table are permitted.\n\no Truncation operations do not return a meaningful value for the number\n of deleted rows. The usual result is \"0 rows affected,\" which should\n be interpreted as \"no information.\"\n\no As long as the table format file tbl_name.frm is valid, the table can\n be re-created as an empty table with TRUNCATE TABLE, even if the data\n or index files have become corrupted.\n\no Any AUTO_INCREMENT value is reset to its start value. This is true\n even for MyISAM and InnoDB, which normally do not reuse sequence\n values.\n\no When used with partitioned tables, TRUNCATE TABLE preserves the\n partitioning; that is, the data and index files are dropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\n\no The TRUNCATE TABLE statement does not invoke ON DELETE triggers.\n\nURL: https://mariadb.com/kb/en/truncate-table/\n\n','','https://mariadb.com/kb/en/truncate-table/'),(322,'BIT_XOR',16,'Syntax:\nBIT_XOR(expr)\n\nReturns the bitwise XOR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_xor/\n\n','','https://mariadb.com/kb/en/bit_xor/'),(323,'CURRENT_DATE',31,'Syntax:\nCURRENT_DATE, CURRENT_DATE()\n\nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n\nURL: https://mariadb.com/kb/en/current_date/\n\n','','https://mariadb.com/kb/en/current_date/'),(324,'START SLAVE',8,'Syntax:\nSTART SLAVE [thread_types]\n\nSTART SLAVE [SQL_THREAD] UNTIL\n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\n\nSTART SLAVE [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nSTART SLAVE with no thread_type options starts both of the slave\nthreads. The I/O thread reads events from the master server and stores\nthem in the relay log. The SQL thread reads events from the relay log\nand executes them. START SLAVE requires the SUPER privilege.\n\nIf START SLAVE succeeds in starting the slave threads, it returns\nwithout any error. However, even in that case, it might be that the\nslave threads start and then later stop (for example, because they do\nnot manage to connect to the master or read its binary log, or some\nother problem). START SLAVE does not warn you about this. You must\ncheck the slave\'s error log for error messages generated by the slave\nthreads, or check that they are running satisfactorily with SHOW SLAVE\nSTATUS.\n\nURL: https://mariadb.com/kb/en/start-slave/\n\n','','https://mariadb.com/kb/en/start-slave/'),(325,'AREA',2,'Area(poly)\n\nReturns as a double-precision number the area of the Polygon value\npoly, as measured in its spatial reference system.\n\nURL: https://mariadb.com/kb/en/area/\n\n','MariaDB> SET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))\';\nMariaDB> SELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n','https://mariadb.com/kb/en/area/'),(326,'FLUSH',26,'Syntax:\nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n\nThe FLUSH statement has several variant forms that clear or reload\nvarious internal caches, flush tables, or acquire locks. To execute\nFLUSH, you must have the RELOAD privilege. Specific flush options might\nrequire additional privileges, as described later.\n\nBy default, the server writes FLUSH statements to the binary log so\nthat they replicate to replication slaves. To suppress logging, use the\noptional NO_WRITE_TO_BINLOG keyword or its alias LOCAL.\n\n*Note*: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH\nREAD LOCK (with or without a table list) are not written to the binary\nlog in any case because they would cause problems if replicated to a\nslave.\n\nThe FLUSH statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nThe RESET statement is similar to FLUSH. See [HELP RESET], for\ninformation about using the RESET statement with replication.\n\nURL: https://mariadb.com/kb/en/flush/\n\n','','https://mariadb.com/kb/en/flush/'),(327,'BEGIN END',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\nBEGIN ... END syntax is used for writing compound statements, which can\nappear within stored programs (stored procedures and functions,\ntriggers, and events). A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords. statement_list\nrepresents a list of one or more statements, each terminated by a\nsemicolon (;) statement delimiter. The statement_list itself is\noptional, so the empty compound statement (BEGIN END) is legal.\n\nBEGIN ... END blocks can be nested.\n\nUse of multiple statements requires that a client is able to send\nstatement strings containing the ; statement delimiter. In the mysql\ncommand-line client, this is handled with the delimiter command.\nChanging the ; end-of-statement delimiter (for example, to //) permit ;\nto be used in a program body. For an example, see\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nA BEGIN ... END block can be labeled. See [HELP labels].\n\nURL: https://mariadb.com/kb/en/begin-end/\n\n','','https://mariadb.com/kb/en/begin-end/'),(328,'SHOW PROCEDURE STATUS',26,'Syntax:\nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is a MySQL extension. It returns characteristics of a\nstored procedure, such as the database, name, type, creator, creation\nand modification dates, and character set information. A similar\nstatement, SHOW FUNCTION STATUS, displays information about stored\nfunctions (see [HELP SHOW FUNCTION STATUS]).\n\nThe LIKE clause, if present, indicates which procedure or function\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-procedure-status/\n\n','MariaDB> SHOW PROCEDURE STATUS LIKE \'sp1\'\\G\n*************************** 1. row ***************************\n Db: test\n Name: sp1\n Type: PROCEDURE\n Definer: testuser@localhost\n Modified: 2004-08-03 15:29:37\n Created: 2004-08-03 15:29:37\n Security_type: DEFINER\n Comment:\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-procedure-status/'),(329,'DESCRIBE',28,'Syntax:\n{DESCRIBE | DESC} tbl_name [col_name | wild]\n\nDESCRIBE provides information about the columns in a table. It is a\nshortcut for SHOW COLUMNS FROM. These statements also display\ninformation for views. (See [HELP SHOW COLUMNS].)\n\ncol_name can be a column name, or a string containing the SQL \"%\" and\n\"_\" wildcard characters to obtain output only for the columns with\nnames matching the string. There is no need to enclose the string\nwithin quotation marks unless it contains spaces or other special\ncharacters.\n\nMariaDB> DESCRIBE City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nThe description for SHOW COLUMNS provides more information about the\noutput columns (see [HELP SHOW COLUMNS]).\n\nURL: https://mariadb.com/kb/en/describe/\n\n','','https://mariadb.com/kb/en/describe/'),(330,'SHOW WARNINGS',26,'Syntax:\nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW COUNT(*) WARNINGS\n\nSHOW WARNINGS shows information about the conditions (errors, warnings,\nand notes) that resulted from the last statement in the current session\nthat generated messages. It shows nothing if the last statement used a\ntable and generated no messages. (That is, a statement that uses a\ntable but generates no messages clears the message list.) Statements\nthat do not use tables and do not generate messages have no effect on\nthe message list.\n\nWarnings are generated for DML statements such as INSERT, UPDATE, and\nLOAD DATA INFILE as well as DDL statements such as CREATE TABLE and\nALTER TABLE.\n\nSHOW WARNINGS is also used following EXPLAIN EXTENDED, to display the\nextra information generated by EXPLAIN when the EXTENDED keyword is\nused. See https://mariadb.com/kb/en/explain#explain-extended.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nA related statement, SHOW ERRORS, shows only the error conditions (it\nexcludes warnings and notes). See [HELP SHOW ERRORS].\n\nThe SHOW COUNT(*) WARNINGS statement displays the total number of\nerrors, warnings, and notes. You can also retrieve this number from the\nwarning_count system variable:\n\nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n\nURL: https://mariadb.com/kb/en/show-warnings/\n\n','','https://mariadb.com/kb/en/show-warnings/'),(331,'DROP USER',10,'Syntax:\nDROP USER user [, user] ...\n\nThe DROP USER statement removes one or more MySQL accounts and their\nprivileges. It removes privilege rows for the account from all grant\ntables. To use this statement, you must have the global CREATE USER\nprivilege or the DELETE privilege for the mysql database. Each account\nname uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nDROP USER \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nURL: https://mariadb.com/kb/en/drop-user/\n\n','','https://mariadb.com/kb/en/drop-user/'),(332,'STDDEV_POP',16,'Syntax:\nSTDDEV_POP(expr)\n\nReturns the population standard deviation of expr (the square root of\nVAR_POP()). You can also use STD() or STDDEV(), which are equivalent\nbut not standard SQL.\n\nSTDDEV_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_pop/\n\n','','https://mariadb.com/kb/en/stddev_pop/'),(333,'SHOW CHARACTER SET',26,'Syntax:\nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n\nThe SHOW CHARACTER SET statement shows all available character sets.\nThe LIKE clause, if present, indicates which character set names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n\nURL: https://mariadb.com/kb/en/show-character-set/\n\n','','https://mariadb.com/kb/en/show-character-set/'),(334,'SUBSTRING',37,'Syntax:\nSUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n\nThe forms without a len argument return a substring from string str\nstarting at position pos. The forms with a len argument return a\nsubstring len characters long from string str, starting at position\npos. The forms that use FROM are standard SQL syntax. It is also\npossible to use a negative value for pos. In this case, the beginning\nof the substring is pos characters from the end of the string, rather\nthan the beginning. A negative value may be used for pos in any of the\nforms of this function.\n\nFor all forms of SUBSTRING(), the position of the first character in\nthe string from which the substring is to be extracted is reckoned as\n1.\n\nURL: https://mariadb.com/kb/en/substring/\n\n','MariaDB> SELECT SUBSTRING(\'Quadratically\',5);\n -> \'ratically\'\nMariaDB> SELECT SUBSTRING(\'foobarbar\' FROM 4);\n -> \'barbar\'\nMariaDB> SELECT SUBSTRING(\'Quadratically\',5,6);\n -> \'ratica\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -3);\n -> \'ila\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -5, 3);\n -> \'aki\'\nMariaDB> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);\n -> \'ki\'\n','https://mariadb.com/kb/en/substring/'),(335,'ISEMPTY',36,'IsEmpty(g)\n\nReturns 1 if the geometry value g is the empty geometry, 0 if it is not\nempty, and -1 if the argument is NULL. If the geometry is empty, it\nrepresents the empty point set.\n\nURL: https://mariadb.com/kb/en/isempty/\n\n','','https://mariadb.com/kb/en/isempty/'),(336,'SHOW FUNCTION STATUS',26,'Syntax:\nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is similar to SHOW PROCEDURE STATUS but for stored\nfunctions. See [HELP SHOW PROCEDURE STATUS].\n\nURL: https://mariadb.com/kb/en/show-function-status/\n\n','','https://mariadb.com/kb/en/show-function-status/'),(337,'LTRIM',37,'Syntax:\nLTRIM(str)\n\nReturns the string str with leading space characters removed.\n\nURL: https://mariadb.com/kb/en/ltrim/\n\n','MariaDB> SELECT LTRIM(\' barbar\');\n -> \'barbar\'\n','https://mariadb.com/kb/en/ltrim/'),(338,'INTERSECTS',30,'Intersects(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially intersects g2.\n\nURL: https://mariadb.com/kb/en/intersects/\n\n','','https://mariadb.com/kb/en/intersects/'),(339,'CALL',27,'Syntax:\nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n\nThe CALL statement invokes a stored procedure that was defined\npreviously with CREATE PROCEDURE.\n\nStored procedures that take no arguments can be invoked without\nparentheses. That is, CALL p() and CALL p are equivalent.\n\nCALL can pass back values to its caller using parameters that are\ndeclared as OUT or INOUT parameters. When the procedure returns, a\nclient program can also obtain the number of rows affected for the\nfinal statement executed within the routine: At the SQL level, call the\nROW_COUNT() function; from the C API, call the mysql_affected_rows()\nfunction.\n\nURL: https://mariadb.com/kb/en/call/\n\n','','https://mariadb.com/kb/en/call/'),(340,'MBRDISJOINT',6,'MBRDisjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are disjoint (do not intersect).\n\nURL: https://mariadb.com/kb/en/mbrdisjoint/\n\n','','https://mariadb.com/kb/en/mbrdisjoint/'),(341,'VALUES',14,'Syntax:\nVALUES(col_name)\n\nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the\nVALUES(col_name) function in the UPDATE clause to refer to column\nvalues from the INSERT portion of the statement. In other words,\nVALUES(col_name) in the UPDATE clause refers to the value of col_name\nthat would be inserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts. The VALUES()\nfunction is meaningful only in the ON DUPLICATE KEY UPDATE clause of\nINSERT statements and returns NULL otherwise. See\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nURL: https://mariadb.com/kb/en/values/\n\n','MariaDB> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n','https://mariadb.com/kb/en/values/'),(342,'SUBSTRING_INDEX',37,'Syntax:\nSUBSTRING_INDEX(str,delim,count)\n\nReturns the substring from string str before count occurrences of the\ndelimiter delim. If count is positive, everything to the left of the\nfinal delimiter (counting from the left) is returned. If count is\nnegative, everything to the right of the final delimiter (counting from\nthe right) is returned. SUBSTRING_INDEX() performs a case-sensitive\nmatch when searching for delim.\n\nURL: https://mariadb.com/kb/en/substring_index/\n\n','MariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2);\n -> \'www.mariadb\'\nMariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2);\n -> \'mariadb.org\'\n','https://mariadb.com/kb/en/substring_index/'),(343,'ENCODE',12,'Syntax:\nENCODE(str,pass_str)\n\nEncrypt str using pass_str as the password. To decrypt the result, use\nDECODE().\n\nThe result is a binary string of the same length as str.\n\nThe strength of the encryption is based on how good the random\ngenerator is. It should suffice for short strings.\n\nURL: https://mariadb.com/kb/en/encode/\n\n','','https://mariadb.com/kb/en/encode/'),(344,'LOOP',23,'Syntax:\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\nLOOP implements a simple loop construct, enabling repeated execution of\nthe statement list, which consists of one or more statements, each\nterminated by a semicolon (;) statement delimiter. The statements\nwithin the loop are repeated until the loop is terminated. Usually,\nthis is accomplished with a LEAVE statement. Within a stored function,\nRETURN can also be used, which exits the function entirely.\n\nNeglecting to include a loop-termination statement results in an\ninfinite loop.\n\nA LOOP statement can be labeled. For the rules regarding label use, see\n[HELP labels].\n\nURL: https://mariadb.com/kb/en/loop/\n\n','CREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN\n ITERATE label1;\n END IF;\n LEAVE label1;\n END LOOP label1;\n SET @x = p1;\nEND;\n','https://mariadb.com/kb/en/loop/'),(345,'TRUNCATE',4,'Syntax:\nTRUNCATE(X,D)\n\nReturns the number X, truncated to D decimal places. If D is 0, the\nresult has no decimal point or fractional part. D can be negative to\ncause D digits left of the decimal point of the value X to become zero.\n\nURL: https://mariadb.com/kb/en/truncate/\n\n','MariaDB> SELECT TRUNCATE(1.223,1);\n -> 1.2\nMariaDB> SELECT TRUNCATE(1.999,1);\n -> 1.9\nMariaDB> SELECT TRUNCATE(1.999,0);\n -> 1\nMariaDB> SELECT TRUNCATE(-1.999,1);\n -> -1.9\nMariaDB> SELECT TRUNCATE(122,-2);\n -> 100\nMariaDB> SELECT TRUNCATE(10.28*100,0);\n -> 1028\n','https://mariadb.com/kb/en/truncate/'),(346,'TIMESTAMPADD',31,'Syntax:\nTIMESTAMPADD(unit,interval,datetime_expr)\n\nAdds the integer expression interval to the date or datetime expression\ndatetime_expr. The unit for interval is given by the unit argument,\nwhich should be one of the following values: MICROSECOND\n(microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or\nYEAR.\n\nIt is possible to use FRAC_SECOND in place of MICROSECOND, but\nFRAC_SECOND is deprecated. FRAC_SECOND was removed in MySQL 5.5.3.\n\nThe unit value may be specified using one of keywords as shown, or with\na prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY both are legal.\n\nURL: https://mariadb.com/kb/en/timestampadd/\n\n','MariaDB> SELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n -> \'2003-01-02 00:01:00\'\nMariaDB> SELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n -> \'2003-01-09\'\n','https://mariadb.com/kb/en/timestampadd/'),(347,'SHOW',26,'SHOW has many forms that provide information about databases, tables,\ncolumns, or status information about the server. This section describes\nthose following:\n\nSHOW AUTHORS\nSHOW {BINARY | MASTER} LOGS\nSHOW BINLOG EVENTS [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE FUNCTION func_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW MASTER STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW SLAVE HOSTS\nSHOW SLAVE STATUS\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW [FULL] TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n\nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n\nIf the syntax for a given SHOW statement includes a LIKE \'pattern\'\npart, \'pattern\' is a string that can contain the SQL \"%\" and \"_\"\nwildcard characters. The pattern is useful for restricting statement\noutput to matching values.\n\nSeveral SHOW statements also accept a WHERE clause that provides more\nflexibility in specifying which rows to display. See\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show/\n\n','','https://mariadb.com/kb/en/show/'),(348,'GREATEST',18,'Syntax:\nGREATEST(value1,value2,...)\n\nWith two or more arguments, returns the largest (maximum-valued)\nargument. The arguments are compared using the same rules as for\nLEAST().\n\nURL: https://mariadb.com/kb/en/greatest/\n\n','MariaDB> SELECT GREATEST(2,0);\n -> 2\nMariaDB> SELECT GREATEST(34.0,3.0,5.0,767.0);\n -> 767.0\nMariaDB> SELECT GREATEST(\'B\',\'A\',\'C\');\n -> \'C\'\n','https://mariadb.com/kb/en/greatest/'),(349,'SHOW VARIABLES',26,'Syntax:\nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW VARIABLES shows the values of MySQL system variables. This\ninformation also can be obtained using the mysqladmin variables\ncommand. The LIKE clause, if present, indicates which variable names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. This\nstatement does not require any privilege. It requires only the ability\nto connect to the server.\n\nWith the GLOBAL modifier, SHOW VARIABLES displays the values that are\nused for new connections to MySQL. As of MySQL 5.5.3, if a variable has\nno global value, no value is displayed. Before 5.5.3, the session value\nis displayed. With SESSION, SHOW VARIABLES displays the values that are\nin effect for the current connection. If no modifier is present, the\ndefault is SESSION. LOCAL is a synonym for SESSION.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern. To obtain the row for a\nspecific variable, use a LIKE clause as shown:\n\nSHOW VARIABLES LIKE \'max_join_size\';\nSHOW SESSION VARIABLES LIKE \'max_join_size\';\n\nTo get a list of variables whose name match a pattern, use the \"%\"\nwildcard character in a LIKE clause:\n\nSHOW VARIABLES LIKE \'%size%\';\nSHOW GLOBAL VARIABLES LIKE \'%size%\';\n\nWildcard characters can be used in any position within the pattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard that matches\nany single character, you should escape it as \"\\_\" to match it\nliterally. In practice, this is rarely necessary.\n\nURL: https://mariadb.com/kb/en/show-variables/\n\n','','https://mariadb.com/kb/en/show-variables/'),(350,'BINLOG',26,'Syntax:\nBINLOG \'str\'\n\nBINLOG is an internal-use statement. It is generated by the mysqlbinlog\nprogram as the printable representation of certain events in binary log\nfiles. (See https://mariadb.com/kb/en/mysqlbinlog/.)\nThe \'str\' value is a base 64-encoded string the that server decodes to\ndetermine the data change indicated by the corresponding event. This\nstatement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/binlog/\n\n','','https://mariadb.com/kb/en/binlog/'),(351,'BIT_AND',16,'Syntax:\nBIT_AND(expr)\n\nReturns the bitwise AND of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_and/\n\n','','https://mariadb.com/kb/en/bit_and/'),(352,'SECOND',31,'Syntax:\nSECOND(time)\n\nReturns the second for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/second/\n\n','MariaDB> SELECT SECOND(\'10:05:03\');\n -> 3\n','https://mariadb.com/kb/en/second/'),(353,'ATAN2',4,'Syntax:\nATAN(Y,X), ATAN2(Y,X)\n\nReturns the arc tangent of the two variables X and Y. It is similar to\ncalculating the arc tangent of Y / X, except that the signs of both\narguments are used to determine the quadrant of the result.\n\nURL: https://mariadb.com/kb/en/atan2/\n\n','MariaDB> SELECT ATAN(-2,2);\n -> -0.78539816339745\nMariaDB> SELECT ATAN2(PI(),0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/atan2/'),(354,'MBRCONTAINS',6,'MBRContains(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\ncontains the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRWithin().\n\nURL: https://mariadb.com/kb/en/mbrcontains/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Point(1 1)\');\nMariaDB> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n','https://mariadb.com/kb/en/mbrcontains/'),(355,'HOUR',31,'Syntax:\nHOUR(time)\n\nReturns the hour for time. The range of the return value is 0 to 23 for\ntime-of-day values. However, the range of TIME values actually is much\nlarger, so HOUR can return values greater than 23.\n\nURL: https://mariadb.com/kb/en/hour/\n\n','MariaDB> SELECT HOUR(\'10:05:03\');\n -> 10\nMariaDB> SELECT HOUR(\'272:59:59\');\n -> 272\n','https://mariadb.com/kb/en/hour/'),(356,'SELECT',27,'Syntax:\nSELECT\n [ALL | DISTINCT | DISTINCTROW ]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position}\n [ASC | DESC], ... [WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position}\n [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n [PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n export_options\n | INTO DUMPFILE \'file_name\'\n | INTO var_name [, var_name]]\n [FOR UPDATE | LOCK IN SHARE MODE]]\n\nSELECT is used to retrieve rows selected from one or more tables, and\ncan include UNION statements and subqueries. See [HELP UNION], and\nhttps://mariadb.com/kb/en/subqueries/.\n\nThe most commonly used clauses of SELECT statements are these:\n\no Each select_expr indicates a column that you want to retrieve. There\n must be at least one select_expr.\n\no table_references indicates the table or tables from which to retrieve\n rows. Its syntax is described in [HELP JOIN].\n\no The WHERE clause, if given, indicates the condition or conditions\n that rows must satisfy to be selected. where_condition is an\n expression that evaluates to true for each row to be selected. The\n statement selects all rows if there is no WHERE clause.\n\n In the WHERE expression, you can use any of the functions and\n operators that MySQL supports, except for aggregate (summary)\n functions. See\n https://mariadb.com/kb/en/select#select-expressions, and\n https://mariadb.com/kb/en/functions-and-operators/.\n\nSELECT can also be used to retrieve rows computed without reference to\nany table.\n\nURL: https://mariadb.com/kb/en/select/\n\n','','https://mariadb.com/kb/en/select/'),(357,'COT',4,'Syntax:\nCOT(X)\n\nReturns the cotangent of X.\n\nURL: https://mariadb.com/kb/en/cot/\n\n','MariaDB> SELECT COT(12);\n -> -1.5726734063977\nMariaDB> SELECT COT(0);\n -> NULL\n','https://mariadb.com/kb/en/cot/'),(358,'SHOW CREATE EVENT',26,'Syntax:\nSHOW CREATE EVENT event_name\n\nThis statement displays the CREATE EVENT statement needed to re-create\na given event. It requires the EVENT privilege for the database from\nwhich the event is to be shown. For example (using the same event\ne_daily defined and then altered in [HELP SHOW EVENTS]):\n\nURL: https://mariadb.com/kb/en/show-create-event/\n\n','MariaDB> SHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row ***************************\n Event: e_daily\n sql_mode:\n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*)\n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-event/'),(359,'LOAD_FILE',37,'Syntax:\nLOAD_FILE(file_name)\n\nReads the file and returns the file contents as a string. To use this\nfunction, the file must be located on the server host, you must specify\nthe full path name to the file, and you must have the FILE privilege.\nThe file must be readable by all and its size less than\nmax_allowed_packet bytes. If the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nIf the file does not exist or cannot be read because one of the\npreceding conditions is not satisfied, the function returns NULL.\n\nThe character_set_filesystem system variable controls interpretation of\nfile names that are given as literal strings.\n\nURL: https://mariadb.com/kb/en/load_file/\n\n','MariaDB> UPDATE t\n SET blob_col=LOAD_FILE(\'/tmp/picture\')\n WHERE id=1;\n','https://mariadb.com/kb/en/load_file/'),(360,'POINTFROMTEXT',3,'PointFromText(wkt[,srid])\n\nConstructs a POINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromtext/\n\n','','https://mariadb.com/kb/en/pointfromtext/'),(361,'GROUP_CONCAT',16,'Syntax:\nGROUP_CONCAT(expr)\n\nThis function returns a string result with the concatenated non-NULL\nvalues from a group. It returns NULL if there are no non-NULL values.\nThe full syntax is as follows:\n\nGROUP_CONCAT([DISTINCT] expr [,expr ...]\n [ORDER BY {unsigned_integer | col_name | expr}\n [ASC | DESC] [,col_name ...]]\n [SEPARATOR str_val])\n\nURL: https://mariadb.com/kb/en/group_concat/\n\n','MariaDB> SELECT student_name,\n -> GROUP_CONCAT(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/group_concat/'),(362,'DATE_FORMAT',31,'Syntax:\nDATE_FORMAT(date,format)\n\nFormats the date value according to the format string.\n\nURL: https://mariadb.com/kb/en/date_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n -> \'Sunday October 2009\'\nMariaDB> SELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n -> \'22:23:00\'\nMariaDB> SELECT DATE_FORMAT(\'1900-10-04 22:23:00\',\n -> \'%D %y %a %d %m %b %j\');\n -> \'4th 00 Thu 04 10 Oct 277\'\nMariaDB> SELECT DATE_FORMAT(\'1997-10-04 22:23:00\',\n -> \'%H %k %I %r %T %S %w\');\n -> \'22 22 10 10:23:00 PM 22:23:00 00 6\'\nMariaDB> SELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n -> \'1998 52\'\nMariaDB> SELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n -> \'00\'\n','https://mariadb.com/kb/en/date_format/'),(363,'BENCHMARK',17,'Syntax:\nBENCHMARK(count,expr)\n\nThe BENCHMARK() function executes the expression expr repeatedly count\ntimes. It may be used to time how quickly MySQL processes the\nexpression. The result value is always 0. The intended use is from\nwithin the mysql client, which reports query execution times:\n\nURL: https://mariadb.com/kb/en/benchmark/\n\n','MariaDB> SELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (4.74 sec)\n','https://mariadb.com/kb/en/benchmark/'),(364,'YEAR',31,'Syntax:\nYEAR(date)\n\nReturns the year for date, in the range 1000 to 9999, or 0 for the\n\"zero\" date.\n\nURL: https://mariadb.com/kb/en/year/\n\n','MariaDB> SELECT YEAR(\'1987-01-01\');\n -> 1987\n','https://mariadb.com/kb/en/year/'),(365,'SHOW ENGINE',26,'Syntax:\nSHOW ENGINE engine_name {STATUS | MUTEX}\n\nSHOW ENGINE displays operational information about a storage engine.\nThe following statements currently are supported:\n\nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n\nSHOW ENGINE INNODB STATUS displays extensive information from the\nstandard InnoDB Monitor about the state of the InnoDB storage engine.\nFor information about the standard monitor and other InnoDB Monitors\nthat provide information about InnoDB processing, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-monitors.html.\n\nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics. The\nstatement displays the following fields:\n\no Type\n\n Always InnoDB.\n\no Name\n\n The source file where the mutex is implemented, and the line number\n in the file where the mutex is created. The line number may change\n depending on your version of MySQL.\n\no Status\n\n The mutex status. This field displays several values if UNIV_DEBUG\n was defined at MySQL compilation time (for example, in include/univ.i\n in the InnoDB part of the MySQL source tree). If UNIV_DEBUG was not\n defined, the statement displays only the os_waits value. In the\n latter case (without UNIV_DEBUG), the information on which the output\n is based is insufficient to distinguish regular mutexes and mutexes\n that protect rw-locks (which permit multiple readers or a single\n writer). Consequently, the output may appear to contain multiple rows\n for the same mutex.\n\n o count indicates how many times the mutex was requested.\n\n o spin_waits indicates how many times the spinlock had to run.\n\n o spin_rounds indicates the number of spinlock rounds. (spin_rounds\n divided by spin_waits provides the average round count.)\n\n o os_waits indicates the number of operating system waits. This\n occurs when the spinlock did not work (the mutex was not locked\n during the spinlock and it was necessary to yield to the operating\n system and wait).\n\n o os_yields indicates the number of times a the thread trying to lock\n a mutex gave up its timeslice and yielded to the operating system\n (on the presumption that permitting other threads to run will free\n the mutex so that it can be locked).\n\n o os_wait_times indicates the amount of time (in ms) spent in\n operating system waits, if the timed_mutexes system variable is 1\n (ON). If timed_mutexes is 0 (OFF), timing is disabled, so\n os_wait_times is 0. timed_mutexes is off by default.\n\nInformation from this statement can be used to diagnose system\nproblems. For example, large values of spin_waits and spin_rounds may\nindicate scalability problems.\n\nUse SHOW ENGINE PERFORMANCE_SCHEMA STATUS to inspect the internal\noperation of the Performance Schema code:\n\nMariaDB> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\\G\n...\n*************************** 3. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_size\nStatus: 76\n*************************** 4. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_count\nStatus: 10000\n*************************** 5. row ***************************\n Type: performance_schema\n Name: events_waits_history.memory\nStatus: 760000\n...\n*************************** 57. row ***************************\n Type: performance_schema\n Name: performance_schema.memory\nStatus: 26459600\n...\n\nThe intent of this statement is to help the DBA to understand the\neffects that different options have on memory requirements.\n\nName values consist of two parts, which name an internal buffer and an\nattribute of the buffer, respectively:\n\no Internal buffers that are exposed as a table in the\n performance_schema database are named after the table. Examples:\n events_waits_history.row_size, mutex_instances.row_count.\n\no Internal buffers that are not exposed as a table are named within\n parentheses. Examples: (pfs_cond_class).row_size,\n (pfs_mutex_class).memory.\n\no Values that apply to the Performance Schema as a whole begin with\n performance_schema. Example: performance_schema.memory.\n\nAttributes have these meanings:\n\no row_size cannot be changed. It is the size of the internal record\n used by the implementation.\n\no row_count can be changed depending on the configuration options.\n\no For a table, tbl_name.memory is the product of row_size multiplied by\n row_count. For the Performance Schema as a whole,\n performance_schema.memory is the sum of all the memory used (the sum\n of all other memory values).\n\nIn some cases, there is a direct relationship between a configuration\nparameter and a SHOW ENGINE value. For example,\nevents_waits_history_long.row_count corresponds to\nperformance_schema_events_waits_history_long_size. In other cases, the\nrelationship is more complex. For example,\nevents_waits_history.row_count corresponds to\nperformance_schema_events_waits_history_size (the number of rows per\nthread) multiplied by performance_schema_max_thread_instances ( the\nnumber of threads).\n\nURL: https://mariadb.com/kb/en/show-engine/\n\n','','https://mariadb.com/kb/en/show-engine/'),(366,'NAME_CONST',14,'Syntax:\nNAME_CONST(name,value)\n\nReturns the given value. When used to produce a result set column,\nNAME_CONST() causes the column to have the given name. The arguments\nshould be constants.\n\nMariaDB> SELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n\nURL: https://mariadb.com/kb/en/name_const/\n\n','','https://mariadb.com/kb/en/name_const/'),(367,'RELEASE_LOCK',14,'Syntax:\nRELEASE_LOCK(str)\n\nReleases the lock named by the string str that was obtained with\nGET_LOCK(). Returns 1 if the lock was released, 0 if the lock was not\nestablished by this thread (in which case the lock is not released),\nand NULL if the named lock did not exist. The lock does not exist if it\nwas never obtained by a call to GET_LOCK() or if it has previously been\nreleased.\n\nThe DO statement is convenient to use with RELEASE_LOCK(). See [HELP\nDO].\n\nURL: https://mariadb.com/kb/en/release_lock/\n\n','','https://mariadb.com/kb/en/release_lock/'),(368,'IS NULL',18,'Syntax:\nIS NULL\n\nTests whether a value is NULL.\n\nURL: https://mariadb.com/kb/en/is-null/\n\n','MariaDB> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n -> 0, 0, 1\n','https://mariadb.com/kb/en/is-null/'),(369,'CONVERT_TZ',31,'Syntax:\nCONVERT_TZ(dt,from_tz,to_tz)\n\nCONVERT_TZ() converts a datetime value dt from the time zone given by\nfrom_tz to the time zone given by to_tz and returns the resulting\nvalue. Time zones are specified as described in\nhttps://mariadb.com/kb/en/time-zones/. This\nfunction returns NULL if the arguments are invalid.\n\nURL: https://mariadb.com/kb/en/convert_tz/\n\n','MariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'GMT\',\'MET\');\n -> \'2004-01-01 13:00:00\'\nMariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'+00:00\',\'+10:00\');\n -> \'2004-01-01 22:00:00\'\n','https://mariadb.com/kb/en/convert_tz/'),(370,'TIME_TO_SEC',31,'Syntax:\nTIME_TO_SEC(time)\n\nReturns the time argument, converted to seconds.\n\nURL: https://mariadb.com/kb/en/time_to_sec/\n\n','MariaDB> SELECT TIME_TO_SEC(\'22:23:00\');\n -> 80580\nMariaDB> SELECT TIME_TO_SEC(\'00:39:38\');\n -> 2378\n','https://mariadb.com/kb/en/time_to_sec/'),(371,'WEEKDAY',31,'Syntax:\nWEEKDAY(date)\n\nReturns the weekday index for date (0 = Monday, 1 = Tuesday, ... 6 =\nSunday).\n\nURL: https://mariadb.com/kb/en/weekday/\n\n','MariaDB> SELECT WEEKDAY(\'2008-02-03 22:23:00\');\n -> 6\nMariaDB> SELECT WEEKDAY(\'2007-11-06\');\n -> 1\n','https://mariadb.com/kb/en/weekday/'),(372,'EXPORT_SET',37,'Syntax:\nEXPORT_SET(bits,on,off[,separator[,number_of_bits]])\n\nReturns a string such that for every bit set in the value bits, you get\nan on string and for every bit not set in the value, you get an off\nstring. Bits in bits are examined from right to left (from low-order to\nhigh-order bits). Strings are added to the result from left to right,\nseparated by the separator string (the default being the comma\ncharacter \",\"). The number of bits examined is given by number_of_bits,\nwhich has a default of 64 if not specified. number_of_bits is silently\nclipped to 64 if larger than 64. It is treated as an unsigned integer,\nso a value of -1 is effectively the same as 64.\n\nURL: https://mariadb.com/kb/en/export_set/\n\n','MariaDB> SELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n -> \'Y,N,Y,N\'\nMariaDB> SELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n -> \'0,1,1,0,0,0,0,0,0,0\'\n','https://mariadb.com/kb/en/export_set/'),(373,'ALTER SERVER',39,'Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. See [HELP CREATE\nSERVER]. The corresponding fields in the mysql.servers table are\nupdated accordingly. This statement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/alter-server/\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','https://mariadb.com/kb/en/alter-server/'),(374,'RESIGNAL',23,'Syntax:\nRESIGNAL [condition_value]\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nRESIGNAL passes on the error condition information that is available\nduring execution of a condition handler within a compound statement\ninside a stored procedure or function, trigger, or event. RESIGNAL may\nchange some or all information before passing it on. RESIGNAL is\nrelated to SIGNAL, but instead of originating a condition as SIGNAL\ndoes, RESIGNAL relays existing condition information, possibly after\nmodifying it.\n\nRESIGNAL makes it possible to both handle an error and return the error\ninformation. Otherwise, by executing an SQL statement within the\nhandler, information that caused the handler\'s activation is destroyed.\nRESIGNAL also can make some procedures shorter if a given handler can\nhandle part of a situation, then pass the condition \"up the line\" to\nanother handler.\n\nNo special privileges are required to execute the RESIGNAL statement.\n\nFor condition_value and signal_information_item, the definitions and\nrules are the same for RESIGNAL as for SIGNAL (see [HELP SIGNAL]).\n\nThe RESIGNAL statement takes condition_value and SET clauses, both of\nwhich are optional. This leads to several possible uses:\n\no RESIGNAL alone:\n\nRESIGNAL;\n\no RESIGNAL with new signal information:\n\nRESIGNAL SET signal_information_item [, signal_information_item] ...;\n\no RESIGNAL with a condition value and possibly new signal information:\n\nRESIGNAL condition_value\n [SET signal_information_item [, signal_information_item] ...];\n\nURL: https://mariadb.com/kb/en/resignal/\n\n','','https://mariadb.com/kb/en/resignal/'),(375,'TIME FUNCTION',31,'Syntax:\nTIME(expr)\n\nExtracts the time part of the time or datetime expression expr and\nreturns it as a string.\n\nURL: https://mariadb.com/kb/en/time-function/\n\n','MariaDB> SELECT TIME(\'2003-12-31 01:02:03\');\n -> \'01:02:03\'\nMariaDB> SELECT TIME(\'2003-12-31 01:02:03.000123\');\n -> \'01:02:03.000123\'\n','https://mariadb.com/kb/en/time-function/'),(376,'DATE_ADD',31,'Syntax:\nDATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)\n\nThese functions perform date arithmetic. The date argument specifies\nthe starting date or datetime value. expr is an expression specifying\nthe interval value to be added or subtracted from the starting date.\nexpr is a string; it may start with a \"-\" for negative intervals. unit\nis a keyword indicating the units in which the expression should be\ninterpreted.\n\nURL: https://mariadb.com/kb/en/date_add/\n\n','MariaDB> SELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n -> \'2009-01-01 00:00:00\'\nMariaDB> SELECT INTERVAL 1 DAY + \'2008-12-31\';\n -> \'2009-01-01\'\nMariaDB> SELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n -> \'2004-12-31 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2000-12-31 23:59:59\',\n -> INTERVAL 1 SECOND);\n -> \'2001-01-01 00:00:00\'\nMariaDB> SELECT DATE_ADD(\'2010-12-31 23:59:59\',\n -> INTERVAL 1 DAY);\n -> \'2011-01-01 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2100-12-31 23:59:59\',\n -> INTERVAL \'1:1\' MINUTE_SECOND);\n -> \'2101-01-01 00:01:00\'\nMariaDB> SELECT DATE_SUB(\'2005-01-01 00:00:00\',\n -> INTERVAL \'1 1:1:1\' DAY_SECOND);\n -> \'2004-12-30 22:58:59\'\nMariaDB> SELECT DATE_ADD(\'1900-01-01 00:00:00\',\n -> INTERVAL \'-1 10\' DAY_HOUR);\n -> \'1899-12-30 14:00:00\'\nMariaDB> SELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n -> \'1997-12-02\'\nMariaDB> SELECT DATE_ADD(\'1992-12-31 23:59:59.000002\',\n -> INTERVAL \'1.999999\' SECOND_MICROSECOND);\n -> \'1993-01-01 00:00:01.000001\'\n','https://mariadb.com/kb/en/date_add/'),(377,'CAST',37,'Syntax:\nCAST(expr AS type)\n\nThe CAST() function takes an expression of any type and produces a\nresult value of a specified type, similar to CONVERT(). See the\ndescription of CONVERT() for more information.\n\nURL: https://mariadb.com/kb/en/cast/\n\n','','https://mariadb.com/kb/en/cast/'),(378,'SOUNDS LIKE',37,'Syntax:\nexpr1 SOUNDS LIKE expr2\n\nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n\nURL: https://mariadb.com/kb/en/sounds-like/\n\n','','https://mariadb.com/kb/en/sounds-like/'),(379,'PERIOD_DIFF',31,'Syntax:\nPERIOD_DIFF(P1,P2)\n\nReturns the number of months between periods P1 and P2. P1 and P2\nshould be in the format YYMM or YYYYMM. Note that the period arguments\nP1 and P2 are not date values.\n\nURL: https://mariadb.com/kb/en/period_diff/\n\n','MariaDB> SELECT PERIOD_DIFF(200802,200703);\n -> 11\n','https://mariadb.com/kb/en/period_diff/'),(380,'LIKE',37,'Syntax:\nexpr LIKE pat [ESCAPE \'escape_char\']\n\nPattern matching using SQL simple regular expression comparison.\nReturns 1 (TRUE) or 0 (FALSE). If either expr or pat is NULL, the\nresult is NULL.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\nURL: https://mariadb.com/kb/en/like/\n\n','MariaDB> SELECT \'David!\' LIKE \'David_\';\n -> 1\nMariaDB> SELECT \'David!\' LIKE \'%D%v%\';\n -> 1\n','https://mariadb.com/kb/en/like/'),(381,'MULTIPOINT',24,'MultiPoint(pt1,pt2,...)\n\nConstructs a MultiPoint value using Point or WKB Point arguments.\n\nURL: https://mariadb.com/kb/en/multipoint/\n\n','','https://mariadb.com/kb/en/multipoint/'),(382,'>>',19,'Syntax:\n>>\n\nShifts a longlong (BIGINT) number to the right.\n\nURL: https://mariadb.com/kb/en/shift-right/\n\n','MariaDB> SELECT 4 >> 2;\n -> 1\n','https://mariadb.com/kb/en/shift-right/'),(383,'FETCH',23,'Syntax:\nFETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...\n\nThis statement fetches the next row for the SELECT statement associated\nwith the specified cursor (which must be open), and advances the cursor\npointer. If a row exists, the fetched columns are stored in the named\nvariables. The number of columns retrieved by the SELECT statement must\nmatch the number of output variables specified in the FETCH statement.\n\nIf no more rows are available, a No Data condition occurs with SQLSTATE\nvalue \'02000\'. To detect this condition, you can set up a handler for\nit (or for a NOT FOUND condition). For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/fetch/\n\n','','https://mariadb.com/kb/en/fetch/'),(384,'AVG',16,'Syntax:\nAVG([DISTINCT] expr)\n\nReturns the average value of expr. The DISTINCT option can be used to\nreturn the average of the distinct values of expr.\n\nAVG() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/avg/\n\n','MariaDB> SELECT student_name, AVG(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/avg/'),(385,'TRUE FALSE',29,'The constants TRUE and FALSE evaluate to 1 and 0, respectively. The\nconstant names can be written in any lettercase.\n\nMariaDB> SELECT TRUE, true, FALSE, false;\n -> 1, 1, 0, 0\n\nURL: https://mariadb.com/kb/en/true-false/\n\n','','https://mariadb.com/kb/en/true-false/'),(386,'MBRWITHIN',6,'MBRWithin(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\nis within the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRContains().\n\nURL: https://mariadb.com/kb/en/mbrwithin/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nMariaDB> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n','https://mariadb.com/kb/en/mbrwithin/'),(387,'SESSION_USER',17,'Syntax:\nSESSION_USER()\n\nSESSION_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/session_user/\n\n','','https://mariadb.com/kb/en/session_user/'),(388,'IN',18,'Syntax:\nexpr IN (value,...)\n\nReturns 1 if expr is equal to any of the values in the IN list, else\nreturns 0. If all values are constants, they are evaluated according to\nthe type of expr and sorted. The search for the item then is done using\na binary search. This means IN is very quick if the IN value list\nconsists entirely of constants. Otherwise, type conversion takes place\naccording to the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the arguments.\n\nURL: https://mariadb.com/kb/en/in/\n\n','MariaDB> SELECT 2 IN (0,3,5,7);\n -> 0\nMariaDB> SELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n -> 1\n','https://mariadb.com/kb/en/in/'),(389,'QUOTE',37,'Syntax:\nQUOTE(str)\n\nQuotes a string to produce a result that can be used as a properly\nescaped data value in an SQL statement. The string is returned enclosed\nby single quotation marks and with each instance of backslash (\"\\\"),\nsingle quote (\"\'\"), ASCII NUL, and Control+Z preceded by a backslash.\nIf the argument is NULL, the return value is the word \"NULL\" without\nenclosing single quotation marks.\n\nURL: https://mariadb.com/kb/en/quote/\n\n','MariaDB> SELECT QUOTE(\'Don\\\'t!\');\n -> \'Don\\\'t!\'\nMariaDB> SELECT QUOTE(NULL);\n -> NULL\n','https://mariadb.com/kb/en/quote/'),(390,'HELP COMMAND',26,'Syntax:\nMariaDB> help search_string\n\nIf you provide an argument to the help command, mysql uses it as a\nsearch string to access server-side help from the contents of the MySQL\nReference Manual. The proper operation of this command requires that\nthe help tables in the mysql database be initialized with help topic\ninformation .\n\nIf there is no match for the search string, the search fails:\n\nMariaDB> help me\n\nNothing found\nPlease try to run \'help contents\' for a list of all accessible topics\n\nUse help contents to see a list of the help categories:\n\nMariaDB> help contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing categories:\n Account Management\n Administration\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Language Structure\n Plugins\n Storage Engines\n Stored Routines\n Table Maintenance\n Transactions\n Triggers\n\nIf the search string matches multiple items, mysql shows a list of\nmatching topics:\n\nMariaDB> help logs\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following topics:\n SHOW\n SHOW BINARY LOGS\n SHOW ENGINE\n SHOW LOGS\n\nUse a topic as the search string to see the help entry for that topic:\n\nMariaDB> help show binary logs\nName: \'SHOW BINARY LOGS\'\nDescription:\nSyntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [purge-binary-logs], that shows how\nto determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(391,'QUARTER',31,'Syntax:\nQUARTER(date)\n\nReturns the quarter of the year for date, in the range 1 to 4.\n\nURL: https://mariadb.com/kb/en/quarter/\n\n','MariaDB> SELECT QUARTER(\'2008-04-01\');\n -> 2\n','https://mariadb.com/kb/en/quarter/'),(392,'POSITION',37,'Syntax:\nPOSITION(substr IN str)\n\nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n\nURL: https://mariadb.com/kb/en/position/\n\n','','https://mariadb.com/kb/en/position/'),(393,'SHOW CREATE FUNCTION',26,'Syntax:\nSHOW CREATE FUNCTION func_name\n\nThis statement is similar to SHOW CREATE PROCEDURE but for stored\nfunctions. See [HELP SHOW CREATE PROCEDURE].\n\nURL: https://mariadb.com/kb/en/show-create-function/\n\n','','https://mariadb.com/kb/en/show-create-function/'),(394,'IS_USED_LOCK',14,'Syntax:\nIS_USED_LOCK(str)\n\nChecks whether the lock named str is in use (that is, locked). If so,\nit returns the connection identifier of the client that holds the lock.\nOtherwise, it returns NULL.\n\nURL: https://mariadb.com/kb/en/is_used_lock/\n\n','','https://mariadb.com/kb/en/is_used_lock/'),(395,'POLYFROMTEXT',3,'PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])\n\nConstructs a POLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromtext/\n\n','','https://mariadb.com/kb/en/polyfromtext/'),(396,'DES_ENCRYPT',12,'Syntax:\nDES_ENCRYPT(str[,{key_num|key_str}])\n\nEncrypts the string with the given key using the Triple-DES algorithm.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nThe encryption key to use is chosen based on the second argument to\nDES_ENCRYPT(), if one was given. With no argument, the first key from\nthe DES key file is used. With a key_num argument, the given key number\n(0 to 9) from the DES key file is used. With a key_str argument, the\ngiven key string is used to encrypt str.\n\nThe key file can be specified with the --des-key-file server option.\n\nThe return string is a binary string where the first character is\nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT() returns NULL.\n\nThe 128 is added to make it easier to recognize an encrypted key. If\nyou use a string key, key_num is 127.\n\nThe string length for the result is given by this formula:\n\nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n\nEach line in the DES key file has the following format:\n\nkey_num des_key_str\n\nEach key_num value must be a number in the range from 0 to 9. Lines in\nthe file may be in any order. des_key_str is the string that is used to\nencrypt the message. There should be at least one space between the\nnumber and the key. The first key is the default key that is used if\nyou do not specify any key argument to DES_ENCRYPT().\n\nYou can tell MySQL to read new key values from the key file with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD privilege.\n\nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted column\nvalues, without giving the end user the right to decrypt those values.\n\nURL: https://mariadb.com/kb/en/des_encrypt/\n\n','MariaDB> SELECT customer_address FROM customer_table \n > WHERE crypted_credit_card = DES_ENCRYPT(\'credit_card_number\');\n','https://mariadb.com/kb/en/des_encrypt/'),(397,'CEIL',4,'Syntax:\nCEIL(X)\n\nCEIL() is a synonym for CEILING().\n\nURL: https://mariadb.com/kb/en/ceil/\n\n','','https://mariadb.com/kb/en/ceil/'),(398,'LENGTH',37,'Syntax:\nLENGTH(str)\n\nReturns the length of the string str, measured in bytes. A multi-byte\ncharacter counts as multiple bytes. This means that for a string\ncontaining five 2-byte characters, LENGTH() returns 10, whereas\nCHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/length/\n\n','MariaDB> SELECT LENGTH(\'text\');\n -> 4\n','https://mariadb.com/kb/en/length/'),(399,'STR_TO_DATE',31,'Syntax:\nSTR_TO_DATE(str,format)\n\nThis is the inverse of the DATE_FORMAT() function. It takes a string\nstr and a format string format. STR_TO_DATE() returns a DATETIME value\nif the format string contains both date and time parts, or a DATE or\nTIME value if the string contains only date or time parts. If the date,\ntime, or datetime value extracted from str is illegal, STR_TO_DATE()\nreturns NULL and produces a warning.\n\nThe server scans str attempting to match format to it. The format\nstring can contain literal characters and format specifiers beginning\nwith %. Literal characters in format must match literally in str.\nFormat specifiers in format must match a date or time part in str. For\nthe specifiers that can be used in format, see the DATE_FORMAT()\nfunction description.\n\nMariaDB> SELECT STR_TO_DATE(\'01,5,2013\',\'%d,%m,%Y\');\n -> \'2013-05-01\'\nMariaDB> SELECT STR_TO_DATE(\'May 1, 2013\',\'%M %d,%Y\');\n -> \'2013-05-01\'\n\nScanning starts at the beginning of str and fails if format is found\nnot to match. Extra characters at the end of str are ignored.\n\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'a%h:%i:%s\');\n -> \'09:30:17\'\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'%h:%i:%s\');\n -> NULL\nMariaDB> SELECT STR_TO_DATE(\'09:30:17a\',\'%h:%i:%s\');\n -> \'09:30:17\'\n\nUnspecified date or time parts have a value of 0, so incompletely\nspecified values in str produce a result with some or all parts set to\n0:\n\nMariaDB> SELECT STR_TO_DATE(\'abc\',\'abc\');\n -> \'0000-00-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%m\');\n -> \'0000-09-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%s\');\n -> \'00:00:09\'\n\nURL: https://mariadb.com/kb/en/str_to_date/\n\n','','https://mariadb.com/kb/en/str_to_date/'),(400,'Y',11,'Y(p)\n\nReturns the Y-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/y/\n\n','MariaDB> SELECT Y(POINT(56.7, 53.34));\n+-----------------------+\n| Y(POINT(56.7, 53.34)) |\n+-----------------------+\n| 53.34 |\n+-----------------------+\n','https://mariadb.com/kb/en/y/'),(401,'CHECKSUM TABLE',20,'Syntax:\nCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]\n\nCHECKSUM TABLE reports a table checksum. This statement requires the\nSELECT privilege for the table.\n\nWith QUICK, the live table checksum is reported if it is available, or\nNULL otherwise. This is very fast. A live checksum is enabled by\nspecifying the CHECKSUM=1 table option when you create the table;\ncurrently, this is supported only for MyISAM tables. See [HELP CREATE\nTABLE].\n\nWith EXTENDED, the entire table is read row by row and the checksum is\ncalculated. This can be very slow for large tables.\n\nIf neither QUICK nor EXTENDED is specified, MySQL returns a live\nchecksum if the table storage engine supports it and scans the table\notherwise.\n\nFor a nonexistent table, CHECKSUM TABLE returns NULL and generates a\nwarning.\n\nIn MySQL 5.5, CHECKSUM TABLE returns 0 for partitioned tables unless\nyou include the EXTENDED option. This issue is resolved in MySQL 5.6.\n(Bug #11933226, Bug #60681)\n\nThe checksum value depends on the table row format. If the row format\nchanges, the checksum also changes. For example, the storage format for\nVARCHAR changed between MySQL 4.1 and 5.0, so if a 4.1 table is\nupgraded to MySQL 5.0, the checksum value may change.\n\nURL: https://mariadb.com/kb/en/checksum-table/\n\n','','https://mariadb.com/kb/en/checksum-table/'),(402,'NUMINTERIORRINGS',2,'NumInteriorRings(poly)\n\nReturns the number of interior rings in the Polygon value poly.\n\nURL: https://mariadb.com/kb/en/numinteriorrings/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n','https://mariadb.com/kb/en/numinteriorrings/'),(403,'INTERIORRINGN',2,'InteriorRingN(poly,N)\n\nReturns the N-th interior ring for the Polygon value poly as a\nLineString. Rings are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/interiorringn/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n','https://mariadb.com/kb/en/interiorringn/'),(404,'UTC_TIME',31,'Syntax:\nUTC_TIME, UTC_TIME()\n\nReturns the current UTC time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_time/\n\n','MariaDB> SELECT UTC_TIME(), UTC_TIME() + 0;\n -> \'18:07:53\', 180753.000000\n','https://mariadb.com/kb/en/utc_time/'),(405,'DROP FUNCTION',39,'The DROP FUNCTION statement is used to drop stored functions and\nuser-defined functions (UDFs):\n\no For information about dropping stored functions, see [HELP DROP\n PROCEDURE].\n\no For information about dropping user-defined functions, see [HELP DROP\n FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/drop-function/\n\n','','https://mariadb.com/kb/en/drop-function/'),(406,'ALTER EVENT',39,'Syntax:\nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO event_body]\n\nThe ALTER EVENT statement changes one or more of the characteristics of\nan existing event without the need to drop and recreate it. The syntax\nfor each of the DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE /\nDISABLE, and DO clauses is exactly the same as when used with CREATE\nEVENT. (See [HELP CREATE EVENT].)\n\nAny user can alter an event defined on a database for which that user\nhas the EVENT privilege. When a user executes a successful ALTER EVENT\nstatement, that user becomes the definer for the affected event.\n\nALTER EVENT works only with an existing event:\n\nMariaDB> ALTER EVENT no_such_event \n > ON SCHEDULE \n > EVERY \'2:3\' DAY_HOUR;\nERROR 1517 (HY000): Unknown event \'no_such_event\'\n\nURL: https://mariadb.com/kb/en/alter-event/\n\n','','https://mariadb.com/kb/en/alter-event/'),(407,'STDDEV',16,'Syntax:\nSTDDEV(expr)\n\nReturns the population standard deviation of expr. This function is\nprovided for compatibility with Oracle. The standard SQL function\nSTDDEV_POP() can be used instead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev/\n\n','','https://mariadb.com/kb/en/stddev/'),(408,'DATE_SUB',31,'Syntax:\nDATE_SUB(date,INTERVAL expr unit)\n\nSee the description for DATE_ADD().\n\nURL: https://mariadb.com/kb/en/date_sub/\n\n','','https://mariadb.com/kb/en/date_sub/'),(409,'PERIOD_ADD',31,'Syntax:\nPERIOD_ADD(P,N)\n\nAdds N months to period P (in the format YYMM or YYYYMM). Returns a\nvalue in the format YYYYMM. Note that the period argument P is not a\ndate value.\n\nURL: https://mariadb.com/kb/en/period_add/\n\n','MariaDB> SELECT PERIOD_ADD(200801,2);\n -> 200803\n','https://mariadb.com/kb/en/period_add/'),(410,'|',19,'Syntax:\n|\n\nBitwise OR:\n\nURL: https://mariadb.com/kb/en/bitwise-or/\n\n','MariaDB> SELECT 29 | 15;\n -> 31\n','https://mariadb.com/kb/en/bitwise-or/'),(411,'GEOMFROMTEXT',3,'GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])\n\nConstructs a geometry value of any type using its WKT representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromtext/\n\n','','https://mariadb.com/kb/en/geomfromtext/'),(412,'UUID_SHORT',14,'Syntax:\nUUID_SHORT()\n\nReturns a \"short\" universal identifier as a 64-bit unsigned integer\n(rather than a string-form 128-bit identifier as returned by the UUID()\nfunction).\n\nThe value of UUID_SHORT() is guaranteed to be unique if the following\nconditions hold:\n\no The server_id of the current host is unique among your set of master\n and slave servers\n\no server_id is between 0 and 255\n\no You do not set back your system time for your server between mysqld\n restarts\n\no You do not invoke UUID_SHORT() on average more than 16 million times\n per second between mysqld restarts\n\nThe UUID_SHORT() return value is constructed this way:\n\n (server_id & 255) << 56\n+ (server_startup_time_in_seconds << 24)\n+ incremented_variable++;\n\nURL: https://mariadb.com/kb/en/uuid_short/\n\n','MariaDB> SELECT UUID_SHORT();\n -> 92395783831158784\n','https://mariadb.com/kb/en/uuid_short/'),(413,'RIGHT',37,'Syntax:\nRIGHT(str,len)\n\nReturns the rightmost len characters from the string str, or NULL if\nany argument is NULL.\n\nURL: https://mariadb.com/kb/en/right/\n\n','MariaDB> SELECT RIGHT(\'foobarbar\', 4);\n -> \'rbar\'\n','https://mariadb.com/kb/en/right/'),(414,'DATEDIFF',31,'Syntax:\nDATEDIFF(expr1,expr2)\n\nDATEDIFF() returns expr1 - expr2 expressed as a value in days from one\ndate to the other. expr1 and expr2 are date or date-and-time\nexpressions. Only the date parts of the values are used in the\ncalculation.\n\nURL: https://mariadb.com/kb/en/datediff/\n\n','MariaDB> SELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n -> 1\nMariaDB> SELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n -> -31\n','https://mariadb.com/kb/en/datediff/'),(415,'DROP TABLESPACE',39,'Syntax:\nDROP TABLESPACE tablespace_name\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/drop-tablespace/\n\n','','https://mariadb.com/kb/en/drop-tablespace/'),(416,'DROP PROCEDURE',39,'Syntax:\nDROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name\n\nThis statement is used to drop a stored procedure or function. That is,\nthe specified routine is removed from the server. You must have the\nALTER ROUTINE privilege for the routine. (If the\nautomatic_sp_privileges system variable is enabled, that privilege and\nEXECUTE are granted automatically to the routine creator when the\nroutine is created and dropped from the creator when the routine is\ndropped. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n)\n\nThe IF EXISTS clause is a MySQL extension. It prevents an error from\noccurring if the procedure or function does not exist. A warning is\nproduced that can be viewed with SHOW WARNINGS.\n\nURL: https://mariadb.com/kb/en/drop-procedure/\n\n','','https://mariadb.com/kb/en/drop-procedure/'),(417,'CHECK TABLE',20,'Syntax:\nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n\noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED}\n\nCHECK TABLE checks a table or tables for errors. CHECK TABLE works for\nInnoDB, MyISAM, ARCHIVE, and CSV tables. For MyISAM tables, the key\nstatistics are updated as well.\n\nTo check a table, you must have some privilege for it.\n\nCHECK TABLE can also check views for problems, such as tables that are\nreferenced in the view definition that no longer exist.\n\nCHECK TABLE is supported for partitioned tables, and you can use ALTER\nTABLE ... CHECK PARTITION to check one or more partitions; for more\ninformation, see [HELP ALTER TABLE].\n\nURL: https://mariadb.com/kb/en/sql-commands-check-table/\n\n','','https://mariadb.com/kb/en/sql-commands-check-table/'),(418,'BIN',37,'Syntax:\nBIN(N)\n\nReturns a string representation of the binary value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,2). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/bin/\n\n','MariaDB> SELECT BIN(12);\n -> \'1100\'\n','https://mariadb.com/kb/en/bin/'),(419,'INSTALL PLUGIN',5,'Syntax:\nINSTALL PLUGIN plugin_name SONAME \'shared_library_name\'\n\nThis statement installs a server plugin. It requires the INSERT\nprivilege for the mysql.plugin table.\n\nplugin_name is the name of the plugin as defined in the plugin\ndescriptor structure contained in the library file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/plugin-data-structures.html).\nPlugin names are not case sensitive. For maximal compatibility, plugin\nnames should be limited to ASCII letters, digits, and underscore\nbecause they are used in C source files, shell command lines, M4 and\nBourne shell scripts, and SQL environments.\n\nshared_library_name is the name of the shared library that contains the\nplugin code. The name includes the file name extension (for example,\nlibmyplugin.so, libmyplugin.dll, or libmyplugin.dylib).\n\nThe shared library must be located in the plugin directory (the\ndirectory named by the plugin_dir system variable). The library must be\nin the plugin directory itself, not in a subdirectory. By default,\nplugin_dir is the plugin directory under the directory named by the\npkglibdir configuration variable, but it can be changed by setting the\nvalue of plugin_dir at server startup. For example, set its value in a\nmy.cnf file:\n\n[mysqld]\nplugin_dir=/path/to/plugin/directory\n\nIf the value of plugin_dir is a relative path name, it is taken to be\nrelative to the MySQL base directory (the value of the basedir system\nvariable).\n\nINSTALL PLUGIN loads and initializes the plugin code to make the plugin\navailable for use. A plugin is initialized by executing its\ninitialization function, which handles any setup that the plugin must\nperform before it can be used. When the server shuts down, it executes\nthe deinitialization function for each plugin that is loaded so that\nthe plugin has a change to perform any final cleanup.\n\nINSTALL PLUGIN also registers the plugin by adding a line that\nindicates the plugin name and library file name to the mysql.plugin\ntable. At server startup, the server loads and initializes any plugin\nthat is listed in the mysql.plugin table. This means that a plugin is\ninstalled with INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the server is\nstarted with the --skip-grant-tables option.\n\nA plugin library can contain multiple plugins. For each of them to be\ninstalled, use a separate INSTALL PLUGIN statement. Each statement\nnames a different plugin, but all of them specify the same library\nname.\n\nURL: https://mariadb.com/kb/en/install-plugin/\n\n','','https://mariadb.com/kb/en/install-plugin/'),(420,'DECLARE CURSOR',23,'Syntax:\nDECLARE cursor_name CURSOR FOR select_statement\n\nThis statement declares a cursor and associates it with a SELECT\nstatement that retrieves the rows to be traversed by the cursor. To\nfetch the rows later, use a FETCH statement. The number of columns\nretrieved by the SELECT statement must match the number of output\nvariables specified in the FETCH statement.\n\nThe SELECT statement cannot have an INTO clause.\n\nCursor declarations must appear before handler declarations and after\nvariable and condition declarations.\n\nA stored program may contain multiple cursor declarations, but each\ncursor declared in a given block must have a unique name. For an\nexample, see https://mariadb.com/kb/en/programmatic-and-compound-statements-cursors/.\n\nFor information available through SHOW statements, it is possible in\nmany cases to obtain equivalent information by using a cursor with an\nINFORMATION_SCHEMA table.\n\nURL: https://mariadb.com/kb/en/declare-cursor/\n\n','','https://mariadb.com/kb/en/declare-cursor/'),(421,'LOAD DATA',27,'Syntax:\nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number {LINES | ROWS}]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD DATA INFILE statement reads rows from a text file into a table\nat a very high speed. The file name must be given as a literal string.\n\nLOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. (See\nhttps://mariadb.com/kb/en/select-into/.) To write data\nfrom a table to a file, use SELECT ... INTO OUTFILE. To read the file\nback into a table, use LOAD DATA INFILE. The syntax of the FIELDS and\nLINES clauses is the same for both statements. Both clauses are\noptional, but FIELDS must precede LINES if both are specified.\n\nFor more information about the efficiency of INSERT versus LOAD DATA\nINFILE and speeding up LOAD DATA INFILE, see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-speed.html.\n\nThe character set indicated by the character_set_database system\nvariable is used to interpret the information in the file. SET NAMES\nand the setting of character_set_client do not affect interpretation of\ninput. If the contents of the input file use a character set that\ndiffers from the default, it is usually preferable to specify the\ncharacter set of the file by using the CHARACTER SET clause. A\ncharacter set of binary specifies \"no conversion.\"\n\nLOAD DATA INFILE interprets all fields in the file as having the same\ncharacter set, regardless of the data types of the columns into which\nfield values are loaded. For proper interpretation of file contents,\nyou must ensure that it was written with the correct character set. For\nexample, if you write a data file with mysqldump -T or by issuing a\nSELECT ... INTO OUTFILE statement in mysql, be sure to use a\n--default-character-set option with mysqldump or mysql so that output\nis written in the character set to be used when the file is loaded with\nLOAD DATA INFILE.\n\n*Note*: It is not possible to load data files that use the ucs2, utf16,\nor utf32 character set.\n\nThe character_set_filesystem system variable controls the\ninterpretation of the file name.\n\nYou can also load data files by using the mysqlimport utility; it\noperates by sending a LOAD DATA INFILE statement to the server. The\n--local option causes mysqlimport to read data files from the client\nhost. You can specify the --compress option to get better performance\nover slow networks if the client and server support the compressed\nprotocol. See https://mariadb.com/kb/en/mysqlimport/.\n\nIf you use LOW_PRIORITY, execution of the LOAD DATA statement is\ndelayed until no other clients are reading from the table. This affects\nonly storage engines that use only table-level locking (such as MyISAM,\nMEMORY, and MERGE).\n\nIf you specify CONCURRENT with a MyISAM table that satisfies the\ncondition for concurrent inserts (that is, it contains no free blocks\nin the middle), other threads can retrieve data from the table while\nLOAD DATA is executing. Using this option affects the performance of\nLOAD DATA a bit, even if no other thread is using the table at the same\ntime.\n\nPrior to MySQL 5.5.1, CONCURRENT was not replicated when using\nstatement-based replication (see Bug #34628). However, it is replicated\nwhen using row-based replication, regardless of the version. See\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-features-load-data.h\ntml, for more information.\n\nThe LOCAL keyword, if specified, is interpreted with respect to the\nclient end of the connection:\n\no If LOCAL is specified, the file is read by the client program on the\n client host and sent to the server. The file can be given as a full\n path name to specify its exact location. If given as a relative path\n name, the name is interpreted relative to the directory in which the\n client program was started.\n\n When using LOCAL with LOAD DATA, a copy of the file is created in the\n server\'s temporary directory. This is not the directory determined by\n the value of tmpdir or slave_load_tmpdir, but rather the operating\n system\'s temporary directory, and is not configurable in the MySQL\n Server. (Typically the system temporary directory is /tmp on Linux\n systems and C:\\WINDOWS\\TEMP on Windows.) Lack of sufficient space for\n the copy in this directory can cause the LOAD DATA LOCAL statement to\n fail.\n\no If LOCAL is not specified, the file must be located on the server\n host and is read directly by the server. The server uses the\n following rules to locate the file:\n\n o If the file name is an absolute path name, the server uses it as\n given.\n\n o If the file name is a relative path name with one or more leading\n components, the server searches for the file relative to the\n server\'s data directory.\n\n o If a file name with no leading components is given, the server\n looks for the file in the database directory of the default\n database.\n\nNote that, in the non-LOCAL case, these rules mean that a file named as\n./myfile.txt is read from the server\'s data directory, whereas the file\nnamed as myfile.txt is read from the database directory of the default\ndatabase. For example, if db1 is the default database, the following\nLOAD DATA statement reads the file data.txt from the database directory\nfor db1, even though the statement explicitly loads the file into a\ntable in the db2 database:\n\nLOAD DATA INFILE \'data.txt\' INTO TABLE db2.my_table;\n\nWindows path names are specified using forward slashes rather than\nbackslashes. If you do use backslashes, you must double them.\n\nFor security reasons, when reading text files located on the server,\nthe files must either reside in the database directory or be readable\nby all. Also, to use LOAD DATA INFILE on server files, you must have\nthe FILE privilege. See\nhttps://mariadb.com/kb/en/grant/. For\nnon-LOCAL load operations, if the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nURL: https://mariadb.com/kb/en/load-data-infile/\n\n','','https://mariadb.com/kb/en/load-data-infile/'),(422,'MULTILINESTRING',24,'MultiLineString(ls1,ls2,...)\n\nConstructs a MultiLineString value using LineString or WKB LineString\narguments.\n\nURL: https://mariadb.com/kb/en/multilinestring/\n\n','','https://mariadb.com/kb/en/multilinestring/'),(423,'LOCALTIME',31,'Syntax:\nLOCALTIME, LOCALTIME()\n\nLOCALTIME and LOCALTIME() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtime/\n\n','','https://mariadb.com/kb/en/localtime/'),(424,'SHOW RELAYLOG EVENTS',26,'Syntax:\nSHOW RELAYLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the relay log of a replication slave. If you do not\nspecify \'log_name\', the first relay log is displayed. This statement\nhas no effect on the master.\n\nURL: https://mariadb.com/kb/en/show-relaylog-events/\n\n','','https://mariadb.com/kb/en/show-relaylog-events/'),(425,'MPOINTFROMTEXT',3,'MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])\n\nConstructs a MULTIPOINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromtext/\n\n','','https://mariadb.com/kb/en/mpointfromtext/'),(426,'BLOB',22,'BLOB[(M)]\n\nA BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each\nBLOB value is stored using a 2-byte length prefix that indicates the\nnumber of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest BLOB type large enough to hold\nvalues M bytes long.\n\nURL: https://mariadb.com/kb/en/blob/\n\n','','https://mariadb.com/kb/en/blob/'),(427,'SHA1',12,'Syntax:\nSHA1(str), SHA(str)\n\nCalculates an SHA-1 160-bit checksum for the string, as described in\nRFC 3174 (Secure Hash Algorithm). The value is returned as a string of\n40 hex digits, or NULL if the argument was NULL. One of the possible\nuses for this function is as a hash key. See the notes at the beginning\nof this section about storing hash values efficiently. You can also use\nSHA1() as a cryptographic function for storing passwords. SHA() is\nsynonymous with SHA1().\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha1/\n\n','MariaDB> SELECT SHA1(\'abc\');\n -> \'a9993e364706816aba3e25717850c26c9cd0d89d\'\n','https://mariadb.com/kb/en/sha1/'),(428,'SUBSTR',37,'Syntax:\nSUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str\nFROM pos FOR len)\n\nSUBSTR() is a synonym for SUBSTRING().\n\nURL: https://mariadb.com/kb/en/substr/\n\n','','https://mariadb.com/kb/en/substr/'),(429,'PASSWORD',12,'Syntax:\nPASSWORD(str)\n\nCalculates and returns a hashed password string from the plaintext\npassword str and returns a nonbinary string in the connection character\nset (a binary string before MySQL 5.5.3), or NULL if the argument is\nNULL. This function is the SQL interface to the algorithm used by the\nserver to encrypt MySQL passwords for storage in the mysql.user grant\ntable.\n\nThe password hashing method used by PASSWORD() depends on the value of\nthe old_passwords system variable:\n\nURL: https://mariadb.com/kb/en/password/\n\n','MariaDB> SET old_passwords = 0;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+-------------------------------------------+\n| PASSWORD(\'mypass\') |\n+-------------------------------------------+\n| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |\n+-------------------------------------------+\n\nMariaDB> SET old_passwords = 1;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+--------------------+\n| PASSWORD(\'mypass\') |\n+--------------------+\n| 6f8c114b58f2ce9e |\n+--------------------+\n','https://mariadb.com/kb/en/password/'),(430,'CHAR',22,'[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA fixed-length string that is always right-padded with spaces to the\nspecified length when stored. M represents the column length in\ncharacters. The range of M is 0 to 255. If M is omitted, the length is\n1.\n\n*Note*: Trailing spaces are removed when CHAR values are retrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n\nURL: https://mariadb.com/kb/en/char/\n\n','','https://mariadb.com/kb/en/char/'),(431,'UTC_DATE',31,'Syntax:\nUTC_DATE, UTC_DATE()\n\nReturns the current UTC date as a value in \'YYYY-MM-DD\' or YYYYMMDD\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_date/\n\n','MariaDB> SELECT UTC_DATE(), UTC_DATE() + 0;\n -> \'2003-08-14\', 20030814\n','https://mariadb.com/kb/en/utc_date/'),(432,'DIMENSION',36,'Dimension(g)\n\nReturns the inherent dimension of the geometry value g. The result can\nbe -1, 0, 1, or 2. The meaning of these values is given in\nhttps://mariadb.com/kb/en/dimension/.\n\nURL: https://mariadb.com/kb/en/dimension/\n\n','MariaDB> SELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n','https://mariadb.com/kb/en/dimension/'),(433,'COUNT DISTINCT',16,'Syntax:\nCOUNT(DISTINCT expr,[expr...])\n\nReturns a count of the number of rows with different non-NULL expr\nvalues.\n\nCOUNT(DISTINCT) returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count-distinct/\n\n','MariaDB> SELECT COUNT(DISTINCT results) FROM student;\n','https://mariadb.com/kb/en/count-distinct/'),(434,'BIT',22,'BIT[(M)]\n\nA bit-field type. M indicates the number of bits per value, from 1 to\n64. The default is 1 if M is omitted.\n\nURL: https://mariadb.com/kb/en/bit/\n\n','','https://mariadb.com/kb/en/bit/'),(435,'EQUALS',30,'Equals(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially equal to g2.\n\nURL: https://mariadb.com/kb/en/equals/\n\n','','https://mariadb.com/kb/en/equals/'),(436,'SHOW CREATE VIEW',26,'Syntax:\nSHOW CREATE VIEW view_name\n\nThis statement shows a CREATE VIEW statement that creates the given\nview.\n\nURL: https://mariadb.com/kb/en/show-create-view/\n\n','','https://mariadb.com/kb/en/show-create-view/'),(437,'INTERVAL',18,'Syntax:\nINTERVAL(N,N1,N2,N3,...)\n\nReturns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All\narguments are treated as integers. It is required that N1 < N2 < N3 <\n... < Nn for this function to work correctly. This is because a binary\nsearch is used (very fast).\n\nURL: https://mariadb.com/kb/en/interval/\n\n','MariaDB> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\n -> 3\nMariaDB> SELECT INTERVAL(10, 1, 10, 100, 1000);\n -> 2\nMariaDB> SELECT INTERVAL(22, 23, 30, 44, 200);\n -> 0\n','https://mariadb.com/kb/en/interval/'),(438,'FROM_DAYS',31,'Syntax:\nFROM_DAYS(N)\n\nGiven a day number N, returns a DATE value.\n\nURL: https://mariadb.com/kb/en/from_days/\n\n','MariaDB> SELECT FROM_DAYS(730669);\n -> \'2007-07-03\'\n','https://mariadb.com/kb/en/from_days/'),(439,'ALTER PROCEDURE',39,'Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nURL: https://mariadb.com/kb/en/alter-procedure/\n\n','','https://mariadb.com/kb/en/alter-procedure/'),(440,'BIT_COUNT',19,'Syntax:\nBIT_COUNT(N)\n\nReturns the number of bits that are set in the argument N.\n\nURL: https://mariadb.com/kb/en/bit_count/\n\n','MariaDB> SELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n -> 4, 3\n','https://mariadb.com/kb/en/bit_count/'),(441,'OCTET_LENGTH',37,'Syntax:\nOCTET_LENGTH(str)\n\nOCTET_LENGTH() is a synonym for LENGTH().\n\nURL: https://mariadb.com/kb/en/octet_length/\n\n','','https://mariadb.com/kb/en/octet_length/'),(442,'UTC_TIMESTAMP',31,'Syntax:\nUTC_TIMESTAMP, UTC_TIMESTAMP()\n\nReturns the current UTC date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is used in a string or numeric context.\n\nURL: https://mariadb.com/kb/en/utc_timestamp/\n\n','MariaDB> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n -> \'2003-08-14 18:08:04\', 20030814180804.000000\n','https://mariadb.com/kb/en/utc_timestamp/'),(443,'AES_ENCRYPT',12,'Syntax:\nAES_ENCRYPT(str,key_str)\n\nAES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of\ndata using the official AES (Advanced Encryption Standard) algorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit key length is\nused, but you can extend it up to 256 bits by modifying the source. We\nchose 128 bits because it is much faster and it is secure enough for\nmost purposes.\n\nAES_ENCRYPT() encrypts a string and returns a binary string.\nAES_DECRYPT() decrypts the encrypted string and returns the original\nstring. The input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n\nBecause AES is a block-level algorithm, padding is used to encode\nuneven length strings and so the result string length may be calculated\nusing this formula:\n\n16 * (trunc(string_length / 16) + 1)\n\nIf AES_DECRYPT() detects invalid data or incorrect padding, it returns\nNULL. However, it is possible for AES_DECRYPT() to return a non-NULL\nvalue (possibly garbage) if the input data or the key is invalid.\n\nYou can use the AES functions to store data in an encrypted form by\nmodifying your queries:\n\nURL: https://mariadb.com/kb/en/aes_encrypt/\n\n','INSERT INTO t VALUES (1,AES_ENCRYPT(\'text\',\'password\'));\n','https://mariadb.com/kb/en/aes_encrypt/'),(444,'+',4,'Syntax:\n+\n\nAddition:\n\nURL: https://mariadb.com/kb/en/addition-operator/\n\n','MariaDB> SELECT 3+5;\n -> 8\n','https://mariadb.com/kb/en/addition-operator/'),(445,'INET_NTOA',14,'Syntax:\nINET_NTOA(expr)\n\nGiven a numeric IPv4 network address in network byte order, returns the\ndotted-quad representation of the address as a string. INET_NTOA()\nreturns NULL if it does not understand its argument.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/inet_ntoa/\n\n','MariaDB> SELECT INET_NTOA(167773449);\n -> \'10.0.5.9\'\n','https://mariadb.com/kb/en/inet_ntoa/'),(446,'ACOS',4,'Syntax:\nACOS(X)\n\nReturns the arc cosine of X, that is, the value whose cosine is X.\nReturns NULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/acos/\n\n','MariaDB> SELECT ACOS(1);\n -> 0\nMariaDB> SELECT ACOS(1.0001);\n -> NULL\nMariaDB> SELECT ACOS(0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/acos/'),(447,'ISOLATION',8,'Syntax:\nSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL\n {\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n }\n\nThis statement sets the transaction isolation level, used for\noperations on InnoDB tables.\n\nScope of the Isolation Level\n\nYou can set the isolation level globally, for the current session, or\nfor the next transaction:\n\no With the GLOBAL keyword, the statement sets the default transaction\n level globally for all subsequent sessions. Existing sessions are\n unaffected.\n\no With the SESSION keyword, the statement sets the default transaction\n level for all subsequent transactions performed within the current\n session.\n\no Without any SESSION or GLOBAL keyword, the statement sets the\n isolation level for the next (not started) transaction performed\n within the current session.\n\nA change to the global default isolation level requires the SUPER\nprivilege. Any session is free to change its session isolation level\n(even in the middle of a transaction), or the isolation level for its\nnext transaction.\n\nSET TRANSACTION ISOLATION LEVEL without GLOBAL or SESSION is not\npermitted while there is an active transaction:\n\nMariaDB> START TRANSACTION;\nQuery OK, 0 rows affected (0.02 sec)\n\nMariaDB> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction isolation level can\'t be changed\nwhile a transaction is in progress\n\nTo set the global default isolation level at server startup, use the\n--transaction-isolation=level option to mysqld on the command line or\nin an option file. Values of level for this option use dashes rather\nthan spaces, so the permissible values are READ-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example, to set\nthe default isolation level to REPEATABLE READ, use these lines in the\n[mysqld] section of an option file:\n\n[mysqld]\ntransaction-isolation = REPEATABLE-READ\n\nIt is possible to check or set the global and session transaction\nisolation levels at runtime by using the tx_isolation system variable:\n\nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\nSET GLOBAL tx_isolation=\'REPEATABLE-READ\';\nSET SESSION tx_isolation=\'SERIALIZABLE\';\n\nDetails and Usage of Isolation Levels\n\nInnoDB supports each of the transaction isolation levels described here\nusing different locking strategies. You can enforce a high degree of\nconsistency with the default REPEATABLE READ level, for operations on\ncrucial data where ACID compliance is important. Or you can relax the\nconsistency rules with READ COMMITTED or even READ UNCOMMITTED, in\nsituations such as bulk reporting where precise consistency and\nrepeatable results are less important than minimizing the amount of\noverhead for locking. SERIALIZABLE enforces even stricter rules than\nREPEATABLE READ, and is used mainly in specialized situations, such as\nwith XA transactions and for troubleshooting issues with concurrency\nand deadlocks.\n\nFor full information about how these isolation levels work with InnoDB\ntransactions, see\nhttp://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html.\nIn particular, for additional information about InnoDB record-level\nlocks and how it uses them to execute various types of statements, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html\nand http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html.\n\nThe following list describes how MySQL supports the different\ntransaction levels. The list goes from the most commonly used level to\nthe least used.\n\no REPEATABLE READ\n\n This is the default isolation level for InnoDB. For consistent reads,\n there is an important difference from the READ COMMITTED isolation\n level: All consistent reads within the same transaction read the\n snapshot established by the first read. This convention means that if\n you issue several plain (nonlocking) SELECT statements within the\n same transaction, these SELECT statements are consistent also with\n respect to each other. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n UPDATE, and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition, or a\n range-type search condition. For a unique index with a unique search\n condition, InnoDB locks only the index record found, not the gap\n before it. For other search conditions, InnoDB locks the index range\n scanned, using gap locks or next-key (gap plus index-record) locks to\n block insertions by other sessions into the gaps covered by the\n range.\n\no READ COMMITTED\n\n A somewhat Oracle-like isolation level with respect to consistent\n (nonlocking) reads: Each consistent read, even within the same\n transaction, sets and reads its own fresh snapshot. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n InnoDB locks only index records, not the gaps before them, and thus\n permits the free insertion of new records next to locked records. For\n UPDATE and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition (such as\n WHERE id = 100), or a range-type search condition (such as WHERE id >\n 100). For a unique index with a unique search condition, InnoDB locks\n only the index record found, not the gap before it. For range-type\n searches, InnoDB locks the index range scanned, using gap locks or\n next-key (gap plus index-record) locks to block insertions by other\n sessions into the gaps covered by the range. This is necessary\n because \"phantom rows\" must be blocked for MySQL replication and\n recovery to work.\n\n *Note*: In MySQL 5.5, if the READ COMMITTED isolation level is used\n or the innodb_locks_unsafe_for_binlog system variable is enabled,\n there is no InnoDB gap locking except for foreign-key constraint\n checking and duplicate-key checking. Also, record locks for\n nonmatching rows are released after MySQL has evaluated the WHERE\n condition. If you use READ COMMITTED or enable\n innodb_locks_unsafe_for_binlog, you must use row-based binary\n logging.\n\no READ UNCOMMITTED\n\n SELECT statements are performed in a nonlocking fashion, but a\n possible earlier version of a row might be used. Thus, using this\n isolation level, such reads are not consistent. This is also called a\n \"dirty read.\" Otherwise, this isolation level works like READ\n COMMITTED.\n\no SERIALIZABLE\n\n This level is like REPEATABLE READ, but InnoDB implicitly converts\n all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if\n autocommit is disabled. If autocommit is enabled, the SELECT is its\n own transaction. It therefore is known to be read only and can be\n serialized if performed as a consistent (nonlocking) read and need\n not block for other transactions. (To force a plain SELECT to block\n if other transactions have modified the selected rows, disable\n autocommit.)\n\nURL: https://mariadb.com/kb/en/set-transaction-isolation-level/\n\n','','https://mariadb.com/kb/en/set-transaction-isolation-level/'),(448,'CEILING',4,'Syntax:\nCEILING(X)\n\nReturns the smallest integer value not less than X.\n\nURL: https://mariadb.com/kb/en/ceiling/\n\n','MariaDB> SELECT CEILING(1.23);\n -> 2\nMariaDB> SELECT CEILING(-1.23);\n -> -1\n','https://mariadb.com/kb/en/ceiling/'),(449,'SIN',4,'Syntax:\nSIN(X)\n\nReturns the sine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/sin/\n\n','MariaDB> SELECT SIN(PI());\n -> 1.2246063538224e-16\nMariaDB> SELECT ROUND(SIN(PI()));\n -> 0\n','https://mariadb.com/kb/en/sin/'),(450,'DAYOFWEEK',31,'Syntax:\nDAYOFWEEK(date)\n\nReturns the weekday index for date (1 = Sunday, 2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC standard.\n\nURL: https://mariadb.com/kb/en/dayofweek/\n\n','MariaDB> SELECT DAYOFWEEK(\'2007-02-03\');\n -> 7\n','https://mariadb.com/kb/en/dayofweek/'),(451,'SHOW PROCESSLIST',26,'Syntax:\nSHOW [FULL] PROCESSLIST\n\nSHOW PROCESSLIST shows you which threads are running. You can also get\nthis information from the INFORMATION_SCHEMA PROCESSLIST table or the\nmysqladmin processlist command. If you have the PROCESS privilege, you\ncan see all threads. Otherwise, you can see only your own threads (that\nis, threads associated with the MySQL account that you are using). If\nyou do not use the FULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n\nURL: https://mariadb.com/kb/en/show-processlist/\n\n','','https://mariadb.com/kb/en/show-processlist/'),(452,'LINEFROMWKB',32,'LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])\n\nConstructs a LINESTRING value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromwkb/\n\n','','https://mariadb.com/kb/en/linefromwkb/'),(453,'GEOMETRYTYPE',36,'GeometryType(g)\n\nReturns as a binary string the name of the geometry type of which the\ngeometry instance g is a member. The name corresponds to one of the\ninstantiable Geometry subclasses.\n\nURL: https://mariadb.com/kb/en/geometrytype/\n\n','MariaDB> SELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n','https://mariadb.com/kb/en/geometrytype/'),(454,'CREATE VIEW',39,'Syntax:\nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThe CREATE VIEW statement creates a new view, or replaces an existing\none if the OR REPLACE clause is given. If the view does not exist,\nCREATE OR REPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR REPLACE VIEW is the same as ALTER VIEW.\n\nThe select_statement is a SELECT statement that provides the definition\nof the view. (When you select from the view, you select in effect using\nthe SELECT statement.) select_statement can select from base tables or\nother views.\n\nThe view definition is \"frozen\" at creation time, so changes to the\nunderlying tables afterward do not affect the view definition. For\nexample, if a view is defined as SELECT * on a table, new columns added\nto the table later do not become part of the view.\n\nThe ALGORITHM clause affects how MySQL processes the view. The DEFINER\nand SQL SECURITY clauses specify the security context to be used when\nchecking access privileges at view invocation time. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates to rows in\ntables referenced by the view. These clauses are described later in\nthis section.\n\nThe CREATE VIEW statement requires the CREATE VIEW privilege for the\nview, and some privilege for each column selected by the SELECT\nstatement. For columns used elsewhere in the SELECT statement you must\nhave the SELECT privilege. If the OR REPLACE clause is present, you\nmust also have the DROP privilege for the view. CREATE VIEW might also\nrequire the SUPER privilege, depending on the DEFINER value, as\ndescribed later in this section.\n\nWhen a view is referenced, privilege checking occurs as described later\nin this section.\n\nA view belongs to a database. By default, a new view is created in the\ndefault database. To create the view explicitly in a given database,\nspecify the name as db_name.view_name when you create it:\n\nMariaDB> CREATE VIEW test.v AS SELECT * FROM t;\n\nWithin a database, base tables and views share the same namespace, so a\nbase table and a view cannot have the same name.\n\nColumns retrieved by the SELECT statement can be simple references to\ntable columns. They can also be expressions that use functions,\nconstant values, operators, and so forth.\n\nViews must have unique column names with no duplicates, just like base\ntables. By default, the names of the columns retrieved by the SELECT\nstatement are used for the view column names. To define explicit names\nfor the view columns, the optional column_list clause can be given as a\nlist of comma-separated identifiers. The number of names in column_list\nmust be the same as the number of columns retrieved by the SELECT\nstatement.\n\nUnqualified table or view names in the SELECT statement are interpreted\nwith respect to the default database. A view can refer to tables or\nviews in other databases by qualifying the table or view name with the\nproper database name.\n\nA view can be created from many kinds of SELECT statements. It can\nrefer to base tables or other views. It can use joins, UNION, and\nsubqueries. The SELECT need not even refer to any tables. The following\nexample defines a view that selects two columns from another table, as\nwell as an expression calculated from those columns:\n\nMariaDB> CREATE TABLE t (qty INT, price INT);\nMariaDB> INSERT INTO t VALUES(3, 50);\nMariaDB> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;\nMariaDB> SELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n\nA view definition is subject to the following restrictions:\n\no The SELECT statement cannot contain a subquery in the FROM clause.\n\no The SELECT statement cannot refer to system or user variables.\n\no Within a stored program, the definition cannot refer to program\n parameters or local variables.\n\no The SELECT statement cannot refer to prepared statement parameters.\n\no Any table or view referred to in the definition must exist. However,\n after a view has been created, it is possible to drop a table or view\n that the definition refers to. In this case, use of the view results\n in an error. To check a view definition for problems of this kind,\n use the CHECK TABLE statement.\n\no The definition cannot refer to a TEMPORARY table, and you cannot\n create a TEMPORARY view.\n\no Any tables named in the view definition must exist at definition\n time.\n\no You cannot associate a trigger with a view.\n\no Aliases for column names in the SELECT statement are checked against\n the maximum column length of 64 characters (not the maximum alias\n length of 256 characters).\n\nORDER BY is permitted in a view definition, but it is ignored if you\nselect from a view using a statement that has its own ORDER BY.\n\nFor other options or clauses in the definition, they are added to the\noptions or clauses of the statement that references the view, but the\neffect is undefined. For example, if a view definition includes a LIMIT\nclause, and you select from the view using a statement that has its own\nLIMIT clause, it is undefined which limit applies. This same principle\napplies to options such as ALL, DISTINCT, or SQL_SMALL_RESULT that\nfollow the SELECT keyword, and to clauses such as INTO, FOR UPDATE,\nLOCK IN SHARE MODE, and PROCEDURE.\n\nIf you create a view and then change the query processing environment\nby changing system variables, that may affect the results that you get\nfrom the view:\n\nMariaDB> CREATE VIEW v (mycol) AS SELECT \'abc\';\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SET sql_mode = \'\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol |\n+-------+\n1 row in set (0.01 sec)\n\nMariaDB> SET sql_mode = \'ANSI_QUOTES\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc |\n+-------+\n1 row in set (0.00 sec)\n\nThe DEFINER and SQL SECURITY clauses determine which MySQL account to\nuse when checking access privileges for the view when a statement is\nexecuted that references the view. The valid SQL SECURITY\ncharacteristic values are DEFINER and INVOKER. These indicate that the\nrequired privileges must be held by the user who defined or invoked the\nview, respectively. The default SQL SECURITY value is DEFINER.\n\nIf a user value is given for the DEFINER clause, it should be a MySQL\naccount specified as \'user_name\'@\'host_name\' (the same format used in\nthe GRANT statement), CURRENT_USER, or CURRENT_USER(). The default\nDEFINER value is the user who executes the CREATE VIEW statement. This\nis the same as specifying DEFINER = CURRENT_USER explicitly.\n\nIf you specify the DEFINER clause, these rules determine the valid\nDEFINER user values:\n\no If you do not have the SUPER privilege, the only valid user value is\n your own account, either specified literally or by using\n CURRENT_USER. You cannot set the definer to some other account.\n\no If you have the SUPER privilege, you can specify any syntactically\n valid account name. If the account does not actually exist, a warning\n is generated.\n\no Although it is possible to create a view with a nonexistent DEFINER\n account, an error occurs when the view is referenced if the SQL\n SECURITY value is DEFINER but the definer account does not exist.\n\nFor more information about view security, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nWithin a view definition, CURRENT_USER returns the view\'s DEFINER value\nby default. For views defined with the SQL SECURITY INVOKER\ncharacteristic, CURRENT_USER returns the account for the view\'s\ninvoker. For information about user auditing within views, see\nhttp://dev.mysql.com/doc/refman/5.5/en/account-activity-auditing.html.\n\nWithin a stored routine that is defined with the SQL SECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER value. This\nalso affects a view defined within such a routine, if the view\ndefinition contains a DEFINER value of CURRENT_USER.\n\nView privileges are checked like this:\n\no At view definition time, the view creator must have the privileges\n needed to use the top-level objects accessed by the view. For\n example, if the view definition refers to table columns, the creator\n must have some privilege for each column in the select list of the\n definition, and the SELECT privilege for each column used elsewhere\n in the definition. If the definition refers to a stored function,\n only the privileges needed to invoke the function can be checked. The\n privileges required at function invocation time can be checked only\n as it executes: For different invocations, different execution paths\n within the function might be taken.\n\no The user who references a view must have appropriate privileges to\n access it (SELECT to select from it, INSERT to insert into it, and so\n forth.)\n\no When a view has been referenced, privileges for objects accessed by\n the view are checked against the privileges held by the view DEFINER\n account or invoker, depending on whether the SQL SECURITY\n characteristic is DEFINER or INVOKER, respectively.\n\no If reference to a view causes execution of a stored function,\n privilege checking for statements executed within the function depend\n on whether the function SQL SECURITY characteristic is DEFINER or\n INVOKER. If the security characteristic is DEFINER, the function runs\n with the privileges of the DEFINER account. If the characteristic is\n INVOKER, the function runs with the privileges determined by the\n view\'s SQL SECURITY characteristic.\n\nExample: A view might depend on a stored function, and that function\nmight invoke other stored routines. For example, the following view\ninvokes a stored function f():\n\nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n\nSuppose that f() contains a statement such as this:\n\nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n\nThe privileges required for executing statements within f() need to be\nchecked when f() executes. This might mean that privileges are needed\nfor p1() or p2(), depending on the execution path within f(). Those\nprivileges must be checked at runtime, and the user who must possess\nthe privileges is determined by the SQL SECURITY values of the view v\nand the function f().\n\nThe DEFINER and SQL SECURITY clauses for views are extensions to\nstandard SQL. In standard SQL, views are handled using the rules for\nSQL SECURITY DEFINER. The standard says that the definer of the view,\nwhich is the same as the owner of the view\'s schema, gets applicable\nprivileges on the view (for example, SELECT) and may grant them. MySQL\nhas no concept of a schema \"owner\", so MySQL adds a clause to identify\nthe definer. The DEFINER clause is an extension where the intent is to\nhave what the standard has; that is, a permanent record of who defined\nthe view. This is why the default DEFINER value is the account of the\nview creator.\n\nThe optional ALGORITHM clause is a MySQL extension to standard SQL. It\naffects how MySQL processes the view. ALGORITHM takes three values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is UNDEFINED if\nno ALGORITHM clause is present. For more information, see\nhttps://mariadb.com/kb/en/view-algorithms/.\n\nSome views are updatable. That is, you can use them in statements such\nas UPDATE, DELETE, or INSERT to update the contents of the underlying\ntable. For a view to be updatable, there must be a one-to-one\nrelationship between the rows in the view and the rows in the\nunderlying table. There are also certain other constructs that make a\nview nonupdatable.\n\nThe WITH CHECK OPTION clause can be given for an updatable view to\nprevent inserts or updates to rows except those for which the WHERE\nclause in the select_statement is true.\n\nIn a WITH CHECK OPTION clause for an updatable view, the LOCAL and\nCASCADED keywords determine the scope of check testing when the view is\ndefined in terms of another view. The LOCAL keyword restricts the CHECK\nOPTION only to the view being defined. CASCADED causes the checks for\nunderlying views to be evaluated as well. When neither keyword is\ngiven, the default is CASCADED.\n\nFor more information about updatable views and the WITH CHECK OPTION\nclause, see\nhttps://mariadb.com/kb/en/inserting-and-updating-with-views/.\n\nURL: https://mariadb.com/kb/en/create-view/\n\n','','https://mariadb.com/kb/en/create-view/'),(455,'TRIM',37,'Syntax:\nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr\nFROM] str)\n\nReturns the string str with all remstr prefixes or suffixes removed. If\nnone of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is\nassumed. remstr is optional and, if not specified, spaces are removed.\n\nURL: https://mariadb.com/kb/en/trim/\n\n','MariaDB> SELECT TRIM(\' bar \');\n -> \'bar\'\nMariaDB> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');\n -> \'barxxx\'\nMariaDB> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');\n -> \'bar\'\nMariaDB> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');\n -> \'barx\'\n','https://mariadb.com/kb/en/trim/'),(456,'IS',18,'Syntax:\nIS boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is/\n\n','MariaDB> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n -> 1, 1, 1\n','https://mariadb.com/kb/en/is/'),(457,'GET_FORMAT',31,'Syntax:\nGET_FORMAT({DATE|TIME|DATETIME}, {\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n\nReturns a format string. This function is useful in combination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n\nURL: https://mariadb.com/kb/en/get_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n -> \'03.10.2003\'\nMariaDB> SELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n -> \'2003-10-31\'\n','https://mariadb.com/kb/en/get_format/'),(458,'TINYBLOB',22,'TINYBLOB\n\nA BLOB column with a maximum length of 255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a 1-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinyblob/\n\n','','https://mariadb.com/kb/en/tinyblob/'),(459,'SIGNAL',23,'Syntax:\nSIGNAL condition_value\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nSIGNAL is the way to \"return\" an error. SIGNAL provides error\ninformation to a handler, to an outer portion of the application, or to\nthe client. Also, it provides control over the error\'s characteristics\n(error number, SQLSTATE value, message). Without SIGNAL, it is\nnecessary to resort to workarounds such as deliberately referring to a\nnonexistent table to cause a routine to return an error.\n\nNo special privileges are required to execute the SIGNAL statement.\n\nThe condition_value in a SIGNAL statement indicates the error value to\nbe returned. It can be an SQLSTATE value (a 5-character string literal)\nor a condition_name that refers to a named condition previously defined\nwith DECLARE ... CONDITION (see [HELP DECLARE CONDITION]).\n\nAn SQLSTATE value can indicate errors, warnings, or \"not found.\" The\nfirst two characters of the value indicate its error class, as\ndiscussed in\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items. Some signal values cause statement termination; see\nhttps://mariadb.com/kb/en/signal/#signal-effects.\n\nThe SQLSTATE value for a SIGNAL statement should not start with \'00\'\nbecause such values indicate success and are not valid for signaling an\nerror. This is true whether the SQLSTATE value is specified directly in\nthe SIGNAL statement or in a named condition referred to in the\nstatement. If the value is invalid, a Bad SQLSTATE error occurs.\n\nTo signal a generic SQLSTATE value, use \'45000\', which means \"unhandled\nuser-defined exception.\"\n\nThe SIGNAL statement optionally includes a SET clause that contains\nmultiple signal items, in a comma-separated list of\ncondition_information_item_name = simple_value_specification\nassignments.\n\nEach condition_information_item_name may be specified only once in the\nSET clause. Otherwise, a Duplicate condition information item error\noccurs.\n\nValid simple_value_specification designators can be specified using\nstored procedure or function parameters, stored program local variables\ndeclared with DECLARE, user-defined variables, system variables, or\nliterals. A character literal may include a _charset introducer.\n\nFor information about permissible condition_information_item_name\nvalues, see\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items.\n\nURL: https://mariadb.com/kb/en/signal/\n\n','CREATE PROCEDURE p (pval INT)\nBEGIN\n DECLARE specialty CONDITION FOR SQLSTATE \'45000\';\n IF pval = 0 THEN\n SIGNAL SQLSTATE \'01000\';\n ELSEIF pval = 1 THEN\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSEIF pval = 2 THEN\n SIGNAL specialty\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSE\n SIGNAL SQLSTATE \'01000\'\n SET MESSAGE_TEXT = \'A warning occurred\', MYSQL_ERRNO = 1000;\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\', MYSQL_ERRNO = 1001;\n END IF;\nEND;\n','https://mariadb.com/kb/en/signal/'),(460,'SAVEPOINT',8,'Syntax:\nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n\nInnoDB supports the SQL statements SAVEPOINT, ROLLBACK TO SAVEPOINT,\nRELEASE SAVEPOINT and the optional WORK keyword for ROLLBACK.\n\nURL: https://mariadb.com/kb/en/savepoint/\n\n','','https://mariadb.com/kb/en/savepoint/'),(461,'USER',17,'Syntax:\nUSER()\n\nReturns the current MySQL user name and host name as a string in the\nutf8 character set.\n\nURL: https://mariadb.com/kb/en/user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\n','https://mariadb.com/kb/en/user/'),(462,'LABELS',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nLabels are permitted for BEGIN ... END blocks and for the LOOP, REPEAT,\nand WHILE statements. Label use for those statements follows these\nrules:\n\no begin_label must be followed by a colon.\n\no begin_label can be given without end_label. If end_label is present,\n it must be the same as begin_label.\n\no end_label cannot be given without begin_label.\n\no Labels at the same nesting level must be distinct.\n\no Labels can be up to 16 characters long.\n\nTo refer to a label within the labeled construct, use an ITERATE or\nLEAVE statement. The following example uses those statements to\ncontinue iterating or terminate the loop:\n\nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN ITERATE label1; END IF;\n LEAVE label1;\n END LOOP label1;\nEND;\n\nThe scope of a block label does not include the code for handlers\ndeclared within the block. For details, see [HELP DECLARE HANDLER].\n\nURL: https://mariadb.com/kb/en/labels/\n\n','','https://mariadb.com/kb/en/labels/'),(463,'ALTER TABLE',39,'Syntax:\nALTER [ONLINE | OFFLINE] [IGNORE] TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (index_col_name,...)\n reference_definition\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] col_name\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} index_name\n | DROP FOREIGN KEY fk_symbol\n | MAX_ROWS = rows\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO|AS] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | FORCE\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO (partition_definitions)]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | PARTITION BY partitioning_expression\n | REMOVE PARTITIONING\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\ntable_options:\n table_option [[,] table_option] ... (see CREATE TABLE options)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\nPartitioning-related clauses for ALTER TABLE can be used with\npartitioned tables for repartitioning, for adding, dropping, merging,\nand splitting partitions, and for performing partitioning maintenance.\nFor more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations\n.html.\n\nFollowing the table name, specify the alterations to be made. If none\nare given, ALTER TABLE does nothing.\n\nURL: https://mariadb.com/kb/en/alter-table/\n\n','','https://mariadb.com/kb/en/alter-table/'),(464,'MPOINTFROMWKB',32,'MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])\n\nConstructs a MULTIPOINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromwkb/\n\n','','https://mariadb.com/kb/en/mpointfromwkb/'),(465,'CHAR BYTE',22,'The CHAR BYTE data type is an alias for the BINARY data type. This is a\ncompatibility feature.\n\nURL: https://mariadb.com/kb/en/char-byte/\n\n','','https://mariadb.com/kb/en/char-byte/'),(466,'REPAIR TABLE',20,'Syntax:\nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n\nREPAIR TABLE repairs a possibly corrupted table. By default, it has the\nsame effect as myisamchk --recover tbl_name. REPAIR TABLE works for\nMyISAM, ARCHIVE, and CSV tables. See\nhttps://mariadb.com/kb/en/myisam-storage-engine/, and\nhttps://mariadb.com/kb/en/archive/, and\nhttps://mariadb.com/kb/en/csv/\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nREPAIR TABLE is supported for partitioned tables. However, the USE_FRM\noption cannot be used with this statement on a partitioned table.\n\nYou can use ALTER TABLE ... REPAIR PARTITION to repair one or more\npartitions; for more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/repair-table/\n\n','','https://mariadb.com/kb/en/repair-table/'),(467,'MERGE',39,'The MERGE storage engine, also known as the MRG_MyISAM engine, is a\ncollection of identical MyISAM tables that can be used as one.\n\"Identical\" means that all tables have identical column and index\ninformation. You cannot merge MyISAM tables in which the columns are\nlisted in a different order, do not have exactly the same columns, or\nhave the indexes in different order. However, any or all of the MyISAM\ntables can be compressed with myisampack. See\nhttps://mariadb.com/kb/en/myisampack/. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS do not\nmatter.\n\nURL: https://mariadb.com/kb/en/merge/\n\n','MariaDB> CREATE TABLE t1 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> CREATE TABLE t2 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> INSERT INTO t1 (message) VALUES (\'Testing\'),(\'table\'),(\'t1\');\nMariaDB> INSERT INTO t2 (message) VALUES (\'Testing\'),(\'table\'),(\'t2\');\nMariaDB> CREATE TABLE total (\n -> a INT NOT NULL AUTO_INCREMENT,\n -> message CHAR(20), INDEX(a))\n -> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n','https://mariadb.com/kb/en/merge/'),(468,'CREATE TABLE',39,'Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n select_statement\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT default_value]\n [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [STORAGE {DISK|MEMORY|DEFAULT}]\n [reference_definition]\n\ndata_type:\n BIT[(length)]\n | TINYINT[(length)] [UNSIGNED] [ZEROFILL]\n | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]\n | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]\n | INT[(length)] [UNSIGNED] [ZEROFILL]\n | INTEGER[(length)] [UNSIGNED] [ZEROFILL]\n | BIGINT[(length)] [UNSIGNED] [ZEROFILL]\n | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | DATE\n | TIME\n | TIMESTAMP\n | DATETIME\n | YEAR\n | CHAR[(length)]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | VARCHAR(length)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | BINARY[(length)]\n | VARBINARY(length)\n | TINYBLOB\n | BLOB\n | MEDIUMBLOB\n | LONGBLOB\n | TINYTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | TEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | MEDIUMTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | LONGTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | ENUM(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | SET(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | spatial_type\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES \n {LESS THAN {(expr | value_list) | MAXVALUE} \n | \n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n\nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some valid select statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nRules for permissible table names are given in\nhttps://mariadb.com/kb/en/identifier-names/. By default,\nthe table is created in the default database, using the InnoDB storage\nengine. An error occurs if the table exists, if there is no default\ndatabase, or if the database does not exist.\n\nURL: https://mariadb.com/kb/en/create-table/\n\n','','https://mariadb.com/kb/en/create-table/'),(469,'>',18,'Syntax:\n>\n\nGreater than:\n\nURL: https://mariadb.com/kb/en/greater-than/\n\n','MariaDB> SELECT 2 > 2;\n -> 0\n','https://mariadb.com/kb/en/greater-than/'),(470,'ANALYZE TABLE',20,'Syntax:\nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nANALYZE TABLE analyzes and stores the key distribution for a table.\nDuring the analysis, the table is locked with a read lock for InnoDB\nand MyISAM. This statement works with InnoDB, Aria and MyISAM tables.\nFor MyISAM tables, this statement is equivalent to using myisamchk\n--analyze.\n\nFor more information on how the analysis works within InnoDB, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html.\n\nMySQL uses the stored key distribution to decide the order in which\ntables should be joined when you perform a join on something other than\na constant. In addition, key distributions can be used when deciding\nwhich indexes to use for a specific table within a query.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nANALYZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... ANALYZE PARTITION to analyze one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/analyze-table/\n\n','','https://mariadb.com/kb/en/analyze-table/'),(471,'MICROSECOND',31,'Syntax:\nMICROSECOND(expr)\n\nReturns the microseconds from the time or datetime expression expr as a\nnumber in the range from 0 to 999999.\n\nURL: https://mariadb.com/kb/en/microsecond/\n\n','MariaDB> SELECT MICROSECOND(\'12:00:00.123456\');\n -> 123456\nMariaDB> SELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n -> 10\n','https://mariadb.com/kb/en/microsecond/'),(472,'CONSTRAINT',39,'InnoDB supports foreign keys, which let you cross-reference related\ndata across tables, and foreign key constraints, which help keep this\nspread-out data consistent. The syntax for an InnoDB foreign key\nconstraint definition in the CREATE TABLE or ALTER TABLE statement\nlooks like this:\n\n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\nURL: https://mariadb.com/kb/en/constraint/\n\n','CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n','https://mariadb.com/kb/en/constraint/'),(473,'CREATE SERVER',39,'Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nwithin the servers table within the mysql database. This statement\nrequires the SUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name should be mysql, and may be quoted with single\nquotation marks. Other values for wrapper_name are not currently\nsupported.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*: Note that the OWNER option is currently not applied, and has no\neffect on the ownership or operation of the server connection that is\ncreated.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: https://mariadb.com/kb/en/create-server/\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE \'test\');\n','https://mariadb.com/kb/en/create-server/'),(474,'FIELD',37,'Syntax:\nFIELD(str,str1,str2,str3,...)\n\nReturns the index (position) of str in the str1, str2, str3, ... list.\nReturns 0 if str is not found.\n\nIf all arguments to FIELD() are strings, all arguments are compared as\nstrings. If all arguments are numbers, they are compared as numbers.\nOtherwise, the arguments are compared as double.\n\nIf str is NULL, the return value is 0 because NULL fails equality\ncomparison with any value. FIELD() is the complement of ELT().\n\nURL: https://mariadb.com/kb/en/field/\n\n','MariaDB> SELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 2\nMariaDB> SELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 0\n','https://mariadb.com/kb/en/field/'),(475,'MAKETIME',31,'Syntax:\nMAKETIME(hour,minute,second)\n\nReturns a time value calculated from the hour, minute, and second\narguments.\n\nURL: https://mariadb.com/kb/en/maketime/\n\n','MariaDB> SELECT MAKETIME(12,15,30);\n -> \'12:15:30\'\n','https://mariadb.com/kb/en/maketime/'),(476,'CURDATE',31,'Syntax:\nCURDATE()\n\nReturns the current date as a value in \'YYYY-MM-DD\' or YYYYMMDD format,\ndepending on whether the function is used in a string or numeric\ncontext.\n\nURL: https://mariadb.com/kb/en/curdate/\n\n','MariaDB> SELECT CURDATE();\n -> \'2008-06-13\'\nMariaDB> SELECT CURDATE() + 0;\n -> 20080613\n','https://mariadb.com/kb/en/curdate/'),(477,'SET PASSWORD',10,'Syntax:\nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'cleartext password\')\n | OLD_PASSWORD(\'cleartext password\')\n | \'encrypted password\'\n }\n\nThe SET PASSWORD statement assigns a password to an existing MySQL user\naccount. When the read_only system variable is enabled, the SUPER\nprivilege is required to use SET PASSWORD, in addition to whatever\nother privileges might be required.\n\nIf the password is specified using the PASSWORD() or OLD_PASSWORD()\nfunction, the cleartext (unencrypted) password should be given as the\nargument to the function, which hashes the password and returns the\nencrypted password string. If the password is specified without using\neither function, it should be the already encrypted password value as a\nliteral string. In all cases, the encrypted password string must be in\nthe format required by the authentication method used for the account.\n\nThe old_passwords system variable value determines the hashing method\nused by PASSWORD(). If you specify the password using that function and\nSET PASSWORD rejects the password as not being in the correct format,\nit may be necessary to set old_passwords to change the hashing method.\nFor descriptions of the permitted values, see\nhttps://mariadb.com/kb/en/server-system-variables#old_passwords.\n\nWith no FOR user clause, this statement sets the password for the\ncurrent user. (To see which account the server authenticated you as,\ninvoke the CURRENT_USER() function.) Any client who successfully\nconnects to the server using a nonanonymous account can change the\npassword for that account.\n\nWith a FOR user clause, this statement sets the password for the named\nuser. You must have the UPDATE privilege for the mysql database to do\nthis. The user account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. The user\nvalue should be given as \'user_name\'@\'host_name\', where \'user_name\' and\n\'host_name\' are exactly as listed in the User and Host columns of the\nmysql.user table row. (If you specify only a user name, a host name of\n\'%\' is used.) For example, to set the password for an account with User\nand Host column values of \'bob\' and \'%.example.org\', write the\nstatement like this:\n\nSET PASSWORD FOR \'bob\'@\'%.example.org\' = PASSWORD(\'cleartext password\');\n\nURL: https://mariadb.com/kb/en/set-password/\n\n','','https://mariadb.com/kb/en/set-password/'),(478,'ALTER TABLESPACE',39,'Syntax:\nALTER TABLESPACE tablespace_name\n {ADD|DROP} DATAFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/alter-tablespace/\n\n','','https://mariadb.com/kb/en/alter-tablespace/'),(479,'IF FUNCTION',7,'Syntax:\nIF(expr1,expr2,expr3)\n\nIf expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns\nexpr2; otherwise it returns expr3. IF() returns a numeric or string\nvalue, depending on the context in which it is used.\n\nURL: https://mariadb.com/kb/en/if-function/\n\n','MariaDB> SELECT IF(1>2,2,3);\n -> 3\nMariaDB> SELECT IF(1<2,\'yes\',\'no\');\n -> \'yes\'\nMariaDB> SELECT IF(STRCMP(\'test\',\'test1\'),\'no\',\'yes\');\n -> \'no\'\n','https://mariadb.com/kb/en/if-function/'),(480,'ENUM',22,'ENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nAn enumeration. A string object that can have only one value, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or the special \'\'\nerror value. An ENUM column can have a maximum of 65,535 distinct\nvalues. ENUM values are represented internally as integers.\n\nURL: https://mariadb.com/kb/en/enum/\n\n','','https://mariadb.com/kb/en/enum/'),(481,'DATABASE',17,'Syntax:\nDATABASE()\n\nReturns the default (current) database name as a string in the utf8\ncharacter set. If there is no default database, DATABASE() returns\nNULL. Within a stored routine, the default database is the database\nthat the routine is associated with, which is not necessarily the same\nas the database that is the default in the calling context.\n\nURL: https://mariadb.com/kb/en/database/\n\n','MariaDB> SELECT DATABASE();\n -> \'test\'\n','https://mariadb.com/kb/en/database/'),(482,'POINTFROMWKB',32,'PointFromWKB(wkb[,srid])\n\nConstructs a POINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromwkb/\n\n','','https://mariadb.com/kb/en/pointfromwkb/'),(483,'POWER',4,'Syntax:\nPOWER(X,Y)\n\nThis is a synonym for POW().\n\nURL: https://mariadb.com/kb/en/power/\n\n','','https://mariadb.com/kb/en/power/'),(484,'ATAN',4,'Syntax:\nATAN(X)\n\nReturns the arc tangent of X, that is, the value whose tangent is X.\n\nURL: https://mariadb.com/kb/en/atan/\n\n','MariaDB> SELECT ATAN(2);\n -> 1.1071487177941\nMariaDB> SELECT ATAN(-2);\n -> -1.1071487177941\n','https://mariadb.com/kb/en/atan/'),(485,'STRCMP',37,'Syntax:\nSTRCMP(expr1,expr2)\n\nSTRCMP() returns 0 if the strings are the same, -1 if the first\nargument is smaller than the second according to the current sort\norder, and 1 otherwise.\n\nURL: https://mariadb.com/kb/en/strcmp/\n\n','MariaDB> SELECT STRCMP(\'text\', \'text2\');\n -> -1\nMariaDB> SELECT STRCMP(\'text2\', \'text\');\n -> 1\nMariaDB> SELECT STRCMP(\'text\', \'text\');\n -> 0\n','https://mariadb.com/kb/en/strcmp/'),(486,'INSERT DELAYED',27,'Syntax:\nINSERT DELAYED ...\n\nThe DELAYED option for the INSERT statement is a MySQL extension to\nstandard SQL that is very useful if you have clients that cannot or\nneed not wait for the INSERT to complete. This is a common situation\nwhen you use MySQL for logging and you also periodically run SELECT and\nUPDATE statements that take a long time to complete.\n\nWhen a client uses INSERT DELAYED, it gets an okay from the server at\nonce, and the row is queued to be inserted when the table is not in use\nby any other thread.\n\nAnother major benefit of using INSERT DELAYED is that inserts from many\nclients are bundled together and written in one block. This is much\nfaster than performing many separate inserts.\n\nNote that INSERT DELAYED is slower than a normal INSERT if the table is\nnot otherwise in use. There is also the additional overhead for the\nserver to handle a separate thread for each table for which there are\ndelayed rows. This means that you should use INSERT DELAYED only when\nyou are really sure that you need it.\n\nThe queued rows are held only in memory until they are inserted into\nthe table. This means that if you terminate mysqld forcibly (for\nexample, with kill -9) or if mysqld dies unexpectedly, any queued rows\nthat have not been written to disk are lost.\n\nThere are some constraints on the use of DELAYED:\n\no INSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE, and BLACKHOLE\n tables. For engines that do not support DELAYED, an error occurs.\n\no An error occurs for INSERT DELAYED if used with a table that has been\n locked with LOCK TABLES because the insert must be handled by a\n separate thread, not by the session that holds the lock.\n\no For MyISAM tables, if there are no free blocks in the middle of the\n data file, concurrent SELECT and INSERT statements are supported.\n Under these circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\n\no INSERT DELAYED should be used only for INSERT statements that specify\n value lists. The server ignores DELAYED for INSERT ... SELECT or\n INSERT ... ON DUPLICATE KEY UPDATE statements.\n\no Because the INSERT DELAYED statement returns immediately, before the\n rows are inserted, you cannot use LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\n\no DELAYED rows are not visible to SELECT statements until they actually\n have been inserted.\n\no Prior to MySQL 5.5.7, INSERT DELAYED was treated as a normal INSERT\n if the statement inserted multiple rows, binary logging was enabled,\n and the global logging format was statement-based (that is, whenever\n binlog_format was set to STATEMENT). Beginning with MySQL 5.5.7,\n INSERT DELAYED is always handled as a simple INSERT (that is, without\n the DELAYED option) whenever the value of binlog_format is STATEMENT\n or MIXED. (In the latter case, the statement no longer triggers a\n switch to row-based logging, and so is logged using the\n statement-based format.)\n\n This does not apply when using row-based binary logging mode\n (binlog_format set to ROW), in which INSERT DELAYED statements are\n always executed using the DELAYED option as specified, and logged as\n row-update events.\n\no DELAYED is ignored on slave replication servers, so that INSERT\n DELAYED is treated as a normal INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than the master.\n\no Pending INSERT DELAYED statements are lost if a table is write locked\n and ALTER TABLE is used to modify the table structure.\n\no INSERT DELAYED is not supported for views.\n\no INSERT DELAYED is not supported for partitioned tables.\n\nURL: https://mariadb.com/kb/en/insert-delayed/\n\n','','https://mariadb.com/kb/en/insert-delayed/'),(487,'SHOW PROFILE',26,'Syntax:\nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n\ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n\nThe SHOW PROFILE and SHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements executed\nduring the course of the current session.\n\nProfiling is controlled by the profiling session variable, which has a\ndefault value of 0 (OFF). Profiling is enabled by setting profiling to\n1 or ON:\n\nMariaDB> SET profiling = 1;\n\nSHOW PROFILES displays a list of the most recent statements sent to the\nserver. The size of the list is controlled by the\nprofiling_history_size session variable, which has a default value of\n15. The maximum value is 100. Setting the value to 0 has the practical\neffect of disabling profiling.\n\nAll statements are profiled except SHOW PROFILE and SHOW PROFILES, so\nyou will find neither of those statements in the profile list.\nMalformed statements are profiled. For example, SHOW PROFILING is an\nillegal statement, and a syntax error occurs if you try to execute it,\nbut it will show up in the profiling list.\n\nSHOW PROFILE displays detailed information about a single statement.\nWithout the FOR QUERY n clause, the output pertains to the most\nrecently executed statement. If FOR QUERY n is included, SHOW PROFILE\ndisplays information for statement n. The values of n correspond to the\nQuery_ID values displayed by SHOW PROFILES.\n\nThe LIMIT row_count clause may be given to limit the output to\nrow_count rows. If LIMIT is given, OFFSET offset may be added to begin\nthe output offset rows into the full set of rows.\n\nBy default, SHOW PROFILE displays Status and Duration columns. The\nStatus values are like the State values displayed by SHOW PROCESSLIST,\nalthough there might be some minor differences in interpretion for the\ntwo statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.5/en/thread-information.html).\n\nOptional type values may be specified to display specific additional\ntypes of information:\n\no ALL displays all information\n\no BLOCK IO displays counts for block input and output operations\n\no CONTEXT SWITCHES displays counts for voluntary and involuntary\n context switches\n\no CPU displays user and system CPU usage times\n\no IPC displays counts for messages sent and received\n\no MEMORY is not currently implemented\n\no PAGE FAULTS displays counts for major and minor page faults\n\no SOURCE displays the names of functions from the source code, together\n with the name and line number of the file in which the function\n occurs\n\no SWAPS displays swap counts\n\nProfiling is enabled per session. When a session ends, its profiling\ninformation is lost.\n\nURL: https://mariadb.com/kb/en/show-profile/\n\n','MariaDB> SELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> SET profiling = 1;\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> DROP TABLE IF EXISTS t1;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nMariaDB> CREATE TABLE T1 (id INT);\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SHOW PROFILES;\n+----------+----------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+----------+--------------------------+\n| 0 | 0.000088 | SET PROFILING = 1 |\n| 1 | 0.000136 | DROP TABLE IF EXISTS t1 |\n| 2 | 0.011947 | CREATE TABLE t1 (id INT) |\n+----------+----------+--------------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| checking permissions | 0.000040 |\n| creating table | 0.000056 |\n| After create | 0.011363 |\n| query end | 0.000375 |\n| freeing items | 0.000089 |\n| logging slow query | 0.000019 |\n| cleaning up | 0.000005 |\n+----------------------+----------+\n7 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE FOR QUERY 1;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| query end | 0.000107 |\n| freeing items | 0.000008 |\n| logging slow query | 0.000015 |\n| cleaning up | 0.000006 |\n+--------------------+----------+\n4 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE CPU FOR QUERY 2;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| checking permissions | 0.000040 | 0.000038 | 0.000002 |\n| creating table | 0.000056 | 0.000028 | 0.000028 |\n| After create | 0.011363 | 0.000217 | 0.001571 |\n| query end | 0.000375 | 0.000013 | 0.000028 |\n| freeing items | 0.000089 | 0.000010 | 0.000014 |\n| logging slow query | 0.000019 | 0.000009 | 0.000010 |\n| cleaning up | 0.000005 | 0.000003 | 0.000002 |\n+----------------------+----------+----------+------------+\n7 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-profile/'),(488,'SHOW PROCEDURE CODE',26,'Syntax:\nSHOW PROCEDURE CODE proc_name\n\nThis statement is a MySQL extension that is available only for servers\nthat have been built with debugging support. It displays a\nrepresentation of the internal implementation of the named stored\nprocedure. A similar statement, SHOW FUNCTION CODE, displays\ninformation about stored functions (see [HELP SHOW FUNCTION CODE]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table.\n\nIf the named routine is available, each statement produces a result\nset. Each row in the result set corresponds to one \"instruction\" in the\nroutine. The first column is Pos, which is an ordinal number beginning\nwith 0. The second column is Instruction, which contains an SQL\nstatement (usually changed from the original source), or a directive\nwhich has meaning only to the stored-routine handler.\n\nURL: https://mariadb.com/kb/en/show-procedure-code/\n\n','MariaDB> DELIMITER //\nMariaDB> CREATE PROCEDURE p1 ()\n -> BEGIN\n -> DECLARE fanta INT DEFAULT 55;\n -> DROP TABLE t2;\n -> LOOP\n -> INSERT INTO t3 VALUES (fanta);\n -> END LOOP;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n4 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-procedure-code/'),(489,'MEDIUMTEXT',22,'MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 16,777,215 (224 - 1) characters.\nThe effective maximum length is less if the value contains multi-byte\ncharacters. Each MEDIUMTEXT value is stored using a 3-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumtext/\n\n','','https://mariadb.com/kb/en/mediumtext/'),(490,'LN',4,'Syntax:\nLN(X)\n\nReturns the natural logarithm of X; that is, the base-e logarithm of X.\nIf X is less than or equal to 0, then NULL is returned.\n\nURL: https://mariadb.com/kb/en/ln/\n\n','MariaDB> SELECT LN(2);\n -> 0.69314718055995\nMariaDB> SELECT LN(-2);\n -> NULL\n','https://mariadb.com/kb/en/ln/'),(491,'RETURN',23,'Syntax:\nRETURN expr\n\nThe RETURN statement terminates execution of a stored function and\nreturns the value expr to the function caller. There must be at least\none RETURN statement in a stored function. There may be more than one\nif the function has multiple exit points.\n\nThis statement is not used in stored procedures, triggers, or events.\nThe LEAVE statement can be used to exit a stored program of those\ntypes.\n\nURL: https://mariadb.com/kb/en/return/\n\n','','https://mariadb.com/kb/en/return/'),(492,'SHOW COLLATION',26,'Syntax:\nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement lists collations supported by the server. By default,\nthe output from SHOW COLLATION includes all available collations. The\nLIKE clause, if present, indicates which collation names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | | 0 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |\n| latin1_danish_ci | latin1 | 15 | | | 0 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 0 |\n| latin1_general_ci | latin1 | 48 | | | 0 |\n| latin1_general_cs | latin1 | 49 | | | 0 |\n| latin1_spanish_ci | latin1 | 94 | | | 0 |\n+-------------------+---------+----+---------+----------+---------+\n\nURL: https://mariadb.com/kb/en/show-collation/\n\n','','https://mariadb.com/kb/en/show-collation/'),(493,'LOG',4,'Syntax:\nLOG(X), LOG(B,X)\n\nIf called with one parameter, this function returns the natural\nlogarithm of X. If X is less than or equal to 0, then NULL is returned.\n\nThe inverse of this function (when called with a single argument) is\nthe EXP() function.\n\nURL: https://mariadb.com/kb/en/log/\n\n','MariaDB> SELECT LOG(2);\n -> 0.69314718055995\nMariaDB> SELECT LOG(-2);\n -> NULL\n','https://mariadb.com/kb/en/log/'),(494,'SET SQL_LOG_BIN',8,'Syntax:\nSET sql_log_bin = {0|1}\n\nThe sql_log_bin variable controls whether logging to the binary log is\ndone. The default value is 1 (do logging). To change logging for the\ncurrent session, change the session value of this variable. The session\nuser must have the SUPER privilege to set this variable.\n\nBeginning with MySQL 5.5.5, it is no longer possible to set\n@@session.sql_log_bin within a transaction or subquery. (Bug #53437)\n\nURL: https://mariadb.com/kb/en/set-sql_log_bin/\n\n','','https://mariadb.com/kb/en/set-sql_log_bin/'),(495,'!=',18,'Syntax:\n<>, !=\n\nNot equal:\n\nURL: https://mariadb.com/kb/en/not-equal/\n\n','MariaDB> SELECT \'.01\' <> \'0.01\';\n -> 1\nMariaDB> SELECT .01 <> \'0.01\';\n -> 0\nMariaDB> SELECT \'zapp\' <> \'zappp\';\n -> 1\n','https://mariadb.com/kb/en/not-equal/'),(496,'WHILE',23,'Syntax:\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nThe statement list within a WHILE statement is repeated as long as the\nsearch_condition expression is true. statement_list consists of one or\nmore SQL statements, each terminated by a semicolon (;) statement\ndelimiter.\n\nA WHILE statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/while/\n\n','CREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n\n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n END WHILE;\nEND;\n','https://mariadb.com/kb/en/while/'),(497,'AES_DECRYPT',12,'Syntax:\nAES_DECRYPT(crypt_str,key_str)\n\nThis function decrypts data using the official AES (Advanced Encryption\nStandard) algorithm. For more information, see the description of\nAES_ENCRYPT().\n\nURL: https://mariadb.com/kb/en/aes_decrypt/\n\n','','https://mariadb.com/kb/en/aes_decrypt/'),(498,'DAYNAME',31,'Syntax:\nDAYNAME(date)\n\nReturns the name of the weekday for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-system-variables#lc_time_names).\n\nURL: https://mariadb.com/kb/en/dayname/\n\n','MariaDB> SELECT DAYNAME(\'2007-02-03\');\n -> \'Saturday\'\n','https://mariadb.com/kb/en/dayname/'),(499,'COERCIBILITY',17,'Syntax:\nCOERCIBILITY(str)\n\nReturns the collation coercibility value of the string argument.\n\nURL: https://mariadb.com/kb/en/coercibility/\n\n','MariaDB> SELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n -> 0\nMariaDB> SELECT COERCIBILITY(USER());\n -> 3\nMariaDB> SELECT COERCIBILITY(\'abc\');\n -> 4\n','https://mariadb.com/kb/en/coercibility/'),(500,'INT',22,'INT[(M)] [UNSIGNED] [ZEROFILL]\n\nA normal-size integer. The signed range is -2147483648 to 2147483647.\nThe unsigned range is 0 to 4294967295.\n\nURL: https://mariadb.com/kb/en/int/\n\n','','https://mariadb.com/kb/en/int/'),(501,'GLENGTH',13,'GLength(ls)\n\nReturns as a double-precision number the length of the LineString value\nls in its associated spatial reference.\n\nURL: https://mariadb.com/kb/en/glength/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.8284271247462 |\n+----------------------------+\n','https://mariadb.com/kb/en/glength/'),(502,'RADIANS',4,'Syntax:\nRADIANS(X)\n\nReturns the argument X, converted from degrees to radians. (Note that\nπ radians equals 180 degrees.)\n\nURL: https://mariadb.com/kb/en/radians/\n\n','MariaDB> SELECT RADIANS(90);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/radians/'),(503,'COLLATION',17,'Syntax:\nCOLLATION(str)\n\nReturns the collation of the string argument.\n\nURL: https://mariadb.com/kb/en/collation/\n\n','MariaDB> SELECT COLLATION(\'abc\');\n -> \'latin1_swedish_ci\'\nMariaDB> SELECT COLLATION(_utf8\'abc\');\n -> \'utf8_general_ci\'\n','https://mariadb.com/kb/en/collation/'),(504,'COALESCE',18,'Syntax:\nCOALESCE(value,...)\n\nReturns the first non-NULL value in the list, or NULL if there are no\nnon-NULL values.\n\nURL: https://mariadb.com/kb/en/coalesce/\n\n','MariaDB> SELECT COALESCE(NULL,1);\n -> 1\nMariaDB> SELECT COALESCE(NULL,NULL,NULL);\n -> NULL\n','https://mariadb.com/kb/en/coalesce/'),(505,'VERSION',17,'Syntax:\nVERSION()\n\nReturns a string that indicates the MySQL server version. The string\nuses the utf8 character set. The value might have a suffix in addition\nto the version number. See the description of the version system\nvariable in\nhttps://mariadb.com/kb/en/server-system-variables#version.\n\nURL: https://mariadb.com/kb/en/version/\n\n','MariaDB> SELECT VERSION();\n -> \'5.5.29-standard\'\n','https://mariadb.com/kb/en/version/'),(506,'MAKE_SET',37,'Syntax:\nMAKE_SET(bits,str1,str2,...)\n\nReturns a set value (a string containing substrings separated by \",\"\ncharacters) consisting of the strings that have the corresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL\nvalues in str1, str2, ... are not appended to the result.\n\nURL: https://mariadb.com/kb/en/make_set/\n\n','MariaDB> SELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n -> \'a\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n -> \'hello,world\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n -> \'hello\'\nMariaDB> SELECT MAKE_SET(0,\'a\',\'b\',\'c\');\n -> \'\'\n','https://mariadb.com/kb/en/make_set/'),(507,'FIND_IN_SET',37,'Syntax:\nFIND_IN_SET(str,strlist)\n\nReturns a value in the range of 1 to N if the string str is in the\nstring list strlist consisting of N substrings. A string list is a\nstring composed of substrings separated by \",\" characters. If the first\nargument is a constant string and the second is a column of type SET,\nthe FIND_IN_SET() function is optimized to use bit arithmetic. Returns\n0 if str is not in strlist or if strlist is the empty string. Returns\nNULL if either argument is NULL. This function does not work properly\nif the first argument contains a comma (\",\") character.\n\nURL: https://mariadb.com/kb/en/find_in_set/\n\n','MariaDB> SELECT FIND_IN_SET(\'b\',\'a,b,c,d\');\n -> 2\n','https://mariadb.com/kb/en/find_in_set/'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `host` +-- + +DROP TABLE IF EXISTS `host`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `host` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `host` +-- + +LOCK TABLES `host` WRITE; +/*!40000 ALTER TABLE `host` DISABLE KEYS */; +/*!40000 ALTER TABLE `host` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `index_stats` +-- + +DROP TABLE IF EXISTS `index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `index_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `prefix_arity` int(11) unsigned NOT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `index_stats` +-- + +LOCK TABLES `index_stats` WRITE; +/*!40000 ALTER TABLE `index_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_index_stats` +-- + +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_index_stats` +-- + +LOCK TABLES `innodb_index_stats` WRITE; +/*!40000 ALTER TABLE `innodb_index_stats` DISABLE KEYS */; +INSERT INTO `innodb_index_stats` VALUES ('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:15:02','n_diff_pfx01',0,1,'domain_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:15:02','n_diff_pfx02',0,1,'domain_id,sub_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:15:02','n_leaf_pages',1,NULL,'Number of leaf pages in the index'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:15:02','size',1,NULL,'Number of pages in the index'); +/*!40000 ALTER TABLE `innodb_index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_table_stats` +-- + +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_table_stats` +-- + +LOCK TABLES `innodb_table_stats` WRITE; +/*!40000 ALTER TABLE `innodb_table_stats` DISABLE KEYS */; +INSERT INTO `innodb_table_stats` VALUES ('mysql','gtid_slave_pos','2020-05-31 16:15:02',0,1,0); +/*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +INSERT INTO `proc` VALUES ('mysql','AddGeometryColumn','PROCEDURE','AddGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64), t_srid int','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:15:02','2020-05-31 16:15:02','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end'),('mysql','DropGeometryColumn','PROCEDURE','DropGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64)','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:15:02','2020-05-31 16:15:02','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end'); +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT 0, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 16:15:02'),('asus','root','','',1,'','2020-05-31 16:15:02'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_mapping` +-- + +DROP TABLE IF EXISTS `roles_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_mapping` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Admin_option` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + UNIQUE KEY `Host` (`Host`,`User`,`Role`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Granted roles'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_mapping` +-- + +LOCK TABLES `roles_mapping` WRITE; +/*!40000 ALTER TABLE `roles_mapping` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_mapping` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` varchar(2048) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(80) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT 0, + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` varchar(512) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `table_stats` +-- + +DROP TABLE IF EXISTS `table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `table_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `cardinality` bigint(21) unsigned DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `table_stats` +-- + +LOCK TABLES `table_stats` WRITE; +/*!40000 ALTER TABLE `table_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT 0, + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT 0, + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', + `ssl_cipher` blob NOT NULL, + `x509_issuer` blob NOT NULL, + `x509_subject` blob NOT NULL, + `max_questions` int(11) unsigned NOT NULL DEFAULT 0, + `max_updates` int(11) unsigned NOT NULL DEFAULT 0, + `max_connections` int(11) unsigned NOT NULL DEFAULT 0, + `max_user_connections` int(11) NOT NULL DEFAULT 0, + `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, + `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, + PRIMARY KEY (`Host`,`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 19:15:21 diff --git a/mysql-test/std_data/mysql_database_10.3.dump b/mysql-test/std_data/mysql_database_10.3.dump new file mode 100644 index 00000000000..c30b121b886 --- /dev/null +++ b/mysql-test/std_data/mysql_database_10.3.dump @@ -0,0 +1,928 @@ +-- MySQL dump 10.17 Distrib 10.3.23-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 10.3.23-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `column_stats` +-- + +DROP TABLE IF EXISTS `column_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, + `nulls_ratio` decimal(12,4) DEFAULT NULL, + `avg_length` decimal(12,4) DEFAULT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + `hist_size` tinyint(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `column_stats` +-- + +LOCK TABLES `column_stats` WRITE; +/*!40000 ALTER TABLE `column_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `column_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + PRIMARY KEY (`db`,`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT 0, + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gtid_slave_pos` +-- + +DROP TABLE IF EXISTS `gtid_slave_pos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gtid_slave_pos` ( + `domain_id` int(10) unsigned NOT NULL, + `sub_id` bigint(20) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `seq_no` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`domain_id`,`sub_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Replication slave GTID position'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gtid_slave_pos` +-- + +LOCK TABLES `gtid_slave_pos` WRITE; +/*!40000 ALTER TABLE `gtid_slave_pos` DISABLE KEYS */; +/*!40000 ALTER TABLE `gtid_slave_pos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control flow functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry constructors',34,''),(25,'GeometryCollection properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (0,'JOIN'),(1,'HOST'),(2,'REPEAT'),(3,'SERIALIZABLE'),(4,'REPLACE'),(5,'AT'),(6,'SCHEDULE'),(7,'RETURNS'),(8,'STARTS'),(9,'MASTER_SSL_CA'),(10,'NCHAR'),(11,'COLUMNS'),(12,'COMPLETION'),(13,'WORK'),(14,'DATETIME'),(15,'MODE'),(16,'OPEN'),(17,'INTEGER'),(18,'ESCAPE'),(19,'VALUE'),(20,'MASTER_SSL_VERIFY_SERVER_CERT'),(21,'SQL_BIG_RESULT'),(22,'DROP'),(23,'GEOMETRYCOLLECTIONFROMWKB'),(24,'EVENTS'),(25,'MONTH'),(26,'PROFILES'),(27,'DUPLICATE'),(28,'REPLICATION'),(29,'UNLOCK'),(30,'INNODB'),(31,'YEAR_MONTH'),(32,'SUBJECT'),(33,'PREPARE'),(34,'LOCK'),(35,'NDB'),(36,'CHECK'),(37,'FULL'),(38,'INT4'),(39,'BY'),(40,'NO'),(41,'MINUTE'),(42,'PARTITION'),(43,'DATA'),(44,'DAY'),(45,'SHARE'),(46,'REAL'),(47,'SEPARATOR'),(48,'MESSAGE_TEXT'),(49,'MASTER_HEARTBEAT_PERIOD'),(50,'DELETE'),(51,'ON'),(52,'COLUMN_NAME'),(53,'CONNECTION'),(54,'CLOSE'),(55,'X509'),(56,'USE'),(57,'SUBCLASS_ORIGIN'),(58,'WHERE'),(59,'PRIVILEGES'),(60,'SPATIAL'),(61,'EVENT'),(62,'SUPER'),(63,'SQL_BUFFER_RESULT'),(64,'IGNORE'),(65,'SHA2'),(66,'QUICK'),(67,'SIGNED'),(68,'OFFLINE'),(69,'SECURITY'),(70,'AUTOEXTEND_SIZE'),(71,'NDBCLUSTER'),(72,'POLYGONFROMWKB'),(73,'FALSE'),(74,'LEVEL'),(75,'FORCE'),(76,'BINARY'),(77,'TO'),(78,'CHANGE'),(79,'CURRENT_USER'),(80,'HOUR_MINUTE'),(81,'UPDATE'),(82,'PRESERVE'),(83,'TABLE_NAME'),(84,'INTO'),(85,'FEDERATED'),(86,'VARYING'),(87,'MAX_SIZE'),(88,'HOUR_SECOND'),(89,'VARIABLE'),(90,'ROLLBACK'),(91,'PROCEDURE'),(92,'TIMESTAMP'),(93,'IMPORT'),(94,'AGAINST'),(95,'CHECKSUM'),(96,'COUNT'),(97,'LONGBINARY'),(98,'THEN'),(99,'INSERT'),(100,'ENGINES'),(101,'HANDLER'),(102,'PORT'),(103,'DAY_SECOND'),(104,'EXISTS'),(105,'MUTEX'),(106,'HELP_DATE'),(107,'RELEASE'),(108,'BOOLEAN'),(109,'MOD'),(110,'DEFAULT'),(111,'TYPE'),(112,'NO_WRITE_TO_BINLOG'),(113,'OPTIMIZE'),(114,'SQLSTATE'),(115,'RESET'),(116,'CLASS_ORIGIN'),(117,'INSTALL'),(118,'ITERATE'),(119,'DO'),(120,'BIGINT'),(121,'SET'),(122,'ISSUER'),(123,'DATE'),(124,'STATUS'),(125,'FULLTEXT'),(126,'COMMENT'),(127,'MASTER_CONNECT_RETRY'),(128,'INNER'),(129,'RELAYLOG'),(130,'STOP'),(131,'MASTER_LOG_FILE'),(132,'MRG_MYISAM'),(133,'PRECISION'),(134,'REQUIRE'),(135,'TRAILING'),(136,'PARTITIONS'),(137,'LONG'),(138,'OPTION'),(139,'REORGANIZE'),(140,'ELSE'),(141,'DEALLOCATE'),(142,'IO_THREAD'),(143,'CASE'),(144,'CIPHER'),(145,'CONTINUE'),(146,'FROM'),(147,'READ'),(148,'LEFT'),(149,'ELSEIF'),(150,'MINUTE_SECOND'),(151,'COMPACT'),(152,'DEC'),(153,'FOR'),(154,'WARNINGS'),(155,'MIN_ROWS'),(156,'STRING'),(157,'CONDITION'),(158,'ENCLOSED'),(159,'FUNCTION'),(160,'AGGREGATE'),(161,'FIELDS'),(162,'INT3'),(163,'ARCHIVE'),(164,'AVG_ROW_LENGTH'),(165,'ADD'),(166,'KILL'),(167,'FLOAT4'),(168,'TABLESPACE'),(169,'VIEW'),(170,'REPEATABLE'),(171,'INFILE'),(172,'HELP_VERSION'),(173,'ORDER'),(174,'USING'),(175,'CONSTRAINT_CATALOG'),(176,'MIDDLEINT'),(177,'GRANT'),(178,'UNSIGNED'),(179,'DECIMAL'),(180,'GEOMETRYFROMTEXT'),(181,'INDEXES'),(182,'FOREIGN'),(183,'CACHE'),(184,'HOSTS'),(185,'MYSQL_ERRNO'),(186,'COMMIT'),(187,'SCHEMAS'),(188,'LEADING'),(189,'SNAPSHOT'),(190,'CONSTRAINT_NAME'),(191,'DECLARE'),(192,'LOAD'),(193,'SQL_CACHE'),(194,'CONVERT'),(195,'DYNAMIC'),(196,'COLLATE'),(197,'POLYGONFROMTEXT'),(198,'BYTE'),(199,'GLOBAL'),(200,'LINESTRINGFROMWKB'),(201,'WHEN'),(202,'HAVING'),(203,'AS'),(204,'STARTING'),(205,'RELOAD'),(206,'AUTOCOMMIT'),(207,'REVOKE'),(208,'GRANTS'),(209,'OUTER'),(210,'CURSOR_NAME'),(211,'FLOOR'),(212,'EXPLAIN'),(213,'WITH'),(214,'AFTER'),(215,'STD'),(216,'CSV'),(217,'DISABLE'),(218,'UNINSTALL'),(219,'OUTFILE'),(220,'LOW_PRIORITY'),(221,'FILE'),(222,'NODEGROUP'),(223,'SCHEMA'),(224,'SONAME'),(225,'POW'),(226,'DUAL'),(227,'MULTIPOINTFROMWKB'),(228,'INDEX'),(229,'MULTIPOINTFROMTEXT'),(230,'DEFINER'),(231,'MASTER_BIND'),(232,'REMOVE'),(233,'EXTENDED'),(234,'MULTILINESTRINGFROMWKB'),(235,'CROSS'),(236,'CONTRIBUTORS'),(237,'NATIONAL'),(238,'GROUP'),(239,'SHA'),(240,'ONLINE'),(241,'UNDO'),(242,'IGNORE_SERVER_IDS'),(243,'ZEROFILL'),(244,'CLIENT'),(245,'MASTER_PASSWORD'),(246,'OWNER'),(247,'RELAY_LOG_FILE'),(248,'TRUE'),(249,'CHARACTER'),(250,'MASTER_USER'),(251,'SCHEMA_NAME'),(252,'TABLE'),(253,'ENGINE'),(254,'INSERT_METHOD'),(255,'CASCADE'),(256,'RELAY_LOG_POS'),(257,'SQL_CALC_FOUND_ROWS'),(258,'UNION'),(259,'MYISAM'),(260,'LEAVE'),(261,'MODIFY'),(262,'MATCH'),(263,'MASTER_LOG_POS'),(264,'DISTINCTROW'),(265,'DESC'),(266,'TIME'),(267,'NUMERIC'),(268,'EXPANSION'),(269,'CODE'),(270,'CURSOR'),(271,'GEOMETRYCOLLECTIONFROMTEXT'),(272,'CHAIN'),(273,'LOGFILE'),(274,'FLUSH'),(275,'CREATE'),(276,'DESCRIBE'),(277,'EXTENT_SIZE'),(278,'MAX_UPDATES_PER_HOUR'),(279,'INT2'),(280,'PROCESSLIST'),(281,'ENDS'),(282,'LOGS'),(283,'DISCARD'),(284,'HEAP'),(285,'SOUNDS'),(286,'BETWEEN'),(287,'MULTILINESTRINGFROMTEXT'),(288,'REPAIR'),(289,'PACK_KEYS'),(290,'FAST'),(291,'VALUES'),(292,'CALL'),(293,'LOOP'),(294,'VARCHARACTER'),(295,'BEFORE'),(296,'TRUNCATE'),(297,'SHOW'),(298,'ALL'),(299,'REDUNDANT'),(300,'USER_RESOURCES'),(301,'PARTIAL'),(302,'BINLOG'),(303,'END'),(304,'SECOND'),(305,'AND'),(306,'FLOAT8'),(307,'PREV'),(308,'HOUR'),(309,'SELECT'),(310,'DATABASES'),(311,'OR'),(312,'IDENTIFIED'),(313,'WRAPPER'),(314,'MASTER_SSL_CIPHER'),(315,'SQL_SLAVE_SKIP_COUNTER'),(316,'BOTH'),(317,'BOOL'),(318,'YEAR'),(319,'MASTER_PORT'),(320,'CONCURRENT'),(321,'HELP'),(322,'UNIQUE'),(323,'TRIGGERS'),(324,'PROCESS'),(325,'OPTIONS'),(326,'RESIGNAL'),(327,'CONSISTENT'),(328,'MASTER_SSL'),(329,'DATE_ADD'),(330,'MAX_CONNECTIONS_PER_HOUR'),(331,'LIKE'),(332,'PLUGIN'),(333,'FETCH'),(334,'IN'),(335,'COLUMN'),(336,'DUMPFILE'),(337,'USAGE'),(338,'EXECUTE'),(339,'MEMORY'),(340,'CEIL'),(341,'QUERY'),(342,'MASTER_HOST'),(343,'LINES'),(344,'SQL_THREAD'),(345,'SERVER'),(346,'MAX_QUERIES_PER_HOUR'),(347,'MASTER_SSL_CERT'),(348,'MULTIPOLYGONFROMWKB'),(349,'TRANSACTION'),(350,'DAY_MINUTE'),(351,'STDDEV'),(352,'DATE_SUB'),(353,'REBUILD'),(354,'GEOMETRYFROMWKB'),(355,'INT1'),(356,'RENAME'),(357,'PARSER'),(358,'RIGHT'),(359,'ALTER'),(360,'MAX_ROWS'),(361,'SOCKET'),(362,'STRAIGHT_JOIN'),(363,'NATURAL'),(364,'VARIABLES'),(365,'ESCAPED'),(366,'SHA1'),(367,'KEY_BLOCK_SIZE'),(368,'PASSWORD'),(369,'OFFSET'),(370,'CHAR'),(371,'NEXT'),(372,'ERRORS'),(373,'SQL_LOG_BIN'),(374,'TEMPORARY'),(375,'COMMITTED'),(376,'SQL_SMALL_RESULT'),(377,'UPGRADE'),(378,'BEGIN'),(379,'DELAY_KEY_WRITE'),(380,'PROFILE'),(381,'MEDIUM'),(382,'INTERVAL'),(383,'SSL'),(384,'DAY_HOUR'),(385,'NAME'),(386,'REFERENCES'),(387,'AES_ENCRYPT'),(388,'STORAGE'),(389,'ISOLATION'),(390,'CEILING'),(391,'EVERY'),(392,'INT8'),(393,'AUTHORS'),(394,'RESTRICT'),(395,'UNCOMMITTED'),(396,'LINESTRINGFROMTEXT'),(397,'IS'),(398,'NOT'),(399,'ANALYSE'),(400,'DATAFILE'),(401,'DES_KEY_FILE'),(402,'SIGNAL'),(403,'COMPRESSED'),(404,'START'),(405,'PLUGINS'),(406,'SAVEPOINT'),(407,'IF'),(408,'ROWS'),(409,'PRIMARY'),(410,'PURGE'),(411,'LAST'),(412,'USER'),(413,'EXIT'),(414,'KEYS'),(415,'LIMIT'),(416,'KEY'),(417,'MERGE'),(418,'UNTIL'),(419,'SQL_NO_CACHE'),(420,'DELAYED'),(421,'CONSTRAINT_SCHEMA'),(422,'ANALYZE'),(423,'CONSTRAINT'),(424,'SERIAL'),(425,'ACTION'),(426,'WRITE'),(427,'INITIAL_SIZE'),(428,'SESSION'),(429,'DATABASE'),(430,'NULL'),(431,'POWER'),(432,'USE_FRM'),(433,'TERMINATED'),(434,'SLAVE'),(435,'NVARCHAR'),(436,'ASC'),(437,'RETURN'),(438,'OPTIONALLY'),(439,'ENABLE'),(440,'DIRECTORY'),(441,'MAX_USER_CONNECTIONS'),(442,'WHILE'),(443,'LOCAL'),(444,'DISTINCT'),(445,'AES_DECRYPT'),(446,'MASTER_SSL_KEY'),(447,'NONE'),(448,'TABLES'),(449,'<>'),(450,'RLIKE'),(451,'TRIGGER'),(452,'COLLATION'),(453,'SHUTDOWN'),(454,'HIGH_PRIORITY'),(455,'BTREE'),(456,'FIRST'),(457,'COALESCE'),(458,'WAIT'),(459,'CATALOG_NAME'),(460,'MASTER'),(461,'FIXED'),(462,'MULTIPOLYGONFROMTEXT'),(463,'ROW_FORMAT'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (1,0),(356,0),(473,1),(232,2),(447,3),(3,4),(130,4),(421,4),(89,5),(89,6),(406,6),(97,7),(89,8),(185,9),(430,10),(21,11),(347,11),(421,11),(463,11),(468,11),(89,12),(406,12),(146,13),(230,14),(88,15),(356,15),(18,16),(106,16),(134,16),(347,16),(97,17),(500,17),(380,18),(3,19),(104,19),(243,19),(374,19),(459,19),(185,20),(356,21),(9,22),(30,22),(34,22),(87,22),(186,22),(237,22),(263,22),(276,22),(300,22),(331,22),(405,22),(415,22),(416,22),(463,22),(478,22),(108,23),(122,24),(170,24),(424,24),(376,25),(82,26),(104,27),(199,28),(36,29),(347,30),(468,30),(376,31),(199,32),(35,33),(237,33),(36,34),(356,34),(468,35),(417,36),(463,36),(468,36),(21,37),(294,37),(347,37),(451,37),(468,37),(500,38),(48,39),(77,39),(83,39),(130,39),(199,39),(356,39),(361,39),(421,39),(463,39),(468,39),(468,40),(472,40),(376,41),(463,42),(468,42),(212,43),(421,43),(468,43),(473,43),(376,44),(356,45),(97,46),(314,46),(361,47),(374,48),(459,48),(185,49),(48,50),(468,50),(472,50),(1,51),(89,51),(406,51),(472,51),(374,52),(459,52),(176,53),(468,53),(51,54),(106,54),(199,55),(1,56),(55,56),(194,56),(374,57),(459,57),(48,58),(83,58),(106,58),(193,59),(199,59),(249,59),(210,60),(463,60),(89,61),(300,61),(358,61),(406,61),(199,62),(356,63),(1,64),(83,64),(104,64),(130,64),(356,64),(421,64),(463,64),(66,65),(48,66),(417,66),(466,66),(230,67),(87,68),(210,68),(463,68),(199,69),(194,70),(468,71),(91,72),(482,72),(385,73),(447,74),(1,75),(39,76),(230,76),(269,76),(185,77),(269,77),(460,77),(185,78),(463,78),(89,79),(406,79),(376,80),(83,81),(104,81),(356,81),(472,81),(89,82),(406,82),(374,83),(459,83),(3,84),(104,84),(304,84),(356,84),(468,85),(257,86),(194,87),(376,88),(129,89),(146,90),(460,90),(17,91),(189,91),(302,91),(328,91),(347,91),(356,91),(416,91),(439,91),(488,91),(99,92),(188,92),(421,93),(463,93),(88,94),(401,95),(468,95),(69,96),(330,96),(433,96),(285,97),(28,98),(57,98),(85,98),(104,99),(195,99),(301,99),(486,99),(282,100),(347,100),(106,101),(313,101),(473,102),(376,103),(9,104),(30,104),(89,104),(155,104),(186,104),(276,104),(300,104),(347,105),(365,105),(109,106),(146,107),(460,107),(24,108),(88,108),(113,109),(174,109),(3,110),(104,110),(155,110),(200,110),(212,110),(243,110),(463,110),(468,110),(463,111),(115,112),(326,112),(466,112),(470,112),(115,113),(463,113),(374,114),(459,114),(38,115),(119,115),(151,115),(264,115),(374,116),(459,116),(419,117),(124,118),(89,119),(125,119),(406,119),(496,119),(221,120),(3,121),(83,121),(104,121),(129,121),(130,121),(146,121),(155,121),(182,121),(212,121),(333,121),(347,121),(356,121),(374,121),(421,121),(459,121),(463,121),(468,121),(472,121),(477,121),(494,121),(199,122),(132,123),(230,123),(262,123),(376,123),(58,124),(137,124),(215,124),(223,124),(328,124),(336,124),(347,124),(365,124),(210,125),(463,125),(468,125),(89,126),(194,126),(210,126),(406,126),(468,126),(185,127),(1,128),(424,129),(52,130),(185,131),(468,132),(314,133),(199,134),(455,135),(255,136),(285,137),(199,138),(249,138),(463,139),(57,140),(85,140),(237,141),(52,142),(324,142),(57,143),(85,143),(199,144),(313,145),(48,146),(122,146),(347,146),(356,146),(424,146),(455,146),(36,147),(106,147),(447,147),(1,148),(28,149),(376,150),(468,151),(209,152),(180,153),(313,153),(347,153),(356,153),(420,153),(330,154),(347,154),(468,155),(97,156),(180,157),(421,158),(34,159),(68,159),(97,159),(211,159),(233,159),(302,159),(336,159),(347,159),(393,159),(405,159),(416,159),(97,160),(347,161),(421,161),(252,162),(468,163),(463,164),(468,164),(60,165),(194,165),(463,165),(478,165),(176,166),(168,167),(194,168),(415,168),(463,168),(478,168),(30,169),(159,169),(454,169),(447,170),(130,171),(421,171),(190,172),(48,173),(83,173),(356,173),(361,173),(463,173),(1,174),(48,174),(86,174),(374,175),(459,175),(252,176),(199,177),(249,177),(24,178),(128,178),(168,178),(209,178),(230,178),(314,178),(500,178),(97,179),(156,179),(230,179),(411,180),(347,181),(463,182),(468,182),(472,182),(473,182),(101,183),(151,183),(304,183),(145,184),(347,184),(374,185),(459,185),(146,186),(160,187),(347,187),(455,188),(146,189),(374,190),(459,190),(180,191),(200,191),(313,191),(420,191),(304,192),(421,192),(356,193),(230,194),(377,194),(468,195),(155,196),(212,196),(468,196),(395,197),(465,198),(129,199),(137,199),(182,199),(349,199),(447,199),(452,200),(57,201),(85,201),(356,202),(1,203),(36,203),(356,203),(421,204),(199,205),(146,206),(249,207),(192,208),(347,208),(1,209),(374,210),(459,210),(221,211),(255,212),(88,213),(199,213),(210,213),(463,213),(468,213),(463,214),(260,215),(421,216),(468,216),(89,217),(406,217),(463,217),(291,218),(356,219),(3,220),(36,220),(48,220),(83,220),(104,220),(130,220),(421,220),(199,221),(194,222),(155,223),(186,223),(212,223),(309,223),(347,223),(97,224),(277,225),(279,226),(464,227),(1,228),(60,228),(87,228),(101,228),(210,228),(304,228),(308,228),(347,228),(463,228),(468,228),(425,229),(89,230),(406,230),(185,231),(463,232),(255,233),(466,233),(272,234),(1,235),(7,236),(347,236),(257,237),(430,237),(194,238),(226,238),(356,238),(427,239),(87,240),(210,240),(463,240),(313,241),(185,242),(24,243),(128,243),(168,243),(209,243),(314,243),(500,243),(199,244),(185,245),(473,246),(185,247),(385,248),(130,249),(155,249),(212,249),(257,249),(333,249),(347,249),(356,249),(421,249),(430,249),(468,249),(185,250),(374,251),(459,251),(60,252),(110,252),(115,252),(215,252),(276,252),(278,252),(321,252),(347,252),(401,252),(417,252),(463,252),(466,252),(468,252),(470,252),(194,253),(347,253),(365,253),(415,253),(463,253),(468,253),(478,253),(468,254),(30,255),(276,255),(468,255),(472,255),(185,256),(356,257),(305,258),(468,259),(310,260),(463,261),(88,262),(185,263),(356,264),(329,265),(356,265),(361,265),(230,266),(315,266),(375,266),(209,267),(88,268),(68,269),(488,269),(420,270),(246,271),(146,272),(194,273),(226,273),(151,274),(326,274),(17,275),(22,275),(60,275),(77,275),(89,275),(97,275),(155,275),(194,275),(210,275),(211,275),(278,275),(302,275),(309,275),(347,275),(358,275),(393,275),(454,275),(468,275),(473,275),(329,276),(194,277),(199,278),(234,279),(347,280),(451,280),(89,281),(39,282),(269,282),(347,282),(463,283),(468,284),(378,285),(147,286),(107,287),(463,288),(466,288),(468,289),(417,290),(3,291),(104,291),(339,292),(344,293),(257,294),(269,295),(321,296),(463,296),(7,297),(10,297),(17,297),(21,297),(25,297),(33,297),(39,297),(58,297),(68,297),(69,297),(82,297),(122,297),(134,297),(137,297),(145,297),(160,297),(170,297),(192,297),(193,297),(215,297),(223,297),(278,297),(282,297),(294,297),(308,297),(309,297),(328,297),(330,297),(333,297),(336,297),(347,297),(349,297),(358,297),(365,297),(393,297),(424,297),(451,297),(487,297),(488,297),(492,297),(38,298),(199,298),(249,298),(305,298),(356,298),(468,299),(326,300),(468,301),(122,302),(350,302),(28,303),(57,303),(85,303),(232,303),(327,303),(344,303),(496,303),(376,304),(147,305),(316,305),(314,306),(106,307),(376,308),(3,309),(104,309),(255,309),(301,309),(356,309),(160,310),(347,310),(141,311),(77,312),(130,312),(199,312),(473,313),(185,314),(182,315),(455,316),(24,317),(111,317),(376,318),(185,319),(130,320),(421,320),(118,321),(390,321),(463,322),(25,323),(347,323),(199,324),(373,325),(473,325),(374,326),(146,327),(185,328),(376,329),(199,330),(347,331),(378,331),(291,332),(347,332),(419,332),(383,333),(88,334),(122,334),(356,334),(424,334),(463,335),(356,336),(199,337),(86,338),(199,338),(356,339),(397,340),(88,341),(151,341),(176,341),(185,342),(130,343),(421,343),(52,344),(324,344),(9,345),(373,345),(473,345),(199,346),(185,347),(123,348),(146,349),(447,349),(376,350),(407,351),(376,352),(463,353),(144,354),(24,355),(110,356),(222,356),(406,356),(463,356),(210,357),(463,357),(468,357),(1,358),(60,359),(159,359),(199,359),(212,359),(226,359),(233,359),(373,359),(406,359),(439,359),(463,359),(478,359),(463,360),(468,360),(473,361),(1,362),(356,362),(1,363),(347,364),(349,364),(421,365),(427,366),(468,367),(77,368),(199,368),(473,368),(477,368),(356,369),(230,370),(465,370),(106,371),(69,372),(347,372),(494,373),(276,374),(447,375),(356,376),(212,377),(417,377),(146,378),(327,378),(468,379),(487,380),(417,381),(89,382),(376,382),(199,383),(376,384),(212,385),(199,386),(468,386),(472,386),(443,387),(282,388),(447,389),(448,390),(89,391),(128,392),(10,393),(347,393),(30,394),(276,394),(472,394),(447,395),(56,396),(84,397),(206,397),(368,397),(456,397),(84,398),(89,398),(155,398),(206,398),(312,398),(189,399),(194,400),(478,400),(326,401),(459,402),(468,403),(146,404),(324,404),(33,405),(460,406),(9,407),(28,407),(30,407),(89,407),(155,407),(186,407),(276,407),(300,407),(479,407),(130,408),(463,409),(269,410),(106,411),(77,412),(222,412),(331,412),(473,412),(313,413),(308,414),(347,414),(463,414),(48,415),(83,415),(106,415),(122,415),(356,415),(424,415),(60,416),(104,416),(463,416),(468,416),(472,416),(468,417),(232,418),(356,419),(3,420),(104,420),(486,420),(374,421),(459,421),(463,422),(470,422),(463,423),(468,423),(243,424),(468,424),(468,425),(472,425),(36,426),(194,427),(478,427),(129,428),(137,428),(349,428),(447,428),(155,429),(186,429),(212,429),(309,429),(347,429),(473,429),(84,430),(368,430),(472,430),(483,431),(466,432),(421,433),(38,434),(52,434),(89,434),(145,434),(223,434),(324,434),(406,434),(257,435),(356,436),(361,436),(491,437),(421,438),(89,439),(406,439),(463,439),(212,440),(468,440),(199,441),(496,442),(36,443),(115,443),(130,443),(326,443),(421,443),(466,443),(470,443),(0,444),(96,444),(288,444),(305,444),(356,444),(361,444),(384,444),(433,444),(497,445),(185,446),(199,447),(36,448),(134,448),(294,448),(347,448),(495,449),(27,450),(22,451),(263,451),(347,451),(347,452),(492,452),(199,453),(104,454),(356,454),(210,455),(106,456),(463,456),(468,456),(463,457),(194,458),(478,458),(374,459),(459,459),(39,460),(58,460),(185,460),(264,460),(269,460),(209,461),(468,461),(201,462),(468,463); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (0,'MIN',16,'Syntax:\nMIN([DISTINCT] expr)\n\nReturns the minimum value of expr. MIN() may take a string argument; in\nsuch cases, it returns the minimum string value.\nThe DISTINCT keyword can be used to find the minimum of the distinct values\nof expr, however, this produces the same result as omitting DISTINCT.\n\nMIN() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/min/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/min/'),(1,'JOIN',27,'MySQL supports the following JOIN syntaxes for the table_references\npart of SELECT statements and multiple-table DELETE and UPDATE\nstatements:\n\ntable_references:\n table_reference [, table_reference] ...\n\ntable_reference:\n table_factor\n | join_table\n\ntable_factor:\n tbl_name [[AS] alias] [index_hint_list]\n | table_subquery [AS] alias\n | ( table_references )\n | { OJ table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n\njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor [join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON conditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor\n\njoin_condition:\n ON conditional_expr\n | USING (column_list)\n\nindex_hint_list:\n index_hint [, index_hint] ...\n\nindex_hint:\n USE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n\nindex_list:\n index_name [, index_name] ...\n\nA table reference is also known as a join expression.\n\nThe syntax of table_factor is extended in comparison with the SQL\nStandard. The latter accepts only table_reference, not a list of them\ninside a pair of parentheses.\n\nThis is a conservative extension if we consider each comma in a list of\ntable_reference items as equivalent to an inner join. For example:\n\nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nis equivalent to:\n\nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nIn MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents\n(they can replace each other). In standard SQL, they are not\nequivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used\notherwise.\n\nIn general, parentheses can be ignored in join expressions containing\nonly inner join operations.\n\nIndex hints can be specified to affect how the MySQL optimizer makes\nuse of indexes. For more information, see\nhttps://mariadb.com/kb/en/how-to-force-query-plans/.\n\nURL: https://mariadb.com/kb/en/join-syntax/\n\n','SELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id\n WHERE right_tbl.id IS NULL;\n','https://mariadb.com/kb/en/join-syntax/'),(2,'HEX',37,'Syntax:\nHEX(str), HEX(N)\n\nFor a string argument str, HEX() returns a hexadecimal string\nrepresentation of str where each character in str is converted to two\nhexadecimal digits. The inverse of this operation is performed by the\nUNHEX() function.\n\nFor a numeric argument N, HEX() returns a hexadecimal string\nrepresentation of the value of N treated as a longlong (BIGINT) number.\nThis is equivalent to CONV(N,10,16). The inverse of this operation is\nperformed by CONV(HEX(N),16,10).\n\nURL: https://mariadb.com/kb/en/hex/\n\n','MariaDB> SELECT 0x616263, HEX(\'abc\'), UNHEX(HEX(\'abc\'));\n -> \'abc\', 616263, \'abc\'\nMariaDB> SELECT HEX(255), CONV(HEX(255),16,10);\n -> \'FF\', 255\n','https://mariadb.com/kb/en/hex/'),(3,'REPLACE',27,'Syntax:\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n\nREPLACE works exactly like INSERT, except that if an old row in the\ntable has the same value as a new row for a PRIMARY KEY or a UNIQUE\nindex, the old row is deleted before the new row is inserted. See [HELP\nINSERT].\n\nREPLACE is a MySQL extension to the SQL standard. It either inserts, or\ndeletes and inserts. For another MySQL extension to standard SQL---that\neither inserts or updates---see\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nNote that unless the table has a PRIMARY KEY or UNIQUE index, using a\nREPLACE statement makes no sense. It becomes equivalent to INSERT,\nbecause there is no index to be used to determine whether a new row\nduplicates another.\n\nValues for all columns are taken from the values specified in the\nREPLACE statement. Any missing columns are set to their default values,\njust as happens for INSERT. You cannot refer to values from the current\nrow and use them in the new row. If you use an assignment such as SET\ncol_name = col_name + 1, the reference to the column name on the right\nhand side is treated as DEFAULT(col_name), so the assignment is\nequivalent to SET col_name = DEFAULT(col_name) + 1.\n\nTo use REPLACE, you must have both the INSERT and DELETE privileges for\nthe table.\n\nURL: https://mariadb.com/kb/en/replace/\n\n','','https://mariadb.com/kb/en/replace/'),(4,'CONTAINS',30,'Contains(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 completely contains g2. This\ntests the opposite relationship as Within().\n\nURL: https://mariadb.com/kb/en/contains/\n\n','','https://mariadb.com/kb/en/contains/'),(5,'SRID',36,'SRID(g)\n\nReturns an integer indicating the Spatial Reference System ID for the\ngeometry value g.\n\nIn MySQL, the SRID value is just an integer associated with the\ngeometry value. All calculations are done assuming Euclidean (planar)\ngeometry.\n\nURL: https://mariadb.com/kb/en/srid/\n\n','MariaDB> SELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n','https://mariadb.com/kb/en/srid/'),(6,'CURRENT_TIMESTAMP',31,'Syntax:\nCURRENT_TIMESTAMP, CURRENT_TIMESTAMP()\n\nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/current_timestamp/\n\n','','https://mariadb.com/kb/en/current_timestamp/'),(7,'SHOW CONTRIBUTORS',26,'Syntax:\nSHOW CONTRIBUTORS\n\nThe SHOW CONTRIBUTORS statement displays information about the people\nwho contribute to MySQL source or to causes that we support. For each\ncontributor, it displays Name, Location, and Comment values.\n\nURL: https://mariadb.com/kb/en/show-contributors/\n\n','','https://mariadb.com/kb/en/show-contributors/'),(8,'VARIANCE',16,'Syntax:\nVARIANCE(expr)\n\nReturns the population standard variance of expr. This is an extension\nto standard SQL. The standard SQL function VAR_POP() can be used\ninstead.\n\nVARIANCE() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/variance/\n\n','','https://mariadb.com/kb/en/variance/'),(9,'DROP SERVER',39,'Syntax:\nDROP SERVER [ IF EXISTS ] server_name\n\nDrops the server definition for the server named server_name. The\ncorresponding row within the mysql.servers table will be deleted. This\nstatement requires the SUPER privilege.\n\nDropping a server for a table does not affect any FEDERATED tables that\nused this connection information when they were created. See [HELP\nCREATE SERVER].\n\nURL: https://mariadb.com/kb/en/drop-server/\n\n','','https://mariadb.com/kb/en/drop-server/'),(10,'SHOW AUTHORS',26,'Syntax:\nSHOW AUTHORS\n\nThe SHOW AUTHORS statement displays information about the people who\nwork on MySQL. For each author, it displays Name, Location, and Comment\nvalues.\n\nURL: https://mariadb.com/kb/en/show-authors/\n\n','','https://mariadb.com/kb/en/show-authors/'),(11,'VAR_SAMP',16,'Syntax:\nVAR_SAMP(expr)\n\nReturns the sample variance of expr. That is, the denominator is the\nnumber of rows minus one.\n\nVAR_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_samp/\n\n','','https://mariadb.com/kb/en/var_samp/'),(12,'CONCAT',37,'Syntax:\nCONCAT(str1,str2,...)\n\nReturns the string that results from concatenating the arguments. May\nhave one or more arguments. If all arguments are nonbinary strings, the\nresult is a nonbinary string. If the arguments include any binary\nstrings, the result is a binary string. A numeric argument is converted\nto its equivalent string form. This is a nonbinary string as of MySQL\n5.5.3. Before 5.5.3, it is a binary string; to to avoid that and\nproduce a nonbinary string, you can use an explicit type cast, as in\nthis example:\n\nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n\nCONCAT() returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/concat/\n\n','MariaDB> SELECT CONCAT(\'My\', \'S\', \'QL\');\n -> \'MySQL\'\nMariaDB> SELECT CONCAT(\'My\', NULL, \'QL\');\n -> NULL\nMariaDB> SELECT CONCAT(14.3);\n -> \'14.3\'\n','https://mariadb.com/kb/en/concat/'),(13,'GEOMETRY HIERARCHY',34,'Geometry is the base class. It is an abstract class. The instantiable\nsubclasses of Geometry are restricted to zero-, one-, and\ntwo-dimensional geometric objects that exist in two-dimensional\ncoordinate space. All instantiable geometry classes are defined so that\nvalid instances of a geometry class are topologically closed (that is,\nall defined geometries include their boundary).\n\nThe base Geometry class has subclasses for Point, Curve, Surface, and\nGeometryCollection:\n\no Point represents zero-dimensional objects.\n\no Curve represents one-dimensional objects, and has subclass\n LineString, with sub-subclasses Line and LinearRing.\n\no Surface is designed for two-dimensional objects and has subclass\n Polygon.\n\no GeometryCollection has specialized zero-, one-, and two-dimensional\n collection classes named MultiPoint, MultiLineString, and\n MultiPolygon for modeling geometries corresponding to collections of\n Points, LineStrings, and Polygons, respectively. MultiCurve and\n MultiSurface are introduced as abstract superclasses that generalize\n the collection interfaces to handle Curves and Surfaces.\n\nGeometry, Curve, Surface, MultiCurve, and MultiSurface are defined as\nnoninstantiable classes. They define a common set of methods for their\nsubclasses and are included for extensibility.\n\nPoint, LineString, Polygon, GeometryCollection, MultiPoint,\nMultiLineString, and MultiPolygon are instantiable classes.\n\nURL: https://mariadb.com/kb/en/geometry-hierarchy/\n\n','','https://mariadb.com/kb/en/geometry-hierarchy/'),(14,'CHAR FUNCTION',37,'Syntax:\nCHAR(N,... [USING charset_name])\n\nCHAR() interprets each argument N as an integer and returns a string\nconsisting of the characters given by the code values of those\nintegers. NULL values are skipped.\nBy default, CHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n\nMariaDB> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n\nIf USING is given and the result string is illegal for the given\ncharacter set, a warning is issued. Also, if strict SQL mode is\nenabled, the result from CHAR() becomes NULL.\n\nURL: https://mariadb.com/kb/en/char-function/\n\n','MariaDB> SELECT CHAR(77,121,83,81,\'76\');\n -> \'MySQL\'\nMariaDB> SELECT CHAR(77,77.3,\'77.3\');\n -> \'MMM\'\n','https://mariadb.com/kb/en/char-function/'),(15,'DATETIME',22,'DATETIME\n\nA date and time combination. The supported range is \'1000-01-01\n00:00:00\' to \'9999-12-31 23:59:59\'. MySQL displays DATETIME values in\n\'YYYY-MM-DD HH:MM:SS\' format, but permits assignment of values to\nDATETIME columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/datetime/\n\n','','https://mariadb.com/kb/en/datetime/'),(16,'SHOW CREATE TRIGGER',26,'Syntax:\nSHOW CREATE TRIGGER trigger_name\n\nThis statement shows a CREATE TRIGGER statement that creates the given\ntrigger.\n\nURL: https://mariadb.com/kb/en/show-create-trigger/\n\n','','https://mariadb.com/kb/en/show-create-trigger/'),(17,'SHOW CREATE PROCEDURE',26,'Syntax:\nSHOW CREATE PROCEDURE proc_name\n\nThis statement is a MySQL extension. It returns the exact string that\ncan be used to re-create the named stored procedure. A similar\nstatement, SHOW CREATE FUNCTION, displays information about stored\nfunctions (see [HELP SHOW CREATE FUNCTION]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table. If you do not have privileges\nfor the routine itself, the value displayed for the Create Procedure or\nCreate Function field will be NULL.\n\nURL: https://mariadb.com/kb/en/show-create-procedure/\n\n','MariaDB> SHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row ***************************\n Procedure: simpleproc\n sql_mode:\n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nMariaDB> SHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row ***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-procedure/'),(18,'OPEN',23,'Syntax:\nOPEN cursor_name\n\nThis statement opens a previously declared cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/open/\n\n','','https://mariadb.com/kb/en/open/'),(19,'INTEGER',22,'INTEGER[(M)] [UNSIGNED] [ZEROFILL]\n\nThis type is a synonym for INT.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-int\n\n','','https://mariadb.com/kb/en/sql_language-data_types-int'),(20,'LOWER',37,'Syntax:\nLOWER(str)\n\nReturns the string str with all characters changed to lowercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT LOWER(\'QUADRATICALLY\');\n -> \'quadratically\'\n\nLOWER() (and UPPER()) are ineffective when applied to binary strings\n(BINARY, VARBINARY, BLOB). To perform lettercase conversion, convert\nthe string to a nonbinary string:\n\nMariaDB> SET @str = BINARY \'New York\';\nMariaDB> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+-------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+-------------+-----------------------------------+\n| New York | new york |\n+-------------+-----------------------------------+\n\nURL: https://mariadb.com/kb/en/lower/\n\n','','https://mariadb.com/kb/en/lower/'),(21,'SHOW COLUMNS',26,'Syntax:\nSHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW COLUMNS displays information about the columns in a given table.\nIt also works for views. The LIKE clause, if present, indicates which\ncolumn names to match. The WHERE clause can be given to select rows\nusing more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nSHOW COLUMNS displays information only for those columns for which you\nhave some privilege.\n\nMariaDB> SHOW COLUMNS FROM City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nIf the data types differ from what you expect them to be based on a\nCREATE TABLE statement, note that MySQL sometimes changes data types\nwhen you create or alter a table. The conditions under which this\noccurs are described in\nhttps://mariadb.com/kb/en/silent-column-changes/.\n\nThe FULL keyword causes the output to include the column collation and\ncomments, as well as the privileges you have for each column.\n\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. In other words, these two statements are equivalent:\n\nMariaDB> SHOW COLUMNS FROM mytable FROM mydb;\nMariaDB> SHOW COLUMNS FROM mydb.mytable;\n\nSHOW COLUMNS displays the following values for each table column:\n\nField indicates the column name.\n\nType indicates the column data type.\n\nCollation indicates the collation for nonbinary string columns, or NULL\nfor other columns. This value is displayed only if you use the FULL\nkeyword.\n\nThe Null field contains YES if NULL values can be stored in the column,\nNO if not.\n\nThe Key field indicates whether the column is indexed:\n\no If Key is empty, the column either is not indexed or is indexed only\n as a secondary column in a multiple-column, nonunique index.\n\no If Key is PRI, the column is a PRIMARY KEY or is one of the columns\n in a multiple-column PRIMARY KEY.\n\no If Key is UNI, the column is the first column of a UNIQUE index. (A\n UNIQUE index permits multiple NULL values, but you can tell whether\n the column permits NULL by checking the Null field.)\n\no If Key is MUL, the column is the first column of a nonunique index in\n which multiple occurrences of a given value are permitted within the\n column.\n\nIf more than one of the Key values applies to a given column of a\ntable, Key displays the one with the highest priority, in the order\nPRI, UNI, MUL.\n\nA UNIQUE index may be displayed as PRI if it cannot contain NULL values\nand there is no PRIMARY KEY in the table. A UNIQUE index may display as\nMUL if several columns form a composite UNIQUE index; although the\ncombination of the columns is unique, each column can still hold\nmultiple occurrences of a given value.\n\nThe Default field indicates the default value that is assigned to the\ncolumn. This is NULL if the column has an explicit default of NULL, or\nif the column definition has no DEFAULT clause.\n\nThe Extra field contains any additional information that is available\nabout a given column. The value is nonempty in these cases:\nauto_increment for columns that have the AUTO_INCREMENT attribute; on\nupdate CURRENT_TIMESTAMP for TIMESTAMP columns that have the ON UPDATE\nCURRENT_TIMESTAMP attribute.\n\nPrivileges indicates the privileges you have for the column. This value\nis displayed only if you use the FULL keyword.\n\nComment indicates any comment the column has. This value is displayed\nonly if you use the FULL keyword.\n\nSHOW FIELDS is a synonym for SHOW COLUMNS. You can also list a table\'s\ncolumns with the mysqlshow db_name tbl_name command.\n\nThe DESCRIBE statement provides information similar to SHOW COLUMNS.\nSee [HELP DESCRIBE].\n\nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX statements\nalso provide information about tables. See [HELP SHOW].\n\nURL: https://mariadb.com/kb/en/show-columns/\n\n','','https://mariadb.com/kb/en/show-columns/'),(22,'CREATE TRIGGER',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name trigger_time trigger_event\n ON tbl_name FOR EACH ROW trigger_body\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section. If\nbinary logging is enabled, CREATE TRIGGER might require the SUPER\nprivilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time. See later in\nthis section for more information.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\ntrigger_event indicates the kind of statement that activates the\ntrigger. The trigger_event can be one of the following:\n\no INSERT: The trigger is activated whenever a new row is inserted into\n the table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger is activated whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger is activated whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. However,\n DROP TABLE and TRUNCATE TABLE statements on the table do not activate\n this trigger, because they do not use DELETE. Dropping a partition\n does not activate DELETE triggers, either. See [HELP TRUNCATE TABLE].\n\nURL: https://mariadb.com/kb/en/create-trigger/\n\n','','https://mariadb.com/kb/en/create-trigger/'),(23,'MONTH',31,'Syntax:\nMONTH(date)\n\nReturns the month for date, in the range 1 to 12 for January to\nDecember, or 0 for dates such as \'0000-00-00\' or \'2008-00-00\' that have\na zero month part.\n\nURL: https://mariadb.com/kb/en/month/\n\n','MariaDB> SELECT MONTH(\'2008-02-03\');\n -> 2\n','https://mariadb.com/kb/en/month/'),(24,'TINYINT',22,'TINYINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA very small integer. The signed range is -128 to 127. The unsigned\nrange is 0 to 255.\n\nURL: https://mariadb.com/kb/en/tinyint/\n\n','','https://mariadb.com/kb/en/tinyint/'),(25,'SHOW TRIGGERS',26,'Syntax:\nSHOW TRIGGERS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TRIGGERS lists the triggers currently defined for tables in a\ndatabase (the default database unless a FROM clause is given). This\nstatement returns results only for databases and tables for which you\nhave the TRIGGER privilege. The LIKE clause, if present, indicates\nwhich table names to match and causes the statement to display triggers\nfor those tables. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nFor the trigger ins_sum as defined in\nhttps://mariadb.com/kb/en/triggers/, the output of\nthis statement is as shown here:\n\nMariaDB> SHOW TRIGGERS LIKE \'acc%\'\\G\n*************************** 1. row ***************************\n Trigger: ins_sum\n Event: INSERT\n Table: account\n Statement: SET @sum = @sum + NEW.amount\n Timing: BEFORE\n Created: NULL\n sql_mode:\n Definer: myname@localhost\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\ncharacter_set_client is the session value of the character_set_client\nsystem variable when the trigger was created. collation_connection is\nthe session value of the collation_connection system variable when the\ntrigger was created. Database Collation is the collation of the\ndatabase with which the trigger is associated.\n\nURL: https://mariadb.com/kb/en/show-triggers/\n\n','','https://mariadb.com/kb/en/show-triggers/'),(26,'MASTER_POS_WAIT',14,'Syntax:\nMASTER_POS_WAIT(log_name,log_pos[,timeout])\n\nThis function is useful for control of master/slave synchronization. It\nblocks until the slave has read and applied all updates up to the\nspecified position in the master log. The return value is the number of\nlog events the slave had to wait for to advance to the specified\nposition. The function returns NULL if the slave SQL thread is not\nstarted, the slave\'s master information is not initialized, the\narguments are incorrect, or an error occurs. It returns -1 if the\ntimeout has been exceeded. If the slave SQL thread stops while\nMASTER_POS_WAIT() is waiting, the function returns NULL. If the slave\nis past the specified position, the function returns immediately.\n\nIf a timeout value is specified, MASTER_POS_WAIT() stops waiting when\ntimeout seconds have elapsed. timeout must be greater than 0; a zero or\nnegative timeout means no timeout.\n\nURL: https://mariadb.com/kb/en/master_pos_wait/\n\n','','https://mariadb.com/kb/en/master_pos_wait/'),(27,'REGEXP',37,'Syntax:\nexpr REGEXP pat, expr RLIKE pat\n\nPerforms a pattern match of a string expression expr against a pattern\npat. The pattern can be an extended regular expression. The syntax for\nregular expressions is discussed in\nhttps://mariadb.com/kb/en/regexp/. Returns 1 if expr\nmatches pat; otherwise it returns 0. If either expr or pat is NULL, the\nresult is NULL. RLIKE is a synonym for REGEXP, provided for mSQL\ncompatibility.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\n*Note*: Because MySQL uses the C escape syntax in strings (for example,\n\"\\n\" to represent the newline character), you must double any \"\\\" that\nyou use in your REGEXP strings.\n\nREGEXP is not case sensitive, except when used with binary strings.\n\nURL: https://mariadb.com/kb/en/regexp/\n\n','MariaDB> SELECT \'Monty!\' REGEXP \'.*\';\n -> 1\nMariaDB> SELECT \'new*\\n*line\' REGEXP \'new\\\\*.\\\\*line\';\n -> 1\nMariaDB> SELECT \'a\' REGEXP \'A\', \'a\' REGEXP BINARY \'A\';\n -> 1 0\nMariaDB> SELECT \'a\' REGEXP \'^[a-d]\';\n -> 1\n','https://mariadb.com/kb/en/regexp/'),(28,'IF STATEMENT',23,'Syntax:\nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF\n\nThe IF statement for stored programs implements a basic conditional\nconstruct.\n\n*Note*: There is also an IF() function, which differs from the IF\nstatement described here. See\nhttps://mariadb.com/kb/en/if-function/. The\nIF statement can have THEN, ELSE, and ELSEIF clauses, and it is\nterminated with END IF.\n\nIf the search_condition evaluates to true, the corresponding THEN or\nELSEIF clause statement_list executes. If no search_condition matches,\nthe ELSE clause statement_list executes.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nURL: https://mariadb.com/kb/en/if-statement/\n\n','','https://mariadb.com/kb/en/if-statement/'),(29,'^',19,'Syntax:\n^\n\nBitwise XOR:\n\nURL: https://mariadb.com/kb/en/bitwise-xor/\n\n','MariaDB> SELECT 1 ^ 1;\n -> 0\nMariaDB> SELECT 1 ^ 0;\n -> 1\nMariaDB> SELECT 11 ^ 3;\n -> 8\n','https://mariadb.com/kb/en/bitwise-xor/'),(30,'DROP VIEW',39,'Syntax:\nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n\nDROP VIEW removes one or more views. You must have the DROP privilege\nfor each view. If any of the views named in the argument list do not\nexist, MySQL returns an error indicating by name which nonexisting\nviews it was unable to drop, but it also drops all of the views in the\nlist that do exist.\n\nThe IF EXISTS clause prevents an error from occurring for views that\ndon\'t exist. When this clause is given, a NOTE is generated for each\nnonexistent view. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE, if given, are parsed and ignored.\n\nURL: https://mariadb.com/kb/en/drop-view/\n\n','','https://mariadb.com/kb/en/drop-view/'),(31,'WITHIN',30,'Within(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially within g2. This\ntests the opposite relationship as Contains().\n\nURL: https://mariadb.com/kb/en/within/\n\n','','https://mariadb.com/kb/en/within/'),(32,'WEEK',31,'Syntax:\nWEEK(date[,mode])\n\nThis function returns the week number for date. The two-argument form\nof WEEK() enables you to specify whether the week starts on Sunday or\nMonday and whether the return value should be in the range from 0 to 53\nor from 1 to 53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/week/\n\n','MariaDB> SELECT WEEK(\'2008-02-20\');\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',0);\n -> 7\nMariaDB> SELECT WEEK(\'2008-02-20\',1);\n -> 8\nMariaDB> SELECT WEEK(\'2008-12-31\',1);\n -> 53\n','https://mariadb.com/kb/en/week/'),(33,'SHOW PLUGINS',26,'Syntax:\nSHOW PLUGINS\n\nSHOW PLUGINS displays information about server plugins. Plugin\ninformation is also available in the INFORMATION_SCHEMA.PLUGINS table.\nSee https://mariadb.com/kb/en/information_schemaplugins-table/.\n\nExample of SHOW PLUGINS output:\n\nMariaDB> SHOW PLUGINS\\G\n*************************** 1. row ***************************\n Name: binlog\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 2. row ***************************\n Name: CSV\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 3. row ***************************\n Name: MEMORY\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 4. row ***************************\n Name: MyISAM\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n...\n\nURL: https://mariadb.com/kb/en/show-plugins/\n\n','','https://mariadb.com/kb/en/show-plugins/'),(34,'DROP FUNCTION UDF',21,'Syntax:\nDROP FUNCTION function_name\n\nThis statement drops the user-defined function (UDF) named\nfunction_name.\n\nTo drop a function, you must have the DELETE privilege for the mysql\ndatabase. This is because DROP FUNCTION removes a row from the\nmysql.func system table that records the function\'s name, type, and\nshared library name.\n\nURL: https://mariadb.com/kb/en/drop-function-udf/\n\n','','https://mariadb.com/kb/en/drop-function-udf/'),(35,'PREPARE',8,'Syntax:\nPREPARE stmt_name FROM preparable_stmt\n\nThe PREPARE statement prepares a statement and assigns it a name,\nstmt_name, by which to refer to the statement later. Statement names\nare not case sensitive. preparable_stmt is either a string literal or a\nuser variable that contains the text of the statement. The text must\nrepresent a single SQL statement, not multiple statements. Within the\nstatement, \"?\" characters can be used as parameter markers to indicate\nwhere data values are to be bound to the query later when you execute\nit. The \"?\" characters should not be enclosed within quotation marks,\neven if you intend to bind them to string values. Parameter markers can\nbe used only where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n\nIf a prepared statement with the given name already exists, it is\ndeallocated implicitly before the new statement is prepared. This means\nthat if the new statement contains an error and cannot be prepared, an\nerror is returned and no statement with the given name exists.\n\nA prepared statement is executed with EXECUTE and released with\nDEALLOCATE PREPARE.\n\nThe scope of a prepared statement is the session within which it is\ncreated. Other sessions cannot see it.\n\nURL: https://mariadb.com/kb/en/prepare-statement/\n\n','','https://mariadb.com/kb/en/prepare-statement/'),(36,'LOCK',8,'Syntax:\nLOCK TABLES\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n\nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n\nUNLOCK TABLES\n\nMySQL enables client sessions to acquire table locks explicitly for the\npurpose of cooperating with other sessions for access to tables, or to\nprevent other sessions from modifying tables during periods when a\nsession requires exclusive access to them. A session can acquire or\nrelease locks only for itself. One session cannot acquire locks for\nanother session or release locks held by another session.\n\nLocks may be used to emulate transactions or to get more speed when\nupdating tables. This is explained in more detail later in this\nsection.\n\nLOCK TABLES explicitly acquires table locks for the current client\nsession. Table locks can be acquired for base tables or views. You must\nhave the LOCK TABLES privilege, and the SELECT privilege for each\nobject to be locked.\n\nFor view locking, LOCK TABLES adds all base tables used in the view to\nthe set of tables to be locked and locks them automatically. If you\nlock a table explicitly with LOCK TABLES, any tables used in triggers\nare also locked implicitly, as described in\nhttps://mariadb.com/kb/en/triggers-and-implicit-locks/.\n\nUNLOCK TABLES explicitly releases any table locks held by the current\nsession. LOCK TABLES implicitly releases any table locks held by the\ncurrent session before acquiring new locks.\n\nAnother use for UNLOCK TABLES is to release the global read lock\nacquired with the FLUSH TABLES WITH READ LOCK statement, which enables\nyou to lock all tables in all databases. See [HELP FLUSH]. (This is a\nvery convenient way to get backups if you have a file system such as\nVeritas that can take snapshots in time.)\n\nURL: https://mariadb.com/kb/en/transactions-lock/\n\n','','https://mariadb.com/kb/en/transactions-lock/'),(37,'UPDATEXML',37,'Syntax:\nUpdateXML(xml_target, xpath_expr, new_xml)\n\nThis function replaces a single portion of a given fragment of XML\nmarkup xml_target with a new XML fragment new_xml, and then returns the\nchanged XML. The portion of xml_target that is replaced matches an\nXPath expression xpath_expr supplied by the user. In MySQL 5.5, the\nXPath expression can contain at most 127 characters. (This limitation\nis lifted in MySQL 5.6.)\n\nIf no expression matching xpath_expr is found, or if multiple matches\nare found, the function returns the original xml_target XML fragment.\nAll three arguments should be strings.\n\nURL: https://mariadb.com/kb/en/updatexml/\n\n','MariaDB> SELECT\n -> UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n -> UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n -> UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n -> \\G\n\n*************************** 1. row ***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n','https://mariadb.com/kb/en/updatexml/'),(38,'RESET SLAVE',8,'Syntax:\nRESET SLAVE [ALL]\n\nRESET SLAVE makes the slave forget its replication position in the\nmaster\'s binary log. This statement is meant to be used for a clean\nstart: It deletes the master.info and relay-log.info files, all the\nrelay log files, and starts a new relay log file. To use RESET SLAVE,\nthe slave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\n*Note*: All relay log files are deleted, even if they have not been\ncompletely executed by the slave SQL thread. (This is a condition\nlikely to exist on a replication slave if you have issued a STOP SLAVE\nstatement or if the slave is highly loaded.)\n\nIn MySQL 5.5 (unlike the case in MySQL 5.1 and earlier), RESET SLAVE\ndoes not change any replication connection parameters such as master\nhost, master port, master user, or master password, which are retained\nin memory. This means that START SLAVE can be issued without requiring\na CHANGE MASTER TO statement following RESET SLAVE.\n\nIn MySQL 5.5.16 and later, you can use RESET SLAVE ALL to reset these\nconnection parameters (Bug #11809016). Connection parameters are also\nreset if the slave mysqld is shut down.\n\nIf the slave SQL thread was in the middle of replicating temporary\ntables when it was stopped, and RESET SLAVE is issued, these replicated\ntemporary tables are deleted on the slave.\n\nURL: https://mariadb.com/kb/en/reset-slave-connection_name/\n\n','','https://mariadb.com/kb/en/reset-slave-connection_name/'),(39,'SHOW BINARY LOGS',26,'Syntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [HELP PURGE BINARY LOGS], that shows\nhow to determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/show-binary-logs/\n\n','','https://mariadb.com/kb/en/show-binary-logs/'),(40,'POLYGON',24,'Polygon(ls1,ls2,...)\n\nConstructs a Polygon value from a number of LineString or WKB\nLineString arguments. If any argument does not represent a LinearRing\n(that is, not a closed and simple LineString), the return value is\nNULL.\n\nURL: https://mariadb.com/kb/en/polygon/\n\n','','https://mariadb.com/kb/en/polygon/'),(41,'MINUTE',31,'Syntax:\nMINUTE(time)\n\nReturns the minute for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/minute/\n\n','MariaDB> SELECT MINUTE(\'2008-02-03 10:05:03\');\n -> 5\n','https://mariadb.com/kb/en/minute/'),(42,'DAY',31,'Syntax:\nDAY(date)\n\nDAY() is a synonym for DAYOFMONTH().\n\nURL: https://mariadb.com/kb/en/day/\n\n','','https://mariadb.com/kb/en/day/'),(43,'MID',37,'Syntax:\nMID(str,pos,len)\n\nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n\nURL: https://mariadb.com/kb/en/mid/\n\n','','https://mariadb.com/kb/en/mid/'),(44,'UUID',14,'Syntax:\nUUID()\n\nReturns a Universal Unique Identifier (UUID) generated according to\n\"DCE 1.1: Remote Procedure Call\" (Appendix A) CAE (Common Applications\nEnvironment) Specifications published by The Open Group in October 1997\n(Document Number C706,\nhttp://www.opengroup.org/public/pubs/catalog/c706.htm).\n\nA UUID is designed as a number that is globally unique in space and\ntime. Two calls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate computers\nthat are not connected to each other.\n\nA UUID is a 128-bit number represented by a utf8 string of five\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format:\n\no The first three numbers are generated from a timestamp.\n\no The fourth number preserves temporal uniqueness in case the timestamp\n value loses monotonicity (for example, due to daylight saving time).\n\no The fifth number is an IEEE 802 node number that provides spatial\n uniqueness. A random number is substituted if the latter is not\n available (for example, because the host computer has no Ethernet\n card, or we do not know how to find the hardware address of an\n interface on your operating system). In this case, spatial uniqueness\n cannot be guaranteed. Nevertheless, a collision should have very low\n probability.\n\n Currently, the MAC address of an interface is taken into account only\n on FreeBSD and Linux. On other operating systems, MySQL uses a\n randomly generated 48-bit number.\n\nURL: https://mariadb.com/kb/en/uuid/\n\n','MariaDB> SELECT UUID();\n -> \'6ccd780c-baba-1026-9564-0040f4311e29\'\n','https://mariadb.com/kb/en/uuid/'),(45,'LINESTRING',24,'LineString(pt1,pt2,...)\n\nConstructs a LineString value from a number of Point or WKB Point\narguments. If the number of arguments is less than two, the return\nvalue is NULL.\n\nURL: https://mariadb.com/kb/en/linestring/\n\n','','https://mariadb.com/kb/en/linestring/'),(46,'SLEEP',14,'Syntax:\nSLEEP(duration)\n\nSleeps (pauses) for the number of seconds given by the duration\nargument, then returns 0. If SLEEP() is interrupted, it returns 1. The\nduration may have a fractional part given in microseconds.\n\nURL: https://mariadb.com/kb/en/sleep/\n\n','','https://mariadb.com/kb/en/sleep/'),(47,'CONNECTION_ID',17,'Syntax:\nCONNECTION_ID()\n\nReturns the connection ID (thread ID) for the connection. Every\nconnection has an ID that is unique among the set of currently\nconnected clients.\n\nURL: https://mariadb.com/kb/en/connection_id/\n\n','MariaDB> SELECT CONNECTION_ID();\n -> 23786\n','https://mariadb.com/kb/en/connection_id/'),(48,'DELETE',27,'Syntax:\nSingle-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n\nOr:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n\nFor the single-table syntax, the DELETE statement deletes rows from\ntbl_name and returns a count of the number of deleted rows. This count\ncan be obtained by calling the ROW_COUNT() function (see\nhttps://mariadb.com/kb/en/information-functions-row_count/). The\nWHERE clause, if given, specifies the conditions that identify which\nrows to delete. With no WHERE clause, all rows are deleted. If the\nORDER BY clause is specified, the rows are deleted in the order that is\nspecified. The LIMIT clause places a limit on the number of rows that\ncan be deleted.\n\nFor the multiple-table syntax, DELETE deletes from each tbl_name the\nrows that satisfy the conditions. In this case, ORDER BY and LIMIT\ncannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe deleted. It is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nCurrently, you cannot delete from a table and select from the same\ntable in a subquery.\n\nYou need the DELETE privilege on a table to delete rows from it. You\nneed only the SELECT privilege for any columns that are only read, such\nas those named in the WHERE clause.\n\nAs stated, a DELETE statement with no WHERE clause deletes all rows. A\nfaster way to do this, when you do not need to know the number of\ndeleted rows, is to use TRUNCATE TABLE. However, within a transaction\nor if you have a lock on the table, TRUNCATE TABLE cannot be used\nwhereas DELETE can. See [HELP TRUNCATE TABLE], and [HELP LOCK].\n\nURL: https://mariadb.com/kb/en/delete/\n\n','','https://mariadb.com/kb/en/delete/'),(49,'ROUND',4,'Syntax:\nROUND(X), ROUND(X,D)\n\nRounds the argument X to D decimal places. The rounding algorithm\ndepends on the data type of X. D defaults to 0 if not specified. D can\nbe negative to cause D digits left of the decimal point of the value X\nto become zero.\n\nURL: https://mariadb.com/kb/en/round/\n\n','MariaDB> SELECT ROUND(-1.23);\n -> -1\nMariaDB> SELECT ROUND(-1.58);\n -> -2\nMariaDB> SELECT ROUND(1.58);\n -> 2\nMariaDB> SELECT ROUND(1.298, 1);\n -> 1.3\nMariaDB> SELECT ROUND(1.298, 0);\n -> 1\nMariaDB> SELECT ROUND(23.298, -1);\n -> 20\n','https://mariadb.com/kb/en/round/'),(50,'NULLIF',7,'Syntax:\nNULLIF(expr1,expr2)\n\nReturns NULL if expr1 = expr2 is true, otherwise returns expr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.\n\nURL: https://mariadb.com/kb/en/nullif/\n\n','MariaDB> SELECT NULLIF(1,1);\n -> NULL\nMariaDB> SELECT NULLIF(1,2);\n -> 1\n','https://mariadb.com/kb/en/nullif/'),(51,'CLOSE',23,'Syntax:\nCLOSE cursor_name\n\nThis statement closes a previously opened cursor. For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nAn error occurs if the cursor is not open.\n\nIf not closed explicitly, a cursor is closed at the end of the BEGIN\n... END block in which it was declared.\n\nURL: https://mariadb.com/kb/en/close/\n\n','','https://mariadb.com/kb/en/close/'),(52,'STOP SLAVE',8,'Syntax:\nSTOP SLAVE [thread_types]\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nStops the slave threads. STOP SLAVE requires the SUPER privilege.\nRecommended best practice is to execute STOP SLAVE on the slave before\nstopping the slave server (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-shutdown.html, for more\ninformation).\n\nWhen using the row-based logging format: You should execute STOP SLAVE\non the slave prior to shutting down the slave server if you are\nreplicating any tables that use a nontransactional storage engine (see\nthe Note later in this section). In MySQL 5.5.9 and later, you can also\nuse STOP SLAVE SQL_THREAD for this purpose.\n\nLike START SLAVE, this statement may be used with the IO_THREAD and\nSQL_THREAD options to name the thread or threads to be stopped.\n\n*Note*: In MySQL 5.5, STOP SLAVE waits until the current replication\nevent group affecting one or more non-transactional tables has finished\nexecuting (if there is any such replication group), or until the user\nissues a KILL QUERY or KILL CONNECTION statement. (Bug #319, Bug\n#38205)\n\nURL: https://mariadb.com/kb/en/stop-slave/\n\n','','https://mariadb.com/kb/en/stop-slave/'),(53,'TIMEDIFF',31,'Syntax:\nTIMEDIFF(expr1,expr2)\n\nTIMEDIFF() returns expr1 - expr2 expressed as a time value. expr1 and\nexpr2 are time or date-and-time expressions, but both must be of the\nsame type.\n\nThe result returned by TIMEDIFF() is limited to the range allowed for\nTIME values. Alternatively, you can use either of the functions\nTIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.\n\nURL: https://mariadb.com/kb/en/timediff/\n\n','MariaDB> SELECT TIMEDIFF(\'2000:01:01 00:00:00\',\n -> \'2000:01:01 00:00:00.000001\');\n -> \'-00:00:00.000001\'\nMariaDB> SELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\',\n -> \'2008-12-30 01:01:01.000002\');\n -> \'46:58:57.999999\'\n','https://mariadb.com/kb/en/timediff/'),(54,'REPLACE FUNCTION',37,'Syntax:\nREPLACE(str,from_str,to_str)\n\nReturns the string str with all occurrences of the string from_str\nreplaced by the string to_str. REPLACE() performs a case-sensitive\nmatch when searching for from_str.\n\nURL: https://mariadb.com/kb/en/replace-function/\n\n','MariaDB> SELECT REPLACE(\'www.mariadb.org\', \'w\', \'Ww\');\n -> \'WwWwWw.mariadb.org\'\n','https://mariadb.com/kb/en/replace-function/'),(55,'USE',28,'Syntax:\nUSE db_name\n\nThe USE db_name statement tells MySQL to use the db_name database as\nthe default (current) database for subsequent statements. The database\nremains the default until the end of the session or another USE\nstatement is issued:\n\nUSE db1;\nSELECT COUNT(*) FROM mytable; # selects from db1.mytable\nUSE db2;\nSELECT COUNT(*) FROM mytable; # selects from db2.mytable\n\nURL: https://mariadb.com/kb/en/use/\n\n','','https://mariadb.com/kb/en/use/'),(56,'LINEFROMTEXT',3,'LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])\n\nConstructs a LINESTRING value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromtext/\n\n','','https://mariadb.com/kb/en/linefromtext/'),(57,'CASE OPERATOR',7,'Syntax:\nCASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN\nresult ...] [ELSE result] END\n\nCASE WHEN [condition] THEN result [WHEN [condition] THEN result ...]\n[ELSE result] END\n\nThe first version returns the result where value=compare_value. The\nsecond version returns the result for the first condition that is true.\nIf there was no matching result value, the result after ELSE is\nreturned, or NULL if there is no ELSE part.\n\nURL: https://mariadb.com/kb/en/case-operator/\n\n','MariaDB> SELECT CASE 1 WHEN 1 THEN \'one\'\n -> WHEN 2 THEN \'two\' ELSE \'more\' END;\n -> \'one\'\nMariaDB> SELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n -> \'true\'\nMariaDB> SELECT CASE BINARY \'B\'\n -> WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END;\n -> NULL\n','https://mariadb.com/kb/en/case-operator/'),(58,'SHOW MASTER STATUS',26,'Syntax:\nSHOW MASTER STATUS\n\nThis statement provides status information about the binary log files\nof the master. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nExample:\n\nMariaDB> SHOW MASTER STATUS;\n+---------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+---------------+----------+--------------+------------------+\n| mysql-bin.003 | 73 | test | manual,mysql |\n+---------------+----------+--------------+------------------+\n\nURL: https://mariadb.com/kb/en/show-master-status/\n\n','','https://mariadb.com/kb/en/show-master-status/'),(59,'ADDTIME',31,'Syntax:\nADDTIME(expr1,expr2)\n\nADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time\nor datetime expression, and expr2 is a time expression.\n\nURL: https://mariadb.com/kb/en/addtime/\n\n','MariaDB> SELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1 1:1:1.000002\');\n -> \'2008-01-02 01:01:01.000001\'\nMariaDB> SELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'03:00:01.999997\'\n','https://mariadb.com/kb/en/addtime/'),(60,'SPATIAL',34,'For MyISAM tables, MySQL can create spatial indexes using syntax\nsimilar to that for creating regular indexes, but extended with the\nSPATIAL keyword. Currently, columns in spatial indexes must be declared\nNOT NULL. The following examples demonstrate how to create spatial\nindexes:\n\no With CREATE TABLE:\n\nCREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;\n\no With ALTER TABLE:\n\nALTER TABLE geom ADD SPATIAL INDEX(g);\n\no With CREATE INDEX:\n\nCREATE SPATIAL INDEX sp_index ON geom (g);\n\nFor MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage\nengines that support nonspatial indexing of spatial columns, the engine\ncreates a B-tree index. A B-tree index on spatial values will be useful\nfor exact-value lookups, but not for range scans.\n\nFor more information on indexing spatial columns, see [HELP CREATE\nINDEX].\n\nTo drop spatial indexes, use ALTER TABLE or DROP INDEX:\n\no With ALTER TABLE:\n\nALTER TABLE geom DROP INDEX g;\n\no With DROP INDEX:\n\nDROP INDEX sp_index ON geom;\n\nExample: Suppose that a table geom contains more than 32,000\ngeometries, which are stored in the column g of type GEOMETRY. The\ntable also has an AUTO_INCREMENT column fid for storing object ID\nvalues.\n\nURL: https://mariadb.com/kb/en/spatial/\n\n','','https://mariadb.com/kb/en/spatial/'),(61,'TO_SECONDS',31,'Syntax:\nTO_SECONDS(expr)\n\nGiven a date or datetime expr, returns a the number of seconds since\nthe year 0. If expr is not a valid date or datetime value, returns\nNULL.\n\nURL: https://mariadb.com/kb/en/to_seconds/\n\n','MariaDB> SELECT TO_SECONDS(950501);\n -> 62966505600\nMariaDB> SELECT TO_SECONDS(\'2009-11-29\');\n -> 63426672000\nMariaDB> SELECT TO_SECONDS(\'2009-11-29 13:43:32\');\n -> 63426721412\nMariaDB> SELECT TO_SECONDS( NOW() );\n -> 63426721458\n','https://mariadb.com/kb/en/to_seconds/'),(62,'TIMESTAMPDIFF',31,'Syntax:\nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n\nReturns datetime_expr2 - datetime_expr1, where datetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One expression may be\na date and the other a datetime; a date value is treated as a datetime\nhaving the time part \'00:00:00\' where necessary. The unit for the\nresult (an integer) is given by the unit argument. The legal values for\nunit are the same as those listed in the description of the\nTIMESTAMPADD() function.\n\nURL: https://mariadb.com/kb/en/timestampdiff/\n\n','MariaDB> SELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n -> 3\nMariaDB> SELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n -> -1\nMariaDB> SELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01 12:05:55\');\n -> 128885\n','https://mariadb.com/kb/en/timestampdiff/'),(63,'UPPER',37,'Syntax:\nUPPER(str)\n\nReturns the string str with all characters changed to uppercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nMariaDB> SELECT UPPER(\'Hej\');\n -> \'HEJ\'\n\nSee the description of LOWER() for information that also applies to\nUPPER(), such as information about how to perform lettercase conversion\nof binary strings (BINARY, VARBINARY, BLOB) for which these functions\nare ineffective.\n\nURL: https://mariadb.com/kb/en/upper/\n\n','','https://mariadb.com/kb/en/upper/'),(64,'FROM_UNIXTIME',31,'Syntax:\nFROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)\n\nReturns a representation of the unix_timestamp argument as a value in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the function is used in a string or numeric context. The value\nis expressed in the current time zone. unix_timestamp is an internal\ntimestamp value such as is produced by the UNIX_TIMESTAMP() function.\n\nIf format is given, the result is formatted according to the format\nstring, which is used the same way as listed in the entry for the\nDATE_FORMAT() function.\n\nURL: https://mariadb.com/kb/en/from_unixtime/\n\n','MariaDB> SELECT FROM_UNIXTIME(1196440219);\n -> \'2007-11-30 10:30:19\'\nMariaDB> SELECT FROM_UNIXTIME(1196440219) + 0;\n -> 20071130103019.000000\nMariaDB> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),\n -> \'%Y %D %M %h:%i:%s %x\');\n -> \'2007 30th November 10:30:59 2007\'\n','https://mariadb.com/kb/en/from_unixtime/'),(65,'MEDIUMBLOB',22,'MEDIUMBLOB\n\nA BLOB column with a maximum length of 16,777,215 (224 - 1) bytes. Each\nMEDIUMBLOB value is stored using a 3-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumblob/\n\n','','https://mariadb.com/kb/en/mediumblob/'),(66,'SHA2',12,'Syntax:\nSHA2(str, hash_length)\n\nCalculates the SHA-2 family of hash functions (SHA-224, SHA-256,\nSHA-384, and SHA-512). The first argument is the cleartext string to be\nhashed. The second argument indicates the desired bit length of the\nresult, which must have a value of 224, 256, 384, 512, or 0 (which is\nequivalent to 256). If either argument is NULL or the hash length is\nnot one of the permitted values, the return value is NULL. Otherwise,\nthe function result is a hash value containing the desired number of\nbits. See the notes at the beginning of this section about storing hash\nvalues efficiently.\n\nAs of MySQL 5.5.6, the return value is a nonbinary string in the\nconnection character set. Before 5.5.6, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha2/\n\n','MariaDB> SELECT SHA2(\'abc\', 224);\n -> \'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\'\n','https://mariadb.com/kb/en/sha2/'),(67,'IFNULL',7,'Syntax:\nIFNULL(expr1,expr2)\n\nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it returns\nexpr2. IFNULL() returns a numeric or string value, depending on the\ncontext in which it is used.\n\nURL: https://mariadb.com/kb/en/ifnull/\n\n','MariaDB> SELECT IFNULL(1,0);\n -> 1\nMariaDB> SELECT IFNULL(NULL,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,10);\n -> 10\nMariaDB> SELECT IFNULL(1/0,\'yes\');\n -> \'yes\'\n','https://mariadb.com/kb/en/ifnull/'),(68,'SHOW FUNCTION CODE',26,'Syntax:\nSHOW FUNCTION CODE func_name\n\nThis statement is similar to SHOW PROCEDURE CODE but for stored\nfunctions. See [HELP SHOW PROCEDURE CODE].\n\nURL: https://mariadb.com/kb/en/show-function-code/\n\n','','https://mariadb.com/kb/en/show-function-code/'),(69,'SHOW ERRORS',26,'Syntax:\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW COUNT(*) ERRORS\n\nThis statement is similar to SHOW WARNINGS, except that it displays\ninformation only for errors, rather than for errors, warnings, and\nnotes.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nThe SHOW COUNT(*) ERRORS statement displays the number of errors. You\ncan also retrieve this number from the error_count variable:\n\nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n\nSHOW ERRORS and error_count apply only to errors, not warnings or\nnotes. In other respects, they are similar to SHOW WARNINGS and\nwarning_count. In particular, SHOW ERRORS cannot display information\nfor more than max_error_count messages, and error_count can exceed the\nvalue of max_error_count if the number of errors exceeds\nmax_error_count.\n\nURL: https://mariadb.com/kb/en/show-errors/\n\n','','https://mariadb.com/kb/en/show-errors/'),(70,'LEAST',18,'Syntax:\nLEAST(value1,value2,...)\n\nWith two or more arguments, returns the smallest (minimum-valued)\nargument. The arguments are compared using the following rules:\n\no If any argument is NULL, the result is NULL. No comparison is needed.\n\no If the return value is used in an INTEGER context or all arguments\n are integer-valued, they are compared as integers.\n\no If the return value is used in a REAL context or all arguments are\n real-valued, they are compared as reals.\n\no If the arguments comprise a mix of numbers and strings, they are\n compared as numbers.\n\no If any argument is a nonbinary (character) string, the arguments are\n compared as nonbinary strings.\n\no In all other cases, the arguments are compared as binary strings.\n\nURL: https://mariadb.com/kb/en/least/\n\n','MariaDB> SELECT LEAST(2,0);\n -> 0\nMariaDB> SELECT LEAST(34.0,3.0,5.0,767.0);\n -> 3.0\nMariaDB> SELECT LEAST(\'B\',\'A\',\'C\');\n -> \'A\'\n','https://mariadb.com/kb/en/least/'),(71,'=',18,'=\n\nEqual:\n\nURL: https://mariadb.com/kb/en/equal/\n\n','MariaDB> SELECT 1 = 0;\n -> 0\nMariaDB> SELECT \'0\' = 0;\n -> 1\nMariaDB> SELECT \'0.0\' = 0;\n -> 1\nMariaDB> SELECT \'0.01\' = 0;\n -> 0\nMariaDB> SELECT \'.01\' = 0.01;\n -> 1\n','https://mariadb.com/kb/en/equal/'),(72,'REVERSE',37,'Syntax:\nREVERSE(str)\n\nReturns the string str with the order of the characters reversed.\n\nURL: https://mariadb.com/kb/en/reverse/\n\n','MariaDB> SELECT REVERSE(\'abc\');\n -> \'cba\'\n','https://mariadb.com/kb/en/reverse/'),(73,'ISNULL',18,'Syntax:\nISNULL(expr)\n\nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n\nURL: https://mariadb.com/kb/en/isnull/\n\n','MariaDB> SELECT ISNULL(1+1);\n -> 0\nMariaDB> SELECT ISNULL(1/0);\n -> 1\n','https://mariadb.com/kb/en/isnull/'),(74,'BINARY',22,'BINARY(M)\n\nThe BINARY type is similar to the CHAR type, but stores binary byte\nstrings rather than nonbinary character strings. M represents the\ncolumn length in bytes.\n\nURL: https://mariadb.com/kb/en/binary/\n\n','','https://mariadb.com/kb/en/binary/'),(75,'BLOB DATA TYPE',22,'A BLOB is a binary large object that can hold a variable amount of\ndata. The four BLOB types are TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB.\nThese differ only in the maximum length of the values they can hold.\nThe four TEXT types are TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. These\ncorrespond to the four BLOB types and have the same maximum lengths and\nstorage requirements. See\nhttps://mariadb.com/kb/en/data-type-storage-requirements/.\n\nURL: https://mariadb.com/kb/en/sql_language-data_types-blob/\n\n','','https://mariadb.com/kb/en/sql_language-data_types-blob/'),(76,'BOUNDARY',36,'Boundary(g)\n\nReturns a geometry that is the closure of the combinatorial boundary of\nthe geometry value g.\n\nURL: https://mariadb.com/kb/en/boundary/\n\n','','https://mariadb.com/kb/en/boundary/'),(77,'CREATE USER',10,'Syntax:\nCREATE USER user_specification\n [, user_specification] ...\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nThe CREATE USER statement creates new MySQL accounts. To use it, you\nmust have the global CREATE USER privilege or the INSERT privilege for\nthe mysql database. For each account, CREATE USER creates a new row in\nthe mysql.user table and assigns the account no privileges. An error\noccurs if the account already exists.\n\nEach account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nThe user specification may indicate how the user should authenticate\nwhen connecting to the server:\n\no To enable the user to connect with no password (which is insecure),\n include no IDENTIFIED BY clause:\n\nCREATE USER \'jeffrey\'@\'localhost\';\n\n In this case, the account uses built-in authentication and clients\n must provide no password.\n\no To assign a password, use IDENTIFIED BY with the literal plaintext\n password value:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To avoid specifying the plaintext password if you know its hash value\n (the value that PASSWORD() would return for the password), specify\n the hash value preceded by the keyword PASSWORD:\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED BY PASSWORD \'*90E462C37378CED12064BB3388827D2BA3A9B689\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To authenticate the account using a specific authentication plugin,\n use IDENTIFIED WITH, where auth_plugin is the plugin name. It can be\n an unquoted name or a quoted string literal. \'auth_string\' is an\n optional quoted string literal to pass to the plugin. The plugin\n interprets the meaning of the string, so its format is plugin\n specific. Consult the documentation for a given plugin for\n information about the authentication string values it accepts.\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED WITH my_auth_plugin;\n\n For connections that use this account, the server invokes the named\n plugin and clients must provide credentials as required for the\n authentication method that the plugin implements. If the server\n cannot find the plugin, either at account-creation time or connect\n time, an error occurs. IDENTIFIED WITH can be used as of MySQL 5.5.7.\n\nThe IDENTIFIED BY and IDENTIFIED WITH clauses are mutually exclusive,\nso at most one of them can be specified for a given user.\n\nFor additional information about setting passwords, see\nhttps://mariadb.com/kb/en/create-user/.\n\nURL: https://mariadb.com/kb/en/create-user/\n\n','','https://mariadb.com/kb/en/create-user/'),(78,'POINT',24,'Point(x,y)\n\nConstructs a Point using its coordinates.\n\nURL: https://mariadb.com/kb/en/point/\n\n','','https://mariadb.com/kb/en/point/'),(79,'CURRENT_USER',17,'Syntax:\nCURRENT_USER, CURRENT_USER()\n\nReturns the user name and host name combination for the MySQL account\nthat the server used to authenticate the current client. This account\ndetermines your access privileges. The return value is a string in the\nutf8 character set.\n\nThe value of CURRENT_USER() can differ from the value of USER().\n\nURL: https://mariadb.com/kb/en/current_user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\nMariaDB> SELECT * FROM mysql.user;\nERROR 1044: Access denied for user \'\'@\'localhost\' to\ndatabase \'mysql\'\nMariaDB> SELECT CURRENT_USER();\n -> \'@localhost\'\n','https://mariadb.com/kb/en/current_user/'),(80,'LCASE',37,'Syntax:\nLCASE(str)\n\nLCASE() is a synonym for LOWER().\n\nURL: https://mariadb.com/kb/en/lcase/\n\n','','https://mariadb.com/kb/en/lcase/'),(81,'<=',18,'Syntax:\n<=\n\nLess than or equal:\n\nURL: https://mariadb.com/kb/en/less-than-or-equal/\n\n','MariaDB> SELECT 0.1 <= 2;\n -> 1\n','https://mariadb.com/kb/en/less-than-or-equal/'),(82,'SHOW PROFILES',26,'Syntax:\nSHOW PROFILES\n\nThe SHOW PROFILES statement, together with SHOW PROFILE, displays\nprofiling information that indicates resource usage for statements\nexecuted during the course of the current session. For more\ninformation, see [HELP SHOW PROFILE].\n\nURL: https://mariadb.com/kb/en/show-profiles/\n\n','','https://mariadb.com/kb/en/show-profiles/'),(83,'UPDATE',27,'Syntax:\nSingle-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_reference\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n\nFor the single-table syntax, the UPDATE statement updates columns of\nexisting rows in the named table with new values. The SET clause\nindicates which columns to modify and the values they should be given.\nEach value can be given as an expression, or the keyword DEFAULT to set\na column explicitly to its default value. The WHERE clause, if given,\nspecifies the conditions that identify which rows to update. With no\nWHERE clause, all rows are updated. If the ORDER BY clause is\nspecified, the rows are updated in the order that is specified. The\nLIMIT clause places a limit on the number of rows that can be updated.\n\nFor the multiple-table syntax, UPDATE updates rows in each table named\nin table_references that satisfy the conditions. In this case, ORDER BY\nand LIMIT cannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe updated. For expression syntax, see\nhttp://dev.mysql.com/doc/refman/5.5/en/expressions.html.\n\ntable_references and where_condition are is specified as described in\nhttps://mariadb.com/kb/en/select/.\n\nYou need the UPDATE privilege only for columns referenced in an UPDATE\nthat are actually updated. You need only the SELECT privilege for any\ncolumns that are read but not modified.\n\nThe UPDATE statement supports the following modifiers:\n\no With the LOW_PRIORITY keyword, execution of the UPDATE is delayed\n until no other clients are reading from the table. This affects only\n storage engines that use only table-level locking (such as MyISAM,\n MEMORY, and MERGE).\n\no With the IGNORE keyword, the update statement does not abort even if\n errors occur during the update. Rows for which duplicate-key\n conflicts occur are not updated. Rows for which columns are updated\n to values that would cause data conversion errors are updated to the\n closest valid values instead.\n\nURL: https://mariadb.com/kb/en/update/\n\n','','https://mariadb.com/kb/en/update/'),(84,'IS NOT NULL',18,'Syntax:\nIS NOT NULL\n\nTests whether a value is not NULL.\n\nURL: https://mariadb.com/kb/en/is-not-null/\n\n','MariaDB> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not-null/'),(85,'CASE STATEMENT',23,'Syntax:\nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nOr:\n\nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nThe CASE statement for stored programs implements a complex conditional\nconstruct.\n\n*Note*: There is also a CASE expression, which differs from the CASE\nstatement described here. See\nhttps://mariadb.com/kb/en/case-operator/. The\nCASE statement cannot have an ELSE NULL clause, and it is terminated\nwith END CASE instead of END.\n\nFor the first syntax, case_value is an expression. This value is\ncompared to the when_value expression in each WHEN clause until one of\nthem is equal. When an equal when_value is found, the corresponding\nTHEN clause statement_list executes. If no when_value is equal, the\nELSE clause statement_list executes, if there is one.\n\nThis syntax cannot be used to test for equality with NULL because NULL\n= NULL is false. See\nhttps://mariadb.com/kb/en/null-values/.\n\nFor the second syntax, each WHEN clause search_condition expression is\nevaluated until one is true, at which point its corresponding THEN\nclause statement_list executes. If no search_condition is equal, the\nELSE clause statement_list executes, if there is one.\n\nIf no when_value or search_condition matches the value tested and the\nCASE statement contains no ELSE clause, a Case not found for CASE\nstatement error results.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nTo handle situations where no value is matched by any WHEN clause, use\nan ELSE containing an empty BEGIN ... END block, as shown in this\nexample. (The indentation used here in the ELSE clause is for purposes\nof clarity only, and is not otherwise significant.)\n\nDELIMITER |\n\nCREATE PROCEDURE p()\n BEGIN\n DECLARE v INT DEFAULT 1;\n\n CASE v\n WHEN 2 THEN SELECT v;\n WHEN 3 THEN SELECT 0;\n ELSE\n BEGIN\n END;\n END CASE;\n END;\n |\n\nURL: https://mariadb.com/kb/en/case-statement/\n\n','','https://mariadb.com/kb/en/case-statement/'),(86,'EXECUTE STATEMENT',8,'Syntax:\nEXECUTE stmt_name\n [USING @var_name [, @var_name] ...]\n\nAfter preparing a statement with PREPARE, you execute it with an\nEXECUTE statement that refers to the prepared statement name. If the\nprepared statement contains any parameter markers, you must supply a\nUSING clause that lists user variables containing the values to be\nbound to the parameters. Parameter values can be supplied only by user\nvariables, and the USING clause must name exactly as many variables as\nthe number of parameter markers in the statement.\n\nYou can execute a given prepared statement multiple times, passing\ndifferent variables to it or setting the variables to different values\nbefore each execution.\n\nURL: https://mariadb.com/kb/en/execute-statement/\n\n','','https://mariadb.com/kb/en/execute-statement/'),(87,'DROP INDEX',39,'Syntax:\nDROP [ONLINE|OFFLINE] INDEX index_name ON tbl_name\n\nDROP INDEX drops the index named index_name from the table tbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop the index.\nSee [HELP ALTER TABLE].\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: https://mariadb.com/kb/en/drop-index/\n\n','','https://mariadb.com/kb/en/drop-index/'),(88,'MATCH AGAINST',37,'Syntax:\nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n\nMySQL has support for full-text indexing and searching:\n\no A full-text index in MySQL is an index of type FULLTEXT.\n\no Full-text indexes can be used only with MyISAM tables, and can be\n created only for CHAR, VARCHAR, or TEXT columns.\n\no A FULLTEXT index definition can be given in the CREATE TABLE\n statement when a table is created, or added later using ALTER TABLE\n or CREATE INDEX.\n\no For large data sets, it is much faster to load your data into a table\n that has no FULLTEXT index and then create the index after that, than\n to load data into a table that has an existing FULLTEXT index.\n\nFull-text searching is performed using MATCH() ... AGAINST syntax.\nMATCH() takes a comma-separated list that names the columns to be\nsearched. AGAINST takes a string to search for, and an optional\nmodifier that indicates what type of search to perform. The search\nstring must be a literal string, not a variable or a column name. There\nare three types of full-text searches:\n\no A natural language search interprets the search string as a phrase in\n natural human language (a phrase in free text). There are no special\n operators. The stopword list applies. In addition, words that are\n present in 50% or more of the rows are considered common and do not\n match.\n\n Full-text searches are natural language searches if the IN NATURAL\n LANGUAGE MODE modifier is given or if no modifier is given. For more\n information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-natural-language-mode\n .\n\no A boolean search interprets the search string using the rules of a\n special query language. The string contains the words to search for.\n It can also contain operators that specify requirements such that a\n word must be present or absent in matching rows, or that it should be\n weighted higher or lower than usual. Common words such as \"some\" or\n \"then\" are stopwords and do not match if present in the search\n string. The IN BOOLEAN MODE modifier specifies a boolean search. For\n more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#in-boolean-mode.\n\no A query expansion search is a modification of a natural language\n search. The search string is used to perform a natural language\n search. Then words from the most relevant rows returned by the search\n are added to the search string and the search is done again. The\n query returns the rows from the second search. The IN NATURAL\n LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier\n specifies a query expansion search. For more information, see\n https://mariadb.com/kb/en/fulltext-index-overview#with-query-expansion.\n\nURL: https://mariadb.com/kb/en/match-against/\n\n','MariaDB> SELECT id, body, MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE) AS score\n -> FROM articles WHERE MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |\n| 6 | When configured properly, MySQL ... | 1.3114095926285 |\n+----+-------------------------------------+-----------------+\n2 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/match-against/'),(89,'CREATE EVENT',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n EVENT\n [IF NOT EXISTS]\n event_name\n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO event_body;\n\nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval\n [STARTS timestamp [+ INTERVAL interval] ...]\n [ENDS timestamp [+ INTERVAL interval] ...]\n\ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n\nThis statement creates and schedules a new event. The event will not\nrun unless the Event Scheduler is enabled. For information about\nchecking Event Scheduler status and enabling it if necessary, see\nhttps://mariadb.com/kb/en/events/.\n\nCREATE EVENT requires the EVENT privilege for the schema in which the\nevent is to be created. It might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section.\n\nThe minimum requirements for a valid CREATE EVENT statement are as\nfollows:\n\no The keywords CREATE EVENT plus an event name, which uniquely\n identifies the event in a database schema.\n\no An ON SCHEDULE clause, which determines when and how often the event\n executes.\n\no A DO clause, which contains the SQL statement to be executed by an\n event.\n\nThis is an example of a minimal CREATE EVENT statement:\n\nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n\nThe previous statement creates an event named myevent. This event\nexecutes once---one hour following its creation---by running an SQL\nstatement that increments the value of the myschema.mytable table\'s\nmycol column by 1.\n\nThe event_name must be a valid MySQL identifier with a maximum length\nof 64 characters. Event names are not case sensitive, so you cannot\nhave two events named myevent and MyEvent in the same schema. In\ngeneral, the rules governing event names are the same as those for\nnames of stored routines. See\nhttps://mariadb.com/kb/en/identifier-names/.\n\nAn event is associated with a schema. If no schema is indicated as part\nof event_name, the default (current) schema is assumed. To create an\nevent in a specific schema, qualify the event name with a schema using\nschema_name.event_name syntax.\n\nURL: https://mariadb.com/kb/en/create-event/\n\n','','https://mariadb.com/kb/en/create-event/'),(90,'ABS',4,'Syntax:\nABS(X)\n\nReturns the absolute value of X.\n\nURL: https://mariadb.com/kb/en/abs/\n\n','MariaDB> SELECT ABS(2);\n -> 2\nMariaDB> SELECT ABS(-32);\n -> 32\n','https://mariadb.com/kb/en/abs/'),(91,'POLYFROMWKB',32,'PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])\n\nConstructs a POLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromwkb/\n\n','','https://mariadb.com/kb/en/polyfromwkb/'),(92,'NOT LIKE',37,'Syntax:\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n\nThis is the same as NOT (expr LIKE pat [ESCAPE \'escape_char\']).\n\nURL: https://mariadb.com/kb/en/not-like/\n\n','','https://mariadb.com/kb/en/not-like/'),(93,'SPACE',37,'Syntax:\nSPACE(N)\n\nReturns a string consisting of N space characters.\n\nURL: https://mariadb.com/kb/en/space/\n\n','MariaDB> SELECT SPACE(6);\n -> \' \'\n','https://mariadb.com/kb/en/space/'),(94,'MBR DEFINITION',6,'Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding\ngeometry, formed by the minimum and maximum (X,Y) coordinates:\n\nURL: https://mariadb.com/kb/en/mbr-definition/\n\n','((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n','https://mariadb.com/kb/en/mbr-definition/'),(95,'GEOMETRYCOLLECTION',24,'GeometryCollection(g1,g2,...)\n\nConstructs a GeometryCollection.\n\nURL: https://mariadb.com/kb/en/geometrycollection/\n\n','','https://mariadb.com/kb/en/geometrycollection/'),(96,'MAX',16,'Syntax:\nMAX([DISTINCT] expr)\n\nReturns the maximum value of expr. MAX() may take a string argument; in\nsuch cases, it returns the maximum string value. See\nhttps://mariadb.com/kb/en/max/. The DISTINCT\nkeyword can be used to find the maximum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMAX() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/max/\n\n','MariaDB> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/max/'),(97,'CREATE FUNCTION UDF',21,'Syntax:\nCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n\nA user-defined function (UDF) is a way to extend MySQL with a new\nfunction that works like a native (built-in) MySQL function such as\nABS() or CONCAT().\n\nfunction_name is the name that should be used in SQL statements to\ninvoke the function. The RETURNS clause indicates the type of the\nfunction\'s return value. DECIMAL is a legal value after RETURNS, but\ncurrently DECIMAL functions return string values and should be written\nlike STRING functions.\n\nshared_library_name is the basename of the shared object file that\ncontains the code that implements the function. The file must be\nlocated in the plugin directory. This directory is given by the value\nof the plugin_dir system variable. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/udf-compiling.html.\n\nTo create a function, you must have the INSERT privilege for the mysql\ndatabase. This is necessary because CREATE FUNCTION adds a row to the\nmysql.func system table that records the function\'s name, type, and\nshared library name. If you do not have this table, you should run the\nmysql_upgrade command to create it. See\nhttps://mariadb.com/kb/en/mysql_upgrade/.\n\nURL: https://mariadb.com/kb/en/create-function-udf/\n\n','','https://mariadb.com/kb/en/create-function-udf/'),(98,'*',4,'Syntax:\n*\n\nMultiplication:\n\nURL: https://mariadb.com/kb/en/multiplication-operator/\n\n','MariaDB> SELECT 3*5;\n -> 15\nMariaDB> SELECT 18014398509481984*18014398509481984.0;\n -> 324518553658426726783156020576256.0\nMariaDB> SELECT 18014398509481984*18014398509481984;\n -> 0\n','https://mariadb.com/kb/en/multiplication-operator/'),(99,'TIMESTAMP',22,'TIMESTAMP\n\nA timestamp. The range is \'1970-01-01 00:00:01\' UTC to \'2038-01-19\n03:14:07\' UTC. TIMESTAMP values are stored as the number of seconds\nsince the epoch (\'1970-01-01 00:00:00\' UTC). A TIMESTAMP cannot\nrepresent the value \'1970-01-01 00:00:00\' because that is equivalent to\n0 seconds from the epoch and the value 0 is reserved for representing\n\'0000-00-00 00:00:00\', the \"zero\" TIMESTAMP value.\n\nUnless specified otherwise, the first TIMESTAMP column in a table is\ndefined to be automatically set to the date and time of the most recent\nmodification if not explicitly assigned a value. This makes TIMESTAMP\nuseful for recording the timestamp of an INSERT or UPDATE operation.\nYou can also set any TIMESTAMP column to the current date and time by\nassigning it a NULL value, unless it has been defined with the NULL\nattribute to permit NULL values. The automatic initialization and\nupdating to the current date and time can be specified using DEFAULT\nCURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, as described\nin\nhttps://mariadb.com/kb/en/timestamp/.\n\n*Note*: The TIMESTAMP format that was used prior to MySQL 4.1 is not\nsupported in MySQL 5.5; see MySQL 3.23, 4.0, 4.1 Reference Manual for\ninformation regarding the old format.\n\nURL: https://mariadb.com/kb/en/timestamp/\n\n','','https://mariadb.com/kb/en/timestamp/'),(100,'DES_DECRYPT',12,'Syntax:\nDES_DECRYPT(crypt_str[,key_str])\n\nDecrypts a string encrypted with DES_ENCRYPT(). If an error occurs,\nthis function returns NULL.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nIf no key_str argument is given, DES_DECRYPT() examines the first byte\nof the encrypted string to determine the DES key number that was used\nto encrypt the original string, and then reads the key from the DES key\nfile to decrypt the message. For this to work, the user must have the\nSUPER privilege. The key file can be specified with the --des-key-file\nserver option.\n\nIf you pass this function a key_str argument, that string is used as\nthe key for decrypting the message.\n\nIf the crypt_str argument does not appear to be an encrypted string,\nMySQL returns the given crypt_str.\n\nURL: https://mariadb.com/kb/en/des_decrypt/\n\n','','https://mariadb.com/kb/en/des_decrypt/'),(101,'CACHE INDEX',26,'Syntax:\nCACHE INDEX\n tbl_index_list [, tbl_index_list] ...\n [PARTITION (partition_list | ALL)]\n IN key_cache_name\n\ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe CACHE INDEX statement assigns table indexes to a specific key\ncache. It is used only for MyISAM tables. After the indexes have been\nassigned, they can be preloaded into the cache if desired with LOAD\nINDEX INTO CACHE.\n\nThe following statement assigns indexes from the tables t1, t2, and t3\nto the key cache named hot_cache:\n\nMariaDB> CACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n\nURL: https://mariadb.com/kb/en/cache-index/\n\n','','https://mariadb.com/kb/en/cache-index/'),(102,'ENDPOINT',13,'EndPoint(ls)\n\nReturns the Point that is the endpoint of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/endpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/endpoint/'),(103,'COMPRESS',12,'Syntax:\nCOMPRESS(string_to_compress)\n\nCompresses a string and returns the result as a binary string. This\nfunction requires MySQL to have been compiled with a compression\nlibrary such as zlib. Otherwise, the return value is always NULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n\nURL: https://mariadb.com/kb/en/compress/\n\n','MariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n -> 21\nMariaDB> SELECT LENGTH(COMPRESS(\'\'));\n -> 0\nMariaDB> SELECT LENGTH(COMPRESS(\'a\'));\n -> 13\nMariaDB> SELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n -> 15\n','https://mariadb.com/kb/en/compress/'),(104,'INSERT',27,'Syntax:\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nINSERT inserts new rows into an existing table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based on\nexplicitly specified values. The INSERT ... SELECT form inserts rows\nselected from another table or tables. INSERT ... SELECT is discussed\nfurther in [HELP INSERT SELECT].\n\nURL: https://mariadb.com/kb/en/insert/\n\n','','https://mariadb.com/kb/en/insert/'),(105,'COUNT',16,'Syntax:\nCOUNT(expr)\n\nReturns a count of the number of non-NULL values of expr in the rows\nretrieved by a SELECT statement. The result is a BIGINT value.\n\nCOUNT() returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count/\n\n','MariaDB> SELECT student.student_name,COUNT(*)\n -> FROM student,course\n -> WHERE student.student_id=course.student_id\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/count/'),(106,'HANDLER',27,'Syntax:\nHANDLER tbl_name OPEN [ [AS] alias]\n\nHANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ { FIRST | NEXT }\n [ WHERE where_condition ] [LIMIT ... ]\n\nHANDLER tbl_name CLOSE\n\nThe HANDLER statement provides direct access to table storage engine\ninterfaces. It is available for MyISAM and InnoDB tables.\n\nURL: https://mariadb.com/kb/en/handler-commands/\n\n','','https://mariadb.com/kb/en/handler-commands/'),(107,'MLINEFROMTEXT',3,'MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])\n\nConstructs a MULTILINESTRING value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromtext/\n\n','','https://mariadb.com/kb/en/mlinefromtext/'),(108,'GEOMCOLLFROMWKB',32,'GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkb[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromwkb/\n\n','','https://mariadb.com/kb/en/geomcollfromwkb/'),(109,'HELP_DATE',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25\n','',''),(110,'RENAME TABLE',39,'Syntax:\nRENAME TABLE tbl_name TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n\nThis statement renames one or more tables.\n\nThe rename operation is done atomically, which means that no other\nsession can access any of the tables while the rename is running. For\nexample, if you have an existing table old_table, you can create\nanother table new_table that has the same structure but is empty, and\nthen replace the existing table with the empty one as follows (assuming\nthat backup_table does not already exist):\n\nURL: https://mariadb.com/kb/en/rename-table/\n\n','CREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO old_table;\n','https://mariadb.com/kb/en/rename-table/'),(111,'BOOLEAN',22,'BOOL, BOOLEAN\n\nThese types are synonyms for TINYINT(1). A value of zero is considered\nfalse. Nonzero values are considered true:\n\nMariaDB> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n\nMariaDB> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nMariaDB> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nHowever, the values TRUE and FALSE are merely aliases for 1 and 0,\nrespectively, as shown here:\n\nMariaDB> SELECT IF(0 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n\nMariaDB> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n\nMariaDB> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n\nThe last two statements display the results shown because 2 is equal to\nneither 1 nor 0.\n\nURL: https://mariadb.com/kb/en/boolean/\n\n','','https://mariadb.com/kb/en/boolean/'),(112,'DEFAULT',14,'Syntax:\nDEFAULT(col_name)\n\nReturns the default value for a table column. An error results if the\ncolumn has no default value.\n\nURL: https://mariadb.com/kb/en/default/\n\n','MariaDB> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\n','https://mariadb.com/kb/en/default/'),(113,'MOD',4,'Syntax:\nMOD(N,M), N % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M.\n\nURL: https://mariadb.com/kb/en/mod/\n\n','MariaDB> SELECT MOD(234, 10);\n -> 4\nMariaDB> SELECT 253 % 7;\n -> 1\nMariaDB> SELECT MOD(29,9);\n -> 2\nMariaDB> SELECT 29 MOD 9;\n -> 2\n','https://mariadb.com/kb/en/mod/'),(114,'TINYTEXT',22,'TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 255 (28 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TINYTEXT value is stored using a 1-byte length prefix\nthat indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinytext/\n\n','','https://mariadb.com/kb/en/tinytext/'),(115,'OPTIMIZE TABLE',20,'Syntax:\nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nOPTIMIZE TABLE should be used if you have deleted a large part of a\ntable or if you have made many changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT columns).\nDeleted rows are maintained in a linked list and subsequent INSERT\noperations reuse old row positions. You can use OPTIMIZE TABLE to\nreclaim the unused space and to defragment the data file. After\nextensive changes to a table, this statement may also improve\nperformance of statements that use the table, sometimes significantly.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nOPTIMIZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... OPTIMIZE PARTITION to optimize one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/optimize-table/\n\n','','https://mariadb.com/kb/en/optimize-table/'),(116,'DECODE',12,'Syntax:\nDECODE(crypt_str,pass_str)\n\nDecrypts the encrypted string crypt_str using pass_str as the password.\ncrypt_str should be a string returned from ENCODE().\n\nURL: https://mariadb.com/kb/en/decode/\n\n','','https://mariadb.com/kb/en/decode/'),(117,'<=>',18,'Syntax:\n<=>\n\nNULL-safe equal. This operator performs an equality comparison like the\n= operator, but returns 1 rather than NULL if both operands are NULL,\nand 0 rather than NULL if one operand is NULL.\n\nURL: https://mariadb.com/kb/en/null-safe-equal/\n\n','MariaDB> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\n -> 1, 1, 0\nMariaDB> SELECT 1 = 1, NULL = NULL, 1 = NULL;\n -> 1, NULL, NULL\n','https://mariadb.com/kb/en/null-safe-equal/'),(118,'HELP STATEMENT',28,'Syntax:\nHELP \'search_string\'\n\nThe HELP statement returns online information from the MySQL Reference\nmanual. Its proper operation requires that the help tables in the mysql\ndatabase be initialized with help topic information.\n\nThe HELP statement searches the help tables for the given search string\nand displays the result of the search. The search string is not case\nsensitive.\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(119,'RESET',26,'Syntax:\nRESET reset_option [, reset_option] ...\n\nThe RESET statement is used to clear the state of various server\noperations. You must have the RELOAD privilege to execute RESET.\n\nRESET acts as a stronger version of the FLUSH statement. See [HELP\nFLUSH].\n\nThe RESET statement causes an implicit commit. See\nhttps://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/.\n\nURL: https://mariadb.com/kb/en/reset/\n\n','','https://mariadb.com/kb/en/reset/'),(120,'GET_LOCK',14,'Syntax:\nGET_LOCK(str,timeout)\n\nTries to obtain a lock with a name given by the string str, using a\ntimeout of timeout seconds. Returns 1 if the lock was obtained\nsuccessfully, 0 if the attempt timed out (for example, because another\nclient has previously locked the name), or NULL if an error occurred\n(such as running out of memory or the thread was killed with mysqladmin\nkill). If you have a lock obtained with GET_LOCK(), it is released when\nyou execute RELEASE_LOCK(), execute a new GET_LOCK(), or your\nconnection terminates (either normally or abnormally). Locks obtained\nwith GET_LOCK() do not interact with transactions. That is, committing\na transaction does not release any such locks obtained during the\ntransaction.\n\nThis function can be used to implement application locks or to simulate\nrecord locks. Names are locked on a server-wide basis. If a name has\nbeen locked by one client, GET_LOCK() blocks any request by another\nclient for a lock with the same name. This enables clients that agree\non a given lock name to use the name to perform cooperative advisory\nlocking. But be aware that it also enables a client that is not among\nthe set of cooperating clients to lock a name, either inadvertently or\ndeliberately, and thus prevent any of the cooperating clients from\nlocking that name. One way to reduce the likelihood of this is to use\nlock names that are database-specific or application-specific. For\nexample, use lock names of the form db_name.str or app_name.str.\n\nURL: https://mariadb.com/kb/en/get_lock/\n\n','MariaDB> SELECT GET_LOCK(\'lock1\',10);\n -> 1\nMariaDB> SELECT IS_FREE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT GET_LOCK(\'lock2\',10);\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock2\');\n -> 1\nMariaDB> SELECT RELEASE_LOCK(\'lock1\');\n -> NULL\n','https://mariadb.com/kb/en/get_lock/'),(121,'UCASE',37,'Syntax:\nUCASE(str)\n\nUCASE() is a synonym for UPPER().\n\nURL: https://mariadb.com/kb/en/ucase/\n\n','','https://mariadb.com/kb/en/ucase/'),(122,'SHOW BINLOG EVENTS',26,'Syntax:\nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the binary log. If you do not specify \'log_name\',\nthe first binary log is displayed.\n\nURL: https://mariadb.com/kb/en/show-binlog-events/\n\n','','https://mariadb.com/kb/en/show-binlog-events/'),(123,'MPOLYFROMWKB',32,'MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])\n\nConstructs a MULTIPOLYGON value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromwkb/\n\n','','https://mariadb.com/kb/en/mpolyfromwkb/'),(124,'ITERATE',23,'Syntax:\nITERATE label\n\nITERATE can appear only within LOOP, REPEAT, and WHILE statements.\nITERATE means \"start the loop again.\"\n\nURL: https://mariadb.com/kb/en/iterate/\n\n','','https://mariadb.com/kb/en/iterate/'),(125,'DO',27,'Syntax:\nDO expr [, expr] ...\n\nDO executes the expressions but does not return any results. In most\nrespects, DO is shorthand for SELECT expr, ..., but has the advantage\nthat it is slightly faster when you do not care about the result.\n\nDO is useful primarily with functions that have side effects, such as\nRELEASE_LOCK().\n\nURL: https://mariadb.com/kb/en/do/\n\n','','https://mariadb.com/kb/en/do/'),(126,'CURTIME',31,'Syntax:\nCURTIME()\n\nReturns the current time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context. The value is expressed in the current time zone.\n\nURL: https://mariadb.com/kb/en/curtime/\n\n','MariaDB> SELECT CURTIME();\n -> \'23:50:26\'\nMariaDB> SELECT CURTIME() + 0;\n -> 235026.000000\n','https://mariadb.com/kb/en/curtime/'),(127,'CHAR_LENGTH',37,'Syntax:\nCHAR_LENGTH(str)\n\nReturns the length of the string str, measured in characters. A\nmulti-byte character counts as a single character. This means that for\na string containing five 2-byte characters, LENGTH() returns 10,\nwhereas CHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/char_length/\n\n','','https://mariadb.com/kb/en/char_length/'),(128,'BIGINT',22,'BIGINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to 18446744073709551615.\n\nSERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.\n\nURL: https://mariadb.com/kb/en/bigint/\n\n','','https://mariadb.com/kb/en/bigint/'),(129,'SET',26,'Syntax:\nSET variable_assignment [, variable_assignment] ...\n\nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n\nThe SET statement assigns values to different types of variables that\naffect the operation of the server or your client. Older versions of\nMySQL employed SET OPTION, but this syntax is deprecated in favor of\nSET without OPTION.\n\nURL: https://mariadb.com/kb/en/set/\n\n','','https://mariadb.com/kb/en/set/'),(130,'LOAD XML',27,'Syntax:\nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD XML statement reads data from an XML file into a table. The\nfile_name must be given as a literal string. The tagname in the\noptional ROWS IDENTIFIED BY clause must also be given as a literal\nstring, and must be surrounded by angle brackets (< and >).\n\nLOAD XML acts as the complement of running the mysql client in XML\noutput mode (that is, starting the client with the --xml option). To\nwrite data from a table to an XML file, use a command such as the\nfollowing one from the system shell:\n\nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n\nTo read the file back into a table, use LOAD XML INFILE. By default,\nthe element is considered to be the equivalent of a database\ntable row; this can be changed using the ROWS IDENTIFIED BY clause.\n\nThis statement supports three different XML formats:\n\no Column names as attributes and column values as attribute values:\n\n\n\no Column names as tags and column values as the content of these tags:\n\n\n value1\n value2\n\n\no Column names are the name attributes of tags, and values are\n the contents of these tags:\n\n\n value1\n value2\n\n\n This is the format used by other MySQL tools, such as mysqldump.\n\nAll 3 formats can be used in the same XML file; the import routine\nautomatically detects the format for each row and interprets it\ncorrectly. Tags are matched based on the tag or attribute name and the\ncolumn name.\n\nThe following clauses work essentially the same way for LOAD XML as\nthey do for LOAD DATA:\n\no LOW_PRIORITY or CONCURRENT\n\no LOCAL\n\no REPLACE or IGNORE\n\no CHARACTER SET\n\no (column_or_user_var,...)\n\no SET\n\nSee [HELP LOAD DATA], for more information about these clauses.\n\nThe IGNORE number LINES or IGNORE number ROWS clause causes the first\nnumber rows in the XML file to be skipped. It is analogous to the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n\nURL: https://mariadb.com/kb/en/load-xml/\n\n','','https://mariadb.com/kb/en/load-xml/'),(131,'CONV',4,'Syntax:\nCONV(N,from_base,to_base)\n\nConverts numbers between different number bases. Returns a string\nrepresentation of the number N, converted from base from_base to base\nto_base. Returns NULL if any argument is NULL. The argument N is\ninterpreted as an integer, but may be specified as an integer or a\nstring. The minimum base is 2 and the maximum base is 36. If to_base is\na negative number, N is regarded as a signed number. Otherwise, N is\ntreated as unsigned. CONV() works with 64-bit precision.\n\nURL: https://mariadb.com/kb/en/conv/\n\n','MariaDB> SELECT CONV(\'a\',16,2);\n -> \'1010\'\nMariaDB> SELECT CONV(\'6E\',18,8);\n -> \'172\'\nMariaDB> SELECT CONV(-17,10,-18);\n -> \'-H\'\nMariaDB> SELECT CONV(10+\'10\'+\'10\'+0xa,10,10);\n -> \'40\'\n','https://mariadb.com/kb/en/conv/'),(132,'DATE',22,'DATE\n\nA date. The supported range is \'1000-01-01\' to \'9999-12-31\'. MySQL\ndisplays DATE values in \'YYYY-MM-DD\' format, but permits assignment of\nvalues to DATE columns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/date/\n\n','','https://mariadb.com/kb/en/date/'),(133,'ASSIGN-VALUE',15,'Syntax:\n:=\n\nAssignment operator. Causes the user variable on the left hand side of\nthe operator to take on the value to its right. The value on the right\nhand side may be a literal value, another variable storing a value, or\nany legal expression that yields a scalar value, including the result\nof a query (provided that this value is a scalar value). You can\nperform multiple assignments in the same SET statement. You can perform\nmultiple assignments in the same statement-\n\nUnlike =, the := operator is never interpreted as a comparison\noperator. This means you can use := in any valid SQL statement (not\njust in SET statements) to assign a value to a variable.\n\nURL: https://mariadb.com/kb/en/assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n\nMariaDB> SELECT @var1:=COUNT(*) FROM t1;\n -> 4\nMariaDB> SELECT @var1;\n -> 4\n','https://mariadb.com/kb/en/assignment-operator/'),(134,'SHOW OPEN TABLES',26,'Syntax:\nSHOW OPEN TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW OPEN TABLES lists the non-TEMPORARY tables that are currently open\nin the table cache. See\nhttp://dev.mysql.com/doc/refman/5.5/en/table-cache.html. The FROM\nclause, if present, restricts the tables shown to those present in the\ndb_name database. The LIKE clause, if present, indicates which table\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-open-tables/\n\n','','https://mariadb.com/kb/en/show-open-tables/'),(135,'EXTRACT',31,'Syntax:\nEXTRACT(unit FROM date)\n\nThe EXTRACT() function uses the same kinds of unit specifiers as\nDATE_ADD() or DATE_SUB(), but extracts parts from the date rather than\nperforming date arithmetic.\n\nURL: https://mariadb.com/kb/en/extract/\n\n','MariaDB> SELECT EXTRACT(YEAR FROM \'2009-07-02\');\n -> 2009\nMariaDB> SELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n -> 200907\nMariaDB> SELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n -> 20102\nMariaDB> SELECT EXTRACT(MICROSECOND\n -> FROM \'2003-01-02 10:30:00.000123\');\n -> 123\n','https://mariadb.com/kb/en/extract/'),(136,'ENCRYPT',12,'Syntax:\nENCRYPT(str[,salt])\n\nEncrypts str using the Unix crypt() system call and returns a binary\nstring. The salt argument must be a string with at least two characters\nor the result will be NULL. If no salt argument is given, a random\nvalue is used.\n\nURL: https://mariadb.com/kb/en/encrypt/\n\n','MariaDB> SELECT ENCRYPT(\'hello\');\n -> \'VxuFAJXVARROc\'\n','https://mariadb.com/kb/en/encrypt/'),(137,'SHOW STATUS',26,'Syntax:\nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW STATUS provides server status information. This information also\ncan be obtained using the mysqladmin extended-status command. The LIKE\nclause, if present, indicates which variable names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\nThis statement does not require any privilege. It requires only the\nability to connect to the server.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern:\n\nMariaDB> SHOW STATUS LIKE \'Key%\';\n+--------------------+----------+\n| Variable_name | Value |\n+--------------------+----------+\n| Key_blocks_used | 14955 |\n| Key_read_requests | 96854827 |\n| Key_reads | 162040 |\n| Key_write_requests | 7589728 |\n| Key_writes | 3813196 |\n+--------------------+----------+\n\nWith the GLOBAL modifier, SHOW STATUS displays the status values for\nall connections to MySQL. With SESSION, it displays the status values\nfor the current connection. If no modifier is present, the default is\nSESSION. LOCAL is a synonym for SESSION.\n\nSome status variables have only a global value. For these, you get the\nsame value for both GLOBAL and SESSION. The scope for each status\nvariable is listed at\nhttps://mariadb.com/kb/en/server-status-variables/.\n\nEach invocation of the SHOW STATUS statement uses an internal temporary\ntable and increments the global Created_tmp_tables value.\n\nURL: https://mariadb.com/kb/en/show-status/\n\n','','https://mariadb.com/kb/en/show-status/'),(138,'EXTRACTVALUE',37,'Syntax:\nExtractValue(xml_frag, xpath_expr)\n\nExtractValue() takes two string arguments, a fragment of XML markup\nxml_frag and an XPath expression xpath_expr (also known as a locator);\nit returns the text (CDATA) of the first text node which is a child of\nthe elements or elements matched by the XPath expression. In MySQL 5.5,\nthe XPath expression can contain at most 127 characters. (This\nlimitation is lifted in MySQL 5.6.)\n\nUsing this function is the equivalent of performing a match using the\nxpath_expr after appending /text(). In other words,\nExtractValue(\'Sakila\', \'/a/b\') and\nExtractValue(\'Sakila\', \'/a/b/text()\') produce the same\nresult.\n\nIf multiple matches are found, the content of the first child text node\nof each matching element is returned (in the order matched) as a\nsingle, space-delimited string.\n\nIf no matching text node is found for the expression (including the\nimplicit /text())---for whatever reason, as long as xpath_expr is\nvalid, and xml_frag consists of elements which are properly nested and\nclosed---an empty string is returned. No distinction is made between a\nmatch on an empty element and no match at all. This is by design.\n\nIf you need to determine whether no matching element was found in\nxml_frag or such an element was found but contained no child text\nnodes, you should test the result of an expression that uses the XPath\ncount() function. For example, both of these statements return an empty\nstring, as shown here:\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nHowever, you can determine whether there was actually a matching\nelement using the following:\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 1 |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nMariaDB> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n1 row in set (0.01 sec)\n\n*Important*: ExtractValue() returns only CDATA, and does not return any\ntags that might be contained within a matching tag, nor any of their\ncontent (see the result returned as val1 in the following example).\n\nURL: https://mariadb.com/kb/en/extractvalue/\n\n','MariaDB> SELECT\n -> ExtractValue(\'cccddd\', \'/a\') AS val1,\n -> ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n -> ExtractValue(\'cccddd\', \'//b\') AS val3,\n -> ExtractValue(\'cccddd\', \'/b\') AS val4,\n -> ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n\n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n','https://mariadb.com/kb/en/extractvalue/'),(139,'OLD_PASSWORD',12,'Syntax:\nOLD_PASSWORD(str)\n\nOLD_PASSWORD() was added when the implementation of PASSWORD() was\nchanged in MySQL 4.1 to improve security. OLD_PASSWORD() returns the\nvalue of the pre-4.1 implementation of PASSWORD() as a string, and is\nintended to permit you to reset passwords for any pre-4.1 clients that\nneed to connect to your version 5.5 MySQL server without locking them\nout. See http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/old_password/\n\n','','https://mariadb.com/kb/en/old_password/'),(140,'FORMAT',37,'Syntax:\nFORMAT(X,D[,locale])\n\nFormats the number X to a format like \'#,###,###.##\', rounded to D\ndecimal places, and returns the result as a string. If D is 0, the\nresult has no decimal point or fractional part.\n\nThe optional third parameter enables a locale to be specified to be\nused for the result number\'s decimal point, thousands separator, and\ngrouping between separators. Permissible locale values are the same as\nthe legal values for the lc_time_names system variable (see\nhttps://mariadb.com/kb/en/server-locale/). If no\nlocale is specified, the default is \'en_US\'.\n\nURL: https://mariadb.com/kb/en/format/\n\n','MariaDB> SELECT FORMAT(12332.123456, 4);\n -> \'12,332.1235\'\nMariaDB> SELECT FORMAT(12332.1,4);\n -> \'12,332.1000\'\nMariaDB> SELECT FORMAT(12332.2,0);\n -> \'12,332\'\nMariaDB> SELECT FORMAT(12332.2,2,\'de_DE\');\n -> \'12.332,20\'\n','https://mariadb.com/kb/en/format/'),(141,'||',15,'Syntax:\nOR, ||\n\nLogical OR. When both operands are non-NULL, the result is 1 if any\noperand is nonzero, and 0 otherwise. With a NULL operand, the result is\n1 if the other operand is nonzero, and NULL otherwise. If both operands\nare NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/or/\n\n','MariaDB> SELECT 1 || 1;\n -> 1\nMariaDB> SELECT 1 || 0;\n -> 1\nMariaDB> SELECT 0 || 0;\n -> 0\nMariaDB> SELECT 0 || NULL;\n -> NULL\nMariaDB> SELECT 1 || NULL;\n -> 1\n','https://mariadb.com/kb/en/or/'),(142,'BIT_LENGTH',37,'Syntax:\nBIT_LENGTH(str)\n\nReturns the length of the string str in bits.\n\nURL: https://mariadb.com/kb/en/bit_length/\n\n','MariaDB> SELECT BIT_LENGTH(\'text\');\n -> 32\n','https://mariadb.com/kb/en/bit_length/'),(143,'EXTERIORRING',2,'ExteriorRing(poly)\n\nReturns the exterior ring of the Polygon value poly as a LineString.\n\nURL: https://mariadb.com/kb/en/exteriorring/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n','https://mariadb.com/kb/en/exteriorring/'),(144,'GEOMFROMWKB',32,'GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkb[,srid])\n\nConstructs a geometry value of any type using its WKB representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromwkb/\n\n','','https://mariadb.com/kb/en/geomfromwkb/'),(145,'SHOW SLAVE HOSTS',26,'Syntax:\nSHOW SLAVE HOSTS\n\nDisplays a list of replication slaves currently registered with the\nmaster. (Before MySQL 5.5.3, only slaves started with the\n--report-host=host_name option are visible in this list.)\n\nThe list is displayed on any server (not just the master server). The\noutput looks like this:\n\nMariaDB> SHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\n\no Server_id: The unique server ID of the slave server, as configured in\n the server\'s option file, or on the command line with\n --server-id=value.\n\no Host: The host name of the slave server, as configured in the\n server\'s option file, or on the command line with\n --report-host=host_name. Note that this can differ from the machine\n name as configured in the operating system.\n\no Port: The port the slave server is listening on.\n\n In MySQL 5.5.23 and later, a zero in this column means that the slave\n port (--report-port) was not set. Prior to MySQL 5.5.23, 3306 was\n used as the default in such cases (Bug #13333431).\n\no Master_id: The unique server ID of the master server that the slave\n server is replicating from.\n\nSome MySQL versions report another variable, Rpl_recovery_rank. This\nvariable was never used, and was removed in MySQL 5.5.3. (Bug #13963)\n\nURL: https://mariadb.com/kb/en/show-slave-hosts/\n\n','','https://mariadb.com/kb/en/show-slave-hosts/'),(146,'START TRANSACTION',8,'Syntax:\nSTART TRANSACTION [WITH CONSISTENT SNAPSHOT]\nBEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n\nThese statements provide control over use of transactions:\n\no START TRANSACTION or BEGIN start a new transaction.\n\no COMMIT commits the current transaction, making its changes permanent.\n\no ROLLBACK rolls back the current transaction, canceling its changes.\n\no SET autocommit disables or enables the default autocommit mode for\n the current session.\n\nBy default, MySQL runs with autocommit mode enabled. This means that as\nsoon as you execute a statement that updates (modifies) a table, MySQL\nstores the update on disk to make it permanent. The change cannot be\nrolled back.\n\nTo disable autocommit mode implicitly for a single series of\nstatements, use the START TRANSACTION statement:\n\nSTART TRANSACTION;\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\nUPDATE table2 SET summary=@A WHERE type=1;\nCOMMIT;\n\nWith START TRANSACTION, autocommit remains disabled until you end the\ntransaction with COMMIT or ROLLBACK. The autocommit mode then reverts\nto its previous state.\n\nYou can also begin a transaction like this:\n\nSTART TRANSACTION WITH CONSISTENT SNAPSHOT;\n\nThe WITH CONSISTENT SNAPSHOT option starts a consistent read for\nstorage engines that are capable of it. This applies only to InnoDB.\nThe effect is the same as issuing a START TRANSACTION followed by a\nSELECT from any InnoDB table. See\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html. The\nWITH CONSISTENT SNAPSHOT option does not change the current transaction\nisolation level, so it provides a consistent snapshot only if the\ncurrent isolation level is one that permits consistent read (REPEATABLE\nREAD or SERIALIZABLE).\n\n*Important*: Many APIs used for writing MySQL client applications (such\nas JDBC) provide their own methods for starting transactions that can\n(and sometimes should) be used instead of sending a START TRANSACTION\nstatement from the client. See\nhttp://dev.mysql.com/doc/refman/5.5/en/connectors-apis.html, or the\ndocumentation for your API, for more information.\n\nTo disable autocommit mode explicitly, use the following statement:\n\nSET autocommit=0;\n\nAfter disabling autocommit mode by setting the autocommit variable to\nzero, changes to transaction-safe tables (such as those for InnoDB) are not made permanent immediately. You must use COMMIT to\nstore your changes to disk or ROLLBACK to ignore the changes.\n\nautocommit is a session variable and must be set for each session. To\ndisable autocommit mode for each new connection, see the description of\nthe autocommit system variable at\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nBEGIN and BEGIN WORK are supported as aliases of START TRANSACTION for\ninitiating a transaction. START TRANSACTION is standard SQL syntax and\nis the recommended way to start an ad-hoc transaction.\n\nThe BEGIN statement differs from the use of the BEGIN keyword that\nstarts a BEGIN ... END compound statement. The latter does not begin a\ntransaction. See [HELP BEGIN END].\n\n*Note*: Within all stored programs (stored procedures and functions,\ntriggers, and events), the parser treats BEGIN [WORK] as the beginning\nof a BEGIN ... END block. Begin a transaction in this context with\nSTART TRANSACTION instead.\n\nThe optional WORK keyword is supported for COMMIT and ROLLBACK, as are\nthe CHAIN and RELEASE clauses. CHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of the\ncompletion_type system variable determines the default completion\nbehavior. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nThe AND CHAIN clause causes a new transaction to begin as soon as the\ncurrent one ends, and the new transaction has the same isolation level\nas the just-terminated transaction. The RELEASE clause causes the\nserver to disconnect the current client session after terminating the\ncurrent transaction. Including the NO keyword suppresses CHAIN or\nRELEASE completion, which can be useful if the completion_type system\nvariable is set to cause chaining or release completion by default.\n\nURL: https://mariadb.com/kb/en/start-transaction/\n\n','','https://mariadb.com/kb/en/start-transaction/'),(147,'BETWEEN AND',18,'Syntax:\nexpr BETWEEN min AND max\n\nIf expr is greater than or equal to min and expr is less than or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is equivalent\nto the expression (min <= expr AND expr <= max) if all the arguments\nare of the same type. Otherwise type conversion takes place according\nto the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the three arguments.\n\nURL: https://mariadb.com/kb/en/between-and/\n\n','MariaDB> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;\n -> 1, 0\nMariaDB> SELECT 1 BETWEEN 2 AND 3;\n -> 0\nMariaDB> SELECT \'b\' BETWEEN \'a\' AND \'c\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'3\';\n -> 1\nMariaDB> SELECT 2 BETWEEN 2 AND \'x-3\';\n -> 0\n','https://mariadb.com/kb/en/between-and/'),(148,'MULTIPOLYGON',24,'MultiPolygon(poly1,poly2,...)\n\nConstructs a MultiPolygon value from a set of Polygon or WKB Polygon\narguments.\n\nURL: https://mariadb.com/kb/en/multipolygon/\n\n','','https://mariadb.com/kb/en/multipolygon/'),(149,'TIME_FORMAT',31,'Syntax:\nTIME_FORMAT(time,format)\n\nThis is used like the DATE_FORMAT() function, but the format string may\ncontain format specifiers only for hours, minutes, seconds, and\nmicroseconds. Other specifiers produce a NULL value or 0.\n\nURL: https://mariadb.com/kb/en/time_format/\n\n','MariaDB> SELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n -> \'100 100 04 04 4\'\n','https://mariadb.com/kb/en/time_format/'),(150,'LEFT',37,'Syntax:\nLEFT(str,len)\n\nReturns the leftmost len characters from the string str, or NULL if any\nargument is NULL.\n\nURL: https://mariadb.com/kb/en/left/\n\n','MariaDB> SELECT LEFT(\'foobarbar\', 5);\n -> \'fooba\'\n','https://mariadb.com/kb/en/left/'),(151,'FLUSH QUERY CACHE',26,'You can defragment the query cache to better utilize its memory with\nthe FLUSH QUERY CACHE statement. The statement does not remove any\nqueries from the cache.\n\nThe RESET QUERY CACHE statement removes all query results from the\nquery cache. The FLUSH TABLES statement also does this.\n\nURL: https://mariadb.com/kb/en/flush-query-cache/\n\n','','https://mariadb.com/kb/en/flush-query-cache/'),(152,'SET DATA TYPE',22,'SET(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA set. A string object that can have zero or more values, each of which\nmust be chosen from the list of values \'value1\', \'value2\', ... A SET\ncolumn can have a maximum of 64 members. SET values are represented\ninternally as integers.\n\nURL: https://mariadb.com/kb/en/set-data-type/\n\n','','https://mariadb.com/kb/en/set-data-type/'),(153,'RAND',4,'Syntax:\nRAND(), RAND(N)\n\nReturns a random floating-point value v in the range 0 <= v < 1.0. If a\nconstant integer argument N is specified, it is used as the seed value,\nwhich produces a repeatable sequence of column values. In the following\nexample, note that the sequences of values produced by RAND(3) is the\nsame both places where it occurs.\n\nURL: https://mariadb.com/kb/en/rand/\n\n','MariaDB> CREATE TABLE t (i INT);\nQuery OK, 0 rows affected (0.42 sec)\n\nMariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.61914388706828 |\n| 2 | 0.93845168309142 |\n| 3 | 0.83482678498591 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.35877890638893 |\n| 2 | 0.28941420772058 |\n| 3 | 0.37073435016976 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.01 sec)\n','https://mariadb.com/kb/en/rand/'),(154,'RPAD',37,'Syntax:\nRPAD(str,len,padstr)\n\nReturns the string str, right-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\nURL: https://mariadb.com/kb/en/rpad/\n\n','MariaDB> SELECT RPAD(\'hi\',5,\'?\');\n -> \'hi???\'\nMariaDB> SELECT RPAD(\'hi\',1,\'?\');\n -> \'h\'\n','https://mariadb.com/kb/en/rpad/'),(155,'CREATE DATABASE',39,'Syntax:\nCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n [create_specification] ...\n\ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nCREATE DATABASE creates a database with the given name. To use this\nstatement, you need the CREATE privilege for the database. CREATE\nSCHEMA is a synonym for CREATE DATABASE.\n\nURL: https://mariadb.com/kb/en/create-database/\n\n','','https://mariadb.com/kb/en/create-database/'),(156,'DEC',22,'DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED]\n[ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nThese types are synonyms for DECIMAL. The FIXED synonym is available\nfor compatibility with other database systems.\n\nURL: https://mariadb.com/kb/en/dec-numeric-fixed/\n\n','','https://mariadb.com/kb/en/dec-numeric-fixed/'),(157,'VAR_POP',16,'Syntax:\nVAR_POP(expr)\n\nReturns the population standard variance of expr. It considers rows as\nthe whole population, not as a sample, so it has the number of rows as\nthe denominator. You can also use VARIANCE(), which is equivalent but\nis not standard SQL.\n\nVAR_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/var_pop/\n\n','','https://mariadb.com/kb/en/var_pop/'),(158,'ELT',37,'Syntax:\nELT(N,str1,str2,str3,...)\n\nReturns str1 if N = 1, str2 if N = 2, and so on. Returns NULL if N is\nless than 1 or greater than the number of arguments. ELT() is the\ncomplement of FIELD().\n\nURL: https://mariadb.com/kb/en/elt/.html\n\n','MariaDB> SELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'ej\'\nMariaDB> SELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'foo\'\n','https://mariadb.com/kb/en/elt/.html'),(159,'ALTER VIEW',39,'Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW and the effect is the same as\nfor CREATE OR REPLACE VIEW. See [HELP CREATE VIEW]. This statement\nrequires the CREATE VIEW and DROP privileges for the view, and some\nprivilege for each column referred to in the SELECT statement. ALTER\nVIEW is permitted only to the definer or users with the SUPER\nprivilege.\n\nURL: https://mariadb.com/kb/en/alter-view/\n\n','','https://mariadb.com/kb/en/alter-view/'),(160,'SHOW DATABASES',26,'Syntax:\nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW DATABASES lists the databases on the MySQL server host. SHOW\nSCHEMAS is a synonym for SHOW DATABASES. The LIKE clause, if present,\nindicates which database names to match. The WHERE clause can be given\nto select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou see only those databases for which you have some kind of privilege,\nunless you have the global SHOW DATABASES privilege. You can also get\nthis list using the mysqlshow command.\n\nIf the server was started with the --skip-show-database option, you\ncannot use this statement at all unless you have the SHOW DATABASES\nprivilege.\n\nURL: https://mariadb.com/kb/en/show-databases/\n\n','','https://mariadb.com/kb/en/show-databases/'),(161,'~',19,'Syntax:\n~\n\nInvert all bits.\n\nURL: https://mariadb.com/kb/en/3489/\n\n','MariaDB> SELECT 5 & ~1;\n -> 4\n','https://mariadb.com/kb/en/3489/'),(162,'TEXT',22,'TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 65,535 (216 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TEXT value is stored using a 2-byte length prefix that\nindicates the number of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest TEXT type large enough to hold\nvalues M characters long.\n\nURL: https://mariadb.com/kb/en/text/\n\n','','https://mariadb.com/kb/en/text/'),(163,'CONCAT_WS',37,'Syntax:\nCONCAT_WS(separator,str1,str2,...)\n\nCONCAT_WS() stands for Concatenate With Separator and is a special form\nof CONCAT(). The first argument is the separator for the rest of the\narguments. The separator is added between the strings to be\nconcatenated. The separator can be a string, as can the rest of the\narguments. If the separator is NULL, the result is NULL.\n\nURL: https://mariadb.com/kb/en/concat_ws/\n\n','MariaDB> SELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last Name\');\n -> \'First name,Second name,Last Name\'\nMariaDB> SELECT CONCAT_WS(\',\',\'First name\',NULL,\'Last Name\');\n -> \'First name,Last Name\'\n','https://mariadb.com/kb/en/concat_ws/'),(164,'ROW_COUNT',17,'Syntax:\nROW_COUNT()\n\nBefore MySQL 5.5.5, ROW_COUNT() returns the number of rows changed,\ndeleted, or inserted by the last statement if it was an UPDATE, DELETE,\nor INSERT. For other statements, the value may not be meaningful.\n\nAs of MySQL 5.5.5, ROW_COUNT() returns a value as follows:\n\no DDL statements: 0. This applies to statements such as CREATE TABLE or\n DROP TABLE.\n\no DML statements other than SELECT: The number of affected rows. This\n applies to statements such as UPDATE, INSERT, or DELETE (as before),\n but now also to statements such as ALTER TABLE and LOAD DATA INFILE.\n\no SELECT: -1 if the statement returns a result set, or the number of\n rows \"affected\" if it does not. For example, for SELECT * FROM t1,\n ROW_COUNT() returns -1. For SELECT * FROM t1 INTO OUTFILE\n \'file_name\', ROW_COUNT() returns the number of rows written to the\n file.\n\no SIGNAL statements: 0.\n\nFor UPDATE statements, the affected-rows value by default is the number\nof rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() when connecting to mysqld, the affected-rows value\nis the number of rows \"found\"; that is, matched by the WHERE clause.\n\nFor REPLACE statements, the affected-rows value is 2 if the new row\nreplaced an old row, because in this case, one row was inserted after\nthe duplicate was deleted.\n\nFor INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows\nvalue is 1 if the row is inserted as a new row and 2 if an existing row\nis updated.\n\nThe ROW_COUNT() value is similar to the value from the\nmysql_affected_rows() C API function and the row count that the mysql\nclient displays following statement execution.\n\nURL: https://mariadb.com/kb/en/information-functions-row_count/\n\n','MariaDB> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> DELETE FROM t WHERE i IN(1,2);\nQuery OK, 2 rows affected (0.00 sec)\n\nMariaDB> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/information-functions-row_count/'),(165,'ASIN',4,'Syntax:\nASIN(X)\n\nReturns the arc sine of X, that is, the value whose sine is X. Returns\nNULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/asin/\n\n','MariaDB> SELECT ASIN(0.2);\n -> 0.20135792079033\nMariaDB> SELECT ASIN(\'foo\');\n\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n1 row in set, 1 warning (0.00 sec)\n\nMariaDB> SHOW WARNINGS;\n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\' |\n+---------+------+-----------------------------------------+\n','https://mariadb.com/kb/en/asin/'),(166,'SIGN',4,'Syntax:\nSIGN(X)\n\nReturns the sign of the argument as -1, 0, or 1, depending on whether X\nis negative, zero, or positive.\n\nURL: https://mariadb.com/kb/en/sign/\n\n','MariaDB> SELECT SIGN(-32);\n -> -1\nMariaDB> SELECT SIGN(0);\n -> 0\nMariaDB> SELECT SIGN(234);\n -> 1\n','https://mariadb.com/kb/en/sign/'),(167,'SEC_TO_TIME',31,'Syntax:\nSEC_TO_TIME(seconds)\n\nReturns the seconds argument, converted to hours, minutes, and seconds,\nas a TIME value. The range of the result is constrained to that of the\nTIME data type. A warning occurs if the argument corresponds to a value\noutside that range.\n\nURL: https://mariadb.com/kb/en/sec_to_time/\n\n','MariaDB> SELECT SEC_TO_TIME(2378);\n -> \'00:39:38\'\nMariaDB> SELECT SEC_TO_TIME(2378) + 0;\n -> 3938\n','https://mariadb.com/kb/en/sec_to_time/'),(168,'FLOAT',22,'FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA small (single-precision) floating-point number. Permissible values\nare -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to\n3.402823466E+38. These are the theoretical limits, based on the IEEE\nstandard. The actual range might be slightly smaller depending on your\nhardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A single-precision floating-point\nnumber is accurate to approximately 7 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nUsing FLOAT might give you some unexpected problems because all\ncalculations in MySQL are done with double precision. See\nhttps://mariadb.com/kb/en/floating-point-accuracy/.\n\nURL: https://mariadb.com/kb/en/float/\n\n','','https://mariadb.com/kb/en/float/'),(169,'LOCATE',37,'Syntax:\nLOCATE(substr,str), LOCATE(substr,str,pos)\n\nThe first syntax returns the position of the first occurrence of\nsubstring substr in string str. The second syntax returns the position\nof the first occurrence of substring substr in string str, starting at\nposition pos. Returns 0 if substr is not in str.\n\nURL: https://mariadb.com/kb/en/locate/\n\n','MariaDB> SELECT LOCATE(\'bar\', \'foobarbar\');\n -> 4\nMariaDB> SELECT LOCATE(\'xbar\', \'foobar\');\n -> 0\nMariaDB> SELECT LOCATE(\'bar\', \'foobarbar\', 5);\n -> 7\n','https://mariadb.com/kb/en/locate/'),(170,'SHOW EVENTS',26,'Syntax:\nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement displays information about Event Manager events. It\nrequires the EVENT privilege for the database from which the events are\nto be shown.\n\nIn its simplest form, SHOW EVENTS lists all of the events in the\ncurrent schema:\n\nMariaDB> SELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n1 row in set (0.00 sec)\n\nMariaDB> SHOW EVENTS\\G\n*************************** 1. row ***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nTo see events for a specific schema, use the FROM clause. For example,\nto see events for the test schema, use the following statement:\n\nSHOW EVENTS FROM test;\n\nThe LIKE clause, if present, indicates which event names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-events/\n\n','','https://mariadb.com/kb/en/show-events/'),(171,'CHARSET',17,'Syntax:\nCHARSET(str)\n\nReturns the character set of the string argument.\n\nURL: https://mariadb.com/kb/en/charset/\n\n','MariaDB> SELECT CHARSET(\'abc\');\n -> \'latin1\'\nMariaDB> SELECT CHARSET(CONVERT(\'abc\' USING utf8));\n -> \'utf8\'\nMariaDB> SELECT CHARSET(USER());\n -> \'utf8\'\n','https://mariadb.com/kb/en/charset/'),(172,'SUBDATE',31,'Syntax:\nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, SUBDATE()\nis a synonym for DATE_SUB(). For information on the INTERVAL unit\nargument, see the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\nMariaDB> SELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\n\nThe second form enables the use of an integer value for days. In such\ncases, it is interpreted as the number of days to be subtracted from\nthe date or datetime expression expr.\n\nMariaDB> SELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n -> \'2007-12-02 12:00:00\'\n\nURL: https://mariadb.com/kb/en/subdate/\n\n','','https://mariadb.com/kb/en/subdate/'),(173,'DAYOFYEAR',31,'Syntax:\nDAYOFYEAR(date)\n\nReturns the day of the year for date, in the range 1 to 366.\n\nURL: https://mariadb.com/kb/en/dayofyear/\n\n','MariaDB> SELECT DAYOFYEAR(\'2007-02-03\');\n -> 34\n','https://mariadb.com/kb/en/dayofyear/'),(174,'%',4,'Syntax:\nN % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M. For more\ninformation, see the description for the MOD() function in\nhttps://mariadb.com/kb/en/mod/.\n\nURL: https://mariadb.com/kb/en/modulo-operator/\n\n','','https://mariadb.com/kb/en/modulo-operator/'),(175,'LONGTEXT',22,'LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\ncharacters. The effective maximum length is less if the value contains\nmulti-byte characters. The effective maximum length of LONGTEXT columns\nalso depends on the configured maximum packet size in the client/server\nprotocol and available memory. Each LONGTEXT value is stored using a\n4-byte length prefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longtext/\n\n','','https://mariadb.com/kb/en/longtext/'),(176,'KILL',26,'Syntax:\nKILL [CONNECTION | QUERY] thread_id\n\nEach connection to mysqld runs in a separate thread. You can see which\nthreads are running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement.\n\nKILL permits an optional CONNECTION or QUERY modifier:\n\no KILL CONNECTION is the same as KILL with no modifier: It terminates\n the connection associated with the given thread_id.\n\no KILL QUERY terminates the statement that the connection is currently\n executing, but leaves the connection itself intact.\n\nIf you have the PROCESS privilege, you can see all threads. If you have\nthe SUPER privilege, you can kill all threads and statements.\nOtherwise, you can see and kill only your own threads and statements.\n\nYou can also use the mysqladmin processlist and mysqladmin kill\ncommands to examine and kill threads.\n\n*Note*: You cannot use KILL with the Embedded MySQL Server library\nbecause the embedded server merely runs inside the threads of the host\napplication. It does not create any connection threads of its own.\n\nURL: https://mariadb.com/kb/en/data-manipulation-kill-connection-query/\n\n','','https://mariadb.com/kb/en/data-manipulation-kill-connection-query/'),(177,'DISJOINT',30,'Disjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially disjoint from (does\nnot intersect) g2.\n\nURL: https://mariadb.com/kb/en/disjoint/\n\n','','https://mariadb.com/kb/en/disjoint/'),(178,'ASTEXT',3,'AsText(g), AsWKT(g)\n\nConverts a value in internal geometry format to its WKT representation\nand returns the string result.\n\nURL: https://mariadb.com/kb/en/astext/\n\n','MariaDB> SET @g = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(GeomFromText(@g));\n+--------------------------+\n| AsText(GeomFromText(@g)) |\n+--------------------------+\n| LINESTRING(1 1,2 2,3 3) |\n+--------------------------+\n','https://mariadb.com/kb/en/astext/'),(179,'LPAD',37,'Syntax:\nLPAD(str,len,padstr)\n\nReturns the string str, left-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\n\nURL: https://mariadb.com/kb/en/lpad/\n\n','MariaDB> SELECT LPAD(\'hi\',4,\'??\');\n -> \'??hi\'\nMariaDB> SELECT LPAD(\'hi\',1,\'??\');\n -> \'h\'\n','https://mariadb.com/kb/en/lpad/'),(180,'DECLARE CONDITION',23,'Syntax:\nDECLARE condition_name CONDITION FOR condition_value\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n\nThe DECLARE ... CONDITION statement declares a named error condition,\nassociating a name with a condition that needs specific handling. The\nname can be referred to in a subsequent DECLARE ... HANDLER statement\n(see [HELP DECLARE HANDLER]).\n\nCondition declarations must appear before cursor or handler\ndeclarations.\n\nThe condition_value for DECLARE ... CONDITION can be a MySQL error code\n(a number) or an SQLSTATE value (a 5-character string literal). You\nshould not use MySQL error code 0 or SQLSTATE values that begin with\n\'00\', because those indicate success rather than an error condition.\nFor a list of MySQL error codes and SQLSTATE values, see\nhttps://mariadb.com/kb/en/mariadb-error-codes/.\n\nURL: https://mariadb.com/kb/en/declare-condition/\n\n','','https://mariadb.com/kb/en/declare-condition/'),(181,'OVERLAPS',30,'Overlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially overlaps g2. The term\nspatially overlaps is used if two geometries intersect and their\nintersection results in a geometry of the same dimension but not equal\nto either of the given geometries.\n\nURL: https://mariadb.com/kb/en/overlaps/\n\n','','https://mariadb.com/kb/en/overlaps/'),(182,'SET GLOBAL SQL_SLAVE_SKIP_COUNTER',8,'Syntax:\nSET GLOBAL sql_slave_skip_counter = N\n\nThis statement skips the next N events from the master. This is useful\nfor recovering from replication stops caused by a statement.\n\nThis statement is valid only when the slave threads are not running.\nOtherwise, it produces an error.\n\nURL: https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/\n\n','','https://mariadb.com/kb/en/set-global-sql_slave_skip_counter/'),(183,'NUMGEOMETRIES',25,'NumGeometries(gc)\n\nReturns the number of geometries in the GeometryCollection value gc.\n\nURL: https://mariadb.com/kb/en/numgeometries/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT NumGeometries(GeomFromText(@gc));\n+----------------------------------+\n| NumGeometries(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n','https://mariadb.com/kb/en/numgeometries/'),(184,'MONTHNAME',31,'Syntax:\nMONTHNAME(date)\n\nReturns the full name of the month for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-locale/).\n\nURL: https://mariadb.com/kb/en/monthname/\n\n','MariaDB> SELECT MONTHNAME(\'2008-02-03\');\n -> \'February\'\n','https://mariadb.com/kb/en/monthname/'),(185,'CHANGE MASTER TO',8,'Syntax:\nCHANGE MASTER TO option [, option] ...\n\noption:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | IGNORE_SERVER_IDS = (server_id_list)\n\nserver_id_list:\n [server_id [, server_id] ... ]\n\nCHANGE MASTER TO changes the parameters that the slave server uses for\nconnecting to the master server, for reading the master binary log, and\nreading the slave relay log. It also updates the contents of the\nmaster.info and relay-log.info files. To use CHANGE MASTER TO, the\nslave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\nOptions not specified retain their value, except as indicated in the\nfollowing discussion. Thus, in most cases, there is no need to specify\noptions that do not change. For example, if the password to connect to\nyour MySQL master has changed, you just need to issue these statements\nto tell the slave about the new password:\n\nSTOP SLAVE; -- if replication was running\nCHANGE MASTER TO MASTER_PASSWORD=\'new3cret\';\nSTART SLAVE; -- if you want to restart replication\n\nMASTER_HOST, MASTER_USER, MASTER_PASSWORD, and MASTER_PORT provide\ninformation to the slave about how to connect to its master:\n\no MASTER_HOST and MASTER_PORT are the host name (or IP address) of the\n master host and its TCP/IP port.\n\n *Note*: Replication cannot use Unix socket files. You must be able to\n connect to the master MySQL server using TCP/IP.\n\n If you specify the MASTER_HOST or MASTER_PORT option, the slave\n assumes that the master server is different from before (even if the\n option value is the same as its current value.) In this case, the old\n values for the master binary log file name and position are\n considered no longer applicable, so if you do not specify\n MASTER_LOG_FILE and MASTER_LOG_POS in the statement,\n MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4 are silently appended to it.\n\n Setting MASTER_HOST=\'\' (that is, setting its value explicitly to an\n empty string) is not the same as not setting MASTER_HOST at all.\n Beginning with MySQL 5.5, trying to set MASTER_HOST to an empty\n string fails with an error. Previously, setting MASTER_HOST to an\n empty string caused START SLAVE subsequently to fail. (Bug #28796)\n\no MASTER_USER and MASTER_PASSWORD are the user name and password of the\n account to use for connecting to the master.\n\n In MySQL 5.5.20 and later, MASTER_USER cannot be made empty; setting\n MASTER_USER = \'\' or leaving it unset when setting a value for for\n MASTER_PASSWORD causes an error (Bug #13427949).\n\n Currently, a password used for a replication slave account is\n effectively limited to 32 characters in length; the password can be\n longer, but any excess characters are truncated. This is not due to\n any limit imposed by the MySQL Server generally, but rather is an\n issue specific to MySQL Replication. (For more information, see Bug\n #43439.)\n\n The text of a running CHANGE MASTER TO statement, including values\n for MASTER_USER and MASTER_PASSWORD, can be seen in the output of a\n concurrent SHOW PROCESSLIST statement.\n\nThe MASTER_SSL_xxx options provide information about using SSL for the\nconnection. They correspond to the --ssl-xxx options described in\nhttps://mariadb.com/kb/en/ssl-server-system-variables/, and\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-solutions-ssl.html.\nThese options can be changed even on slaves that are compiled without\nSSL support. They are saved to the master.info file, but are ignored if\nthe slave does not have SSL support enabled.\n\nMASTER_CONNECT_RETRY specifies how many seconds to wait between connect\nretries. The default is 60. The number of reconnection attempts is\nlimited by the --master-retry-count server option; for more\ninformation, see\nhttps://mariadb.com/kb/en/replication-and-binary-log-server-system-variables/.\n\nMASTER_HEARTBEAT_PERIOD sets the interval in seconds between\nreplication heartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is reset.\ninterval is a decimal value having the range 0 to 4294967 seconds and a\nresolution in milliseconds; the smallest nonzero value is 0.001.\nHeartbeats are sent by the master only if there are no unsent events in\nthe binary log file for a period longer than interval.\n\nSetting interval to 0 disables heartbeats altogether. The default value\nfor interval is equal to the value of slave_net_timeout divided by 2.\n\nSetting @@global.slave_net_timeout to a value less than that of the\ncurrent heartbeat interval results in a warning being issued. The\neffect of issuing RESET SLAVE on the heartbeat interval is to reset it\nto the default value.\n\nMASTER_LOG_FILE and MASTER_LOG_POS are the coordinates at which the\nslave I/O thread should begin reading from the master the next time the\nthread starts. RELAY_LOG_FILE and RELAY_LOG_POS are the coordinates at\nwhich the slave SQL thread should begin reading from the relay log the\nnext time the thread starts. If you specify either of MASTER_LOG_FILE\nor MASTER_LOG_POS, you cannot specify RELAY_LOG_FILE or RELAY_LOG_POS.\nIf neither of MASTER_LOG_FILE or MASTER_LOG_POS is specified, the slave\nuses the last coordinates of the slave SQL thread before CHANGE MASTER\nTO was issued. This ensures that there is no discontinuity in\nreplication, even if the slave SQL thread was late compared to the\nslave I/O thread, when you merely want to change, say, the password to\nuse.\n\nCHANGE MASTER TO deletes all relay log files and starts a new one,\nunless you specify RELAY_LOG_FILE or RELAY_LOG_POS. In that case, relay\nlog files are kept; the relay_log_purge global variable is set silently\nto 0.\n\nPrior to MySQL 5.5, RELAY_LOG_FILE required an absolute path. In MySQL\n5.5, the path can be relative, in which case the path is assumed to be\nrelative to the slave\'s data directory. (Bug #12190)\n\nIGNORE_SERVER_IDS was added in MySQL 5.5. This option takes a\ncomma-separated list of 0 or more server IDs. Events originating from\nthe corresponding servers are ignored, with the exception of log\nrotation and deletion events, which are still recorded in the relay\nlog.\n\nIn circular replication, the originating server normally acts as the\nterminator of its own events, so that they are not applied more than\nonce. Thus, this option is useful in circular replication when one of\nthe servers in the circle is removed. Suppose that you have a circular\nreplication setup with 4 servers, having server IDs 1, 2, 3, and 4, and\nserver 3 fails. When bridging the gap by starting replication from\nserver 2 to server 4, you can include IGNORE_SERVER_IDS = (3) in the\nCHANGE MASTER TO statement that you issue on server 4 to tell it to use\nserver 2 as its master instead of server 3. Doing so causes it to\nignore and not to propagate any statements that originated with the\nserver that is no longer in use.\n\nIf a CHANGE MASTER TO statement is issued without any IGNORE_SERVER_IDS\noption, any existing list is preserved; RESET SLAVE also has no effect\non the server ID list. To clear the list of ignored servers, it is\nnecessary to use the option with an empty list:\n\nCHANGE MASTER TO IGNORE_SERVER_IDS = ();\n\nIf IGNORE_SERVER_IDS contains the server\'s own ID and the server was\nstarted with the --replicate-same-server-id option enabled, an error\nresults.\n\nAlso beginning with MySQL 5.5, the master.info file and the output of\nSHOW SLAVE STATUS are extended to provide the list of servers that are\ncurrently ignored. For more information, see\nhttps://mariadb.com/kb/en/show-slave-status/, and\n[HELP SHOW SLAVE STATUS].\n\nBeginning with MySQL 5.5.5, invoking CHANGE MASTER TO causes the\nprevious values for MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE, and\nMASTER_LOG_POS to be written to the error log, along with other\ninformation about the slave\'s state prior to execution.\n\nCHANGE MASTER TO is useful for setting up a slave when you have the\nsnapshot of the master and have recorded the master binary log\ncoordinates corresponding to the time of the snapshot. After loading\nthe snapshot into the slave to synchronize it to the slave, you can run\nCHANGE MASTER TO MASTER_LOG_FILE=\'log_name\', MASTER_LOG_POS=log_pos on\nthe slave to specify the coordinates at which the slave should begin\nreading the master binary log.\n\nThe following example changes the master server the slave uses and\nestablishes the master binary log coordinates from which the slave\nbegins reading. This is used when you want to set up the slave to\nreplicate the master:\n\nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n\nThe next example shows an operation that is less frequently employed.\nIt is used when the slave has relay log files that you want it to\nexecute again for some reason. To do this, the master need not be\nreachable. You need only use CHANGE MASTER TO and start the SQL thread\n(START SLAVE SQL_THREAD):\n\nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n\nURL: https://mariadb.com/kb/en/change-master-to/\n\n','','https://mariadb.com/kb/en/change-master-to/'),(186,'DROP DATABASE',39,'Syntax:\nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n\nDROP DATABASE drops all tables in the database and deletes the\ndatabase. Be very careful with this statement! To use DROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is a synonym\nfor DROP DATABASE.\n\n*Important*: When a database is dropped, user privileges on the\ndatabase are not automatically dropped. See [HELP GRANT].\n\nIF EXISTS is used to prevent an error from occurring if the database\ndoes not exist.\n\nURL: https://mariadb.com/kb/en/drop-database/\n\n','','https://mariadb.com/kb/en/drop-database/'),(187,'MBREQUAL',6,'MBREqual(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are the same.\n\nURL: https://mariadb.com/kb/en/mbrequal/\n\n','','https://mariadb.com/kb/en/mbrequal/'),(188,'TIMESTAMP FUNCTION',31,'Syntax:\nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n\nWith a single argument, this function returns the date or datetime\nexpression expr as a datetime value. With two arguments, it adds the\ntime expression expr2 to the date or datetime expression expr1 and\nreturns the result as a datetime value.\n\nURL: https://mariadb.com/kb/en/timestamp-function/\n\n','MariaDB> SELECT TIMESTAMP(\'2003-12-31\');\n -> \'2003-12-31 00:00:00\'\nMariaDB> SELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'12:00:00\');\n -> \'2004-01-01 00:00:00\'\n','https://mariadb.com/kb/en/timestamp-function/'),(189,'PROCEDURE ANALYSE',33,'Syntax:\nANALYSE([max_elements[,max_memory]])\n\nANALYSE() examines the result from a query and returns an analysis of\nthe results that suggests optimal data types for each column that may\nhelp reduce table sizes. To obtain this analysis, append PROCEDURE\nANALYSE to the end of a SELECT statement:\n\nSELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])\n\nFor example:\n\nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n\nThe results show some statistics for the values returned by the query,\nand propose an optimal data type for the columns. This can be helpful\nfor checking your existing tables, or after importing new data. You may\nneed to try different settings for the arguments so that PROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n\nThe arguments are optional and are used as follows:\n\no max_elements (default 256) is the maximum number of distinct values\n that ANALYSE() notices per column. This is used by ANALYSE() to check\n whether the optimal data type should be of type ENUM; if there are\n more than max_elements distinct values, then ENUM is not a suggested\n type.\n\no max_memory (default 8192) is the maximum amount of memory that\n ANALYSE() should allocate per column while trying to find all\n distinct values.\n\nURL: https://mariadb.com/kb/en/procedure-analyse/\n\n','','https://mariadb.com/kb/en/procedure-analyse/'),(190,'HELP_VERSION',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25 (revision: 31914)\n\nThis information applies to MySQL 5.5 through 5.5.29.\n','',''),(191,'CHARACTER_LENGTH',37,'Syntax:\nCHARACTER_LENGTH(str)\n\nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n\nURL: https://mariadb.com/kb/en/character_length/\n\n','','https://mariadb.com/kb/en/character_length/'),(192,'SHOW GRANTS',26,'Syntax:\nSHOW GRANTS [FOR user]\n\nThis statement lists the GRANT statement or statements that must be\nissued to duplicate the privileges that are granted to a MySQL user\naccount. The account is named using the same format as for the GRANT\nstatement; for example, \'jeffrey\'@\'localhost\'. If you specify only the\nuser name part of the account name, a host name part of \'%\' is used.\nFor additional information about specifying account names, see [HELP\nGRANT].\n\nMariaDB> SHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION |\n+---------------------------------------------------------------------+\n\nTo list the privileges granted to the account that you are using to\nconnect to the server, you can use any of the following statements:\n\nSHOW GRANTS;\nSHOW GRANTS FOR CURRENT_USER;\nSHOW GRANTS FOR CURRENT_USER();\n\nIf SHOW GRANTS FOR CURRENT_USER (or any of the equivalent syntaxes) is\nused in DEFINER context, such as within a stored procedure that is\ndefined with SQL SECURITY DEFINER), the grants displayed are those of\nthe definer and not the invoker.\n\nURL: https://mariadb.com/kb/en/show-grants/\n\n','','https://mariadb.com/kb/en/show-grants/'),(193,'SHOW PRIVILEGES',26,'Syntax:\nSHOW PRIVILEGES\n\nSHOW PRIVILEGES shows the list of system privileges that the MySQL\nserver supports. The exact list of privileges depends on the version of\nyour server.\n\nURL: https://mariadb.com/kb/en/show-privileges/\n\n','','https://mariadb.com/kb/en/show-privileges/'),(194,'CREATE TABLESPACE',39,'Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n USE LOGFILE GROUP logfile_group\n [EXTENT_SIZE [=] extent_size]\n [INITIAL_SIZE [=] initial_size]\n [AUTOEXTEND_SIZE [=] autoextend_size]\n [MAX_SIZE [=] max_size]\n [NODEGROUP [=] nodegroup_id]\n [WAIT]\n [COMMENT [=] comment_text]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.','','https://mariadb.com/kb/en/create-tablespace/'),(195,'INSERT FUNCTION',37,'Syntax:\nINSERT(str,pos,len,newstr)\n\nReturns the string str, with the substring beginning at position pos\nand len characters long replaced by the string newstr. Returns the\noriginal string if pos is not within the length of the string. Replaces\nthe rest of the string from position pos if len is not within the\nlength of the rest of the string. Returns NULL if any argument is NULL.\n\nURL: https://mariadb.com/kb/en/insert-function/\n\n','MariaDB> SELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n -> \'QuWhattic\'\nMariaDB> SELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n -> \'Quadratic\'\nMariaDB> SELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n -> \'QuWhat\'\n','https://mariadb.com/kb/en/insert-function/'),(196,'CRC32',4,'Syntax:\nCRC32(expr)\n\nComputes a cyclic redundancy check value and returns a 32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The argument is\nexpected to be a string and (if possible) is treated as one if it is\nnot.\n\nURL: https://mariadb.com/kb/en/crc32/\n\n','MariaDB> SELECT CRC32(\'MySQL\');\n -> 3259397556\nMariaDB> SELECT CRC32(\'mysql\');\n -> 2501908538\n','https://mariadb.com/kb/en/crc32/'),(197,'XOR',15,'Syntax:\nXOR\n\nLogical XOR. Returns NULL if either operand is NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is nonzero,\notherwise 0 is returned.\n\nURL: https://mariadb.com/kb/en/xor/\n\n','MariaDB> SELECT 1 XOR 1;\n -> 0\nMariaDB> SELECT 1 XOR 0;\n -> 1\nMariaDB> SELECT 1 XOR NULL;\n -> NULL\nMariaDB> SELECT 1 XOR 1 XOR 1;\n -> 1\n','https://mariadb.com/kb/en/xor/'),(198,'STARTPOINT',13,'StartPoint(ls)\n\nReturns the Point that is the start point of the LineString value ls.\n\nURL: https://mariadb.com/kb/en/startpoint/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(StartPoint(GeomFromText(@ls)));\n+---------------------------------------+\n| AsText(StartPoint(GeomFromText(@ls))) |\n+---------------------------------------+\n| POINT(1 1) |\n+---------------------------------------+\n','https://mariadb.com/kb/en/startpoint/'),(199,'GRANT',10,'Syntax:\nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [, user_specification] ...\n [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]\n [WITH with_option ...]\n\nGRANT PROXY ON user_specification\n TO user_specification [, user_specification] ...\n [WITH GRANT OPTION]\n\nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n\npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nssl_option:\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n\nwith_option:\n GRANT OPTION\n | MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n\nThe GRANT statement grants privileges to MySQL user accounts. GRANT\nalso serves to specify other account characteristics such as use of\nsecure connections and limits on access to server resources. To use\nGRANT, you must have the GRANT OPTION privilege, and you must have the\nprivileges that you are granting.\n\nNormally, a database administrator first uses CREATE USER to create an\naccount, then GRANT to define its privileges and characteristics. For\nexample:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\nGRANT ALL ON db1.* TO \'jeffrey\'@\'localhost\';\nGRANT SELECT ON db2.invoice TO \'jeffrey\'@\'localhost\';\nGRANT USAGE ON *.* TO \'jeffrey\'@\'localhost\' WITH MAX_QUERIES_PER_HOUR 90;\n\nHowever, if an account named in a GRANT statement does not already\nexist, GRANT may create it under the conditions described later in the\ndiscussion of the NO_AUTO_CREATE_USER SQL mode.\n\nThe REVOKE statement is related to GRANT and enables administrators to\nremove account privileges. See [HELP REVOKE].\n\nWhen successfully executed from the mysql program, GRANT responds with\nQuery OK, 0 rows affected. To determine what privileges result from the\noperation, use SHOW GRANTS. See [HELP SHOW GRANTS].\n\nURL: https://mariadb.com/kb/en/grant/\n\n','','https://mariadb.com/kb/en/grant/'),(200,'DECLARE VARIABLE',23,'Syntax:\nDECLARE var_name [, var_name] ... type [DEFAULT value]\n\nThis statement declares local variables within stored programs. To\nprovide a default value for a variable, include a DEFAULT clause. The\nvalue can be specified as an expression; it need not be a constant. If\nthe DEFAULT clause is missing, the initial value is NULL.\n\nLocal variables are treated like stored routine parameters with respect\nto data type and overflow checking. See [HELP CREATE PROCEDURE].\n\nVariable declarations must appear before cursor or handler\ndeclarations.\n\nLocal variable names are not case sensitive. Permissible characters and\nquoting rules are the same as for other identifiers, as described in\nhttps://mariadb.com/kb/en/identifier-names/.\n\nThe scope of a local variable is the BEGIN ... END block within which\nit is declared. The variable can be referred to in blocks nested within\nthe declaring block, except those blocks that declare a variable with\nthe same name.\n\nURL: https://mariadb.com/kb/en/declare-variable/\n\n','','https://mariadb.com/kb/en/declare-variable/'),(201,'MPOLYFROMTEXT',3,'MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])\n\nConstructs a MULTIPOLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpolyfromtext/\n\n','','https://mariadb.com/kb/en/mpolyfromtext/'),(202,'MBRINTERSECTS',6,'MBRIntersects(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 intersect.\n\nURL: https://mariadb.com/kb/en/mbrintersects/\n\n','','https://mariadb.com/kb/en/mbrintersects/'),(203,'BIT_OR',16,'Syntax:\nBIT_OR(expr)\n\nReturns the bitwise OR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_or/\n\n','','https://mariadb.com/kb/en/bit_or/'),(204,'YEARWEEK',31,'Syntax:\nYEARWEEK(date), YEARWEEK(date,mode)\n\nReturns year and week for a date. The mode argument works exactly like\nthe mode argument to WEEK(). The year in the result may be different\nfrom the year in the date argument for the first and the last week of\nthe year.\n\nURL: https://mariadb.com/kb/en/yearweek/\n\n','MariaDB> SELECT YEARWEEK(\'1987-01-01\');\n -> 198653\n','https://mariadb.com/kb/en/yearweek/'),(205,'NOT BETWEEN',18,'Syntax:\nexpr NOT BETWEEN min AND max\n\nThis is the same as NOT (expr BETWEEN min AND max).\n\nURL: https://mariadb.com/kb/en/not-between/\n\n','','https://mariadb.com/kb/en/not-between/'),(206,'IS NOT',18,'Syntax:\nIS NOT boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is-not/\n\n','MariaDB> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;\n -> 1, 1, 0\n','https://mariadb.com/kb/en/is-not/'),(207,'LOG10',4,'Syntax:\nLOG10(X)\n\nReturns the base-10 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log10/\n\n','MariaDB> SELECT LOG10(2);\n -> 0.30102999566398\nMariaDB> SELECT LOG10(100);\n -> 2\nMariaDB> SELECT LOG10(-100);\n -> NULL\n','https://mariadb.com/kb/en/log10/'),(208,'SQRT',4,'Syntax:\nSQRT(X)\n\nReturns the square root of a nonnegative number X.\n\nURL: https://mariadb.com/kb/en/sqrt/\n\n','MariaDB> SELECT SQRT(4);\n -> 2\nMariaDB> SELECT SQRT(20);\n -> 4.4721359549996\nMariaDB> SELECT SQRT(-16);\n -> NULL\n','https://mariadb.com/kb/en/sqrt/'),(209,'DECIMAL',22,'DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nA packed \"exact\" fixed-point number. M is the total number of digits\n(the precision) and D is the number of digits after the decimal point\n(the scale). The decimal point and (for negative numbers) the \"-\" sign\nare not counted in M. If D is 0, values have no decimal point or\nfractional part. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30. If D is omitted,\nthe default is 0. If M is omitted, the default is 10.\n\nUNSIGNED, if specified, disallows negative values.\n\nAll basic calculations (+, -, *, /) with DECIMAL columns are done with\na precision of 65 digits.\n\nURL: https://mariadb.com/kb/en/decimal/\n\n','','https://mariadb.com/kb/en/decimal/'),(210,'CREATE INDEX',39,'Syntax:\nCREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [index_option] ...\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nCREATE INDEX is mapped to an ALTER TABLE statement to create indexes.\nSee [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY\nKEY; use ALTER TABLE instead. For more information about indexes, see\nhttps://mariadb.com/kb/en/optimization-and-indexes/.\n\nURL: https://mariadb.com/kb/en/create-index/\n\n','','https://mariadb.com/kb/en/create-index/'),(211,'CREATE FUNCTION',39,'The CREATE FUNCTION statement is used to create stored functions and\nuser-defined functions (UDFs):\n\no For information about creating stored functions, see [HELP CREATE\n PROCEDURE].\n\no For information about creating user-defined functions, see [HELP\n CREATE FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/create-function/\n\n','','https://mariadb.com/kb/en/create-function/'),(212,'ALTER DATABASE',39,'Syntax:\nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n\nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nALTER DATABASE enables you to change the overall characteristics of a\ndatabase. These characteristics are stored in the db.opt file in the\ndatabase directory. To use ALTER DATABASE, you need the ALTER privilege\non the database. ALTER SCHEMA is a synonym for ALTER DATABASE.\n\nThe database name can be omitted from the first syntax, in which case\nthe statement applies to the default database.\n\nNational Language Characteristics\n\nThe CHARACTER SET clause changes the default database character set.\nThe COLLATE clause changes the default database collation.\nhttps://mariadb.com/kb/en/data-types-character-sets-and-collations/, discusses\ncharacter set and collation names.\n\nYou can see what character sets and collations are available using,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION statements. See\n[HELP SHOW CHARACTER SET], and [HELP SHOW COLLATION], for more\ninformation.\n\nIf you change the default character set or collation for a database,\nstored routines that use the database defaults must be dropped and\nrecreated so that they use the new defaults. (In a stored routine,\nvariables with character data types use the database defaults if the\ncharacter set or collation are not specified explicitly. See [HELP\nCREATE PROCEDURE].)\n\nUpgrading from Versions Older than MySQL 5.1\n\nThe syntax that includes the UPGRADE DATA DIRECTORY NAME clause updates\nthe name of the directory associated with the database to use the\nencoding implemented in MySQL 5.1 for mapping database names to\ndatabase directory names (see\nhttps://mariadb.com/kb/en/identifier-to-file-name-mapping/). This\nclause is for use under these conditions:\n\no It is intended when upgrading MySQL to 5.1 or later from older\n versions.\n\no It is intended to update a database directory name to the current\n encoding format if the name contains special characters that need\n encoding.\n\no The statement is used by mysqlcheck (as invoked by mysql_upgrade).\n\nFor example, if a database in MySQL 5.0 has the name a-b-c, the name\ncontains instances of the - (dash) character. In MySQL 5.0, the\ndatabase directory is also named a-b-c, which is not necessarily safe\nfor all file systems. In MySQL 5.1 and later, the same database name is\nencoded as a@002db@002dc to produce a file system-neutral directory\nname.\n\nWhen a MySQL installation is upgraded to MySQL 5.1 or later from an\nolder version,the server displays a name such as a-b-c (which is in the\nold format) as #mysql50#a-b-c, and you must refer to the name using the\n#mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME in this case to\nexplicitly tell the server to re-encode the database directory name to\nthe current encoding format:\n\nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n\nAfter executing this statement, you can refer to the database as a-b-c\nwithout the special #mysql50# prefix.\n\nURL: https://mariadb.com/kb/en/alter-database/\n\n','','https://mariadb.com/kb/en/alter-database/'),(213,'GEOMETRYN',25,'GeometryN(gc,N)\n\nReturns the N-th geometry in the GeometryCollection value gc.\nGeometries are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/geometryn/\n\n','MariaDB> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nMariaDB> SELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n','https://mariadb.com/kb/en/geometryn/'),(214,'<<',19,'Syntax:\n<<\n\nShifts a longlong (BIGINT) number to the left.\n\nURL: https://mariadb.com/kb/en/shift-left/\n\n','MariaDB> SELECT 1 << 2;\n -> 4\n','https://mariadb.com/kb/en/shift-left/'),(215,'SHOW TABLE STATUS',26,'Syntax:\nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLE STATUS works likes SHOW TABLES, but provides a lot of\ninformation about each non-TEMPORARY table. You can also get this list\nusing the mysqlshow --status db_name command. The LIKE clause, if\npresent, indicates which table names to match. The WHERE clause can be\ngiven to select rows using more general conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-table-status/\n\n','','https://mariadb.com/kb/en/show-table-status/'),(216,'MD5',12,'Syntax:\nMD5(str)\n\nCalculates an MD5 128-bit checksum for the string. The value is\nreturned as a string of 32 hex digits, or NULL if the argument was\nNULL. The return value can, for example, be used as a hash key. See the\nnotes at the beginning of this section about storing hash values\nefficiently.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/md5/\n\n','MariaDB> SELECT MD5(\'testing\');\n -> \'ae2b1fca515949e5d54fb22b8ed95575\'\n','https://mariadb.com/kb/en/md5/'),(217,'<',18,'Syntax:\n<\n\nLess than:\n\nURL: https://mariadb.com/kb/en/less-than/\n\n','MariaDB> SELECT 2 < 2;\n -> 0\n','https://mariadb.com/kb/en/less-than/'),(218,'UNIX_TIMESTAMP',31,'Syntax:\nUNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)\n\nIf called with no argument, returns a Unix timestamp (seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If UNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the argument as\nseconds since \'1970-01-01 00:00:00\' UTC. date may be a DATE string, a\nDATETIME string, a TIMESTAMP, or a number in the format YYMMDD or\nYYYYMMDD. The server interprets date as a value in the current time\nzone and converts it to an internal value in UTC. Clients can set their\ntime zone as described in\nhttps://mariadb.com/kb/en/time-zones/.\n\nURL: https://mariadb.com/kb/en/unix_timestamp/\n\n','MariaDB> SELECT UNIX_TIMESTAMP();\n -> 1196440210\nMariaDB> SELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n -> 1196440219\n','https://mariadb.com/kb/en/unix_timestamp/'),(219,'DAYOFMONTH',31,'Syntax:\nDAYOFMONTH(date)\n\nReturns the day of the month for date, in the range 1 to 31, or 0 for\ndates such as \'0000-00-00\' or \'2008-00-00\' that have a zero day part.\n\nURL: https://mariadb.com/kb/en/dayofmonth/\n\n','MariaDB> SELECT DAYOFMONTH(\'2007-02-03\');\n -> 3\n','https://mariadb.com/kb/en/dayofmonth/'),(220,'ASCII',37,'Syntax:\nASCII(str)\n\nReturns the numeric value of the leftmost character of the string str.\nReturns 0 if str is the empty string. Returns NULL if str is NULL.\nASCII() works for 8-bit characters.\n\nURL: https://mariadb.com/kb/en/ascii/\n\n','MariaDB> SELECT ASCII(\'2\');\n -> 50\nMariaDB> SELECT ASCII(2);\n -> 50\nMariaDB> SELECT ASCII(\'dx\');\n -> 100\n','https://mariadb.com/kb/en/ascii/'),(221,'DIV',4,'Syntax:\nDIV\n\nInteger division. Similar to FLOOR(), but is safe with BIGINT values.\n\nAs of MySQL 5.5.3, if either operand has a noninteger type, the\noperands are converted to DECIMAL and divided using DECIMAL arithmetic\nbefore converting the result to BIGINT. If the result exceeds BIGINT\nrange, an error occurs. Before MySQL 5.5.3, incorrect results may occur\nfor noninteger operands that exceed BIGINT range.\n\nURL: https://mariadb.com/kb/en/div/\n\n','MariaDB> SELECT 5 DIV 2;\n -> 2\n','https://mariadb.com/kb/en/div/'),(222,'RENAME USER',10,'Syntax:\nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n\nThe RENAME USER statement renames existing MySQL accounts. To use it,\nyou must have the global CREATE USER privilege or the UPDATE privilege\nfor the mysql database. An error occurs if any old account does not\nexist or any new account exists. Each account name uses the format\ndescribed in https://mariadb.com/kb/en/create-user/#account-names.\nFor example:\n\nRENAME USER \'jeffrey\'@\'localhost\' TO \'jeff\'@\'127.0.0.1\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nRENAME USER causes the privileges held by the old user to be those held\nby the new user. However, RENAME USER does not automatically drop or\ninvalidate databases or objects within them that the old user created.\nThis includes stored programs or views for which the DEFINER attribute\nnames the old user. Attempts to access such objects may produce an\nerror if they execute in definer security context. (For information\nabout security context, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.)\n\nThe privilege changes take effect as indicated in\nhttp://dev.mysql.com/doc/refman/5.5/en/privilege-changes.html.\n\nURL: https://mariadb.com/kb/en/rename-user/\n\n','','https://mariadb.com/kb/en/rename-user/'),(223,'SHOW SLAVE STATUS',26,'Syntax:\nSHOW SLAVE STATUS\n\nThis statement provides status information on essential parameters of\nthe slave threads. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nIf you issue this statement using the mysql client, you can use a \\G\nstatement terminator rather than a semicolon to obtain a more readable\nvertical layout:\n\nMariaDB> SHOW SLAVE STATUS\\G\n*************************** 1. row ***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: localhost\n Master_User: root\n Master_Port: 3306\n Connect_Retry: 3\n Master_Log_File: gbichot-bin.005\n Read_Master_Log_Pos: 79\n Relay_Log_File: gbichot-relay-bin.005\n Relay_Log_Pos: 548\n Relay_Master_Log_File: gbichot-bin.005\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB:\n Replicate_Ignore_DB:\n Replicate_Do_Table:\n Replicate_Ignore_Table:\n Replicate_Wild_Do_Table:\n Replicate_Wild_Ignore_Table:\n Last_Errno: 0\n Last_Error:\n Skip_Counter: 0\n Exec_Master_Log_Pos: 79\n Relay_Log_Space: 552\n Until_Condition: None\n Until_Log_File:\n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File:\n Master_SSL_CA_Path:\n Master_SSL_Cert:\n Master_SSL_Cipher:\n Master_SSL_Key:\n Seconds_Behind_Master: 8\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error:\n Last_SQL_Errno: 0\n Last_SQL_Error:\n Replicate_Ignore_Server_Ids: 0\n Master_Server_Id: 1\n\nURL: https://mariadb.com/kb/en/show-slave-status/\n\n','','https://mariadb.com/kb/en/show-slave-status/'),(224,'GEOMETRY',34,'MySQL provides a standard way of creating spatial columns for geometry\ntypes, for example, with CREATE TABLE or ALTER TABLE. Currently,\nspatial columns are supported for MyISAM, Aria, InnoDB and ARCHIVE\ntables. See also the annotations about spatial indexes under [HELP\nSPATIAL].\n\nURL: https://mariadb.com/kb/en/gis-functionality/\n\n','CREATE TABLE geom (g GEOMETRY);\n','https://mariadb.com/kb/en/gis-functionality/'),(225,'NUMPOINTS',13,'NumPoints(ls)\n\nReturns the number of Point objects in the LineString value ls.\n\nURL: https://mariadb.com/kb/en/numpoints/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n','https://mariadb.com/kb/en/numpoints/'),(226,'ALTER LOGFILE GROUP',39,'Syntax:\nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n','','https://mariadb.com/kb/en/alter-logfile-group/'),(227,'&',19,'Syntax:\n&\n\nBitwise AND:\n\nURL: https://mariadb.com/kb/en/bitwise_and/\n\n','MariaDB> SELECT 29 & 15;\n -> 13\n','https://mariadb.com/kb/en/bitwise_and/'),(228,'LOCALTIMESTAMP',31,'Syntax:\nLOCALTIMESTAMP, LOCALTIMESTAMP()\n\nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtimestamp/\n\n','','https://mariadb.com/kb/en/localtimestamp/'),(229,'ASSIGN-EQUAL',15,'Syntax:\n=\n\nThis operator is used to perform value assignments in two cases,\ndescribed in the next two paragraphs.\n\nWithin a SET statement, = is treated as an assignment operator that\ncauses the user variable on the left hand side of the operator to take\non the value to its right. (In other words, when used in a SET\nstatement, = is treated identically to :=.) The value on the right hand\nside may be a literal value, another variable storing a value, or any\nlegal expression that yields a scalar value, including the result of a\nquery (provided that this value is a scalar value). You can perform\nmultiple assignments in the same SET statement.\n\nIn the SET clause of an UPDATE statement, = also acts as an assignment\noperator; in this case, however, it causes the column named on the left\nhand side of the operator to assume the value given to the right,\nprovided any WHERE conditions that are part of the UPDATE are met. You\ncan make multiple assignments in the same SET clause of an UPDATE\nstatement.\n\nIn any other context, = is treated as a comparison operator.\n\nURL: https://mariadb.com/kb/en/assignment-operators-assignment-operator/\n\n','MariaDB> SELECT @var1, @var2;\n -> NULL, NULL\nMariaDB> SELECT @var1 := 1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2;\n -> 1, NULL\nMariaDB> SELECT @var1, @var2 := @var1;\n -> 1, 1\nMariaDB> SELECT @var1, @var2;\n -> 1, 1\n','https://mariadb.com/kb/en/assignment-operators-assignment-operator/'),(230,'CONVERT',37,'Syntax:\nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n\nThe CONVERT() and CAST() functions take an expression of any type and\nproduce a result value of a specified type.\n\nThe type for the result can be one of the following values:\n\no BINARY[(N)]\n\no CHAR[(N)]\n\no DATE\n\no DATETIME\n\no DECIMAL[(M[,D])]\n\no SIGNED [INTEGER]\n\no TIME\n\no UNSIGNED [INTEGER]\n\nBINARY produces a string with the BINARY data type. See\nhttps://mariadb.com/kb/en/binary/ for a\ndescription of how this affects comparisons. If the optional length N\nis given, BINARY(N) causes the cast to use no more than N bytes of the\nargument. Values shorter than N bytes are padded with 0x00 bytes to a\nlength of N.\n\nCHAR(N) causes the cast to use no more than N characters of the\nargument.\n\nCAST() and CONVERT(... USING ...) are standard SQL syntax. The\nnon-USING form of CONVERT() is ODBC syntax.\n\nCONVERT() with USING is used to convert data between different\ncharacter sets. In MySQL, transcoding names are the same as the\ncorresponding character set names. For example, this statement converts\nthe string \'abc\' in the default character set to the corresponding\nstring in the utf8 character set:\n\nSELECT CONVERT(\'abc\' USING utf8);\n\nURL: https://mariadb.com/kb/en/convert/\n\n','SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);\n','https://mariadb.com/kb/en/convert/'),(231,'ADDDATE',31,'Syntax:\nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, ADDDATE()\nis a synonym for DATE_ADD(). The related function SUBDATE() is a\nsynonym for DATE_SUB(). For information on the INTERVAL unit argument,\nsee the discussion for DATE_ADD().\n\nMariaDB> SELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\nMariaDB> SELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\n\nWhen invoked with the days form of the second argument, MySQL treats it\nas an integer number of days to be added to expr.\n\nURL: https://mariadb.com/kb/en/adddate/\n\n','MariaDB> SELECT ADDDATE(\'2008-01-02\', 31);\n -> \'2008-02-02\'\n','https://mariadb.com/kb/en/adddate/'),(232,'REPEAT LOOP',23,'Syntax:\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\nThe statement list within a REPEAT statement is repeated until the\nsearch_condition expression is true. Thus, a REPEAT always enters the\nloop at least once. statement_list consists of one or more statements,\neach terminated by a semicolon (;) statement delimiter.\n\nA REPEAT statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/repeat-loop/\n\n','MariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE dorepeat(p1 INT)\n -> BEGIN\n -> SET @x = 0;\n -> REPEAT\n -> SET @x = @x + 1;\n -> UNTIL @x > p1 END REPEAT;\n -> END\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL dorepeat(1000)//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/repeat-loop/'),(233,'ALTER FUNCTION',39,'Syntax:\nALTER FUNCTION func_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nfunction. More than one change may be specified in an ALTER FUNCTION\nstatement. However, you cannot change the parameters or body of a\nstored function using this statement; to make such changes, you must\ndrop and re-create the function using DROP FUNCTION and CREATE\nFUNCTION.\n\nYou must have the ALTER ROUTINE privilege for the function. (That\nprivilege is granted automatically to the function creator.) If binary\nlogging is enabled, the ALTER FUNCTION statement might also require the\nSUPER privilege, as described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nURL: https://mariadb.com/kb/en/alter-function/\n\n','','https://mariadb.com/kb/en/alter-function/'),(234,'SMALLINT',22,'SMALLINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA small integer. The signed range is -32768 to 32767. The unsigned\nrange is 0 to 65535.\n\nURL: https://mariadb.com/kb/en/smallint/\n\n','','https://mariadb.com/kb/en/smallint/'),(235,'DOUBLE PRECISION',22,'DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED]\n[ZEROFILL]\n\nThese types are synonyms for DOUBLE. Exception: If the REAL_AS_FLOAT\nSQL mode is enabled, REAL is a synonym for FLOAT rather than DOUBLE.\n\nURL: https://mariadb.com/kb/en/double-precision/\n\n','','https://mariadb.com/kb/en/double-precision/'),(236,'ORD',37,'Syntax:\nORD(str)\n\nIf the leftmost character of the string str is a multi-byte character,\nreturns the code for that character, calculated from the numeric values\nof its constituent bytes using this formula:\n\n (1st byte code)\n+ (2nd byte code * 256)\n+ (3rd byte code * 2562) ...\n\nIf the leftmost character is not a multi-byte character, ORD() returns\nthe same value as the ASCII() function.\n\nURL: https://mariadb.com/kb/en/ord/\n\n','MariaDB> SELECT ORD(\'2\');\n -> 50\n','https://mariadb.com/kb/en/ord/'),(237,'DEALLOCATE PREPARE',8,'Syntax:\n{DEALLOCATE | DROP} PREPARE stmt_name\n\nTo deallocate a prepared statement produced with PREPARE, use a\nDEALLOCATE PREPARE statement that refers to the prepared statement\nname. Attempting to execute a prepared statement after deallocating it\nresults in an error.\n\nURL: https://mariadb.com/kb/en/deallocate-drop-prepared-statement/\n\n','','https://mariadb.com/kb/en/deallocate-drop-prepared-statement/'),(238,'ENVELOPE',36,'Envelope(g)\n\nReturns the Minimum Bounding Rectangle (MBR) for the geometry value g.\nThe result is returned as a Polygon value.\n\nThe polygon is defined by the corner points of the bounding box:\n\nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n\nURL: https://mariadb.com/kb/en/envelope/\n\n','MariaDB> SELECT AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\')));\n+-------------------------------------------------------+\n| AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\'))) |\n+-------------------------------------------------------+\n| POLYGON((1 1,2 1,2 2,1 2,1 1)) |\n+-------------------------------------------------------+\n','https://mariadb.com/kb/en/envelope/'),(239,'IS_FREE_LOCK',14,'Syntax:\nIS_FREE_LOCK(str)\n\nChecks whether the lock named str is free to use (that is, not locked).\nReturns 1 if the lock is free (no one is using the lock), 0 if the lock\nis in use, and NULL if an error occurs (such as an incorrect argument).\n\nURL: https://mariadb.com/kb/en/is_free_lock/\n\n','','https://mariadb.com/kb/en/is_free_lock/'),(240,'TOUCHES',30,'Touches(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially touches g2. Two\ngeometries spatially touch if the interiors of the geometries do not\nintersect, but the boundary of one of the geometries intersects either\nthe boundary or the interior of the other.\n\nURL: https://mariadb.com/kb/en/touches/\n\n','','https://mariadb.com/kb/en/touches/'),(241,'INET_ATON',14,'Syntax:\nINET_ATON(expr)\n\nGiven the dotted-quad representation of an IPv4 network address as a\nstring, returns an integer that represents the numeric value of the\naddress in network byte order (big endian). INET_ATON() returns NULL if\nit does not understand its argument.\n\nURL: https://mariadb.com/kb/en/inet_aton/\n\n','MariaDB> SELECT INET_ATON(\'10.0.5.9\');\n -> 167773449\n','https://mariadb.com/kb/en/inet_aton/'),(242,'UNCOMPRESS',12,'Syntax:\nUNCOMPRESS(string_to_uncompress)\n\nUncompresses a string compressed by the COMPRESS() function. If the\nargument is not a compressed value, the result is NULL. This function\nrequires MySQL to have been compiled with a compression library such as\nzlib. Otherwise, the return value is always NULL.\n\nURL: https://mariadb.com/kb/en/uncompress/\n\n','MariaDB> SELECT UNCOMPRESS(COMPRESS(\'any string\'));\n -> \'any string\'\nMariaDB> SELECT UNCOMPRESS(\'any string\');\n -> NULL\n','https://mariadb.com/kb/en/uncompress/'),(243,'AUTO_INCREMENT',22,'The AUTO_INCREMENT attribute can be used to generate a unique identity\nfor new rows:\n\nURL: https://mariadb.com/kb/en/auto_increment/\n\n','CREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n);\n\nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'lax\'),(\'whale\'),(\'ostrich\');\n\nSELECT * FROM animals;\n','https://mariadb.com/kb/en/auto_increment/'),(244,'ISSIMPLE',36,'IsSimple(g)\n\nCurrently, this function is a placeholder and should not be used. If\nimplemented, its behavior will be as described in the next paragraph.\n\nReturns 1 if the geometry value g has no anomalous geometric points,\nsuch as self-intersection or self-tangency. IsSimple() returns 0 if the\nargument is not simple, and -1 if it is NULL.\n\nThe description of each instantiable geometric class given earlier in\nthe chapter includes the specific conditions that cause an instance of\nthat class to be classified as not simple. (See [HELP Geometry\nhierarchy].)\n\nURL: https://mariadb.com/kb/en/issimple/\n\n','','https://mariadb.com/kb/en/issimple/'),(245,'- BINARY',4,'Syntax:\n-\n\nSubtraction:\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT 3-5;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(246,'GEOMCOLLFROMTEXT',3,'GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKT representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/geomcollfromtext/\n\n','','https://mariadb.com/kb/en/geomcollfromtext/'),(247,'WKT DEFINITION',3,'The Well-Known Text (WKT) representation of Geometry is designed to\nexchange geometry data in ASCII form. For a Backus-Naur grammar that\nspecifies the formal production rules for writing WKT values, see the\nOpenGIS specification document referenced in\nhttps://mariadb.com/kb/en/gis-resources/.\n\nURL: https://mariadb.com/kb/en/wkt-definition/\n\n','','https://mariadb.com/kb/en/wkt-definition/'),(248,'CURRENT_TIME',31,'Syntax:\nCURRENT_TIME, CURRENT_TIME()\n\nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n\nURL: https://mariadb.com/kb/en/current_time/\n\n','','https://mariadb.com/kb/en/current_time/'),(249,'REVOKE',10,'Syntax:\nREVOKE\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n\nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n\nREVOKE PROXY ON user\n FROM user [, user] ...\n\nThe REVOKE statement enables system administrators to revoke privileges\nfrom MySQL accounts. Each account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nREVOKE INSERT ON *.* FROM \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nFor details on the levels at which privileges exist, the permissible\npriv_type and priv_level values, and the syntax for specifying users\nand passwords, see [HELP GRANT]\n\nTo use the first REVOKE syntax, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are revoking.\n\nTo revoke all privileges, use the second syntax, which drops all\nglobal, database, table, column, and routine privileges for the named\nuser or users:\n\nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n\nTo use this REVOKE syntax, you must have the global CREATE USER\nprivilege or the UPDATE privilege for the mysql database.\n\nURL: https://mariadb.com/kb/en/revoke/\n\n','','https://mariadb.com/kb/en/revoke/'),(250,'LAST_INSERT_ID',17,'Syntax:\nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n\nLAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value\nrepresenting the first automatically generated value successfully\ninserted for an AUTO_INCREMENT column as a result of the most recently\nexecuted INSERT statement. The value of LAST_INSERT_ID() remains\nunchanged if no rows are successfully inserted.\n\nFor example, after inserting a row that generates an AUTO_INCREMENT\nvalue, you can get the value like this:\n\nMariaDB> SELECT LAST_INSERT_ID();\n -> 195\n\nThe currently executing statement does not affect the value of\nLAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table with its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain\nstable in the second statement; its value for the second and later rows\nis not affected by the earlier row insertions. (However, if you mix\nreferences to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is\nundefined.)\n\nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if the\nstatement is rolled back due to an error, the value of LAST_INSERT_ID()\nis left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID()\nis not restored to that before the transaction; it remains as it was at\nthe point of the ROLLBACK.\n\nWithin the body of a stored routine (procedure or function) or a\ntrigger, the value of LAST_INSERT_ID() changes the same way as for\nstatements executed outside the body of these kinds of objects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements depends on the\nkind of routine:\n\no If a stored procedure executes statements that change the value of\n LAST_INSERT_ID(), the changed value is seen by statements that follow\n the procedure call.\n\no For stored functions and triggers that change the value, the value is\n restored when the function or trigger ends, so following statements\n will not see a changed value.\n\nURL: https://mariadb.com/kb/en/last_insert_id/\n\n','','https://mariadb.com/kb/en/last_insert_id/'),(251,'LAST_DAY',31,'Syntax:\nLAST_DAY(date)\n\nTakes a date or datetime value and returns the corresponding value for\nthe last day of the month. Returns NULL if the argument is invalid.\n\nURL: https://mariadb.com/kb/en/last_day/\n\n','MariaDB> SELECT LAST_DAY(\'2003-02-05\');\n -> \'2003-02-28\'\nMariaDB> SELECT LAST_DAY(\'2004-02-05\');\n -> \'2004-02-29\'\nMariaDB> SELECT LAST_DAY(\'2004-01-01 01:01:01\');\n -> \'2004-01-31\'\nMariaDB> SELECT LAST_DAY(\'2003-03-32\');\n -> NULL\n','https://mariadb.com/kb/en/last_day/'),(252,'MEDIUMINT',22,'MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA medium-sized integer. The signed range is -8388608 to 8388607. The\nunsigned range is 0 to 16777215.\n\nURL: https://mariadb.com/kb/en/mediumint/\n\n','','https://mariadb.com/kb/en/mediumint/'),(253,'FLOOR',4,'Syntax:\nFLOOR(X)\n\nReturns the largest integer value not greater than X.\n\nURL: https://mariadb.com/kb/en/floor/\n\n','MariaDB> SELECT FLOOR(1.23);\n -> 1\nMariaDB> SELECT FLOOR(-1.23);\n -> -2\n','https://mariadb.com/kb/en/floor/'),(254,'RTRIM',37,'Syntax:\nRTRIM(str)\n\nReturns the string str with trailing space characters removed.\n\nURL: https://mariadb.com/kb/en/rtrim/\n\n','MariaDB> SELECT RTRIM(\'barbar \');\n -> \'barbar\'\n','https://mariadb.com/kb/en/rtrim/'),(255,'EXPLAIN',28,'Syntax:\nEXPLAIN [explain_type] SELECT select_options\n\nexplain_type:\n EXTENDED\n | PARTITIONS\n\nOr:\n\nEXPLAIN tbl_name\n\nThe EXPLAIN statement can be used either as a way to obtain information\nabout how MySQL executes a statement, or as a synonym for DESCRIBE:\n\no When you precede a SELECT statement with the keyword EXPLAIN, MySQL\n displays information from the optimizer about the query execution\n plan. That is, MySQL explains how it would process the statement,\n including information about how tables are joined and in which order.\n EXPLAIN EXTENDED can be used to obtain additional information.\n\n For information about using EXPLAIN and EXPLAIN EXTENDED to obtain\n query execution plan information, see\n https://mariadb.com/kb/en/explain/.\n\no EXPLAIN PARTITIONS is useful only when examining queries involving\n partitioned tables. For details, see\n http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.\n\no EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS\n FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see\n [HELP DESCRIBE], and [HELP SHOW COLUMNS].\n\nURL: https://mariadb.com/kb/en/explain/\n\n','','https://mariadb.com/kb/en/explain/'),(256,'DEGREES',4,'Syntax:\nDEGREES(X)\n\nReturns the argument X, converted from radians to degrees.\n\nURL: https://mariadb.com/kb/en/degrees/\n\n','MariaDB> SELECT DEGREES(PI());\n -> 180\nMariaDB> SELECT DEGREES(PI() / 2);\n -> 90\n','https://mariadb.com/kb/en/degrees/'),(257,'VARCHAR',22,'[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA variable-length string. M represents the maximum column length in\ncharacters. The range of M is 0 to 65,535. The effective maximum length\nof a VARCHAR is subject to the maximum row size (65,535 bytes, which is\nshared among all columns) and the character set used. For example, utf8\ncharacters can require up to three bytes per character, so a VARCHAR\ncolumn that uses the utf8 character set can be declared to be a maximum\nof 21,844 characters. See\nhttp://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html.\n\nMySQL stores VARCHAR values as a 1-byte or 2-byte length prefix plus\ndata. The length prefix indicates the number of bytes in the value. A\nVARCHAR column uses one length byte if values require no more than 255\nbytes, two length bytes if values may require more than 255 bytes.\n\n*Note*: MySQL 5.5 follows the standard SQL specification, and does not\nremove trailing spaces from VARCHAR values.\n\nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR is the\nstandard SQL way to define that a VARCHAR column should use some\npredefined character set. MySQL 4.1 and up uses utf8 as this predefined\ncharacter set.\nhttps://mariadb.com/kb/en/varchar/. NVARCHAR\nis shorthand for NATIONAL VARCHAR.\n\nURL: https://mariadb.com/kb/en/varchar/\n\n','','https://mariadb.com/kb/en/varchar/'),(258,'UNHEX',37,'Syntax:\n\nUNHEX(str)\n\nFor a string argument str, UNHEX(str) performs the inverse operation of\nHEX(str). That is, it interprets each pair of characters in the\nargument as a hexadecimal number and converts it to the character\nrepresented by the number. The return value is a binary string.\n\nURL: https://mariadb.com/kb/en/unhex/\n\n','MariaDB> SELECT UNHEX(\'4D7953514C\');\n -> \'MySQL\'\nMariaDB> SELECT 0x4D7953514C;\n -> \'MySQL\'\nMariaDB> SELECT UNHEX(HEX(\'string\'));\n -> \'string\'\nMariaDB> SELECT HEX(UNHEX(\'1267\'));\n -> \'1267\'\n','https://mariadb.com/kb/en/unhex/'),(259,'- UNARY',4,'Syntax:\n-\n\nUnary minus. This operator changes the sign of the operand.\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/\n\n','MariaDB> SELECT - 2;\n -> -2\n','https://mariadb.com/kb/en/subtraction-operator-/'),(260,'STD',16,'Syntax:\nSTD(expr)\n\nReturns the population standard deviation of expr. This is an extension\nto standard SQL. The standard SQL function STDDEV_POP() can be used\ninstead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/std/\n\n','','https://mariadb.com/kb/en/std/'),(261,'COS',4,'Syntax:\nCOS(X)\n\nReturns the cosine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/cos/\n\n','MariaDB> SELECT COS(PI());\n -> -1\n','https://mariadb.com/kb/en/cos/'),(262,'DATE FUNCTION',31,'Syntax:\nDATE(expr)\n\nExtracts the date part of the date or datetime expression expr.\n\nURL: https://mariadb.com/kb/en/date-function/\n\n','MariaDB> SELECT DATE(\'2003-12-31 01:02:03\');\n -> \'2003-12-31\'\n','https://mariadb.com/kb/en/date-function/'),(263,'DROP TRIGGER',39,'Syntax:\nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n\nThis statement drops a trigger. The schema (database) name is optional.\nIf the schema is omitted, the trigger is dropped from the default\nschema. DROP TRIGGER requires the TRIGGER privilege for the table\nassociated with the trigger.\n\nUse IF EXISTS to prevent an error from occurring for a trigger that\ndoes not exist. A NOTE is generated for a nonexistent trigger when\nusing IF EXISTS. See [HELP SHOW WARNINGS].\n\nTriggers for a table are also dropped if you drop the table.\n\nURL: https://mariadb.com/kb/en/drop-trigger/\n\n','','https://mariadb.com/kb/en/drop-trigger/'),(264,'RESET MASTER',8,'Syntax:\nRESET MASTER\n\nDeletes all binary log files listed in the index file, resets the\nbinary log index file to be empty, and creates a new binary log file.\nThis statement is intended to be used only when the master is started\nfor the first time.\n\nURL: https://mariadb.com/kb/en/reset-master/\n\n','','https://mariadb.com/kb/en/reset-master/'),(265,'TAN',4,'Syntax:\nTAN(X)\n\nReturns the tangent of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/tan/\n\n','MariaDB> SELECT TAN(PI());\n -> -1.2246063538224e-16\nMariaDB> SELECT TAN(PI()+1);\n -> 1.5574077246549\n','https://mariadb.com/kb/en/tan/'),(266,'PI',4,'Syntax:\nPI()\n\nReturns the value of π (pi). The default number of decimal places\ndisplayed is seven, but MySQL uses the full double-precision value\ninternally.\n\nURL: https://mariadb.com/kb/en/pi/\n\n','MariaDB> SELECT PI();\n -> 3.141593\nMariaDB> SELECT PI()+0.000000000000000000;\n -> 3.141592653589793116\n','https://mariadb.com/kb/en/pi/'),(267,'WEEKOFYEAR',31,'Syntax:\nWEEKOFYEAR(date)\n\nReturns the calendar week of the date as a number in the range from 1\nto 53. WEEKOFYEAR() is a compatibility function that is equivalent to\nWEEK(date,3).\n\nURL: https://mariadb.com/kb/en/weekofyear/\n\n','MariaDB> SELECT WEEKOFYEAR(\'2008-02-20\');\n -> 8\n','https://mariadb.com/kb/en/weekofyear/'),(268,'/',4,'Syntax:\n/\n\nDivision:\n\nURL: https://mariadb.com/kb/en/division-operator/\n\n','MariaDB> SELECT 3/5;\n -> 0.60\n','https://mariadb.com/kb/en/division-operator/'),(269,'PURGE BINARY LOGS',8,'Syntax:\nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n\nThe binary log is a set of files that contain information about data\nmodifications made by the MySQL server. The log consists of a set of\nbinary log files, plus an index file (see\nhttps://mariadb.com/kb/en/overview-of-the-binary-log/).\n\nThe PURGE BINARY LOGS statement deletes all the binary log files listed\nin the log index file prior to the specified log file name or date.\nBINARY and MASTER are synonyms. Deleted log files also are removed from\nthe list recorded in the index file, so that the given log file becomes\nthe first in the list.\n\nThis statement has no effect if the server was not started with the\n--log-bin option to enable binary logging.\n\nURL: https://mariadb.com/kb/en/sql-commands-purge-logs/\n\n','PURGE BINARY LOGS TO \'mysql-bin.010\';\nPURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\';\n','https://mariadb.com/kb/en/sql-commands-purge-logs/'),(270,'STDDEV_SAMP',16,'Syntax:\nSTDDEV_SAMP(expr)\n\nReturns the sample standard deviation of expr (the square root of\nVAR_SAMP().\n\nSTDDEV_SAMP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_samp/\n\n','','https://mariadb.com/kb/en/stddev_samp/'),(271,'SCHEMA',17,'Syntax:\nSCHEMA()\n\nThis function is a synonym for DATABASE().\n\nURL: https://mariadb.com/kb/en/schema/\n\n','','https://mariadb.com/kb/en/schema/'),(272,'MLINEFROMWKB',32,'MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])\n\nConstructs a MULTILINESTRING value using its WKB representation and\nSRID.\n\nURL: https://mariadb.com/kb/en/mlinefromwkb/\n\n','','https://mariadb.com/kb/en/mlinefromwkb/'),(273,'LOG2',4,'Syntax:\nLOG2(X)\n\nReturns the base-2 logarithm of X.\n\nURL: https://mariadb.com/kb/en/log2/\n\n','MariaDB> SELECT LOG2(65536);\n -> 16\nMariaDB> SELECT LOG2(-100);\n -> NULL\n','https://mariadb.com/kb/en/log2/'),(274,'SUBTIME',31,'Syntax:\nSUBTIME(expr1,expr2)\n\nSUBTIME() returns expr1 - expr2 expressed as a value in the same format\nas expr1. expr1 is a time or datetime expression, and expr2 is a time\nexpression.\n\nURL: https://mariadb.com/kb/en/subtime/\n\n','MariaDB> SELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\');\n -> \'2007-12-30 22:58:58.999997\'\nMariaDB> SELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'-00:59:59.999999\'\n','https://mariadb.com/kb/en/subtime/'),(275,'UNCOMPRESSED_LENGTH',12,'Syntax:\nUNCOMPRESSED_LENGTH(compressed_string)\n\nReturns the length that the compressed string had before being\ncompressed.\n\nURL: https://mariadb.com/kb/en/uncompressed_length/\n\n','MariaDB> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n -> 30\n','https://mariadb.com/kb/en/uncompressed_length/'),(276,'DROP TABLE',39,'Syntax:\nDROP [TEMPORARY] TABLE [IF EXISTS]\n tbl_name [, tbl_name] ...\n [RESTRICT | CASCADE]\n\nDROP TABLE removes one or more tables. You must have the DROP privilege\nfor each table. All table data and the table definition are removed, so\nbe careful with this statement! If any of the tables named in the\nargument list do not exist, MySQL returns an error indicating by name\nwhich nonexisting tables it was unable to drop, but it also drops all\nof the tables in the list that do exist.\n\n*Important*: When a table is dropped, user privileges on the table are\nnot automatically dropped. See [HELP GRANT].\n\nNote that for a partitioned table, DROP TABLE permanently removes the\ntable definition, all of its partitions, and all of the data which was\nstored in those partitions. It also removes the partitioning definition\n(.par) file associated with the dropped table.\n\nUse IF EXISTS to prevent an error from occurring for tables that do not\nexist. A NOTE is generated for each nonexistent table when using IF\nEXISTS. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE are permitted to make porting easier. In MySQL\n5.5, they do nothing.\n\n*Note*: DROP TABLE automatically commits the current active\ntransaction, unless you use the TEMPORARY keyword.\n\nURL: https://mariadb.com/kb/en/drop-table/\n\n','','https://mariadb.com/kb/en/drop-table/'),(277,'POW',4,'Syntax:\nPOW(X,Y)\n\nReturns the value of X raised to the power of Y.\n\nURL: https://mariadb.com/kb/en/pow/\n\n','MariaDB> SELECT POW(2,2);\n -> 4\nMariaDB> SELECT POW(2,-2);\n -> 0.25\n','https://mariadb.com/kb/en/pow/'),(278,'SHOW CREATE TABLE',26,'Syntax:\nSHOW CREATE TABLE tbl_name\n\nShows the CREATE TABLE statement that creates the given table. To use\nthis statement, you must have some privilege for the table. This\nstatement also works with views.\nSHOW CREATE TABLE quotes table and column names according to the value\nof the sql_quote_show_create option. See\nhttps://mariadb.com/kb/en/server-system-variables/.\n\nURL: https://mariadb.com/kb/en/show-create-table/\n\n','MariaDB> SHOW CREATE TABLE t\\G\n*************************** 1. row ***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id INT(11) default NULL auto_increment,\n s char(60) default NULL,\n PRIMARY KEY (id)\n) ENGINE=MyISAM\n','https://mariadb.com/kb/en/show-create-table/'),(279,'DUAL',27,'You are permitted to specify DUAL as a dummy table name in situations\nwhere no tables are referenced:\n\nMariaDB> SELECT 1 + 1 FROM DUAL;\n -> 2\n\nDUAL is purely for the convenience of people who require that all\nSELECT statements should have FROM and possibly other clauses. MySQL\nmay ignore the clauses. MySQL does not require FROM DUAL if no tables\nare referenced.\n\nURL: https://mariadb.com/kb/en/dual/\n\n','','https://mariadb.com/kb/en/dual/'),(280,'INSTR',37,'Syntax:\nINSTR(str,substr)\n\nReturns the position of the first occurrence of substring substr in\nstring str. This is the same as the two-argument form of LOCATE(),\nexcept that the order of the arguments is reversed.\n\nURL: https://mariadb.com/kb/en/instr/\n\n','MariaDB> SELECT INSTR(\'foobarbar\', \'bar\');\n -> 4\nMariaDB> SELECT INSTR(\'xbar\', \'foobar\');\n -> 0\n','https://mariadb.com/kb/en/instr/'),(281,'NOW',31,'Syntax:\nNOW()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed in the\ncurrent time zone.\n\nURL: https://mariadb.com/kb/en/now/\n\n','MariaDB> SELECT NOW();\n -> \'2007-12-15 23:50:26\'\nMariaDB> SELECT NOW() + 0;\n -> 20071215235026.000000\n','https://mariadb.com/kb/en/now/'),(282,'SHOW ENGINES',26,'Syntax:\nSHOW [STORAGE] ENGINES\n\nSHOW ENGINES displays status information about the server\'s storage\nengines. This is particularly useful for checking whether a storage\nengine is supported, or to see what the default engine is.\n\nURL: https://mariadb.com/kb/en/show-engines/\n\n','','https://mariadb.com/kb/en/show-engines/'),(283,'>=',18,'Syntax:\n>=\n\nGreater than or equal:\n\nURL: https://mariadb.com/kb/en/greater-than-or-equal/\n\n','MariaDB> SELECT 2 >= 2;\n -> 1\n','https://mariadb.com/kb/en/greater-than-or-equal/'),(284,'EXP',4,'Syntax:\nEXP(X)\n\nReturns the value of e (the base of natural logarithms) raised to the\npower of X. The inverse of this function is LOG() (using a single\nargument only) or LN().\n\nURL: https://mariadb.com/kb/en/exp/\n\n','MariaDB> SELECT EXP(2);\n -> 7.3890560989307\nMariaDB> SELECT EXP(-2);\n -> 0.13533528323661\nMariaDB> SELECT EXP(0);\n -> 1\n','https://mariadb.com/kb/en/exp/'),(285,'LONGBLOB',22,'LONGBLOB\n\nA BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\nbytes. The effective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol and\navailable memory. Each LONGBLOB value is stored using a 4-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/longblob/\n\n','','https://mariadb.com/kb/en/longblob/'),(286,'POINTN',13,'PointN(ls,N)\n\nReturns the N-th Point in the Linestring value ls. Points are numbered\nbeginning with 1.\n\nURL: https://mariadb.com/kb/en/pointn/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n','https://mariadb.com/kb/en/pointn/'),(287,'YEAR DATA TYPE',22,'YEAR[(2|4)]\n\nA year in two-digit or four-digit format. The default is four-digit\nformat. YEAR(2) or YEAR(4) differ in display format, but have the same\nrange of values. In four-digit format, values display as 1901 to 2155,\nand 0000. In two-digit format, values display as 70 to 69, representing\nyears from 1970 to 2069. MySQL displays YEAR values in YYYY or\nYYformat, but permits assignment of values to YEAR columns using either\nstrings or numbers.\n\n*Note*: The YEAR(2) data type has certain issues that you should\nconsider before choosing to use it. As of MySQL 5.5.27, YEAR(2) is\ndeprecated. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/migrating-to-year4.html.\n\nFor additional information about YEAR display format and inerpretation\nof input values, see https://mariadb.com/kb/en/year-data-type/.\n\nURL: https://mariadb.com/kb/en/year-data-type/\n\n','','https://mariadb.com/kb/en/year-data-type/'),(288,'SUM',16,'Syntax:\nSUM([DISTINCT] expr)\n\nReturns the sum of expr. If the return set has no rows, SUM() returns\nNULL. The DISTINCT keyword can be used to sum only the distinct values\nof expr.\n\nSUM() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/sum/\n\n','','https://mariadb.com/kb/en/sum/'),(289,'OCT',37,'Syntax:\nOCT(N)\n\nReturns a string representation of the octal value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,8). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/oct/\n\n','MariaDB> SELECT OCT(12);\n -> \'14\'\n','https://mariadb.com/kb/en/oct/'),(290,'SYSDATE',31,'Syntax:\nSYSDATE()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context.\n\nSYSDATE() returns the time at which it executes. This differs from the\nbehavior for NOW(), which returns a constant time that indicates the\ntime at which the statement began to execute. (Within a stored function\nor trigger, NOW() returns the time at which the function or triggering\nstatement began to execute.)\n\nMariaDB> SELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |\n+---------------------+----------+---------------------+\n\nMariaDB> SELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |\n+---------------------+----------+---------------------+\n\nIn addition, the SET TIMESTAMP statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp settings in the\nbinary log have no effect on invocations of SYSDATE().\n\nBecause SYSDATE() can return different values even within the same\nstatement, and is not affected by SET TIMESTAMP, it is nondeterministic\nand therefore unsafe for replication if statement-based binary logging\nis used. If that is a problem, you can use row-based logging.\n\nAlternatively, you can use the --sysdate-is-now option to cause\nSYSDATE() to be an alias for NOW(). This works if the option is used on\nboth the master and the slave.\n\nThe nondeterministic nature of SYSDATE() also means that indexes cannot\nbe used for evaluating expressions that refer to it.\n\nURL: https://mariadb.com/kb/en/sysdate/\n\n','','https://mariadb.com/kb/en/sysdate/'),(291,'UNINSTALL PLUGIN',5,'Syntax:\nUNINSTALL PLUGIN plugin_name\n\nThis statement removes an installed server plugin. It requires the\nDELETE privilege for the mysql.plugin table.\n\nplugin_name must be the name of some plugin that is listed in the\nmysql.plugin table. The server executes the plugin\'s deinitialization\nfunction and removes the row for the plugin from the mysql.plugin\ntable, so that subsequent server restarts will not load and initialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s shared\nlibrary file.\n\nURL: https://mariadb.com/kb/en/uninstall-plugin/\n\n','','https://mariadb.com/kb/en/uninstall-plugin/'),(292,'ASBINARY',32,'AsBinary(g), AsWKB(g)\n\nConverts a value in internal geometry format to its WKB representation\nand returns the binary result.\n\nURL: https://mariadb.com/kb/en/asbinary/\n\n','SELECT AsBinary(g) FROM geom;\n','https://mariadb.com/kb/en/asbinary/'),(293,'REPEAT FUNCTION',37,'Syntax:\nREPEAT(str,count)\n\nReturns a string consisting of the string str repeated count times. If\ncount is less than 1, returns an empty string. Returns NULL if str or\ncount are NULL.\n\nURL: https://mariadb.com/kb/en/repeat-function/\n\n','MariaDB> SELECT REPEAT(\'MySQL\', 3);\n -> \'MySQLMySQLMySQL\'\n','https://mariadb.com/kb/en/repeat-function/'),(294,'SHOW TABLES',26,'Syntax:\nSHOW [FULL] TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLES lists the non-TEMPORARY tables in a given database. You can\nalso get this list using the mysqlshow db_name command. The LIKE\nclause, if present, indicates which table names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in https://mariadb.com/kb/en/extended-show/.\n\nThis statement also lists any views in the database. The FULL modifier\nis supported such that SHOW FULL TABLES displays a second output\ncolumn. Values for the second column are BASE TABLE for a table and\nVIEW for a view.\n\nIf you have no privileges for a base table or view, it does not show up\nin the output from SHOW TABLES or mysqlshow db_name.\n\nURL: https://mariadb.com/kb/en/show-tables/\n\n','','https://mariadb.com/kb/en/show-tables/'),(295,'MAKEDATE',31,'Syntax:\nMAKEDATE(year,dayofyear)\n\nReturns a date, given year and day-of-year values. dayofyear must be\ngreater than 0 or the result is NULL.\n\nURL: https://mariadb.com/kb/en/makedate/\n\n','MariaDB> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n -> \'2011-01-31\', \'2011-02-01\'\nMariaDB> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n -> \'2011-12-31\', \'2014-12-31\'\nMariaDB> SELECT MAKEDATE(2011,0);\n -> NULL\n','https://mariadb.com/kb/en/makedate/'),(296,'BINARY OPERATOR',37,'Syntax:\nBINARY\n\nThe BINARY operator casts the string following it to a binary string.\nThis is an easy way to force a column comparison to be done byte by\nbyte rather than character by character. This causes the comparison to\nbe case sensitive even if the column is not defined as BINARY or BLOB.\nBINARY also causes trailing spaces to be significant.\n\nURL: https://mariadb.com/kb/en/binary-operator/\n\n','MariaDB> SELECT \'a\' = \'A\';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'A\';\n -> 0\nMariaDB> SELECT \'a\' = \'a \';\n -> 1\nMariaDB> SELECT BINARY \'a\' = \'a \';\n -> 0\n','https://mariadb.com/kb/en/binary-operator/'),(297,'MBROVERLAPS',6,'MBROverlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 overlap. The term spatially overlaps is\nused if two geometries intersect and their intersection results in a\ngeometry of the same dimension but not equal to either of the given\ngeometries.\n\nURL: https://mariadb.com/kb/en/mbroverlaps/\n\n','','https://mariadb.com/kb/en/mbroverlaps/'),(298,'SOUNDEX',37,'Syntax:\nSOUNDEX(str)\n\nReturns a soundex string from str. Two strings that sound almost the\nsame should have identical soundex strings. A standard soundex string\nis four characters long, but the SOUNDEX() function returns an\narbitrarily long string. You can use SUBSTRING() on the result to get a\nstandard soundex string. All nonalphabetic characters in str are\nignored. All international alphabetic characters outside the A-Z range\nare treated as vowels.\n\n*Important*: When using SOUNDEX(), you should be aware of the following\nlimitations:\n\no This function, as currently implemented, is intended to work well\n with strings that are in the English language only. Strings in other\n languages may not produce reliable results.\n\no This function is not guaranteed to provide consistent results with\n strings that use multi-byte character sets, including utf-8.\n\n We hope to remove these limitations in a future release. See Bug\n #22638 for more information.\n\nURL: https://mariadb.com/kb/en/soundex/\n\n','MariaDB> SELECT SOUNDEX(\'Hello\');\n -> \'H400\'\nMariaDB> SELECT SOUNDEX(\'Quadratically\');\n -> \'Q36324\'\n','https://mariadb.com/kb/en/soundex/'),(299,'MBRTOUCHES',6,'MBRTouches(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially touch if\nthe interiors of the geometries do not intersect, but the boundary of\none of the geometries intersects either the boundary or the interior of\nthe other.\n\nURL: https://mariadb.com/kb/en/mbrtouches/\n\n','','https://mariadb.com/kb/en/mbrtouches/'),(300,'DROP EVENT',39,'Syntax:\nDROP EVENT [IF EXISTS] event_name\n\nThis statement drops the event named event_name. The event immediately\nceases being active, and is deleted completely from the server.\n\nIf the event does not exist, the error ERROR 1517 (HY000): Unknown\nevent \'event_name\' results. You can override this and cause the\nstatement to generate a warning for nonexistent events instead using IF\nEXISTS.\n\nThis statement requires the EVENT privilege for the schema to which the\nevent to be dropped belongs.\n\nURL: https://mariadb.com/kb/en/drop-event/\n\n','','https://mariadb.com/kb/en/drop-event/'),(301,'INSERT SELECT',27,'Syntax:\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n\nWith INSERT ... SELECT, you can quickly insert many rows into a table\nfrom one or many tables. For example:\n\nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n\nURL: https://mariadb.com/kb/en/insert-select/\n\n','','https://mariadb.com/kb/en/insert-select/'),(302,'CREATE PROCEDURE',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n FUNCTION sp_name ([func_parameter[,...]])\n RETURNS type\n [characteristic ...] routine_body\n\nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n\nfunc_parameter:\n param_name type\n\ntype:\n Any valid MySQL data type\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nroutine_body:\n Valid SQL routine statement\n\nThese statements create stored routines. By default, a routine is\nassociated with the default database. To associate the routine\nexplicitly with a given database, specify the name as db_name.sp_name\nwhen you create it.\n\nThe CREATE FUNCTION statement is also used in MySQL to support UDFs\n(user-defined functions). See\nhttps://mariadb.com/kb/en/create-function-udf/. A UDF can\nbe regarded as an external stored function. Stored functions share\ntheir namespace with UDFs. See\nhttp://dev.mysql.com/doc/refman/5.5/en/function-resolution.html, for\nthe rules describing how the server interprets references to different\nkinds of functions.\n\nTo invoke a stored procedure, use the CALL statement (see [HELP CALL]).\nTo invoke a stored function, refer to it in an expression. The function\nreturns a value during expression evaluation.\n\nCREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE\nprivilege. They might also require the SUPER privilege, depending on\nthe DEFINER value, as described later in this section. If binary\nlogging is enabled, CREATE FUNCTION might require the SUPER privilege,\nas described in\nhttps://mariadb.com/kb/en/binary-logging-of-stored-routines/.\n\nBy default, MySQL automatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the routine creator. This behavior can be changed by\ndisabling the automatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nThe DEFINER and SQL SECURITY clauses specify the security context to be\nused when checking access privileges at routine execution time, as\ndescribed later in this section.\n\nIf the routine name is the same as the name of a built-in SQL function,\na syntax error occurs unless you use a space between the name and the\nfollowing parenthesis when defining the routine or invoking it later.\nFor this reason, avoid using the names of existing SQL functions for\nyour own stored routines.\n\nThe IGNORE_SPACE SQL mode applies to built-in functions, not to stored\nroutines. It is always permissible to have spaces after a stored\nroutine name, regardless of whether IGNORE_SPACE is enabled.\n\nThe parameter list enclosed within parentheses must always be present.\nIf there are no parameters, an empty parameter list of () should be\nused. Parameter names are not case sensitive.\n\nEach parameter is an IN parameter by default. To specify otherwise for\na parameter, use the keyword OUT or INOUT before the parameter name.\n\n*Note*: Specifying a parameter as IN, OUT, or INOUT is valid only for a\nPROCEDURE. For a FUNCTION, parameters are always regarded as IN\nparameters.\n\nAn IN parameter passes a value into a procedure. The procedure might\nmodify the value, but the modification is not visible to the caller\nwhen the procedure returns. An OUT parameter passes a value from the\nprocedure back to the caller. Its initial value is NULL within the\nprocedure, and its value is visible to the caller when the procedure\nreturns. An INOUT parameter is initialized by the caller, can be\nmodified by the procedure, and any change made by the procedure is\nvisible to the caller when the procedure returns.\n\nFor each OUT or INOUT parameter, pass a user-defined variable in the\nCALL statement that invokes the procedure so that you can obtain its\nvalue when the procedure returns. If you are calling the procedure from\nwithin another stored procedure or function, you can also pass a\nroutine parameter or local routine variable as an IN or INOUT\nparameter.\n\nThe following example shows a simple stored procedure that uses an OUT\nparameter:\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE simpleproc (OUT param1 INT)\n -> BEGIN\n -> SELECT COUNT(*) INTO param1 FROM t;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter ;\n\nMariaDB> CALL simpleproc(@a);\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @a;\n+------+\n| @a |\n+------+\n| 3 |\n+------+\n1 row in set (0.00 sec)\n\nThe example uses the mysql client delimiter command to change the\nstatement delimiter from ; to // while the procedure is being defined.\nThis enables the ; delimiter used in the procedure body to be passed\nthrough to the server rather than being interpreted by mysql itself.\nSee\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nThe RETURNS clause may be specified only for a FUNCTION, for which it\nis mandatory. It indicates the return type of the function, and the\nfunction body must contain a RETURN value statement. If the RETURN\nstatement returns a value of a different type, the value is coerced to\nthe proper type. For example, if a function specifies an ENUM or SET\nvalue in the RETURNS clause, but the RETURN statement returns an\ninteger, the value returned from the function is the string for the\ncorresponding ENUM member of set of SET members.\n\nThe following example function takes a parameter, performs an operation\nusing an SQL function, and returns the result. In this case, it is\nunnecessary to use delimiter because the function definition contains\nno internal ; statement delimiters:\n\nMariaDB> CREATE FUNCTION hello (s CHAR(20))\nMariaDB> RETURNS CHAR(50) DETERMINISTIC\n -> RETURN CONCAT(\'Hello, \',s,\'!\');\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n1 row in set (0.00 sec)\n\nParameter types and function return types can be declared to use any\nvalid data type, except that the COLLATE attribute cannot be used prior\nto MySQL 5.5.3. As of 5.5.3, COLLATE can be used if preceded by the\nCHARACTER SET attribute.\n\nThe routine_body consists of a valid SQL routine statement. This can be\na simple statement such as SELECT or INSERT, or a compound statement\nwritten using BEGIN and END. Compound statements can contain\ndeclarations, loops, and other control structure statements. The syntax\nfor these statements is described in\nhttps://mariadb.com/kb/programmatic-and-compound-statements.\n\nMySQL permits routines to contain DDL statements, such as CREATE and\nDROP. MySQL also permits stored procedures (but not stored functions)\nto contain SQL transaction statements such as COMMIT. Stored functions\nmay not contain statements that perform explicit or implicit commit or\nrollback. Support for these statements is not required by the SQL\nstandard, which states that each DBMS vendor may decide whether to\npermit them.\n\nStatements that return a result set can be used within a stored\nprocedure but not within a stored function. This prohibition includes\nSELECT statements that do not have an INTO var_list clause and other\nstatements such as SHOW, EXPLAIN, and CHECK TABLE. For statements that\ncan be determined at function definition time to return a result set, a\nNot allowed to return a result set from a function error occurs\n(ER_SP_NO_RETSET). For statements that can be determined only at\nruntime to return a result set, a PROCEDURE %s can\'t return a result\nset in the given context error occurs (ER_SP_BADSELECT).\n\nUSE statements within stored routines are not permitted. When a routine\nis invoked, an implicit USE db_name is performed (and undone when the\nroutine terminates). The causes the routine to have the given default\ndatabase while it executes. References to objects in databases other\nthan the routine default database should be qualified with the\nappropriate database name.\n\nFor additional information about statements that are not permitted in\nstored routines, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/\n.\n\nFor information about invoking stored procedures from within programs\nwritten in a language that has a MySQL interface, see [HELP CALL].\n\nMySQL stores the sql_mode system variable setting that is in effect at\nthe time a routine is created, and always executes the routine with\nthis setting in force, regardless of the server SQL mode in effect when\nthe routine is invoked.\n\nThe switch from the SQL mode of the invoker to that of the routine\noccurs after evaluation of arguments and assignment of the resulting\nvalues to routine parameters. If you define a routine in strict SQL\nmode but invoke it in nonstrict mode, assignment of arguments to\nroutine parameters does not take place in strict mode. If you require\nthat expressions passed to a routine be assigned in strict SQL mode,\nyou should invoke the routine with strict mode in effect.\n\nURL: https://mariadb.com/kb/en/create-procedure/\n\n','','https://mariadb.com/kb/en/create-procedure/'),(303,'VARBINARY',22,'VARBINARY(M)\n\nThe VARBINARY type is similar to the VARCHAR type, but stores binary\nbyte strings rather than nonbinary character strings. M represents the\nmaximum column length in bytes.\n\nURL: https://mariadb.com/kb/en/varbinary/\n\n','','https://mariadb.com/kb/en/varbinary/'),(304,'LOAD INDEX',26,'Syntax:\nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n\ntbl_index_list:\n tbl_name\n [PARTITION (partition_list | ALL)]\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe LOAD INDEX INTO CACHE statement preloads a table index into the key\ncache to which it has been assigned by an explicit CACHE INDEX\nstatement, or into the default key cache otherwise.\n\nLOAD INDEX INTO CACHE is used only for MyISAM tables. In MySQL 5.5, it\nis also supported for partitioned MyISAM tables; in addition, indexes\non partitioned tables can be preloaded for one, several, or all\npartitions.\n\nThe IGNORE LEAVES modifier causes only blocks for the nonleaf nodes of\nthe index to be preloaded.\n\nIGNORE LEAVES is also supported for partitioned MyISAM tables.\n\nURL: https://mariadb.com/kb/en/load-index/\n\n','','https://mariadb.com/kb/en/load-index/'),(305,'UNION',27,'Syntax:\nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n\nUNION is used to combine the result from multiple SELECT statements\ninto a single result set.\n\nThe column names from the first SELECT statement are used as the column\nnames for the results returned. Selected columns listed in\ncorresponding positions of each SELECT statement should have the same\ndata type. (For example, the first column selected by the first\nstatement should have the same type as the first column selected by the\nother statements.)\n\nURL: https://mariadb.com/kb/en/union/\n\n','','https://mariadb.com/kb/en/union/'),(306,'TO_DAYS',31,'Syntax:\nTO_DAYS(date)\n\nGiven a date date, returns a day number (the number of days since year\n0).\n\nURL: https://mariadb.com/kb/en/to_days/\n\n','MariaDB> SELECT TO_DAYS(950501);\n -> 728779\nMariaDB> SELECT TO_DAYS(\'2007-10-07\');\n -> 733321\n','https://mariadb.com/kb/en/to_days/'),(307,'NOT REGEXP',37,'Syntax:\nexpr NOT REGEXP pat, expr NOT RLIKE pat\n\nThis is the same as NOT (expr REGEXP pat).\n\nURL: https://mariadb.com/kb/en/not-regexp/\n\n','','https://mariadb.com/kb/en/not-regexp/'),(308,'SHOW INDEX',26,'Syntax:\nSHOW {INDEX | INDEXES | KEYS}\n {FROM | IN} tbl_name\n [{FROM | IN} db_name]\n [WHERE expr]\n\nSHOW INDEX returns table index information. The format resembles that\nof the SQLStatistics call in ODBC. This statement requires some\nprivilege for any column in the table.\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. These two statements are equivalent:\n\nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n\nThe WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nYou can also list a table\'s indexes with the mysqlshow -k db_name\ntbl_name command.\n\nURL: https://mariadb.com/kb/en/show-index/\n\n','','https://mariadb.com/kb/en/show-index/'),(309,'SHOW CREATE DATABASE',26,'Syntax:\nSHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n\nShows the CREATE DATABASE statement that creates the given database. If\nthe SHOW statement includes an IF NOT EXISTS clause, the output too\nincludes such a clause. SHOW CREATE SCHEMA is a synonym for SHOW CREATE\nDATABASE.\n\nURL: https://mariadb.com/kb/en/show-create-database/\n\n','MariaDB> SHOW CREATE DATABASE test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n\nMariaDB> SHOW CREATE SCHEMA test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n','https://mariadb.com/kb/en/show-create-database/'),(310,'LEAVE',23,'Syntax:\nLEAVE label\n\nThis statement is used to exit the flow control construct that has the\ngiven label. If the label is for the outermost stored program block,\nLEAVE exits the program.\n\nLEAVE can be used within BEGIN ... END or loop constructs (LOOP,\nREPEAT, WHILE).\n\nURL: https://mariadb.com/kb/en/leave/\n\n','','https://mariadb.com/kb/en/leave/'),(311,'NOT IN',18,'Syntax:\nexpr NOT IN (value,...)\n\nThis is the same as NOT (expr IN (value,...)).\n\nURL: https://mariadb.com/kb/en/not-in/\n\n','','https://mariadb.com/kb/en/not-in/'),(312,'!',15,'Syntax:\nNOT, !\n\nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is\nnonzero, and NOT NULL returns NULL.\n\nURL: https://mariadb.com/kb/en/not/\n\n','MariaDB> SELECT NOT 10;\n -> 0\nMariaDB> SELECT NOT 0;\n -> 1\nMariaDB> SELECT NOT NULL;\n -> NULL\nMariaDB> SELECT ! (1+1);\n -> 0\nMariaDB> SELECT ! 1+1;\n -> 1\n','https://mariadb.com/kb/en/not/'),(313,'DECLARE HANDLER',23,'Syntax:\nDECLARE handler_action HANDLER\n FOR condition_value [, condition_value] ...\n statement\n\nhandler_action:\n CONTINUE\n | EXIT\n | UNDO\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n\nThe DECLARE ... HANDLER statement specifies a handler that deals with\none or more conditions. If one of these conditions occurs, the\nspecified statement executes. statement can be a simple statement such\nas SET var_name = value, or a compound statement written using BEGIN\nand END (see [HELP BEGIN END]).\n\nHandler declarations must appear after variable or condition\ndeclarations.\n\nThe handler_action value indicates what action the handler takes after\nexecution of the handler statement:\n\no CONTINUE: Execution of the current program continues.\n\no EXIT: Execution terminates for the BEGIN ... END compound statement\n in which the handler is declared. This is true even if the condition\n occurs in an inner block.\n\no UNDO: Not supported.\n\nThe condition_value for DECLARE ... HANDLER indicates the specific\ncondition or class of conditions that activates the handler:\n\no A MySQL error code (a number) or an SQLSTATE value (a 5-character\n string literal). You should not use MySQL error code 0 or SQLSTATE\n values that begin with \'00\', because those indicate success rather\n than an error condition. For a list of MySQL error codes and SQLSTATE\n values, see\n https://mariadb.com/kb/en/mariadb-error-codes/.\n\no A condition name previously specified with DECLARE ... CONDITION. A\n condition name can be associated with a MySQL error code or SQLSTATE\n value. See [HELP DECLARE CONDITION].\n\no SQLWARNING is shorthand for the class of SQLSTATE values that begin\n with \'01\'.\n\no NOT FOUND is shorthand for the class of SQLSTATE values that begin\n with \'02\'. This is relevant within the context of cursors and is used\n to control what happens when a cursor reaches the end of a data set.\n If no more rows are available, a No Data condition occurs with\n SQLSTATE value \'02000\'. To detect this condition, you can set up a\n handler for it (or for a NOT FOUND condition). For an example, see\n https://mariadb.com/kb/en/cursor-overview/. This condition\n also occurs for SELECT ... INTO var_list statements that retrieve no\n rows.\n\no SQLEXCEPTION is shorthand for the class of SQLSTATE values that do\n not begin with \'00\', \'01\', or \'02\'.\n\nIf a condition occurs for which no handler has been declared, the\naction taken depends on the condition class:\n\no For SQLEXCEPTION conditions, the stored program terminates at the\n statement that raised the condition, as if there were an EXIT\n handler. If the program was called by another stored program, the\n calling program handles the condition using the handler selection\n rules applied to its own handlers.\n\no For SQLWARNING conditions, the program continues executing, as if\n there were a CONTINUE handler.\n\no For NOT FOUND conditions, if the condition was raised normally, the\n action is CONTINUE. If it was raised by SIGNAL or RESIGNAL, the\n action is EXIT.\n\nURL: https://mariadb.com/kb/en/declare-handler/\n\n','MariaDB> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> delimiter //\n\nMariaDB> CREATE PROCEDURE handlerdemo ()\n -> BEGIN\n -> DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 = 1;\n -> SET @x = 1;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 2;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 3;\n -> END;\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> CALL handlerdemo()//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT @x//\n +------+\n | @x |\n +------+\n | 3 |\n +------+\n 1 row in set (0.00 sec)\n','https://mariadb.com/kb/en/declare-handler/'),(314,'DOUBLE',22,'DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA normal-size (double-precision) floating-point number. Permissible\nvalues are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and\n2.2250738585072014E-308 to 1.7976931348623157E+308. These are the\ntheoretical limits, based on the IEEE standard. The actual range might\nbe slightly smaller depending on your hardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A double-precision floating-point\nnumber is accurate to approximately 15 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nURL: https://mariadb.com/kb/en/double/\n\n','','https://mariadb.com/kb/en/double/'),(315,'TIME',22,'TIME\n\nA time. The range is \'-838:59:59\' to \'838:59:59\'. MySQL displays TIME\nvalues in \'HH:MM:SS\' format, but permits assignment of values to TIME\ncolumns using either strings or numbers.\n\nURL: https://mariadb.com/kb/en/time/\n\n','','https://mariadb.com/kb/en/time/'),(316,'&&',15,'Syntax:\nAND, &&\n\nLogical AND. Evaluates to 1 if all operands are nonzero and not NULL,\nto 0 if one or more operands are 0, otherwise NULL is returned.\n\nURL: https://mariadb.com/kb/en/and/\n\n','MariaDB> SELECT 1 && 1;\n -> 1\nMariaDB> SELECT 1 && 0;\n -> 0\nMariaDB> SELECT 1 && NULL;\n -> NULL\nMariaDB> SELECT 0 && NULL;\n -> 0\nMariaDB> SELECT NULL && 0;\n -> 0\n','https://mariadb.com/kb/en/and/'),(317,'X',11,'X(p)\n\nReturns the X-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/x/\n\n','MariaDB> SELECT X(POINT(56.7, 53.34));\n+-----------------------+\n| X(POINT(56.7, 53.34)) |\n+-----------------------+\n| 56.7 |\n+-----------------------+\n','https://mariadb.com/kb/en/x/'),(318,'SYSTEM_USER',17,'Syntax:\nSYSTEM_USER()\n\nSYSTEM_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/system_user/\n\n','','https://mariadb.com/kb/en/system_user/'),(319,'FOUND_ROWS',17,'Syntax:\nFOUND_ROWS()\n\nA SELECT statement may include a LIMIT clause to restrict the number of\nrows the server returns to the client. In some cases, it is desirable\nto know how many rows the statement would have returned without the\nLIMIT, but without running the statement again. To obtain this row\ncount, include a SQL_CALC_FOUND_ROWS option in the SELECT statement,\nand then invoke FOUND_ROWS() afterward:\n\nURL: https://mariadb.com/kb/en/found_rows/\n\n','MariaDB> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name\n -> WHERE id > 100 LIMIT 10;\nMariaDB> SELECT FOUND_ROWS();\n','https://mariadb.com/kb/en/found_rows/'),(320,'CROSSES',30,'Crosses(g1,g2)\n\nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon\nor a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise,\nreturns 0.\n\nThe term spatially crosses denotes a spatial relation between two given\ngeometries that has the following properties:\n\no The two geometries intersect\n\no Their intersection results in a geometry that has a dimension that is\n one less than the maximum dimension of the two given geometries\n\no Their intersection is not equal to either of the two given geometries\n\nURL: https://mariadb.com/kb/en/crosses/\n\n','','https://mariadb.com/kb/en/crosses/'),(321,'TRUNCATE TABLE',39,'Syntax:\nTRUNCATE [TABLE] tbl_name\n\nTRUNCATE TABLE empties a table completely. It requires the DROP\nprivilege.\n\nLogically, TRUNCATE TABLE is similar to a DELETE statement that deletes\nall rows, or a sequence of DROP TABLE and CREATE TABLE statements. To\nachieve high performance, it bypasses the DML method of deleting data.\nThus, it cannot be rolled back, it does not cause ON DELETE triggers to\nfire, and it cannot be performed for InnoDB tables with parent-child\nforeign key relationships.\n\nAlthough TRUNCATE TABLE is similar to DELETE, it is classified as a DDL\nstatement rather than a DML statement. It differs from DELETE in the\nfollowing ways in MySQL 5.5:\n\no Truncate operations drop and re-create the table, which is much\n faster than deleting rows one by one, particularly for large tables.\n\no Truncate operations cause an implicit commit, and so cannot be rolled\n back.\n\no Truncation operations cannot be performed if the session holds an\n active table lock.\n\no TRUNCATE TABLE fails for an InnoDB table if there are any FOREIGN KEY\n constraints from other tables that reference the table. Foreign key\n constraints between columns of the same table are permitted.\n\no Truncation operations do not return a meaningful value for the number\n of deleted rows. The usual result is \"0 rows affected,\" which should\n be interpreted as \"no information.\"\n\no As long as the table format file tbl_name.frm is valid, the table can\n be re-created as an empty table with TRUNCATE TABLE, even if the data\n or index files have become corrupted.\n\no Any AUTO_INCREMENT value is reset to its start value. This is true\n even for MyISAM and InnoDB, which normally do not reuse sequence\n values.\n\no When used with partitioned tables, TRUNCATE TABLE preserves the\n partitioning; that is, the data and index files are dropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\n\no The TRUNCATE TABLE statement does not invoke ON DELETE triggers.\n\nURL: https://mariadb.com/kb/en/truncate-table/\n\n','','https://mariadb.com/kb/en/truncate-table/'),(322,'BIT_XOR',16,'Syntax:\nBIT_XOR(expr)\n\nReturns the bitwise XOR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_xor/\n\n','','https://mariadb.com/kb/en/bit_xor/'),(323,'CURRENT_DATE',31,'Syntax:\nCURRENT_DATE, CURRENT_DATE()\n\nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n\nURL: https://mariadb.com/kb/en/current_date/\n\n','','https://mariadb.com/kb/en/current_date/'),(324,'START SLAVE',8,'Syntax:\nSTART SLAVE [thread_types]\n\nSTART SLAVE [SQL_THREAD] UNTIL\n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\n\nSTART SLAVE [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nSTART SLAVE with no thread_type options starts both of the slave\nthreads. The I/O thread reads events from the master server and stores\nthem in the relay log. The SQL thread reads events from the relay log\nand executes them. START SLAVE requires the SUPER privilege.\n\nIf START SLAVE succeeds in starting the slave threads, it returns\nwithout any error. However, even in that case, it might be that the\nslave threads start and then later stop (for example, because they do\nnot manage to connect to the master or read its binary log, or some\nother problem). START SLAVE does not warn you about this. You must\ncheck the slave\'s error log for error messages generated by the slave\nthreads, or check that they are running satisfactorily with SHOW SLAVE\nSTATUS.\n\nURL: https://mariadb.com/kb/en/start-slave/\n\n','','https://mariadb.com/kb/en/start-slave/'),(325,'AREA',2,'Area(poly)\n\nReturns as a double-precision number the area of the Polygon value\npoly, as measured in its spatial reference system.\n\nURL: https://mariadb.com/kb/en/area/\n\n','MariaDB> SET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))\';\nMariaDB> SELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n','https://mariadb.com/kb/en/area/'),(326,'FLUSH',26,'Syntax:\nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n\nThe FLUSH statement has several variant forms that clear or reload\nvarious internal caches, flush tables, or acquire locks. To execute\nFLUSH, you must have the RELOAD privilege. Specific flush options might\nrequire additional privileges, as described later.\n\nBy default, the server writes FLUSH statements to the binary log so\nthat they replicate to replication slaves. To suppress logging, use the\noptional NO_WRITE_TO_BINLOG keyword or its alias LOCAL.\n\n*Note*: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH\nREAD LOCK (with or without a table list) are not written to the binary\nlog in any case because they would cause problems if replicated to a\nslave.\n\nThe FLUSH statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nThe RESET statement is similar to FLUSH. See [HELP RESET], for\ninformation about using the RESET statement with replication.\n\nURL: https://mariadb.com/kb/en/flush/\n\n','','https://mariadb.com/kb/en/flush/'),(327,'BEGIN END',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\nBEGIN ... END syntax is used for writing compound statements, which can\nappear within stored programs (stored procedures and functions,\ntriggers, and events). A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords. statement_list\nrepresents a list of one or more statements, each terminated by a\nsemicolon (;) statement delimiter. The statement_list itself is\noptional, so the empty compound statement (BEGIN END) is legal.\n\nBEGIN ... END blocks can be nested.\n\nUse of multiple statements requires that a client is able to send\nstatement strings containing the ; statement delimiter. In the mysql\ncommand-line client, this is handled with the delimiter command.\nChanging the ; end-of-statement delimiter (for example, to //) permit ;\nto be used in a program body. For an example, see\nhttps://mariadb.com/kb/en/stored-procedure-overview/.\n\nA BEGIN ... END block can be labeled. See [HELP labels].\n\nURL: https://mariadb.com/kb/en/begin-end/\n\n','','https://mariadb.com/kb/en/begin-end/'),(328,'SHOW PROCEDURE STATUS',26,'Syntax:\nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is a MySQL extension. It returns characteristics of a\nstored procedure, such as the database, name, type, creator, creation\nand modification dates, and character set information. A similar\nstatement, SHOW FUNCTION STATUS, displays information about stored\nfunctions (see [HELP SHOW FUNCTION STATUS]).\n\nThe LIKE clause, if present, indicates which procedure or function\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show-procedure-status/\n\n','MariaDB> SHOW PROCEDURE STATUS LIKE \'sp1\'\\G\n*************************** 1. row ***************************\n Db: test\n Name: sp1\n Type: PROCEDURE\n Definer: testuser@localhost\n Modified: 2004-08-03 15:29:37\n Created: 2004-08-03 15:29:37\n Security_type: DEFINER\n Comment:\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-procedure-status/'),(329,'DESCRIBE',28,'Syntax:\n{DESCRIBE | DESC} tbl_name [col_name | wild]\n\nDESCRIBE provides information about the columns in a table. It is a\nshortcut for SHOW COLUMNS FROM. These statements also display\ninformation for views. (See [HELP SHOW COLUMNS].)\n\ncol_name can be a column name, or a string containing the SQL \"%\" and\n\"_\" wildcard characters to obtain output only for the columns with\nnames matching the string. There is no need to enclose the string\nwithin quotation marks unless it contains spaces or other special\ncharacters.\n\nMariaDB> DESCRIBE City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nThe description for SHOW COLUMNS provides more information about the\noutput columns (see [HELP SHOW COLUMNS]).\n\nURL: https://mariadb.com/kb/en/describe/\n\n','','https://mariadb.com/kb/en/describe/'),(330,'SHOW WARNINGS',26,'Syntax:\nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW COUNT(*) WARNINGS\n\nSHOW WARNINGS shows information about the conditions (errors, warnings,\nand notes) that resulted from the last statement in the current session\nthat generated messages. It shows nothing if the last statement used a\ntable and generated no messages. (That is, a statement that uses a\ntable but generates no messages clears the message list.) Statements\nthat do not use tables and do not generate messages have no effect on\nthe message list.\n\nWarnings are generated for DML statements such as INSERT, UPDATE, and\nLOAD DATA INFILE as well as DDL statements such as CREATE TABLE and\nALTER TABLE.\n\nSHOW WARNINGS is also used following EXPLAIN EXTENDED, to display the\nextra information generated by EXPLAIN when the EXTENDED keyword is\nused. See https://mariadb.com/kb/en/explain#explain-extended.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttps://mariadb.com/kb/en/select/.\n\nA related statement, SHOW ERRORS, shows only the error conditions (it\nexcludes warnings and notes). See [HELP SHOW ERRORS].\n\nThe SHOW COUNT(*) WARNINGS statement displays the total number of\nerrors, warnings, and notes. You can also retrieve this number from the\nwarning_count system variable:\n\nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n\nURL: https://mariadb.com/kb/en/show-warnings/\n\n','','https://mariadb.com/kb/en/show-warnings/'),(331,'DROP USER',10,'Syntax:\nDROP USER user [, user] ...\n\nThe DROP USER statement removes one or more MySQL accounts and their\nprivileges. It removes privilege rows for the account from all grant\ntables. To use this statement, you must have the global CREATE USER\nprivilege or the DELETE privilege for the mysql database. Each account\nname uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. For example:\n\nDROP USER \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nURL: https://mariadb.com/kb/en/drop-user/\n\n','','https://mariadb.com/kb/en/drop-user/'),(332,'STDDEV_POP',16,'Syntax:\nSTDDEV_POP(expr)\n\nReturns the population standard deviation of expr (the square root of\nVAR_POP()). You can also use STD() or STDDEV(), which are equivalent\nbut not standard SQL.\n\nSTDDEV_POP() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev_pop/\n\n','','https://mariadb.com/kb/en/stddev_pop/'),(333,'SHOW CHARACTER SET',26,'Syntax:\nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n\nThe SHOW CHARACTER SET statement shows all available character sets.\nThe LIKE clause, if present, indicates which character set names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n\nURL: https://mariadb.com/kb/en/show-character-set/\n\n','','https://mariadb.com/kb/en/show-character-set/'),(334,'SUBSTRING',37,'Syntax:\nSUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n\nThe forms without a len argument return a substring from string str\nstarting at position pos. The forms with a len argument return a\nsubstring len characters long from string str, starting at position\npos. The forms that use FROM are standard SQL syntax. It is also\npossible to use a negative value for pos. In this case, the beginning\nof the substring is pos characters from the end of the string, rather\nthan the beginning. A negative value may be used for pos in any of the\nforms of this function.\n\nFor all forms of SUBSTRING(), the position of the first character in\nthe string from which the substring is to be extracted is reckoned as\n1.\n\nURL: https://mariadb.com/kb/en/substring/\n\n','MariaDB> SELECT SUBSTRING(\'Quadratically\',5);\n -> \'ratically\'\nMariaDB> SELECT SUBSTRING(\'foobarbar\' FROM 4);\n -> \'barbar\'\nMariaDB> SELECT SUBSTRING(\'Quadratically\',5,6);\n -> \'ratica\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -3);\n -> \'ila\'\nMariaDB> SELECT SUBSTRING(\'Sakila\', -5, 3);\n -> \'aki\'\nMariaDB> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);\n -> \'ki\'\n','https://mariadb.com/kb/en/substring/'),(335,'ISEMPTY',36,'IsEmpty(g)\n\nReturns 1 if the geometry value g is the empty geometry, 0 if it is not\nempty, and -1 if the argument is NULL. If the geometry is empty, it\nrepresents the empty point set.\n\nURL: https://mariadb.com/kb/en/isempty/\n\n','','https://mariadb.com/kb/en/isempty/'),(336,'SHOW FUNCTION STATUS',26,'Syntax:\nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is similar to SHOW PROCEDURE STATUS but for stored\nfunctions. See [HELP SHOW PROCEDURE STATUS].\n\nURL: https://mariadb.com/kb/en/show-function-status/\n\n','','https://mariadb.com/kb/en/show-function-status/'),(337,'LTRIM',37,'Syntax:\nLTRIM(str)\n\nReturns the string str with leading space characters removed.\n\nURL: https://mariadb.com/kb/en/ltrim/\n\n','MariaDB> SELECT LTRIM(\' barbar\');\n -> \'barbar\'\n','https://mariadb.com/kb/en/ltrim/'),(338,'INTERSECTS',30,'Intersects(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially intersects g2.\n\nURL: https://mariadb.com/kb/en/intersects/\n\n','','https://mariadb.com/kb/en/intersects/'),(339,'CALL',27,'Syntax:\nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n\nThe CALL statement invokes a stored procedure that was defined\npreviously with CREATE PROCEDURE.\n\nStored procedures that take no arguments can be invoked without\nparentheses. That is, CALL p() and CALL p are equivalent.\n\nCALL can pass back values to its caller using parameters that are\ndeclared as OUT or INOUT parameters. When the procedure returns, a\nclient program can also obtain the number of rows affected for the\nfinal statement executed within the routine: At the SQL level, call the\nROW_COUNT() function; from the C API, call the mysql_affected_rows()\nfunction.\n\nURL: https://mariadb.com/kb/en/call/\n\n','','https://mariadb.com/kb/en/call/'),(340,'MBRDISJOINT',6,'MBRDisjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are disjoint (do not intersect).\n\nURL: https://mariadb.com/kb/en/mbrdisjoint/\n\n','','https://mariadb.com/kb/en/mbrdisjoint/'),(341,'VALUES',14,'Syntax:\nVALUES(col_name)\n\nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the\nVALUES(col_name) function in the UPDATE clause to refer to column\nvalues from the INSERT portion of the statement. In other words,\nVALUES(col_name) in the UPDATE clause refers to the value of col_name\nthat would be inserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts. The VALUES()\nfunction is meaningful only in the ON DUPLICATE KEY UPDATE clause of\nINSERT statements and returns NULL otherwise. See\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/.\n\nURL: https://mariadb.com/kb/en/values/\n\n','MariaDB> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n','https://mariadb.com/kb/en/values/'),(342,'SUBSTRING_INDEX',37,'Syntax:\nSUBSTRING_INDEX(str,delim,count)\n\nReturns the substring from string str before count occurrences of the\ndelimiter delim. If count is positive, everything to the left of the\nfinal delimiter (counting from the left) is returned. If count is\nnegative, everything to the right of the final delimiter (counting from\nthe right) is returned. SUBSTRING_INDEX() performs a case-sensitive\nmatch when searching for delim.\n\nURL: https://mariadb.com/kb/en/substring_index/\n\n','MariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2);\n -> \'www.mariadb\'\nMariaDB> SELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2);\n -> \'mariadb.org\'\n','https://mariadb.com/kb/en/substring_index/'),(343,'ENCODE',12,'Syntax:\nENCODE(str,pass_str)\n\nEncrypt str using pass_str as the password. To decrypt the result, use\nDECODE().\n\nThe result is a binary string of the same length as str.\n\nThe strength of the encryption is based on how good the random\ngenerator is. It should suffice for short strings.\n\nURL: https://mariadb.com/kb/en/encode/\n\n','','https://mariadb.com/kb/en/encode/'),(344,'LOOP',23,'Syntax:\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\nLOOP implements a simple loop construct, enabling repeated execution of\nthe statement list, which consists of one or more statements, each\nterminated by a semicolon (;) statement delimiter. The statements\nwithin the loop are repeated until the loop is terminated. Usually,\nthis is accomplished with a LEAVE statement. Within a stored function,\nRETURN can also be used, which exits the function entirely.\n\nNeglecting to include a loop-termination statement results in an\ninfinite loop.\n\nA LOOP statement can be labeled. For the rules regarding label use, see\n[HELP labels].\n\nURL: https://mariadb.com/kb/en/loop/\n\n','CREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN\n ITERATE label1;\n END IF;\n LEAVE label1;\n END LOOP label1;\n SET @x = p1;\nEND;\n','https://mariadb.com/kb/en/loop/'),(345,'TRUNCATE',4,'Syntax:\nTRUNCATE(X,D)\n\nReturns the number X, truncated to D decimal places. If D is 0, the\nresult has no decimal point or fractional part. D can be negative to\ncause D digits left of the decimal point of the value X to become zero.\n\nURL: https://mariadb.com/kb/en/truncate/\n\n','MariaDB> SELECT TRUNCATE(1.223,1);\n -> 1.2\nMariaDB> SELECT TRUNCATE(1.999,1);\n -> 1.9\nMariaDB> SELECT TRUNCATE(1.999,0);\n -> 1\nMariaDB> SELECT TRUNCATE(-1.999,1);\n -> -1.9\nMariaDB> SELECT TRUNCATE(122,-2);\n -> 100\nMariaDB> SELECT TRUNCATE(10.28*100,0);\n -> 1028\n','https://mariadb.com/kb/en/truncate/'),(346,'TIMESTAMPADD',31,'Syntax:\nTIMESTAMPADD(unit,interval,datetime_expr)\n\nAdds the integer expression interval to the date or datetime expression\ndatetime_expr. The unit for interval is given by the unit argument,\nwhich should be one of the following values: MICROSECOND\n(microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or\nYEAR.\n\nIt is possible to use FRAC_SECOND in place of MICROSECOND, but\nFRAC_SECOND is deprecated. FRAC_SECOND was removed in MySQL 5.5.3.\n\nThe unit value may be specified using one of keywords as shown, or with\na prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY both are legal.\n\nURL: https://mariadb.com/kb/en/timestampadd/\n\n','MariaDB> SELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n -> \'2003-01-02 00:01:00\'\nMariaDB> SELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n -> \'2003-01-09\'\n','https://mariadb.com/kb/en/timestampadd/'),(347,'SHOW',26,'SHOW has many forms that provide information about databases, tables,\ncolumns, or status information about the server. This section describes\nthose following:\n\nSHOW AUTHORS\nSHOW {BINARY | MASTER} LOGS\nSHOW BINLOG EVENTS [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE FUNCTION func_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW MASTER STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW SLAVE HOSTS\nSHOW SLAVE STATUS\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW [FULL] TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n\nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n\nIf the syntax for a given SHOW statement includes a LIKE \'pattern\'\npart, \'pattern\' is a string that can contain the SQL \"%\" and \"_\"\nwildcard characters. The pattern is useful for restricting statement\noutput to matching values.\n\nSeveral SHOW statements also accept a WHERE clause that provides more\nflexibility in specifying which rows to display. See\nhttps://mariadb.com/kb/en/extended-show/.\n\nURL: https://mariadb.com/kb/en/show/\n\n','','https://mariadb.com/kb/en/show/'),(348,'GREATEST',18,'Syntax:\nGREATEST(value1,value2,...)\n\nWith two or more arguments, returns the largest (maximum-valued)\nargument. The arguments are compared using the same rules as for\nLEAST().\n\nURL: https://mariadb.com/kb/en/greatest/\n\n','MariaDB> SELECT GREATEST(2,0);\n -> 2\nMariaDB> SELECT GREATEST(34.0,3.0,5.0,767.0);\n -> 767.0\nMariaDB> SELECT GREATEST(\'B\',\'A\',\'C\');\n -> \'C\'\n','https://mariadb.com/kb/en/greatest/'),(349,'SHOW VARIABLES',26,'Syntax:\nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW VARIABLES shows the values of MySQL system variables. This\ninformation also can be obtained using the mysqladmin variables\ncommand. The LIKE clause, if present, indicates which variable names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttps://mariadb.com/kb/en/extended-show/. This\nstatement does not require any privilege. It requires only the ability\nto connect to the server.\n\nWith the GLOBAL modifier, SHOW VARIABLES displays the values that are\nused for new connections to MySQL. As of MySQL 5.5.3, if a variable has\nno global value, no value is displayed. Before 5.5.3, the session value\nis displayed. With SESSION, SHOW VARIABLES displays the values that are\nin effect for the current connection. If no modifier is present, the\ndefault is SESSION. LOCAL is a synonym for SESSION.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern. To obtain the row for a\nspecific variable, use a LIKE clause as shown:\n\nSHOW VARIABLES LIKE \'max_join_size\';\nSHOW SESSION VARIABLES LIKE \'max_join_size\';\n\nTo get a list of variables whose name match a pattern, use the \"%\"\nwildcard character in a LIKE clause:\n\nSHOW VARIABLES LIKE \'%size%\';\nSHOW GLOBAL VARIABLES LIKE \'%size%\';\n\nWildcard characters can be used in any position within the pattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard that matches\nany single character, you should escape it as \"\\_\" to match it\nliterally. In practice, this is rarely necessary.\n\nURL: https://mariadb.com/kb/en/show-variables/\n\n','','https://mariadb.com/kb/en/show-variables/'),(350,'BINLOG',26,'Syntax:\nBINLOG \'str\'\n\nBINLOG is an internal-use statement. It is generated by the mysqlbinlog\nprogram as the printable representation of certain events in binary log\nfiles. (See https://mariadb.com/kb/en/mysqlbinlog/.)\nThe \'str\' value is a base 64-encoded string the that server decodes to\ndetermine the data change indicated by the corresponding event. This\nstatement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/binlog/\n\n','','https://mariadb.com/kb/en/binlog/'),(351,'BIT_AND',16,'Syntax:\nBIT_AND(expr)\n\nReturns the bitwise AND of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: https://mariadb.com/kb/en/bit_and/\n\n','','https://mariadb.com/kb/en/bit_and/'),(352,'SECOND',31,'Syntax:\nSECOND(time)\n\nReturns the second for time, in the range 0 to 59.\n\nURL: https://mariadb.com/kb/en/second/\n\n','MariaDB> SELECT SECOND(\'10:05:03\');\n -> 3\n','https://mariadb.com/kb/en/second/'),(353,'ATAN2',4,'Syntax:\nATAN(Y,X), ATAN2(Y,X)\n\nReturns the arc tangent of the two variables X and Y. It is similar to\ncalculating the arc tangent of Y / X, except that the signs of both\narguments are used to determine the quadrant of the result.\n\nURL: https://mariadb.com/kb/en/atan2/\n\n','MariaDB> SELECT ATAN(-2,2);\n -> -0.78539816339745\nMariaDB> SELECT ATAN2(PI(),0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/atan2/'),(354,'MBRCONTAINS',6,'MBRContains(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\ncontains the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRWithin().\n\nURL: https://mariadb.com/kb/en/mbrcontains/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Point(1 1)\');\nMariaDB> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n','https://mariadb.com/kb/en/mbrcontains/'),(355,'HOUR',31,'Syntax:\nHOUR(time)\n\nReturns the hour for time. The range of the return value is 0 to 23 for\ntime-of-day values. However, the range of TIME values actually is much\nlarger, so HOUR can return values greater than 23.\n\nURL: https://mariadb.com/kb/en/hour/\n\n','MariaDB> SELECT HOUR(\'10:05:03\');\n -> 10\nMariaDB> SELECT HOUR(\'272:59:59\');\n -> 272\n','https://mariadb.com/kb/en/hour/'),(356,'SELECT',27,'Syntax:\nSELECT\n [ALL | DISTINCT | DISTINCTROW ]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position}\n [ASC | DESC], ... [WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position}\n [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n [PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n export_options\n | INTO DUMPFILE \'file_name\'\n | INTO var_name [, var_name]]\n [FOR UPDATE | LOCK IN SHARE MODE]]\n\nSELECT is used to retrieve rows selected from one or more tables, and\ncan include UNION statements and subqueries. See [HELP UNION], and\nhttps://mariadb.com/kb/en/subqueries/.\n\nThe most commonly used clauses of SELECT statements are these:\n\no Each select_expr indicates a column that you want to retrieve. There\n must be at least one select_expr.\n\no table_references indicates the table or tables from which to retrieve\n rows. Its syntax is described in [HELP JOIN].\n\no The WHERE clause, if given, indicates the condition or conditions\n that rows must satisfy to be selected. where_condition is an\n expression that evaluates to true for each row to be selected. The\n statement selects all rows if there is no WHERE clause.\n\n In the WHERE expression, you can use any of the functions and\n operators that MySQL supports, except for aggregate (summary)\n functions. See\n https://mariadb.com/kb/en/select#select-expressions, and\n https://mariadb.com/kb/en/functions-and-operators/.\n\nSELECT can also be used to retrieve rows computed without reference to\nany table.\n\nURL: https://mariadb.com/kb/en/select/\n\n','','https://mariadb.com/kb/en/select/'),(357,'COT',4,'Syntax:\nCOT(X)\n\nReturns the cotangent of X.\n\nURL: https://mariadb.com/kb/en/cot/\n\n','MariaDB> SELECT COT(12);\n -> -1.5726734063977\nMariaDB> SELECT COT(0);\n -> NULL\n','https://mariadb.com/kb/en/cot/'),(358,'SHOW CREATE EVENT',26,'Syntax:\nSHOW CREATE EVENT event_name\n\nThis statement displays the CREATE EVENT statement needed to re-create\na given event. It requires the EVENT privilege for the database from\nwhich the event is to be shown. For example (using the same event\ne_daily defined and then altered in [HELP SHOW EVENTS]):\n\nURL: https://mariadb.com/kb/en/show-create-event/\n\n','MariaDB> SHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row ***************************\n Event: e_daily\n sql_mode:\n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*)\n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','https://mariadb.com/kb/en/show-create-event/'),(359,'LOAD_FILE',37,'Syntax:\nLOAD_FILE(file_name)\n\nReads the file and returns the file contents as a string. To use this\nfunction, the file must be located on the server host, you must specify\nthe full path name to the file, and you must have the FILE privilege.\nThe file must be readable by all and its size less than\nmax_allowed_packet bytes. If the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nIf the file does not exist or cannot be read because one of the\npreceding conditions is not satisfied, the function returns NULL.\n\nThe character_set_filesystem system variable controls interpretation of\nfile names that are given as literal strings.\n\nURL: https://mariadb.com/kb/en/load_file/\n\n','MariaDB> UPDATE t\n SET blob_col=LOAD_FILE(\'/tmp/picture\')\n WHERE id=1;\n','https://mariadb.com/kb/en/load_file/'),(360,'POINTFROMTEXT',3,'PointFromText(wkt[,srid])\n\nConstructs a POINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromtext/\n\n','','https://mariadb.com/kb/en/pointfromtext/'),(361,'GROUP_CONCAT',16,'Syntax:\nGROUP_CONCAT(expr)\n\nThis function returns a string result with the concatenated non-NULL\nvalues from a group. It returns NULL if there are no non-NULL values.\nThe full syntax is as follows:\n\nGROUP_CONCAT([DISTINCT] expr [,expr ...]\n [ORDER BY {unsigned_integer | col_name | expr}\n [ASC | DESC] [,col_name ...]]\n [SEPARATOR str_val])\n\nURL: https://mariadb.com/kb/en/group_concat/\n\n','MariaDB> SELECT student_name,\n -> GROUP_CONCAT(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/group_concat/'),(362,'DATE_FORMAT',31,'Syntax:\nDATE_FORMAT(date,format)\n\nFormats the date value according to the format string.\n\nURL: https://mariadb.com/kb/en/date_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n -> \'Sunday October 2009\'\nMariaDB> SELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n -> \'22:23:00\'\nMariaDB> SELECT DATE_FORMAT(\'1900-10-04 22:23:00\',\n -> \'%D %y %a %d %m %b %j\');\n -> \'4th 00 Thu 04 10 Oct 277\'\nMariaDB> SELECT DATE_FORMAT(\'1997-10-04 22:23:00\',\n -> \'%H %k %I %r %T %S %w\');\n -> \'22 22 10 10:23:00 PM 22:23:00 00 6\'\nMariaDB> SELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n -> \'1998 52\'\nMariaDB> SELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n -> \'00\'\n','https://mariadb.com/kb/en/date_format/'),(363,'BENCHMARK',17,'Syntax:\nBENCHMARK(count,expr)\n\nThe BENCHMARK() function executes the expression expr repeatedly count\ntimes. It may be used to time how quickly MySQL processes the\nexpression. The result value is always 0. The intended use is from\nwithin the mysql client, which reports query execution times:\n\nURL: https://mariadb.com/kb/en/benchmark/\n\n','MariaDB> SELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (4.74 sec)\n','https://mariadb.com/kb/en/benchmark/'),(364,'YEAR',31,'Syntax:\nYEAR(date)\n\nReturns the year for date, in the range 1000 to 9999, or 0 for the\n\"zero\" date.\n\nURL: https://mariadb.com/kb/en/year/\n\n','MariaDB> SELECT YEAR(\'1987-01-01\');\n -> 1987\n','https://mariadb.com/kb/en/year/'),(365,'SHOW ENGINE',26,'Syntax:\nSHOW ENGINE engine_name {STATUS | MUTEX}\n\nSHOW ENGINE displays operational information about a storage engine.\nThe following statements currently are supported:\n\nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n\nSHOW ENGINE INNODB STATUS displays extensive information from the\nstandard InnoDB Monitor about the state of the InnoDB storage engine.\nFor information about the standard monitor and other InnoDB Monitors\nthat provide information about InnoDB processing, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-monitors.html.\n\nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics. The\nstatement displays the following fields:\n\no Type\n\n Always InnoDB.\n\no Name\n\n The source file where the mutex is implemented, and the line number\n in the file where the mutex is created. The line number may change\n depending on your version of MySQL.\n\no Status\n\n The mutex status. This field displays several values if UNIV_DEBUG\n was defined at MySQL compilation time (for example, in include/univ.i\n in the InnoDB part of the MySQL source tree). If UNIV_DEBUG was not\n defined, the statement displays only the os_waits value. In the\n latter case (without UNIV_DEBUG), the information on which the output\n is based is insufficient to distinguish regular mutexes and mutexes\n that protect rw-locks (which permit multiple readers or a single\n writer). Consequently, the output may appear to contain multiple rows\n for the same mutex.\n\n o count indicates how many times the mutex was requested.\n\n o spin_waits indicates how many times the spinlock had to run.\n\n o spin_rounds indicates the number of spinlock rounds. (spin_rounds\n divided by spin_waits provides the average round count.)\n\n o os_waits indicates the number of operating system waits. This\n occurs when the spinlock did not work (the mutex was not locked\n during the spinlock and it was necessary to yield to the operating\n system and wait).\n\n o os_yields indicates the number of times a the thread trying to lock\n a mutex gave up its timeslice and yielded to the operating system\n (on the presumption that permitting other threads to run will free\n the mutex so that it can be locked).\n\n o os_wait_times indicates the amount of time (in ms) spent in\n operating system waits, if the timed_mutexes system variable is 1\n (ON). If timed_mutexes is 0 (OFF), timing is disabled, so\n os_wait_times is 0. timed_mutexes is off by default.\n\nInformation from this statement can be used to diagnose system\nproblems. For example, large values of spin_waits and spin_rounds may\nindicate scalability problems.\n\nUse SHOW ENGINE PERFORMANCE_SCHEMA STATUS to inspect the internal\noperation of the Performance Schema code:\n\nMariaDB> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\\G\n...\n*************************** 3. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_size\nStatus: 76\n*************************** 4. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_count\nStatus: 10000\n*************************** 5. row ***************************\n Type: performance_schema\n Name: events_waits_history.memory\nStatus: 760000\n...\n*************************** 57. row ***************************\n Type: performance_schema\n Name: performance_schema.memory\nStatus: 26459600\n...\n\nThe intent of this statement is to help the DBA to understand the\neffects that different options have on memory requirements.\n\nName values consist of two parts, which name an internal buffer and an\nattribute of the buffer, respectively:\n\no Internal buffers that are exposed as a table in the\n performance_schema database are named after the table. Examples:\n events_waits_history.row_size, mutex_instances.row_count.\n\no Internal buffers that are not exposed as a table are named within\n parentheses. Examples: (pfs_cond_class).row_size,\n (pfs_mutex_class).memory.\n\no Values that apply to the Performance Schema as a whole begin with\n performance_schema. Example: performance_schema.memory.\n\nAttributes have these meanings:\n\no row_size cannot be changed. It is the size of the internal record\n used by the implementation.\n\no row_count can be changed depending on the configuration options.\n\no For a table, tbl_name.memory is the product of row_size multiplied by\n row_count. For the Performance Schema as a whole,\n performance_schema.memory is the sum of all the memory used (the sum\n of all other memory values).\n\nIn some cases, there is a direct relationship between a configuration\nparameter and a SHOW ENGINE value. For example,\nevents_waits_history_long.row_count corresponds to\nperformance_schema_events_waits_history_long_size. In other cases, the\nrelationship is more complex. For example,\nevents_waits_history.row_count corresponds to\nperformance_schema_events_waits_history_size (the number of rows per\nthread) multiplied by performance_schema_max_thread_instances ( the\nnumber of threads).\n\nURL: https://mariadb.com/kb/en/show-engine/\n\n','','https://mariadb.com/kb/en/show-engine/'),(366,'NAME_CONST',14,'Syntax:\nNAME_CONST(name,value)\n\nReturns the given value. When used to produce a result set column,\nNAME_CONST() causes the column to have the given name. The arguments\nshould be constants.\n\nMariaDB> SELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n\nURL: https://mariadb.com/kb/en/name_const/\n\n','','https://mariadb.com/kb/en/name_const/'),(367,'RELEASE_LOCK',14,'Syntax:\nRELEASE_LOCK(str)\n\nReleases the lock named by the string str that was obtained with\nGET_LOCK(). Returns 1 if the lock was released, 0 if the lock was not\nestablished by this thread (in which case the lock is not released),\nand NULL if the named lock did not exist. The lock does not exist if it\nwas never obtained by a call to GET_LOCK() or if it has previously been\nreleased.\n\nThe DO statement is convenient to use with RELEASE_LOCK(). See [HELP\nDO].\n\nURL: https://mariadb.com/kb/en/release_lock/\n\n','','https://mariadb.com/kb/en/release_lock/'),(368,'IS NULL',18,'Syntax:\nIS NULL\n\nTests whether a value is NULL.\n\nURL: https://mariadb.com/kb/en/is-null/\n\n','MariaDB> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n -> 0, 0, 1\n','https://mariadb.com/kb/en/is-null/'),(369,'CONVERT_TZ',31,'Syntax:\nCONVERT_TZ(dt,from_tz,to_tz)\n\nCONVERT_TZ() converts a datetime value dt from the time zone given by\nfrom_tz to the time zone given by to_tz and returns the resulting\nvalue. Time zones are specified as described in\nhttps://mariadb.com/kb/en/time-zones/. This\nfunction returns NULL if the arguments are invalid.\n\nURL: https://mariadb.com/kb/en/convert_tz/\n\n','MariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'GMT\',\'MET\');\n -> \'2004-01-01 13:00:00\'\nMariaDB> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'+00:00\',\'+10:00\');\n -> \'2004-01-01 22:00:00\'\n','https://mariadb.com/kb/en/convert_tz/'),(370,'TIME_TO_SEC',31,'Syntax:\nTIME_TO_SEC(time)\n\nReturns the time argument, converted to seconds.\n\nURL: https://mariadb.com/kb/en/time_to_sec/\n\n','MariaDB> SELECT TIME_TO_SEC(\'22:23:00\');\n -> 80580\nMariaDB> SELECT TIME_TO_SEC(\'00:39:38\');\n -> 2378\n','https://mariadb.com/kb/en/time_to_sec/'),(371,'WEEKDAY',31,'Syntax:\nWEEKDAY(date)\n\nReturns the weekday index for date (0 = Monday, 1 = Tuesday, ... 6 =\nSunday).\n\nURL: https://mariadb.com/kb/en/weekday/\n\n','MariaDB> SELECT WEEKDAY(\'2008-02-03 22:23:00\');\n -> 6\nMariaDB> SELECT WEEKDAY(\'2007-11-06\');\n -> 1\n','https://mariadb.com/kb/en/weekday/'),(372,'EXPORT_SET',37,'Syntax:\nEXPORT_SET(bits,on,off[,separator[,number_of_bits]])\n\nReturns a string such that for every bit set in the value bits, you get\nan on string and for every bit not set in the value, you get an off\nstring. Bits in bits are examined from right to left (from low-order to\nhigh-order bits). Strings are added to the result from left to right,\nseparated by the separator string (the default being the comma\ncharacter \",\"). The number of bits examined is given by number_of_bits,\nwhich has a default of 64 if not specified. number_of_bits is silently\nclipped to 64 if larger than 64. It is treated as an unsigned integer,\nso a value of -1 is effectively the same as 64.\n\nURL: https://mariadb.com/kb/en/export_set/\n\n','MariaDB> SELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n -> \'Y,N,Y,N\'\nMariaDB> SELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n -> \'0,1,1,0,0,0,0,0,0,0\'\n','https://mariadb.com/kb/en/export_set/'),(373,'ALTER SERVER',39,'Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. See [HELP CREATE\nSERVER]. The corresponding fields in the mysql.servers table are\nupdated accordingly. This statement requires the SUPER privilege.\n\nURL: https://mariadb.com/kb/en/alter-server/\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','https://mariadb.com/kb/en/alter-server/'),(374,'RESIGNAL',23,'Syntax:\nRESIGNAL [condition_value]\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nRESIGNAL passes on the error condition information that is available\nduring execution of a condition handler within a compound statement\ninside a stored procedure or function, trigger, or event. RESIGNAL may\nchange some or all information before passing it on. RESIGNAL is\nrelated to SIGNAL, but instead of originating a condition as SIGNAL\ndoes, RESIGNAL relays existing condition information, possibly after\nmodifying it.\n\nRESIGNAL makes it possible to both handle an error and return the error\ninformation. Otherwise, by executing an SQL statement within the\nhandler, information that caused the handler\'s activation is destroyed.\nRESIGNAL also can make some procedures shorter if a given handler can\nhandle part of a situation, then pass the condition \"up the line\" to\nanother handler.\n\nNo special privileges are required to execute the RESIGNAL statement.\n\nFor condition_value and signal_information_item, the definitions and\nrules are the same for RESIGNAL as for SIGNAL (see [HELP SIGNAL]).\n\nThe RESIGNAL statement takes condition_value and SET clauses, both of\nwhich are optional. This leads to several possible uses:\n\no RESIGNAL alone:\n\nRESIGNAL;\n\no RESIGNAL with new signal information:\n\nRESIGNAL SET signal_information_item [, signal_information_item] ...;\n\no RESIGNAL with a condition value and possibly new signal information:\n\nRESIGNAL condition_value\n [SET signal_information_item [, signal_information_item] ...];\n\nURL: https://mariadb.com/kb/en/resignal/\n\n','','https://mariadb.com/kb/en/resignal/'),(375,'TIME FUNCTION',31,'Syntax:\nTIME(expr)\n\nExtracts the time part of the time or datetime expression expr and\nreturns it as a string.\n\nURL: https://mariadb.com/kb/en/time-function/\n\n','MariaDB> SELECT TIME(\'2003-12-31 01:02:03\');\n -> \'01:02:03\'\nMariaDB> SELECT TIME(\'2003-12-31 01:02:03.000123\');\n -> \'01:02:03.000123\'\n','https://mariadb.com/kb/en/time-function/'),(376,'DATE_ADD',31,'Syntax:\nDATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)\n\nThese functions perform date arithmetic. The date argument specifies\nthe starting date or datetime value. expr is an expression specifying\nthe interval value to be added or subtracted from the starting date.\nexpr is a string; it may start with a \"-\" for negative intervals. unit\nis a keyword indicating the units in which the expression should be\ninterpreted.\n\nURL: https://mariadb.com/kb/en/date_add/\n\n','MariaDB> SELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n -> \'2009-01-01 00:00:00\'\nMariaDB> SELECT INTERVAL 1 DAY + \'2008-12-31\';\n -> \'2009-01-01\'\nMariaDB> SELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n -> \'2004-12-31 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2000-12-31 23:59:59\',\n -> INTERVAL 1 SECOND);\n -> \'2001-01-01 00:00:00\'\nMariaDB> SELECT DATE_ADD(\'2010-12-31 23:59:59\',\n -> INTERVAL 1 DAY);\n -> \'2011-01-01 23:59:59\'\nMariaDB> SELECT DATE_ADD(\'2100-12-31 23:59:59\',\n -> INTERVAL \'1:1\' MINUTE_SECOND);\n -> \'2101-01-01 00:01:00\'\nMariaDB> SELECT DATE_SUB(\'2005-01-01 00:00:00\',\n -> INTERVAL \'1 1:1:1\' DAY_SECOND);\n -> \'2004-12-30 22:58:59\'\nMariaDB> SELECT DATE_ADD(\'1900-01-01 00:00:00\',\n -> INTERVAL \'-1 10\' DAY_HOUR);\n -> \'1899-12-30 14:00:00\'\nMariaDB> SELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n -> \'1997-12-02\'\nMariaDB> SELECT DATE_ADD(\'1992-12-31 23:59:59.000002\',\n -> INTERVAL \'1.999999\' SECOND_MICROSECOND);\n -> \'1993-01-01 00:00:01.000001\'\n','https://mariadb.com/kb/en/date_add/'),(377,'CAST',37,'Syntax:\nCAST(expr AS type)\n\nThe CAST() function takes an expression of any type and produces a\nresult value of a specified type, similar to CONVERT(). See the\ndescription of CONVERT() for more information.\n\nURL: https://mariadb.com/kb/en/cast/\n\n','','https://mariadb.com/kb/en/cast/'),(378,'SOUNDS LIKE',37,'Syntax:\nexpr1 SOUNDS LIKE expr2\n\nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n\nURL: https://mariadb.com/kb/en/sounds-like/\n\n','','https://mariadb.com/kb/en/sounds-like/'),(379,'PERIOD_DIFF',31,'Syntax:\nPERIOD_DIFF(P1,P2)\n\nReturns the number of months between periods P1 and P2. P1 and P2\nshould be in the format YYMM or YYYYMM. Note that the period arguments\nP1 and P2 are not date values.\n\nURL: https://mariadb.com/kb/en/period_diff/\n\n','MariaDB> SELECT PERIOD_DIFF(200802,200703);\n -> 11\n','https://mariadb.com/kb/en/period_diff/'),(380,'LIKE',37,'Syntax:\nexpr LIKE pat [ESCAPE \'escape_char\']\n\nPattern matching using SQL simple regular expression comparison.\nReturns 1 (TRUE) or 0 (FALSE). If either expr or pat is NULL, the\nresult is NULL.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\nURL: https://mariadb.com/kb/en/like/\n\n','MariaDB> SELECT \'David!\' LIKE \'David_\';\n -> 1\nMariaDB> SELECT \'David!\' LIKE \'%D%v%\';\n -> 1\n','https://mariadb.com/kb/en/like/'),(381,'MULTIPOINT',24,'MultiPoint(pt1,pt2,...)\n\nConstructs a MultiPoint value using Point or WKB Point arguments.\n\nURL: https://mariadb.com/kb/en/multipoint/\n\n','','https://mariadb.com/kb/en/multipoint/'),(382,'>>',19,'Syntax:\n>>\n\nShifts a longlong (BIGINT) number to the right.\n\nURL: https://mariadb.com/kb/en/shift-right/\n\n','MariaDB> SELECT 4 >> 2;\n -> 1\n','https://mariadb.com/kb/en/shift-right/'),(383,'FETCH',23,'Syntax:\nFETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...\n\nThis statement fetches the next row for the SELECT statement associated\nwith the specified cursor (which must be open), and advances the cursor\npointer. If a row exists, the fetched columns are stored in the named\nvariables. The number of columns retrieved by the SELECT statement must\nmatch the number of output variables specified in the FETCH statement.\n\nIf no more rows are available, a No Data condition occurs with SQLSTATE\nvalue \'02000\'. To detect this condition, you can set up a handler for\nit (or for a NOT FOUND condition). For an example, see\nhttps://mariadb.com/kb/en/cursor-overview/.\n\nURL: https://mariadb.com/kb/en/fetch/\n\n','','https://mariadb.com/kb/en/fetch/'),(384,'AVG',16,'Syntax:\nAVG([DISTINCT] expr)\n\nReturns the average value of expr. The DISTINCT option can be used to\nreturn the average of the distinct values of expr.\n\nAVG() returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/avg/\n\n','MariaDB> SELECT student_name, AVG(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','https://mariadb.com/kb/en/avg/'),(385,'TRUE FALSE',29,'The constants TRUE and FALSE evaluate to 1 and 0, respectively. The\nconstant names can be written in any lettercase.\n\nMariaDB> SELECT TRUE, true, FALSE, false;\n -> 1, 1, 0, 0\n\nURL: https://mariadb.com/kb/en/true-false/\n\n','','https://mariadb.com/kb/en/true-false/'),(386,'MBRWITHIN',6,'MBRWithin(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\nis within the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRContains().\n\nURL: https://mariadb.com/kb/en/mbrwithin/\n\n','MariaDB> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nMariaDB> SET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nMariaDB> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n','https://mariadb.com/kb/en/mbrwithin/'),(387,'SESSION_USER',17,'Syntax:\nSESSION_USER()\n\nSESSION_USER() is a synonym for USER().\n\nURL: https://mariadb.com/kb/en/session_user/\n\n','','https://mariadb.com/kb/en/session_user/'),(388,'IN',18,'Syntax:\nexpr IN (value,...)\n\nReturns 1 if expr is equal to any of the values in the IN list, else\nreturns 0. If all values are constants, they are evaluated according to\nthe type of expr and sorted. The search for the item then is done using\na binary search. This means IN is very quick if the IN value list\nconsists entirely of constants. Otherwise, type conversion takes place\naccording to the rules described in\nhttps://mariadb.com/kb/en/type-conversion/, but\napplied to all the arguments.\n\nURL: https://mariadb.com/kb/en/in/\n\n','MariaDB> SELECT 2 IN (0,3,5,7);\n -> 0\nMariaDB> SELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n -> 1\n','https://mariadb.com/kb/en/in/'),(389,'QUOTE',37,'Syntax:\nQUOTE(str)\n\nQuotes a string to produce a result that can be used as a properly\nescaped data value in an SQL statement. The string is returned enclosed\nby single quotation marks and with each instance of backslash (\"\\\"),\nsingle quote (\"\'\"), ASCII NUL, and Control+Z preceded by a backslash.\nIf the argument is NULL, the return value is the word \"NULL\" without\nenclosing single quotation marks.\n\nURL: https://mariadb.com/kb/en/quote/\n\n','MariaDB> SELECT QUOTE(\'Don\\\'t!\');\n -> \'Don\\\'t!\'\nMariaDB> SELECT QUOTE(NULL);\n -> NULL\n','https://mariadb.com/kb/en/quote/'),(390,'HELP COMMAND',26,'Syntax:\nMariaDB> help search_string\n\nIf you provide an argument to the help command, mysql uses it as a\nsearch string to access server-side help from the contents of the MySQL\nReference Manual. The proper operation of this command requires that\nthe help tables in the mysql database be initialized with help topic\ninformation .\n\nIf there is no match for the search string, the search fails:\n\nMariaDB> help me\n\nNothing found\nPlease try to run \'help contents\' for a list of all accessible topics\n\nUse help contents to see a list of the help categories:\n\nMariaDB> help contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing categories:\n Account Management\n Administration\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Language Structure\n Plugins\n Storage Engines\n Stored Routines\n Table Maintenance\n Transactions\n Triggers\n\nIf the search string matches multiple items, mysql shows a list of\nmatching topics:\n\nMariaDB> help logs\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following topics:\n SHOW\n SHOW BINARY LOGS\n SHOW ENGINE\n SHOW LOGS\n\nUse a topic as the search string to see the help entry for that topic:\n\nMariaDB> help show binary logs\nName: \'SHOW BINARY LOGS\'\nDescription:\nSyntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [purge-binary-logs], that shows how\nto determine which logs can be purged.\n\nMariaDB> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: https://mariadb.com/kb/en/help-command/\n\n','','https://mariadb.com/kb/en/help-command/'),(391,'QUARTER',31,'Syntax:\nQUARTER(date)\n\nReturns the quarter of the year for date, in the range 1 to 4.\n\nURL: https://mariadb.com/kb/en/quarter/\n\n','MariaDB> SELECT QUARTER(\'2008-04-01\');\n -> 2\n','https://mariadb.com/kb/en/quarter/'),(392,'POSITION',37,'Syntax:\nPOSITION(substr IN str)\n\nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n\nURL: https://mariadb.com/kb/en/position/\n\n','','https://mariadb.com/kb/en/position/'),(393,'SHOW CREATE FUNCTION',26,'Syntax:\nSHOW CREATE FUNCTION func_name\n\nThis statement is similar to SHOW CREATE PROCEDURE but for stored\nfunctions. See [HELP SHOW CREATE PROCEDURE].\n\nURL: https://mariadb.com/kb/en/show-create-function/\n\n','','https://mariadb.com/kb/en/show-create-function/'),(394,'IS_USED_LOCK',14,'Syntax:\nIS_USED_LOCK(str)\n\nChecks whether the lock named str is in use (that is, locked). If so,\nit returns the connection identifier of the client that holds the lock.\nOtherwise, it returns NULL.\n\nURL: https://mariadb.com/kb/en/is_used_lock/\n\n','','https://mariadb.com/kb/en/is_used_lock/'),(395,'POLYFROMTEXT',3,'PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])\n\nConstructs a POLYGON value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/polyfromtext/\n\n','','https://mariadb.com/kb/en/polyfromtext/'),(396,'DES_ENCRYPT',12,'Syntax:\nDES_ENCRYPT(str[,{key_num|key_str}])\n\nEncrypts the string with the given key using the Triple-DES algorithm.\n\nThis function works only if MySQL has been configured with SSL support.\nSee https://mariadb.com/kb/en/ssl-connections/.\n\nThe encryption key to use is chosen based on the second argument to\nDES_ENCRYPT(), if one was given. With no argument, the first key from\nthe DES key file is used. With a key_num argument, the given key number\n(0 to 9) from the DES key file is used. With a key_str argument, the\ngiven key string is used to encrypt str.\n\nThe key file can be specified with the --des-key-file server option.\n\nThe return string is a binary string where the first character is\nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT() returns NULL.\n\nThe 128 is added to make it easier to recognize an encrypted key. If\nyou use a string key, key_num is 127.\n\nThe string length for the result is given by this formula:\n\nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n\nEach line in the DES key file has the following format:\n\nkey_num des_key_str\n\nEach key_num value must be a number in the range from 0 to 9. Lines in\nthe file may be in any order. des_key_str is the string that is used to\nencrypt the message. There should be at least one space between the\nnumber and the key. The first key is the default key that is used if\nyou do not specify any key argument to DES_ENCRYPT().\n\nYou can tell MySQL to read new key values from the key file with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD privilege.\n\nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted column\nvalues, without giving the end user the right to decrypt those values.\n\nURL: https://mariadb.com/kb/en/des_encrypt/\n\n','MariaDB> SELECT customer_address FROM customer_table \n > WHERE crypted_credit_card = DES_ENCRYPT(\'credit_card_number\');\n','https://mariadb.com/kb/en/des_encrypt/'),(397,'CEIL',4,'Syntax:\nCEIL(X)\n\nCEIL() is a synonym for CEILING().\n\nURL: https://mariadb.com/kb/en/ceil/\n\n','','https://mariadb.com/kb/en/ceil/'),(398,'LENGTH',37,'Syntax:\nLENGTH(str)\n\nReturns the length of the string str, measured in bytes. A multi-byte\ncharacter counts as multiple bytes. This means that for a string\ncontaining five 2-byte characters, LENGTH() returns 10, whereas\nCHAR_LENGTH() returns 5.\n\nURL: https://mariadb.com/kb/en/length/\n\n','MariaDB> SELECT LENGTH(\'text\');\n -> 4\n','https://mariadb.com/kb/en/length/'),(399,'STR_TO_DATE',31,'Syntax:\nSTR_TO_DATE(str,format)\n\nThis is the inverse of the DATE_FORMAT() function. It takes a string\nstr and a format string format. STR_TO_DATE() returns a DATETIME value\nif the format string contains both date and time parts, or a DATE or\nTIME value if the string contains only date or time parts. If the date,\ntime, or datetime value extracted from str is illegal, STR_TO_DATE()\nreturns NULL and produces a warning.\n\nThe server scans str attempting to match format to it. The format\nstring can contain literal characters and format specifiers beginning\nwith %. Literal characters in format must match literally in str.\nFormat specifiers in format must match a date or time part in str. For\nthe specifiers that can be used in format, see the DATE_FORMAT()\nfunction description.\n\nMariaDB> SELECT STR_TO_DATE(\'01,5,2013\',\'%d,%m,%Y\');\n -> \'2013-05-01\'\nMariaDB> SELECT STR_TO_DATE(\'May 1, 2013\',\'%M %d,%Y\');\n -> \'2013-05-01\'\n\nScanning starts at the beginning of str and fails if format is found\nnot to match. Extra characters at the end of str are ignored.\n\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'a%h:%i:%s\');\n -> \'09:30:17\'\nMariaDB> SELECT STR_TO_DATE(\'a09:30:17\',\'%h:%i:%s\');\n -> NULL\nMariaDB> SELECT STR_TO_DATE(\'09:30:17a\',\'%h:%i:%s\');\n -> \'09:30:17\'\n\nUnspecified date or time parts have a value of 0, so incompletely\nspecified values in str produce a result with some or all parts set to\n0:\n\nMariaDB> SELECT STR_TO_DATE(\'abc\',\'abc\');\n -> \'0000-00-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%m\');\n -> \'0000-09-00\'\nMariaDB> SELECT STR_TO_DATE(\'9\',\'%s\');\n -> \'00:00:09\'\n\nURL: https://mariadb.com/kb/en/str_to_date/\n\n','','https://mariadb.com/kb/en/str_to_date/'),(400,'Y',11,'Y(p)\n\nReturns the Y-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: https://mariadb.com/kb/en/y/\n\n','MariaDB> SELECT Y(POINT(56.7, 53.34));\n+-----------------------+\n| Y(POINT(56.7, 53.34)) |\n+-----------------------+\n| 53.34 |\n+-----------------------+\n','https://mariadb.com/kb/en/y/'),(401,'CHECKSUM TABLE',20,'Syntax:\nCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]\n\nCHECKSUM TABLE reports a table checksum. This statement requires the\nSELECT privilege for the table.\n\nWith QUICK, the live table checksum is reported if it is available, or\nNULL otherwise. This is very fast. A live checksum is enabled by\nspecifying the CHECKSUM=1 table option when you create the table;\ncurrently, this is supported only for MyISAM tables. See [HELP CREATE\nTABLE].\n\nWith EXTENDED, the entire table is read row by row and the checksum is\ncalculated. This can be very slow for large tables.\n\nIf neither QUICK nor EXTENDED is specified, MySQL returns a live\nchecksum if the table storage engine supports it and scans the table\notherwise.\n\nFor a nonexistent table, CHECKSUM TABLE returns NULL and generates a\nwarning.\n\nIn MySQL 5.5, CHECKSUM TABLE returns 0 for partitioned tables unless\nyou include the EXTENDED option. This issue is resolved in MySQL 5.6.\n(Bug #11933226, Bug #60681)\n\nThe checksum value depends on the table row format. If the row format\nchanges, the checksum also changes. For example, the storage format for\nVARCHAR changed between MySQL 4.1 and 5.0, so if a 4.1 table is\nupgraded to MySQL 5.0, the checksum value may change.\n\nURL: https://mariadb.com/kb/en/checksum-table/\n\n','','https://mariadb.com/kb/en/checksum-table/'),(402,'NUMINTERIORRINGS',2,'NumInteriorRings(poly)\n\nReturns the number of interior rings in the Polygon value poly.\n\nURL: https://mariadb.com/kb/en/numinteriorrings/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n','https://mariadb.com/kb/en/numinteriorrings/'),(403,'INTERIORRINGN',2,'InteriorRingN(poly,N)\n\nReturns the N-th interior ring for the Polygon value poly as a\nLineString. Rings are numbered beginning with 1.\n\nURL: https://mariadb.com/kb/en/interiorringn/\n\n','MariaDB> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nMariaDB> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n','https://mariadb.com/kb/en/interiorringn/'),(404,'UTC_TIME',31,'Syntax:\nUTC_TIME, UTC_TIME()\n\nReturns the current UTC time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_time/\n\n','MariaDB> SELECT UTC_TIME(), UTC_TIME() + 0;\n -> \'18:07:53\', 180753.000000\n','https://mariadb.com/kb/en/utc_time/'),(405,'DROP FUNCTION',39,'The DROP FUNCTION statement is used to drop stored functions and\nuser-defined functions (UDFs):\n\no For information about dropping stored functions, see [HELP DROP\n PROCEDURE].\n\no For information about dropping user-defined functions, see [HELP DROP\n FUNCTION UDF].\n\nURL: https://mariadb.com/kb/en/drop-function/\n\n','','https://mariadb.com/kb/en/drop-function/'),(406,'ALTER EVENT',39,'Syntax:\nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO event_body]\n\nThe ALTER EVENT statement changes one or more of the characteristics of\nan existing event without the need to drop and recreate it. The syntax\nfor each of the DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE /\nDISABLE, and DO clauses is exactly the same as when used with CREATE\nEVENT. (See [HELP CREATE EVENT].)\n\nAny user can alter an event defined on a database for which that user\nhas the EVENT privilege. When a user executes a successful ALTER EVENT\nstatement, that user becomes the definer for the affected event.\n\nALTER EVENT works only with an existing event:\n\nMariaDB> ALTER EVENT no_such_event \n > ON SCHEDULE \n > EVERY \'2:3\' DAY_HOUR;\nERROR 1517 (HY000): Unknown event \'no_such_event\'\n\nURL: https://mariadb.com/kb/en/alter-event/\n\n','','https://mariadb.com/kb/en/alter-event/'),(407,'STDDEV',16,'Syntax:\nSTDDEV(expr)\n\nReturns the population standard deviation of expr. This function is\nprovided for compatibility with Oracle. The standard SQL function\nSTDDEV_POP() can be used instead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/stddev/\n\n','','https://mariadb.com/kb/en/stddev/'),(408,'DATE_SUB',31,'Syntax:\nDATE_SUB(date,INTERVAL expr unit)\n\nSee the description for DATE_ADD().\n\nURL: https://mariadb.com/kb/en/date_sub/\n\n','','https://mariadb.com/kb/en/date_sub/'),(409,'PERIOD_ADD',31,'Syntax:\nPERIOD_ADD(P,N)\n\nAdds N months to period P (in the format YYMM or YYYYMM). Returns a\nvalue in the format YYYYMM. Note that the period argument P is not a\ndate value.\n\nURL: https://mariadb.com/kb/en/period_add/\n\n','MariaDB> SELECT PERIOD_ADD(200801,2);\n -> 200803\n','https://mariadb.com/kb/en/period_add/'),(410,'|',19,'Syntax:\n|\n\nBitwise OR:\n\nURL: https://mariadb.com/kb/en/bitwise-or/\n\n','MariaDB> SELECT 29 | 15;\n -> 31\n','https://mariadb.com/kb/en/bitwise-or/'),(411,'GEOMFROMTEXT',3,'GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])\n\nConstructs a geometry value of any type using its WKT representation\nand SRID.\n\nURL: https://mariadb.com/kb/en/geomfromtext/\n\n','','https://mariadb.com/kb/en/geomfromtext/'),(412,'UUID_SHORT',14,'Syntax:\nUUID_SHORT()\n\nReturns a \"short\" universal identifier as a 64-bit unsigned integer\n(rather than a string-form 128-bit identifier as returned by the UUID()\nfunction).\n\nThe value of UUID_SHORT() is guaranteed to be unique if the following\nconditions hold:\n\no The server_id of the current host is unique among your set of master\n and slave servers\n\no server_id is between 0 and 255\n\no You do not set back your system time for your server between mysqld\n restarts\n\no You do not invoke UUID_SHORT() on average more than 16 million times\n per second between mysqld restarts\n\nThe UUID_SHORT() return value is constructed this way:\n\n (server_id & 255) << 56\n+ (server_startup_time_in_seconds << 24)\n+ incremented_variable++;\n\nURL: https://mariadb.com/kb/en/uuid_short/\n\n','MariaDB> SELECT UUID_SHORT();\n -> 92395783831158784\n','https://mariadb.com/kb/en/uuid_short/'),(413,'RIGHT',37,'Syntax:\nRIGHT(str,len)\n\nReturns the rightmost len characters from the string str, or NULL if\nany argument is NULL.\n\nURL: https://mariadb.com/kb/en/right/\n\n','MariaDB> SELECT RIGHT(\'foobarbar\', 4);\n -> \'rbar\'\n','https://mariadb.com/kb/en/right/'),(414,'DATEDIFF',31,'Syntax:\nDATEDIFF(expr1,expr2)\n\nDATEDIFF() returns expr1 - expr2 expressed as a value in days from one\ndate to the other. expr1 and expr2 are date or date-and-time\nexpressions. Only the date parts of the values are used in the\ncalculation.\n\nURL: https://mariadb.com/kb/en/datediff/\n\n','MariaDB> SELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n -> 1\nMariaDB> SELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n -> -31\n','https://mariadb.com/kb/en/datediff/'),(415,'DROP TABLESPACE',39,'Syntax:\nDROP TABLESPACE tablespace_name\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/drop-tablespace/\n\n','','https://mariadb.com/kb/en/drop-tablespace/'),(416,'DROP PROCEDURE',39,'Syntax:\nDROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name\n\nThis statement is used to drop a stored procedure or function. That is,\nthe specified routine is removed from the server. You must have the\nALTER ROUTINE privilege for the routine. (If the\nautomatic_sp_privileges system variable is enabled, that privilege and\nEXECUTE are granted automatically to the routine creator when the\nroutine is created and dropped from the creator when the routine is\ndropped. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n)\n\nThe IF EXISTS clause is a MySQL extension. It prevents an error from\noccurring if the procedure or function does not exist. A warning is\nproduced that can be viewed with SHOW WARNINGS.\n\nURL: https://mariadb.com/kb/en/drop-procedure/\n\n','','https://mariadb.com/kb/en/drop-procedure/'),(417,'CHECK TABLE',20,'Syntax:\nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n\noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED}\n\nCHECK TABLE checks a table or tables for errors. CHECK TABLE works for\nInnoDB, MyISAM, ARCHIVE, and CSV tables. For MyISAM tables, the key\nstatistics are updated as well.\n\nTo check a table, you must have some privilege for it.\n\nCHECK TABLE can also check views for problems, such as tables that are\nreferenced in the view definition that no longer exist.\n\nCHECK TABLE is supported for partitioned tables, and you can use ALTER\nTABLE ... CHECK PARTITION to check one or more partitions; for more\ninformation, see [HELP ALTER TABLE].\n\nURL: https://mariadb.com/kb/en/sql-commands-check-table/\n\n','','https://mariadb.com/kb/en/sql-commands-check-table/'),(418,'BIN',37,'Syntax:\nBIN(N)\n\nReturns a string representation of the binary value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,2). Returns\nNULL if N is NULL.\n\nURL: https://mariadb.com/kb/en/bin/\n\n','MariaDB> SELECT BIN(12);\n -> \'1100\'\n','https://mariadb.com/kb/en/bin/'),(419,'INSTALL PLUGIN',5,'Syntax:\nINSTALL PLUGIN plugin_name SONAME \'shared_library_name\'\n\nThis statement installs a server plugin. It requires the INSERT\nprivilege for the mysql.plugin table.\n\nplugin_name is the name of the plugin as defined in the plugin\ndescriptor structure contained in the library file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/plugin-data-structures.html).\nPlugin names are not case sensitive. For maximal compatibility, plugin\nnames should be limited to ASCII letters, digits, and underscore\nbecause they are used in C source files, shell command lines, M4 and\nBourne shell scripts, and SQL environments.\n\nshared_library_name is the name of the shared library that contains the\nplugin code. The name includes the file name extension (for example,\nlibmyplugin.so, libmyplugin.dll, or libmyplugin.dylib).\n\nThe shared library must be located in the plugin directory (the\ndirectory named by the plugin_dir system variable). The library must be\nin the plugin directory itself, not in a subdirectory. By default,\nplugin_dir is the plugin directory under the directory named by the\npkglibdir configuration variable, but it can be changed by setting the\nvalue of plugin_dir at server startup. For example, set its value in a\nmy.cnf file:\n\n[mysqld]\nplugin_dir=/path/to/plugin/directory\n\nIf the value of plugin_dir is a relative path name, it is taken to be\nrelative to the MySQL base directory (the value of the basedir system\nvariable).\n\nINSTALL PLUGIN loads and initializes the plugin code to make the plugin\navailable for use. A plugin is initialized by executing its\ninitialization function, which handles any setup that the plugin must\nperform before it can be used. When the server shuts down, it executes\nthe deinitialization function for each plugin that is loaded so that\nthe plugin has a change to perform any final cleanup.\n\nINSTALL PLUGIN also registers the plugin by adding a line that\nindicates the plugin name and library file name to the mysql.plugin\ntable. At server startup, the server loads and initializes any plugin\nthat is listed in the mysql.plugin table. This means that a plugin is\ninstalled with INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the server is\nstarted with the --skip-grant-tables option.\n\nA plugin library can contain multiple plugins. For each of them to be\ninstalled, use a separate INSTALL PLUGIN statement. Each statement\nnames a different plugin, but all of them specify the same library\nname.\n\nURL: https://mariadb.com/kb/en/install-plugin/\n\n','','https://mariadb.com/kb/en/install-plugin/'),(420,'DECLARE CURSOR',23,'Syntax:\nDECLARE cursor_name CURSOR FOR select_statement\n\nThis statement declares a cursor and associates it with a SELECT\nstatement that retrieves the rows to be traversed by the cursor. To\nfetch the rows later, use a FETCH statement. The number of columns\nretrieved by the SELECT statement must match the number of output\nvariables specified in the FETCH statement.\n\nThe SELECT statement cannot have an INTO clause.\n\nCursor declarations must appear before handler declarations and after\nvariable and condition declarations.\n\nA stored program may contain multiple cursor declarations, but each\ncursor declared in a given block must have a unique name. For an\nexample, see https://mariadb.com/kb/en/programmatic-and-compound-statements-cursors/.\n\nFor information available through SHOW statements, it is possible in\nmany cases to obtain equivalent information by using a cursor with an\nINFORMATION_SCHEMA table.\n\nURL: https://mariadb.com/kb/en/declare-cursor/\n\n','','https://mariadb.com/kb/en/declare-cursor/'),(421,'LOAD DATA',27,'Syntax:\nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number {LINES | ROWS}]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD DATA INFILE statement reads rows from a text file into a table\nat a very high speed. The file name must be given as a literal string.\n\nLOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. (See\nhttps://mariadb.com/kb/en/select-into/.) To write data\nfrom a table to a file, use SELECT ... INTO OUTFILE. To read the file\nback into a table, use LOAD DATA INFILE. The syntax of the FIELDS and\nLINES clauses is the same for both statements. Both clauses are\noptional, but FIELDS must precede LINES if both are specified.\n\nFor more information about the efficiency of INSERT versus LOAD DATA\nINFILE and speeding up LOAD DATA INFILE, see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-speed.html.\n\nThe character set indicated by the character_set_database system\nvariable is used to interpret the information in the file. SET NAMES\nand the setting of character_set_client do not affect interpretation of\ninput. If the contents of the input file use a character set that\ndiffers from the default, it is usually preferable to specify the\ncharacter set of the file by using the CHARACTER SET clause. A\ncharacter set of binary specifies \"no conversion.\"\n\nLOAD DATA INFILE interprets all fields in the file as having the same\ncharacter set, regardless of the data types of the columns into which\nfield values are loaded. For proper interpretation of file contents,\nyou must ensure that it was written with the correct character set. For\nexample, if you write a data file with mysqldump -T or by issuing a\nSELECT ... INTO OUTFILE statement in mysql, be sure to use a\n--default-character-set option with mysqldump or mysql so that output\nis written in the character set to be used when the file is loaded with\nLOAD DATA INFILE.\n\n*Note*: It is not possible to load data files that use the ucs2, utf16,\nor utf32 character set.\n\nThe character_set_filesystem system variable controls the\ninterpretation of the file name.\n\nYou can also load data files by using the mysqlimport utility; it\noperates by sending a LOAD DATA INFILE statement to the server. The\n--local option causes mysqlimport to read data files from the client\nhost. You can specify the --compress option to get better performance\nover slow networks if the client and server support the compressed\nprotocol. See https://mariadb.com/kb/en/mysqlimport/.\n\nIf you use LOW_PRIORITY, execution of the LOAD DATA statement is\ndelayed until no other clients are reading from the table. This affects\nonly storage engines that use only table-level locking (such as MyISAM,\nMEMORY, and MERGE).\n\nIf you specify CONCURRENT with a MyISAM table that satisfies the\ncondition for concurrent inserts (that is, it contains no free blocks\nin the middle), other threads can retrieve data from the table while\nLOAD DATA is executing. Using this option affects the performance of\nLOAD DATA a bit, even if no other thread is using the table at the same\ntime.\n\nPrior to MySQL 5.5.1, CONCURRENT was not replicated when using\nstatement-based replication (see Bug #34628). However, it is replicated\nwhen using row-based replication, regardless of the version. See\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-features-load-data.h\ntml, for more information.\n\nThe LOCAL keyword, if specified, is interpreted with respect to the\nclient end of the connection:\n\no If LOCAL is specified, the file is read by the client program on the\n client host and sent to the server. The file can be given as a full\n path name to specify its exact location. If given as a relative path\n name, the name is interpreted relative to the directory in which the\n client program was started.\n\n When using LOCAL with LOAD DATA, a copy of the file is created in the\n server\'s temporary directory. This is not the directory determined by\n the value of tmpdir or slave_load_tmpdir, but rather the operating\n system\'s temporary directory, and is not configurable in the MySQL\n Server. (Typically the system temporary directory is /tmp on Linux\n systems and C:\\WINDOWS\\TEMP on Windows.) Lack of sufficient space for\n the copy in this directory can cause the LOAD DATA LOCAL statement to\n fail.\n\no If LOCAL is not specified, the file must be located on the server\n host and is read directly by the server. The server uses the\n following rules to locate the file:\n\n o If the file name is an absolute path name, the server uses it as\n given.\n\n o If the file name is a relative path name with one or more leading\n components, the server searches for the file relative to the\n server\'s data directory.\n\n o If a file name with no leading components is given, the server\n looks for the file in the database directory of the default\n database.\n\nNote that, in the non-LOCAL case, these rules mean that a file named as\n./myfile.txt is read from the server\'s data directory, whereas the file\nnamed as myfile.txt is read from the database directory of the default\ndatabase. For example, if db1 is the default database, the following\nLOAD DATA statement reads the file data.txt from the database directory\nfor db1, even though the statement explicitly loads the file into a\ntable in the db2 database:\n\nLOAD DATA INFILE \'data.txt\' INTO TABLE db2.my_table;\n\nWindows path names are specified using forward slashes rather than\nbackslashes. If you do use backslashes, you must double them.\n\nFor security reasons, when reading text files located on the server,\nthe files must either reside in the database directory or be readable\nby all. Also, to use LOAD DATA INFILE on server files, you must have\nthe FILE privilege. See\nhttps://mariadb.com/kb/en/grant/. For\nnon-LOCAL load operations, if the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nURL: https://mariadb.com/kb/en/load-data-infile/\n\n','','https://mariadb.com/kb/en/load-data-infile/'),(422,'MULTILINESTRING',24,'MultiLineString(ls1,ls2,...)\n\nConstructs a MultiLineString value using LineString or WKB LineString\narguments.\n\nURL: https://mariadb.com/kb/en/multilinestring/\n\n','','https://mariadb.com/kb/en/multilinestring/'),(423,'LOCALTIME',31,'Syntax:\nLOCALTIME, LOCALTIME()\n\nLOCALTIME and LOCALTIME() are synonyms for NOW().\n\nURL: https://mariadb.com/kb/en/localtime/\n\n','','https://mariadb.com/kb/en/localtime/'),(424,'SHOW RELAYLOG EVENTS',26,'Syntax:\nSHOW RELAYLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the relay log of a replication slave. If you do not\nspecify \'log_name\', the first relay log is displayed. This statement\nhas no effect on the master.\n\nURL: https://mariadb.com/kb/en/show-relaylog-events/\n\n','','https://mariadb.com/kb/en/show-relaylog-events/'),(425,'MPOINTFROMTEXT',3,'MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])\n\nConstructs a MULTIPOINT value using its WKT representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromtext/\n\n','','https://mariadb.com/kb/en/mpointfromtext/'),(426,'BLOB',22,'BLOB[(M)]\n\nA BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each\nBLOB value is stored using a 2-byte length prefix that indicates the\nnumber of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest BLOB type large enough to hold\nvalues M bytes long.\n\nURL: https://mariadb.com/kb/en/blob/\n\n','','https://mariadb.com/kb/en/blob/'),(427,'SHA1',12,'Syntax:\nSHA1(str), SHA(str)\n\nCalculates an SHA-1 160-bit checksum for the string, as described in\nRFC 3174 (Secure Hash Algorithm). The value is returned as a string of\n40 hex digits, or NULL if the argument was NULL. One of the possible\nuses for this function is as a hash key. See the notes at the beginning\nof this section about storing hash values efficiently. You can also use\nSHA1() as a cryptographic function for storing passwords. SHA() is\nsynonymous with SHA1().\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: https://mariadb.com/kb/en/sha1/\n\n','MariaDB> SELECT SHA1(\'abc\');\n -> \'a9993e364706816aba3e25717850c26c9cd0d89d\'\n','https://mariadb.com/kb/en/sha1/'),(428,'SUBSTR',37,'Syntax:\nSUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str\nFROM pos FOR len)\n\nSUBSTR() is a synonym for SUBSTRING().\n\nURL: https://mariadb.com/kb/en/substr/\n\n','','https://mariadb.com/kb/en/substr/'),(429,'PASSWORD',12,'Syntax:\nPASSWORD(str)\n\nCalculates and returns a hashed password string from the plaintext\npassword str and returns a nonbinary string in the connection character\nset (a binary string before MySQL 5.5.3), or NULL if the argument is\nNULL. This function is the SQL interface to the algorithm used by the\nserver to encrypt MySQL passwords for storage in the mysql.user grant\ntable.\n\nThe password hashing method used by PASSWORD() depends on the value of\nthe old_passwords system variable:\n\nURL: https://mariadb.com/kb/en/password/\n\n','MariaDB> SET old_passwords = 0;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+-------------------------------------------+\n| PASSWORD(\'mypass\') |\n+-------------------------------------------+\n| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |\n+-------------------------------------------+\n\nMariaDB> SET old_passwords = 1;\nMariaDB> SELECT PASSWORD(\'mypass\');\n+--------------------+\n| PASSWORD(\'mypass\') |\n+--------------------+\n| 6f8c114b58f2ce9e |\n+--------------------+\n','https://mariadb.com/kb/en/password/'),(430,'CHAR',22,'[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA fixed-length string that is always right-padded with spaces to the\nspecified length when stored. M represents the column length in\ncharacters. The range of M is 0 to 255. If M is omitted, the length is\n1.\n\n*Note*: Trailing spaces are removed when CHAR values are retrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n\nURL: https://mariadb.com/kb/en/char/\n\n','','https://mariadb.com/kb/en/char/'),(431,'UTC_DATE',31,'Syntax:\nUTC_DATE, UTC_DATE()\n\nReturns the current UTC date as a value in \'YYYY-MM-DD\' or YYYYMMDD\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: https://mariadb.com/kb/en/utc_date/\n\n','MariaDB> SELECT UTC_DATE(), UTC_DATE() + 0;\n -> \'2003-08-14\', 20030814\n','https://mariadb.com/kb/en/utc_date/'),(432,'DIMENSION',36,'Dimension(g)\n\nReturns the inherent dimension of the geometry value g. The result can\nbe -1, 0, 1, or 2. The meaning of these values is given in\nhttps://mariadb.com/kb/en/dimension/.\n\nURL: https://mariadb.com/kb/en/dimension/\n\n','MariaDB> SELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n','https://mariadb.com/kb/en/dimension/'),(433,'COUNT DISTINCT',16,'Syntax:\nCOUNT(DISTINCT expr,[expr...])\n\nReturns a count of the number of rows with different non-NULL expr\nvalues.\n\nCOUNT(DISTINCT) returns 0 if there were no matching rows.\n\nURL: https://mariadb.com/kb/en/count-distinct/\n\n','MariaDB> SELECT COUNT(DISTINCT results) FROM student;\n','https://mariadb.com/kb/en/count-distinct/'),(434,'BIT',22,'BIT[(M)]\n\nA bit-field type. M indicates the number of bits per value, from 1 to\n64. The default is 1 if M is omitted.\n\nURL: https://mariadb.com/kb/en/bit/\n\n','','https://mariadb.com/kb/en/bit/'),(435,'EQUALS',30,'Equals(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially equal to g2.\n\nURL: https://mariadb.com/kb/en/equals/\n\n','','https://mariadb.com/kb/en/equals/'),(436,'SHOW CREATE VIEW',26,'Syntax:\nSHOW CREATE VIEW view_name\n\nThis statement shows a CREATE VIEW statement that creates the given\nview.\n\nURL: https://mariadb.com/kb/en/show-create-view/\n\n','','https://mariadb.com/kb/en/show-create-view/'),(437,'INTERVAL',18,'Syntax:\nINTERVAL(N,N1,N2,N3,...)\n\nReturns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All\narguments are treated as integers. It is required that N1 < N2 < N3 <\n... < Nn for this function to work correctly. This is because a binary\nsearch is used (very fast).\n\nURL: https://mariadb.com/kb/en/interval/\n\n','MariaDB> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\n -> 3\nMariaDB> SELECT INTERVAL(10, 1, 10, 100, 1000);\n -> 2\nMariaDB> SELECT INTERVAL(22, 23, 30, 44, 200);\n -> 0\n','https://mariadb.com/kb/en/interval/'),(438,'FROM_DAYS',31,'Syntax:\nFROM_DAYS(N)\n\nGiven a day number N, returns a DATE value.\n\nURL: https://mariadb.com/kb/en/from_days/\n\n','MariaDB> SELECT FROM_DAYS(730669);\n -> \'2007-07-03\'\n','https://mariadb.com/kb/en/from_days/'),(439,'ALTER PROCEDURE',39,'Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nURL: https://mariadb.com/kb/en/alter-procedure/\n\n','','https://mariadb.com/kb/en/alter-procedure/'),(440,'BIT_COUNT',19,'Syntax:\nBIT_COUNT(N)\n\nReturns the number of bits that are set in the argument N.\n\nURL: https://mariadb.com/kb/en/bit_count/\n\n','MariaDB> SELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n -> 4, 3\n','https://mariadb.com/kb/en/bit_count/'),(441,'OCTET_LENGTH',37,'Syntax:\nOCTET_LENGTH(str)\n\nOCTET_LENGTH() is a synonym for LENGTH().\n\nURL: https://mariadb.com/kb/en/octet_length/\n\n','','https://mariadb.com/kb/en/octet_length/'),(442,'UTC_TIMESTAMP',31,'Syntax:\nUTC_TIMESTAMP, UTC_TIMESTAMP()\n\nReturns the current UTC date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is used in a string or numeric context.\n\nURL: https://mariadb.com/kb/en/utc_timestamp/\n\n','MariaDB> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n -> \'2003-08-14 18:08:04\', 20030814180804.000000\n','https://mariadb.com/kb/en/utc_timestamp/'),(443,'AES_ENCRYPT',12,'Syntax:\nAES_ENCRYPT(str,key_str)\n\nAES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of\ndata using the official AES (Advanced Encryption Standard) algorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit key length is\nused, but you can extend it up to 256 bits by modifying the source. We\nchose 128 bits because it is much faster and it is secure enough for\nmost purposes.\n\nAES_ENCRYPT() encrypts a string and returns a binary string.\nAES_DECRYPT() decrypts the encrypted string and returns the original\nstring. The input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n\nBecause AES is a block-level algorithm, padding is used to encode\nuneven length strings and so the result string length may be calculated\nusing this formula:\n\n16 * (trunc(string_length / 16) + 1)\n\nIf AES_DECRYPT() detects invalid data or incorrect padding, it returns\nNULL. However, it is possible for AES_DECRYPT() to return a non-NULL\nvalue (possibly garbage) if the input data or the key is invalid.\n\nYou can use the AES functions to store data in an encrypted form by\nmodifying your queries:\n\nURL: https://mariadb.com/kb/en/aes_encrypt/\n\n','INSERT INTO t VALUES (1,AES_ENCRYPT(\'text\',\'password\'));\n','https://mariadb.com/kb/en/aes_encrypt/'),(444,'+',4,'Syntax:\n+\n\nAddition:\n\nURL: https://mariadb.com/kb/en/addition-operator/\n\n','MariaDB> SELECT 3+5;\n -> 8\n','https://mariadb.com/kb/en/addition-operator/'),(445,'INET_NTOA',14,'Syntax:\nINET_NTOA(expr)\n\nGiven a numeric IPv4 network address in network byte order, returns the\ndotted-quad representation of the address as a string. INET_NTOA()\nreturns NULL if it does not understand its argument.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: https://mariadb.com/kb/en/inet_ntoa/\n\n','MariaDB> SELECT INET_NTOA(167773449);\n -> \'10.0.5.9\'\n','https://mariadb.com/kb/en/inet_ntoa/'),(446,'ACOS',4,'Syntax:\nACOS(X)\n\nReturns the arc cosine of X, that is, the value whose cosine is X.\nReturns NULL if X is not in the range -1 to 1.\n\nURL: https://mariadb.com/kb/en/acos/\n\n','MariaDB> SELECT ACOS(1);\n -> 0\nMariaDB> SELECT ACOS(1.0001);\n -> NULL\nMariaDB> SELECT ACOS(0);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/acos/'),(447,'ISOLATION',8,'Syntax:\nSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL\n {\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n }\n\nThis statement sets the transaction isolation level, used for\noperations on InnoDB tables.\n\nScope of the Isolation Level\n\nYou can set the isolation level globally, for the current session, or\nfor the next transaction:\n\no With the GLOBAL keyword, the statement sets the default transaction\n level globally for all subsequent sessions. Existing sessions are\n unaffected.\n\no With the SESSION keyword, the statement sets the default transaction\n level for all subsequent transactions performed within the current\n session.\n\no Without any SESSION or GLOBAL keyword, the statement sets the\n isolation level for the next (not started) transaction performed\n within the current session.\n\nA change to the global default isolation level requires the SUPER\nprivilege. Any session is free to change its session isolation level\n(even in the middle of a transaction), or the isolation level for its\nnext transaction.\n\nSET TRANSACTION ISOLATION LEVEL without GLOBAL or SESSION is not\npermitted while there is an active transaction:\n\nMariaDB> START TRANSACTION;\nQuery OK, 0 rows affected (0.02 sec)\n\nMariaDB> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction isolation level can\'t be changed\nwhile a transaction is in progress\n\nTo set the global default isolation level at server startup, use the\n--transaction-isolation=level option to mysqld on the command line or\nin an option file. Values of level for this option use dashes rather\nthan spaces, so the permissible values are READ-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example, to set\nthe default isolation level to REPEATABLE READ, use these lines in the\n[mysqld] section of an option file:\n\n[mysqld]\ntransaction-isolation = REPEATABLE-READ\n\nIt is possible to check or set the global and session transaction\nisolation levels at runtime by using the tx_isolation system variable:\n\nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\nSET GLOBAL tx_isolation=\'REPEATABLE-READ\';\nSET SESSION tx_isolation=\'SERIALIZABLE\';\n\nDetails and Usage of Isolation Levels\n\nInnoDB supports each of the transaction isolation levels described here\nusing different locking strategies. You can enforce a high degree of\nconsistency with the default REPEATABLE READ level, for operations on\ncrucial data where ACID compliance is important. Or you can relax the\nconsistency rules with READ COMMITTED or even READ UNCOMMITTED, in\nsituations such as bulk reporting where precise consistency and\nrepeatable results are less important than minimizing the amount of\noverhead for locking. SERIALIZABLE enforces even stricter rules than\nREPEATABLE READ, and is used mainly in specialized situations, such as\nwith XA transactions and for troubleshooting issues with concurrency\nand deadlocks.\n\nFor full information about how these isolation levels work with InnoDB\ntransactions, see\nhttp://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html.\nIn particular, for additional information about InnoDB record-level\nlocks and how it uses them to execute various types of statements, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html\nand http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html.\n\nThe following list describes how MySQL supports the different\ntransaction levels. The list goes from the most commonly used level to\nthe least used.\n\no REPEATABLE READ\n\n This is the default isolation level for InnoDB. For consistent reads,\n there is an important difference from the READ COMMITTED isolation\n level: All consistent reads within the same transaction read the\n snapshot established by the first read. This convention means that if\n you issue several plain (nonlocking) SELECT statements within the\n same transaction, these SELECT statements are consistent also with\n respect to each other. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n UPDATE, and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition, or a\n range-type search condition. For a unique index with a unique search\n condition, InnoDB locks only the index record found, not the gap\n before it. For other search conditions, InnoDB locks the index range\n scanned, using gap locks or next-key (gap plus index-record) locks to\n block insertions by other sessions into the gaps covered by the\n range.\n\no READ COMMITTED\n\n A somewhat Oracle-like isolation level with respect to consistent\n (nonlocking) reads: Each consistent read, even within the same\n transaction, sets and reads its own fresh snapshot. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n InnoDB locks only index records, not the gaps before them, and thus\n permits the free insertion of new records next to locked records. For\n UPDATE and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition (such as\n WHERE id = 100), or a range-type search condition (such as WHERE id >\n 100). For a unique index with a unique search condition, InnoDB locks\n only the index record found, not the gap before it. For range-type\n searches, InnoDB locks the index range scanned, using gap locks or\n next-key (gap plus index-record) locks to block insertions by other\n sessions into the gaps covered by the range. This is necessary\n because \"phantom rows\" must be blocked for MySQL replication and\n recovery to work.\n\n *Note*: In MySQL 5.5, if the READ COMMITTED isolation level is used\n or the innodb_locks_unsafe_for_binlog system variable is enabled,\n there is no InnoDB gap locking except for foreign-key constraint\n checking and duplicate-key checking. Also, record locks for\n nonmatching rows are released after MySQL has evaluated the WHERE\n condition. If you use READ COMMITTED or enable\n innodb_locks_unsafe_for_binlog, you must use row-based binary\n logging.\n\no READ UNCOMMITTED\n\n SELECT statements are performed in a nonlocking fashion, but a\n possible earlier version of a row might be used. Thus, using this\n isolation level, such reads are not consistent. This is also called a\n \"dirty read.\" Otherwise, this isolation level works like READ\n COMMITTED.\n\no SERIALIZABLE\n\n This level is like REPEATABLE READ, but InnoDB implicitly converts\n all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if\n autocommit is disabled. If autocommit is enabled, the SELECT is its\n own transaction. It therefore is known to be read only and can be\n serialized if performed as a consistent (nonlocking) read and need\n not block for other transactions. (To force a plain SELECT to block\n if other transactions have modified the selected rows, disable\n autocommit.)\n\nURL: https://mariadb.com/kb/en/set-transaction-isolation-level/\n\n','','https://mariadb.com/kb/en/set-transaction-isolation-level/'),(448,'CEILING',4,'Syntax:\nCEILING(X)\n\nReturns the smallest integer value not less than X.\n\nURL: https://mariadb.com/kb/en/ceiling/\n\n','MariaDB> SELECT CEILING(1.23);\n -> 2\nMariaDB> SELECT CEILING(-1.23);\n -> -1\n','https://mariadb.com/kb/en/ceiling/'),(449,'SIN',4,'Syntax:\nSIN(X)\n\nReturns the sine of X, where X is given in radians.\n\nURL: https://mariadb.com/kb/en/sin/\n\n','MariaDB> SELECT SIN(PI());\n -> 1.2246063538224e-16\nMariaDB> SELECT ROUND(SIN(PI()));\n -> 0\n','https://mariadb.com/kb/en/sin/'),(450,'DAYOFWEEK',31,'Syntax:\nDAYOFWEEK(date)\n\nReturns the weekday index for date (1 = Sunday, 2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC standard.\n\nURL: https://mariadb.com/kb/en/dayofweek/\n\n','MariaDB> SELECT DAYOFWEEK(\'2007-02-03\');\n -> 7\n','https://mariadb.com/kb/en/dayofweek/'),(451,'SHOW PROCESSLIST',26,'Syntax:\nSHOW [FULL] PROCESSLIST\n\nSHOW PROCESSLIST shows you which threads are running. You can also get\nthis information from the INFORMATION_SCHEMA PROCESSLIST table or the\nmysqladmin processlist command. If you have the PROCESS privilege, you\ncan see all threads. Otherwise, you can see only your own threads (that\nis, threads associated with the MySQL account that you are using). If\nyou do not use the FULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n\nURL: https://mariadb.com/kb/en/show-processlist/\n\n','','https://mariadb.com/kb/en/show-processlist/'),(452,'LINEFROMWKB',32,'LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])\n\nConstructs a LINESTRING value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/linefromwkb/\n\n','','https://mariadb.com/kb/en/linefromwkb/'),(453,'GEOMETRYTYPE',36,'GeometryType(g)\n\nReturns as a binary string the name of the geometry type of which the\ngeometry instance g is a member. The name corresponds to one of the\ninstantiable Geometry subclasses.\n\nURL: https://mariadb.com/kb/en/geometrytype/\n\n','MariaDB> SELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n','https://mariadb.com/kb/en/geometrytype/'),(454,'CREATE VIEW',39,'Syntax:\nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThe CREATE VIEW statement creates a new view, or replaces an existing\none if the OR REPLACE clause is given. If the view does not exist,\nCREATE OR REPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR REPLACE VIEW is the same as ALTER VIEW.\n\nThe select_statement is a SELECT statement that provides the definition\nof the view. (When you select from the view, you select in effect using\nthe SELECT statement.) select_statement can select from base tables or\nother views.\n\nThe view definition is \"frozen\" at creation time, so changes to the\nunderlying tables afterward do not affect the view definition. For\nexample, if a view is defined as SELECT * on a table, new columns added\nto the table later do not become part of the view.\n\nThe ALGORITHM clause affects how MySQL processes the view. The DEFINER\nand SQL SECURITY clauses specify the security context to be used when\nchecking access privileges at view invocation time. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates to rows in\ntables referenced by the view. These clauses are described later in\nthis section.\n\nThe CREATE VIEW statement requires the CREATE VIEW privilege for the\nview, and some privilege for each column selected by the SELECT\nstatement. For columns used elsewhere in the SELECT statement you must\nhave the SELECT privilege. If the OR REPLACE clause is present, you\nmust also have the DROP privilege for the view. CREATE VIEW might also\nrequire the SUPER privilege, depending on the DEFINER value, as\ndescribed later in this section.\n\nWhen a view is referenced, privilege checking occurs as described later\nin this section.\n\nA view belongs to a database. By default, a new view is created in the\ndefault database. To create the view explicitly in a given database,\nspecify the name as db_name.view_name when you create it:\n\nMariaDB> CREATE VIEW test.v AS SELECT * FROM t;\n\nWithin a database, base tables and views share the same namespace, so a\nbase table and a view cannot have the same name.\n\nColumns retrieved by the SELECT statement can be simple references to\ntable columns. They can also be expressions that use functions,\nconstant values, operators, and so forth.\n\nViews must have unique column names with no duplicates, just like base\ntables. By default, the names of the columns retrieved by the SELECT\nstatement are used for the view column names. To define explicit names\nfor the view columns, the optional column_list clause can be given as a\nlist of comma-separated identifiers. The number of names in column_list\nmust be the same as the number of columns retrieved by the SELECT\nstatement.\n\nUnqualified table or view names in the SELECT statement are interpreted\nwith respect to the default database. A view can refer to tables or\nviews in other databases by qualifying the table or view name with the\nproper database name.\n\nA view can be created from many kinds of SELECT statements. It can\nrefer to base tables or other views. It can use joins, UNION, and\nsubqueries. The SELECT need not even refer to any tables. The following\nexample defines a view that selects two columns from another table, as\nwell as an expression calculated from those columns:\n\nMariaDB> CREATE TABLE t (qty INT, price INT);\nMariaDB> INSERT INTO t VALUES(3, 50);\nMariaDB> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;\nMariaDB> SELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n\nA view definition is subject to the following restrictions:\n\no The SELECT statement cannot contain a subquery in the FROM clause.\n\no The SELECT statement cannot refer to system or user variables.\n\no Within a stored program, the definition cannot refer to program\n parameters or local variables.\n\no The SELECT statement cannot refer to prepared statement parameters.\n\no Any table or view referred to in the definition must exist. However,\n after a view has been created, it is possible to drop a table or view\n that the definition refers to. In this case, use of the view results\n in an error. To check a view definition for problems of this kind,\n use the CHECK TABLE statement.\n\no The definition cannot refer to a TEMPORARY table, and you cannot\n create a TEMPORARY view.\n\no Any tables named in the view definition must exist at definition\n time.\n\no You cannot associate a trigger with a view.\n\no Aliases for column names in the SELECT statement are checked against\n the maximum column length of 64 characters (not the maximum alias\n length of 256 characters).\n\nORDER BY is permitted in a view definition, but it is ignored if you\nselect from a view using a statement that has its own ORDER BY.\n\nFor other options or clauses in the definition, they are added to the\noptions or clauses of the statement that references the view, but the\neffect is undefined. For example, if a view definition includes a LIMIT\nclause, and you select from the view using a statement that has its own\nLIMIT clause, it is undefined which limit applies. This same principle\napplies to options such as ALL, DISTINCT, or SQL_SMALL_RESULT that\nfollow the SELECT keyword, and to clauses such as INTO, FOR UPDATE,\nLOCK IN SHARE MODE, and PROCEDURE.\n\nIf you create a view and then change the query processing environment\nby changing system variables, that may affect the results that you get\nfrom the view:\n\nMariaDB> CREATE VIEW v (mycol) AS SELECT \'abc\';\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SET sql_mode = \'\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol |\n+-------+\n1 row in set (0.01 sec)\n\nMariaDB> SET sql_mode = \'ANSI_QUOTES\';\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc |\n+-------+\n1 row in set (0.00 sec)\n\nThe DEFINER and SQL SECURITY clauses determine which MySQL account to\nuse when checking access privileges for the view when a statement is\nexecuted that references the view. The valid SQL SECURITY\ncharacteristic values are DEFINER and INVOKER. These indicate that the\nrequired privileges must be held by the user who defined or invoked the\nview, respectively. The default SQL SECURITY value is DEFINER.\n\nIf a user value is given for the DEFINER clause, it should be a MySQL\naccount specified as \'user_name\'@\'host_name\' (the same format used in\nthe GRANT statement), CURRENT_USER, or CURRENT_USER(). The default\nDEFINER value is the user who executes the CREATE VIEW statement. This\nis the same as specifying DEFINER = CURRENT_USER explicitly.\n\nIf you specify the DEFINER clause, these rules determine the valid\nDEFINER user values:\n\no If you do not have the SUPER privilege, the only valid user value is\n your own account, either specified literally or by using\n CURRENT_USER. You cannot set the definer to some other account.\n\no If you have the SUPER privilege, you can specify any syntactically\n valid account name. If the account does not actually exist, a warning\n is generated.\n\no Although it is possible to create a view with a nonexistent DEFINER\n account, an error occurs when the view is referenced if the SQL\n SECURITY value is DEFINER but the definer account does not exist.\n\nFor more information about view security, see\nhttps://mariadb.com/kb/en/stored-routine-privileges/.\n\nWithin a view definition, CURRENT_USER returns the view\'s DEFINER value\nby default. For views defined with the SQL SECURITY INVOKER\ncharacteristic, CURRENT_USER returns the account for the view\'s\ninvoker. For information about user auditing within views, see\nhttp://dev.mysql.com/doc/refman/5.5/en/account-activity-auditing.html.\n\nWithin a stored routine that is defined with the SQL SECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER value. This\nalso affects a view defined within such a routine, if the view\ndefinition contains a DEFINER value of CURRENT_USER.\n\nView privileges are checked like this:\n\no At view definition time, the view creator must have the privileges\n needed to use the top-level objects accessed by the view. For\n example, if the view definition refers to table columns, the creator\n must have some privilege for each column in the select list of the\n definition, and the SELECT privilege for each column used elsewhere\n in the definition. If the definition refers to a stored function,\n only the privileges needed to invoke the function can be checked. The\n privileges required at function invocation time can be checked only\n as it executes: For different invocations, different execution paths\n within the function might be taken.\n\no The user who references a view must have appropriate privileges to\n access it (SELECT to select from it, INSERT to insert into it, and so\n forth.)\n\no When a view has been referenced, privileges for objects accessed by\n the view are checked against the privileges held by the view DEFINER\n account or invoker, depending on whether the SQL SECURITY\n characteristic is DEFINER or INVOKER, respectively.\n\no If reference to a view causes execution of a stored function,\n privilege checking for statements executed within the function depend\n on whether the function SQL SECURITY characteristic is DEFINER or\n INVOKER. If the security characteristic is DEFINER, the function runs\n with the privileges of the DEFINER account. If the characteristic is\n INVOKER, the function runs with the privileges determined by the\n view\'s SQL SECURITY characteristic.\n\nExample: A view might depend on a stored function, and that function\nmight invoke other stored routines. For example, the following view\ninvokes a stored function f():\n\nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n\nSuppose that f() contains a statement such as this:\n\nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n\nThe privileges required for executing statements within f() need to be\nchecked when f() executes. This might mean that privileges are needed\nfor p1() or p2(), depending on the execution path within f(). Those\nprivileges must be checked at runtime, and the user who must possess\nthe privileges is determined by the SQL SECURITY values of the view v\nand the function f().\n\nThe DEFINER and SQL SECURITY clauses for views are extensions to\nstandard SQL. In standard SQL, views are handled using the rules for\nSQL SECURITY DEFINER. The standard says that the definer of the view,\nwhich is the same as the owner of the view\'s schema, gets applicable\nprivileges on the view (for example, SELECT) and may grant them. MySQL\nhas no concept of a schema \"owner\", so MySQL adds a clause to identify\nthe definer. The DEFINER clause is an extension where the intent is to\nhave what the standard has; that is, a permanent record of who defined\nthe view. This is why the default DEFINER value is the account of the\nview creator.\n\nThe optional ALGORITHM clause is a MySQL extension to standard SQL. It\naffects how MySQL processes the view. ALGORITHM takes three values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is UNDEFINED if\nno ALGORITHM clause is present. For more information, see\nhttps://mariadb.com/kb/en/view-algorithms/.\n\nSome views are updatable. That is, you can use them in statements such\nas UPDATE, DELETE, or INSERT to update the contents of the underlying\ntable. For a view to be updatable, there must be a one-to-one\nrelationship between the rows in the view and the rows in the\nunderlying table. There are also certain other constructs that make a\nview nonupdatable.\n\nThe WITH CHECK OPTION clause can be given for an updatable view to\nprevent inserts or updates to rows except those for which the WHERE\nclause in the select_statement is true.\n\nIn a WITH CHECK OPTION clause for an updatable view, the LOCAL and\nCASCADED keywords determine the scope of check testing when the view is\ndefined in terms of another view. The LOCAL keyword restricts the CHECK\nOPTION only to the view being defined. CASCADED causes the checks for\nunderlying views to be evaluated as well. When neither keyword is\ngiven, the default is CASCADED.\n\nFor more information about updatable views and the WITH CHECK OPTION\nclause, see\nhttps://mariadb.com/kb/en/inserting-and-updating-with-views/.\n\nURL: https://mariadb.com/kb/en/create-view/\n\n','','https://mariadb.com/kb/en/create-view/'),(455,'TRIM',37,'Syntax:\nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr\nFROM] str)\n\nReturns the string str with all remstr prefixes or suffixes removed. If\nnone of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is\nassumed. remstr is optional and, if not specified, spaces are removed.\n\nURL: https://mariadb.com/kb/en/trim/\n\n','MariaDB> SELECT TRIM(\' bar \');\n -> \'bar\'\nMariaDB> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');\n -> \'barxxx\'\nMariaDB> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');\n -> \'bar\'\nMariaDB> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');\n -> \'barx\'\n','https://mariadb.com/kb/en/trim/'),(456,'IS',18,'Syntax:\nIS boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: https://mariadb.com/kb/en/is/\n\n','MariaDB> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n -> 1, 1, 1\n','https://mariadb.com/kb/en/is/'),(457,'GET_FORMAT',31,'Syntax:\nGET_FORMAT({DATE|TIME|DATETIME}, {\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n\nReturns a format string. This function is useful in combination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n\nURL: https://mariadb.com/kb/en/get_format/\n\n','MariaDB> SELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n -> \'03.10.2003\'\nMariaDB> SELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n -> \'2003-10-31\'\n','https://mariadb.com/kb/en/get_format/'),(458,'TINYBLOB',22,'TINYBLOB\n\nA BLOB column with a maximum length of 255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a 1-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/tinyblob/\n\n','','https://mariadb.com/kb/en/tinyblob/'),(459,'SIGNAL',23,'Syntax:\nSIGNAL condition_value\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nSIGNAL is the way to \"return\" an error. SIGNAL provides error\ninformation to a handler, to an outer portion of the application, or to\nthe client. Also, it provides control over the error\'s characteristics\n(error number, SQLSTATE value, message). Without SIGNAL, it is\nnecessary to resort to workarounds such as deliberately referring to a\nnonexistent table to cause a routine to return an error.\n\nNo special privileges are required to execute the SIGNAL statement.\n\nThe condition_value in a SIGNAL statement indicates the error value to\nbe returned. It can be an SQLSTATE value (a 5-character string literal)\nor a condition_name that refers to a named condition previously defined\nwith DECLARE ... CONDITION (see [HELP DECLARE CONDITION]).\n\nAn SQLSTATE value can indicate errors, warnings, or \"not found.\" The\nfirst two characters of the value indicate its error class, as\ndiscussed in\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items. Some signal values cause statement termination; see\nhttps://mariadb.com/kb/en/signal/#signal-effects.\n\nThe SQLSTATE value for a SIGNAL statement should not start with \'00\'\nbecause such values indicate success and are not valid for signaling an\nerror. This is true whether the SQLSTATE value is specified directly in\nthe SIGNAL statement or in a named condition referred to in the\nstatement. If the value is invalid, a Bad SQLSTATE error occurs.\n\nTo signal a generic SQLSTATE value, use \'45000\', which means \"unhandled\nuser-defined exception.\"\n\nThe SIGNAL statement optionally includes a SET clause that contains\nmultiple signal items, in a comma-separated list of\ncondition_information_item_name = simple_value_specification\nassignments.\n\nEach condition_information_item_name may be specified only once in the\nSET clause. Otherwise, a Duplicate condition information item error\noccurs.\n\nValid simple_value_specification designators can be specified using\nstored procedure or function parameters, stored program local variables\ndeclared with DECLARE, user-defined variables, system variables, or\nliterals. A character literal may include a _charset introducer.\n\nFor information about permissible condition_information_item_name\nvalues, see\nhttps://mariadb.com/kb/en/signal/#signal-condition-inf\normation-items.\n\nURL: https://mariadb.com/kb/en/signal/\n\n','CREATE PROCEDURE p (pval INT)\nBEGIN\n DECLARE specialty CONDITION FOR SQLSTATE \'45000\';\n IF pval = 0 THEN\n SIGNAL SQLSTATE \'01000\';\n ELSEIF pval = 1 THEN\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSEIF pval = 2 THEN\n SIGNAL specialty\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSE\n SIGNAL SQLSTATE \'01000\'\n SET MESSAGE_TEXT = \'A warning occurred\', MYSQL_ERRNO = 1000;\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\', MYSQL_ERRNO = 1001;\n END IF;\nEND;\n','https://mariadb.com/kb/en/signal/'),(460,'SAVEPOINT',8,'Syntax:\nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n\nInnoDB supports the SQL statements SAVEPOINT, ROLLBACK TO SAVEPOINT,\nRELEASE SAVEPOINT and the optional WORK keyword for ROLLBACK.\n\nURL: https://mariadb.com/kb/en/savepoint/\n\n','','https://mariadb.com/kb/en/savepoint/'),(461,'USER',17,'Syntax:\nUSER()\n\nReturns the current MySQL user name and host name as a string in the\nutf8 character set.\n\nURL: https://mariadb.com/kb/en/user/\n\n','MariaDB> SELECT USER();\n -> \'davida@localhost\'\n','https://mariadb.com/kb/en/user/'),(462,'LABELS',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nLabels are permitted for BEGIN ... END blocks and for the LOOP, REPEAT,\nand WHILE statements. Label use for those statements follows these\nrules:\n\no begin_label must be followed by a colon.\n\no begin_label can be given without end_label. If end_label is present,\n it must be the same as begin_label.\n\no end_label cannot be given without begin_label.\n\no Labels at the same nesting level must be distinct.\n\no Labels can be up to 16 characters long.\n\nTo refer to a label within the labeled construct, use an ITERATE or\nLEAVE statement. The following example uses those statements to\ncontinue iterating or terminate the loop:\n\nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN ITERATE label1; END IF;\n LEAVE label1;\n END LOOP label1;\nEND;\n\nThe scope of a block label does not include the code for handlers\ndeclared within the block. For details, see [HELP DECLARE HANDLER].\n\nURL: https://mariadb.com/kb/en/labels/\n\n','','https://mariadb.com/kb/en/labels/'),(463,'ALTER TABLE',39,'Syntax:\nALTER [ONLINE | OFFLINE] [IGNORE] TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (index_col_name,...)\n reference_definition\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] col_name\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} index_name\n | DROP FOREIGN KEY fk_symbol\n | MAX_ROWS = rows\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO|AS] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | FORCE\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO (partition_definitions)]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | PARTITION BY partitioning_expression\n | REMOVE PARTITIONING\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\ntable_options:\n table_option [[,] table_option] ... (see CREATE TABLE options)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\nPartitioning-related clauses for ALTER TABLE can be used with\npartitioned tables for repartitioning, for adding, dropping, merging,\nand splitting partitions, and for performing partitioning maintenance.\nFor more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations\n.html.\n\nFollowing the table name, specify the alterations to be made. If none\nare given, ALTER TABLE does nothing.\n\nURL: https://mariadb.com/kb/en/alter-table/\n\n','','https://mariadb.com/kb/en/alter-table/'),(464,'MPOINTFROMWKB',32,'MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])\n\nConstructs a MULTIPOINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/mpointfromwkb/\n\n','','https://mariadb.com/kb/en/mpointfromwkb/'),(465,'CHAR BYTE',22,'The CHAR BYTE data type is an alias for the BINARY data type. This is a\ncompatibility feature.\n\nURL: https://mariadb.com/kb/en/char-byte/\n\n','','https://mariadb.com/kb/en/char-byte/'),(466,'REPAIR TABLE',20,'Syntax:\nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n\nREPAIR TABLE repairs a possibly corrupted table. By default, it has the\nsame effect as myisamchk --recover tbl_name. REPAIR TABLE works for\nMyISAM, ARCHIVE, and CSV tables. See\nhttps://mariadb.com/kb/en/myisam-storage-engine/, and\nhttps://mariadb.com/kb/en/archive/, and\nhttps://mariadb.com/kb/en/csv/\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nREPAIR TABLE is supported for partitioned tables. However, the USE_FRM\noption cannot be used with this statement on a partitioned table.\n\nYou can use ALTER TABLE ... REPAIR PARTITION to repair one or more\npartitions; for more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/repair-table/\n\n','','https://mariadb.com/kb/en/repair-table/'),(467,'MERGE',39,'The MERGE storage engine, also known as the MRG_MyISAM engine, is a\ncollection of identical MyISAM tables that can be used as one.\n\"Identical\" means that all tables have identical column and index\ninformation. You cannot merge MyISAM tables in which the columns are\nlisted in a different order, do not have exactly the same columns, or\nhave the indexes in different order. However, any or all of the MyISAM\ntables can be compressed with myisampack. See\nhttps://mariadb.com/kb/en/myisampack/. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS do not\nmatter.\n\nURL: https://mariadb.com/kb/en/merge/\n\n','MariaDB> CREATE TABLE t1 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> CREATE TABLE t2 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nMariaDB> INSERT INTO t1 (message) VALUES (\'Testing\'),(\'table\'),(\'t1\');\nMariaDB> INSERT INTO t2 (message) VALUES (\'Testing\'),(\'table\'),(\'t2\');\nMariaDB> CREATE TABLE total (\n -> a INT NOT NULL AUTO_INCREMENT,\n -> message CHAR(20), INDEX(a))\n -> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n','https://mariadb.com/kb/en/merge/'),(468,'CREATE TABLE',39,'Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n select_statement\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT default_value]\n [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [STORAGE {DISK|MEMORY|DEFAULT}]\n [reference_definition]\n\ndata_type:\n BIT[(length)]\n | TINYINT[(length)] [UNSIGNED] [ZEROFILL]\n | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]\n | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]\n | INT[(length)] [UNSIGNED] [ZEROFILL]\n | INTEGER[(length)] [UNSIGNED] [ZEROFILL]\n | BIGINT[(length)] [UNSIGNED] [ZEROFILL]\n | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | DATE\n | TIME\n | TIMESTAMP\n | DATETIME\n | YEAR\n | CHAR[(length)]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | VARCHAR(length)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | BINARY[(length)]\n | VARBINARY(length)\n | TINYBLOB\n | BLOB\n | MEDIUMBLOB\n | LONGBLOB\n | TINYTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | TEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | MEDIUMTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | LONGTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | ENUM(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | SET(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | spatial_type\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES \n {LESS THAN {(expr | value_list) | MAXVALUE} \n | \n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n\nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some valid select statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nRules for permissible table names are given in\nhttps://mariadb.com/kb/en/identifier-names/. By default,\nthe table is created in the default database, using the InnoDB storage\nengine. An error occurs if the table exists, if there is no default\ndatabase, or if the database does not exist.\n\nURL: https://mariadb.com/kb/en/create-table/\n\n','','https://mariadb.com/kb/en/create-table/'),(469,'>',18,'Syntax:\n>\n\nGreater than:\n\nURL: https://mariadb.com/kb/en/greater-than/\n\n','MariaDB> SELECT 2 > 2;\n -> 0\n','https://mariadb.com/kb/en/greater-than/'),(470,'ANALYZE TABLE',20,'Syntax:\nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nANALYZE TABLE analyzes and stores the key distribution for a table.\nDuring the analysis, the table is locked with a read lock for InnoDB\nand MyISAM. This statement works with InnoDB, Aria and MyISAM tables.\nFor MyISAM tables, this statement is equivalent to using myisamchk\n--analyze.\n\nFor more information on how the analysis works within InnoDB, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html.\n\nMySQL uses the stored key distribution to decide the order in which\ntables should be joined when you perform a join on something other than\na constant. In addition, key distributions can be used when deciding\nwhich indexes to use for a specific table within a query.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nANALYZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... ANALYZE PARTITION to analyze one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: https://mariadb.com/kb/en/analyze-table/\n\n','','https://mariadb.com/kb/en/analyze-table/'),(471,'MICROSECOND',31,'Syntax:\nMICROSECOND(expr)\n\nReturns the microseconds from the time or datetime expression expr as a\nnumber in the range from 0 to 999999.\n\nURL: https://mariadb.com/kb/en/microsecond/\n\n','MariaDB> SELECT MICROSECOND(\'12:00:00.123456\');\n -> 123456\nMariaDB> SELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n -> 10\n','https://mariadb.com/kb/en/microsecond/'),(472,'CONSTRAINT',39,'InnoDB supports foreign keys, which let you cross-reference related\ndata across tables, and foreign key constraints, which help keep this\nspread-out data consistent. The syntax for an InnoDB foreign key\nconstraint definition in the CREATE TABLE or ALTER TABLE statement\nlooks like this:\n\n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\nURL: https://mariadb.com/kb/en/constraint/\n\n','CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n','https://mariadb.com/kb/en/constraint/'),(473,'CREATE SERVER',39,'Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nwithin the servers table within the mysql database. This statement\nrequires the SUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name should be mysql, and may be quoted with single\nquotation marks. Other values for wrapper_name are not currently\nsupported.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*: Note that the OWNER option is currently not applied, and has no\neffect on the ownership or operation of the server connection that is\ncreated.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: https://mariadb.com/kb/en/create-server/\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE \'test\');\n','https://mariadb.com/kb/en/create-server/'),(474,'FIELD',37,'Syntax:\nFIELD(str,str1,str2,str3,...)\n\nReturns the index (position) of str in the str1, str2, str3, ... list.\nReturns 0 if str is not found.\n\nIf all arguments to FIELD() are strings, all arguments are compared as\nstrings. If all arguments are numbers, they are compared as numbers.\nOtherwise, the arguments are compared as double.\n\nIf str is NULL, the return value is 0 because NULL fails equality\ncomparison with any value. FIELD() is the complement of ELT().\n\nURL: https://mariadb.com/kb/en/field/\n\n','MariaDB> SELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 2\nMariaDB> SELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 0\n','https://mariadb.com/kb/en/field/'),(475,'MAKETIME',31,'Syntax:\nMAKETIME(hour,minute,second)\n\nReturns a time value calculated from the hour, minute, and second\narguments.\n\nURL: https://mariadb.com/kb/en/maketime/\n\n','MariaDB> SELECT MAKETIME(12,15,30);\n -> \'12:15:30\'\n','https://mariadb.com/kb/en/maketime/'),(476,'CURDATE',31,'Syntax:\nCURDATE()\n\nReturns the current date as a value in \'YYYY-MM-DD\' or YYYYMMDD format,\ndepending on whether the function is used in a string or numeric\ncontext.\n\nURL: https://mariadb.com/kb/en/curdate/\n\n','MariaDB> SELECT CURDATE();\n -> \'2008-06-13\'\nMariaDB> SELECT CURDATE() + 0;\n -> 20080613\n','https://mariadb.com/kb/en/curdate/'),(477,'SET PASSWORD',10,'Syntax:\nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'cleartext password\')\n | OLD_PASSWORD(\'cleartext password\')\n | \'encrypted password\'\n }\n\nThe SET PASSWORD statement assigns a password to an existing MySQL user\naccount. When the read_only system variable is enabled, the SUPER\nprivilege is required to use SET PASSWORD, in addition to whatever\nother privileges might be required.\n\nIf the password is specified using the PASSWORD() or OLD_PASSWORD()\nfunction, the cleartext (unencrypted) password should be given as the\nargument to the function, which hashes the password and returns the\nencrypted password string. If the password is specified without using\neither function, it should be the already encrypted password value as a\nliteral string. In all cases, the encrypted password string must be in\nthe format required by the authentication method used for the account.\n\nThe old_passwords system variable value determines the hashing method\nused by PASSWORD(). If you specify the password using that function and\nSET PASSWORD rejects the password as not being in the correct format,\nit may be necessary to set old_passwords to change the hashing method.\nFor descriptions of the permitted values, see\nhttps://mariadb.com/kb/en/server-system-variables#old_passwords.\n\nWith no FOR user clause, this statement sets the password for the\ncurrent user. (To see which account the server authenticated you as,\ninvoke the CURRENT_USER() function.) Any client who successfully\nconnects to the server using a nonanonymous account can change the\npassword for that account.\n\nWith a FOR user clause, this statement sets the password for the named\nuser. You must have the UPDATE privilege for the mysql database to do\nthis. The user account name uses the format described in\nhttps://mariadb.com/kb/en/create-user#account-names. The user\nvalue should be given as \'user_name\'@\'host_name\', where \'user_name\' and\n\'host_name\' are exactly as listed in the User and Host columns of the\nmysql.user table row. (If you specify only a user name, a host name of\n\'%\' is used.) For example, to set the password for an account with User\nand Host column values of \'bob\' and \'%.example.org\', write the\nstatement like this:\n\nSET PASSWORD FOR \'bob\'@\'%.example.org\' = PASSWORD(\'cleartext password\');\n\nURL: https://mariadb.com/kb/en/set-password/\n\n','','https://mariadb.com/kb/en/set-password/'),(478,'ALTER TABLESPACE',39,'Syntax:\nALTER TABLESPACE tablespace_name\n {ADD|DROP} DATAFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement is used with NDB cluster, which is not supported by MariaDB.\n\nURL: https://mariadb.com/kb/en/alter-tablespace/\n\n','','https://mariadb.com/kb/en/alter-tablespace/'),(479,'IF FUNCTION',7,'Syntax:\nIF(expr1,expr2,expr3)\n\nIf expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns\nexpr2; otherwise it returns expr3. IF() returns a numeric or string\nvalue, depending on the context in which it is used.\n\nURL: https://mariadb.com/kb/en/if-function/\n\n','MariaDB> SELECT IF(1>2,2,3);\n -> 3\nMariaDB> SELECT IF(1<2,\'yes\',\'no\');\n -> \'yes\'\nMariaDB> SELECT IF(STRCMP(\'test\',\'test1\'),\'no\',\'yes\');\n -> \'no\'\n','https://mariadb.com/kb/en/if-function/'),(480,'ENUM',22,'ENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nAn enumeration. A string object that can have only one value, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or the special \'\'\nerror value. An ENUM column can have a maximum of 65,535 distinct\nvalues. ENUM values are represented internally as integers.\n\nURL: https://mariadb.com/kb/en/enum/\n\n','','https://mariadb.com/kb/en/enum/'),(481,'DATABASE',17,'Syntax:\nDATABASE()\n\nReturns the default (current) database name as a string in the utf8\ncharacter set. If there is no default database, DATABASE() returns\nNULL. Within a stored routine, the default database is the database\nthat the routine is associated with, which is not necessarily the same\nas the database that is the default in the calling context.\n\nURL: https://mariadb.com/kb/en/database/\n\n','MariaDB> SELECT DATABASE();\n -> \'test\'\n','https://mariadb.com/kb/en/database/'),(482,'POINTFROMWKB',32,'PointFromWKB(wkb[,srid])\n\nConstructs a POINT value using its WKB representation and SRID.\n\nURL: https://mariadb.com/kb/en/pointfromwkb/\n\n','','https://mariadb.com/kb/en/pointfromwkb/'),(483,'POWER',4,'Syntax:\nPOWER(X,Y)\n\nThis is a synonym for POW().\n\nURL: https://mariadb.com/kb/en/power/\n\n','','https://mariadb.com/kb/en/power/'),(484,'ATAN',4,'Syntax:\nATAN(X)\n\nReturns the arc tangent of X, that is, the value whose tangent is X.\n\nURL: https://mariadb.com/kb/en/atan/\n\n','MariaDB> SELECT ATAN(2);\n -> 1.1071487177941\nMariaDB> SELECT ATAN(-2);\n -> -1.1071487177941\n','https://mariadb.com/kb/en/atan/'),(485,'STRCMP',37,'Syntax:\nSTRCMP(expr1,expr2)\n\nSTRCMP() returns 0 if the strings are the same, -1 if the first\nargument is smaller than the second according to the current sort\norder, and 1 otherwise.\n\nURL: https://mariadb.com/kb/en/strcmp/\n\n','MariaDB> SELECT STRCMP(\'text\', \'text2\');\n -> -1\nMariaDB> SELECT STRCMP(\'text2\', \'text\');\n -> 1\nMariaDB> SELECT STRCMP(\'text\', \'text\');\n -> 0\n','https://mariadb.com/kb/en/strcmp/'),(486,'INSERT DELAYED',27,'Syntax:\nINSERT DELAYED ...\n\nThe DELAYED option for the INSERT statement is a MySQL extension to\nstandard SQL that is very useful if you have clients that cannot or\nneed not wait for the INSERT to complete. This is a common situation\nwhen you use MySQL for logging and you also periodically run SELECT and\nUPDATE statements that take a long time to complete.\n\nWhen a client uses INSERT DELAYED, it gets an okay from the server at\nonce, and the row is queued to be inserted when the table is not in use\nby any other thread.\n\nAnother major benefit of using INSERT DELAYED is that inserts from many\nclients are bundled together and written in one block. This is much\nfaster than performing many separate inserts.\n\nNote that INSERT DELAYED is slower than a normal INSERT if the table is\nnot otherwise in use. There is also the additional overhead for the\nserver to handle a separate thread for each table for which there are\ndelayed rows. This means that you should use INSERT DELAYED only when\nyou are really sure that you need it.\n\nThe queued rows are held only in memory until they are inserted into\nthe table. This means that if you terminate mysqld forcibly (for\nexample, with kill -9) or if mysqld dies unexpectedly, any queued rows\nthat have not been written to disk are lost.\n\nThere are some constraints on the use of DELAYED:\n\no INSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE, and BLACKHOLE\n tables. For engines that do not support DELAYED, an error occurs.\n\no An error occurs for INSERT DELAYED if used with a table that has been\n locked with LOCK TABLES because the insert must be handled by a\n separate thread, not by the session that holds the lock.\n\no For MyISAM tables, if there are no free blocks in the middle of the\n data file, concurrent SELECT and INSERT statements are supported.\n Under these circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\n\no INSERT DELAYED should be used only for INSERT statements that specify\n value lists. The server ignores DELAYED for INSERT ... SELECT or\n INSERT ... ON DUPLICATE KEY UPDATE statements.\n\no Because the INSERT DELAYED statement returns immediately, before the\n rows are inserted, you cannot use LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\n\no DELAYED rows are not visible to SELECT statements until they actually\n have been inserted.\n\no Prior to MySQL 5.5.7, INSERT DELAYED was treated as a normal INSERT\n if the statement inserted multiple rows, binary logging was enabled,\n and the global logging format was statement-based (that is, whenever\n binlog_format was set to STATEMENT). Beginning with MySQL 5.5.7,\n INSERT DELAYED is always handled as a simple INSERT (that is, without\n the DELAYED option) whenever the value of binlog_format is STATEMENT\n or MIXED. (In the latter case, the statement no longer triggers a\n switch to row-based logging, and so is logged using the\n statement-based format.)\n\n This does not apply when using row-based binary logging mode\n (binlog_format set to ROW), in which INSERT DELAYED statements are\n always executed using the DELAYED option as specified, and logged as\n row-update events.\n\no DELAYED is ignored on slave replication servers, so that INSERT\n DELAYED is treated as a normal INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than the master.\n\no Pending INSERT DELAYED statements are lost if a table is write locked\n and ALTER TABLE is used to modify the table structure.\n\no INSERT DELAYED is not supported for views.\n\no INSERT DELAYED is not supported for partitioned tables.\n\nURL: https://mariadb.com/kb/en/insert-delayed/\n\n','','https://mariadb.com/kb/en/insert-delayed/'),(487,'SHOW PROFILE',26,'Syntax:\nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n\ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n\nThe SHOW PROFILE and SHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements executed\nduring the course of the current session.\n\nProfiling is controlled by the profiling session variable, which has a\ndefault value of 0 (OFF). Profiling is enabled by setting profiling to\n1 or ON:\n\nMariaDB> SET profiling = 1;\n\nSHOW PROFILES displays a list of the most recent statements sent to the\nserver. The size of the list is controlled by the\nprofiling_history_size session variable, which has a default value of\n15. The maximum value is 100. Setting the value to 0 has the practical\neffect of disabling profiling.\n\nAll statements are profiled except SHOW PROFILE and SHOW PROFILES, so\nyou will find neither of those statements in the profile list.\nMalformed statements are profiled. For example, SHOW PROFILING is an\nillegal statement, and a syntax error occurs if you try to execute it,\nbut it will show up in the profiling list.\n\nSHOW PROFILE displays detailed information about a single statement.\nWithout the FOR QUERY n clause, the output pertains to the most\nrecently executed statement. If FOR QUERY n is included, SHOW PROFILE\ndisplays information for statement n. The values of n correspond to the\nQuery_ID values displayed by SHOW PROFILES.\n\nThe LIMIT row_count clause may be given to limit the output to\nrow_count rows. If LIMIT is given, OFFSET offset may be added to begin\nthe output offset rows into the full set of rows.\n\nBy default, SHOW PROFILE displays Status and Duration columns. The\nStatus values are like the State values displayed by SHOW PROCESSLIST,\nalthough there might be some minor differences in interpretion for the\ntwo statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.5/en/thread-information.html).\n\nOptional type values may be specified to display specific additional\ntypes of information:\n\no ALL displays all information\n\no BLOCK IO displays counts for block input and output operations\n\no CONTEXT SWITCHES displays counts for voluntary and involuntary\n context switches\n\no CPU displays user and system CPU usage times\n\no IPC displays counts for messages sent and received\n\no MEMORY is not currently implemented\n\no PAGE FAULTS displays counts for major and minor page faults\n\no SOURCE displays the names of functions from the source code, together\n with the name and line number of the file in which the function\n occurs\n\no SWAPS displays swap counts\n\nProfiling is enabled per session. When a session ends, its profiling\ninformation is lost.\n\nURL: https://mariadb.com/kb/en/show-profile/\n\n','MariaDB> SELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n1 row in set (0.00 sec)\n\nMariaDB> SET profiling = 1;\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> DROP TABLE IF EXISTS t1;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nMariaDB> CREATE TABLE T1 (id INT);\nQuery OK, 0 rows affected (0.01 sec)\n\nMariaDB> SHOW PROFILES;\n+----------+----------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+----------+--------------------------+\n| 0 | 0.000088 | SET PROFILING = 1 |\n| 1 | 0.000136 | DROP TABLE IF EXISTS t1 |\n| 2 | 0.011947 | CREATE TABLE t1 (id INT) |\n+----------+----------+--------------------------+\n3 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| checking permissions | 0.000040 |\n| creating table | 0.000056 |\n| After create | 0.011363 |\n| query end | 0.000375 |\n| freeing items | 0.000089 |\n| logging slow query | 0.000019 |\n| cleaning up | 0.000005 |\n+----------------------+----------+\n7 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE FOR QUERY 1;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| query end | 0.000107 |\n| freeing items | 0.000008 |\n| logging slow query | 0.000015 |\n| cleaning up | 0.000006 |\n+--------------------+----------+\n4 rows in set (0.00 sec)\n\nMariaDB> SHOW PROFILE CPU FOR QUERY 2;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| checking permissions | 0.000040 | 0.000038 | 0.000002 |\n| creating table | 0.000056 | 0.000028 | 0.000028 |\n| After create | 0.011363 | 0.000217 | 0.001571 |\n| query end | 0.000375 | 0.000013 | 0.000028 |\n| freeing items | 0.000089 | 0.000010 | 0.000014 |\n| logging slow query | 0.000019 | 0.000009 | 0.000010 |\n| cleaning up | 0.000005 | 0.000003 | 0.000002 |\n+----------------------+----------+----------+------------+\n7 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-profile/'),(488,'SHOW PROCEDURE CODE',26,'Syntax:\nSHOW PROCEDURE CODE proc_name\n\nThis statement is a MySQL extension that is available only for servers\nthat have been built with debugging support. It displays a\nrepresentation of the internal implementation of the named stored\nprocedure. A similar statement, SHOW FUNCTION CODE, displays\ninformation about stored functions (see [HELP SHOW FUNCTION CODE]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table.\n\nIf the named routine is available, each statement produces a result\nset. Each row in the result set corresponds to one \"instruction\" in the\nroutine. The first column is Pos, which is an ordinal number beginning\nwith 0. The second column is Instruction, which contains an SQL\nstatement (usually changed from the original source), or a directive\nwhich has meaning only to the stored-routine handler.\n\nURL: https://mariadb.com/kb/en/show-procedure-code/\n\n','MariaDB> DELIMITER //\nMariaDB> CREATE PROCEDURE p1 ()\n -> BEGIN\n -> DECLARE fanta INT DEFAULT 55;\n -> DROP TABLE t2;\n -> LOOP\n -> INSERT INTO t3 VALUES (fanta);\n -> END LOOP;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nMariaDB> SHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n4 rows in set (0.00 sec)\n','https://mariadb.com/kb/en/show-procedure-code/'),(489,'MEDIUMTEXT',22,'MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 16,777,215 (224 - 1) characters.\nThe effective maximum length is less if the value contains multi-byte\ncharacters. Each MEDIUMTEXT value is stored using a 3-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: https://mariadb.com/kb/en/mediumtext/\n\n','','https://mariadb.com/kb/en/mediumtext/'),(490,'LN',4,'Syntax:\nLN(X)\n\nReturns the natural logarithm of X; that is, the base-e logarithm of X.\nIf X is less than or equal to 0, then NULL is returned.\n\nURL: https://mariadb.com/kb/en/ln/\n\n','MariaDB> SELECT LN(2);\n -> 0.69314718055995\nMariaDB> SELECT LN(-2);\n -> NULL\n','https://mariadb.com/kb/en/ln/'),(491,'RETURN',23,'Syntax:\nRETURN expr\n\nThe RETURN statement terminates execution of a stored function and\nreturns the value expr to the function caller. There must be at least\none RETURN statement in a stored function. There may be more than one\nif the function has multiple exit points.\n\nThis statement is not used in stored procedures, triggers, or events.\nThe LEAVE statement can be used to exit a stored program of those\ntypes.\n\nURL: https://mariadb.com/kb/en/return/\n\n','','https://mariadb.com/kb/en/return/'),(492,'SHOW COLLATION',26,'Syntax:\nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement lists collations supported by the server. By default,\nthe output from SHOW COLLATION includes all available collations. The\nLIKE clause, if present, indicates which collation names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttps://mariadb.com/kb/en/extended-show/. For example:\n\nMariaDB> SHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | | 0 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |\n| latin1_danish_ci | latin1 | 15 | | | 0 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 0 |\n| latin1_general_ci | latin1 | 48 | | | 0 |\n| latin1_general_cs | latin1 | 49 | | | 0 |\n| latin1_spanish_ci | latin1 | 94 | | | 0 |\n+-------------------+---------+----+---------+----------+---------+\n\nURL: https://mariadb.com/kb/en/show-collation/\n\n','','https://mariadb.com/kb/en/show-collation/'),(493,'LOG',4,'Syntax:\nLOG(X), LOG(B,X)\n\nIf called with one parameter, this function returns the natural\nlogarithm of X. If X is less than or equal to 0, then NULL is returned.\n\nThe inverse of this function (when called with a single argument) is\nthe EXP() function.\n\nURL: https://mariadb.com/kb/en/log/\n\n','MariaDB> SELECT LOG(2);\n -> 0.69314718055995\nMariaDB> SELECT LOG(-2);\n -> NULL\n','https://mariadb.com/kb/en/log/'),(494,'SET SQL_LOG_BIN',8,'Syntax:\nSET sql_log_bin = {0|1}\n\nThe sql_log_bin variable controls whether logging to the binary log is\ndone. The default value is 1 (do logging). To change logging for the\ncurrent session, change the session value of this variable. The session\nuser must have the SUPER privilege to set this variable.\n\nBeginning with MySQL 5.5.5, it is no longer possible to set\n@@session.sql_log_bin within a transaction or subquery. (Bug #53437)\n\nURL: https://mariadb.com/kb/en/set-sql_log_bin/\n\n','','https://mariadb.com/kb/en/set-sql_log_bin/'),(495,'!=',18,'Syntax:\n<>, !=\n\nNot equal:\n\nURL: https://mariadb.com/kb/en/not-equal/\n\n','MariaDB> SELECT \'.01\' <> \'0.01\';\n -> 1\nMariaDB> SELECT .01 <> \'0.01\';\n -> 0\nMariaDB> SELECT \'zapp\' <> \'zappp\';\n -> 1\n','https://mariadb.com/kb/en/not-equal/'),(496,'WHILE',23,'Syntax:\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nThe statement list within a WHILE statement is repeated as long as the\nsearch_condition expression is true. statement_list consists of one or\nmore SQL statements, each terminated by a semicolon (;) statement\ndelimiter.\n\nA WHILE statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: https://mariadb.com/kb/en/while/\n\n','CREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n\n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n END WHILE;\nEND;\n','https://mariadb.com/kb/en/while/'),(497,'AES_DECRYPT',12,'Syntax:\nAES_DECRYPT(crypt_str,key_str)\n\nThis function decrypts data using the official AES (Advanced Encryption\nStandard) algorithm. For more information, see the description of\nAES_ENCRYPT().\n\nURL: https://mariadb.com/kb/en/aes_decrypt/\n\n','','https://mariadb.com/kb/en/aes_decrypt/'),(498,'DAYNAME',31,'Syntax:\nDAYNAME(date)\n\nReturns the name of the weekday for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(https://mariadb.com/kb/en/server-system-variables#lc_time_names).\n\nURL: https://mariadb.com/kb/en/dayname/\n\n','MariaDB> SELECT DAYNAME(\'2007-02-03\');\n -> \'Saturday\'\n','https://mariadb.com/kb/en/dayname/'),(499,'COERCIBILITY',17,'Syntax:\nCOERCIBILITY(str)\n\nReturns the collation coercibility value of the string argument.\n\nURL: https://mariadb.com/kb/en/coercibility/\n\n','MariaDB> SELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n -> 0\nMariaDB> SELECT COERCIBILITY(USER());\n -> 3\nMariaDB> SELECT COERCIBILITY(\'abc\');\n -> 4\n','https://mariadb.com/kb/en/coercibility/'),(500,'INT',22,'INT[(M)] [UNSIGNED] [ZEROFILL]\n\nA normal-size integer. The signed range is -2147483648 to 2147483647.\nThe unsigned range is 0 to 4294967295.\n\nURL: https://mariadb.com/kb/en/int/\n\n','','https://mariadb.com/kb/en/int/'),(501,'GLENGTH',13,'GLength(ls)\n\nReturns as a double-precision number the length of the LineString value\nls in its associated spatial reference.\n\nURL: https://mariadb.com/kb/en/glength/\n\n','MariaDB> SET @ls = \'LineString(1 1,2 2,3 3)\';\nMariaDB> SELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.8284271247462 |\n+----------------------------+\n','https://mariadb.com/kb/en/glength/'),(502,'RADIANS',4,'Syntax:\nRADIANS(X)\n\nReturns the argument X, converted from degrees to radians. (Note that\nπ radians equals 180 degrees.)\n\nURL: https://mariadb.com/kb/en/radians/\n\n','MariaDB> SELECT RADIANS(90);\n -> 1.5707963267949\n','https://mariadb.com/kb/en/radians/'),(503,'COLLATION',17,'Syntax:\nCOLLATION(str)\n\nReturns the collation of the string argument.\n\nURL: https://mariadb.com/kb/en/collation/\n\n','MariaDB> SELECT COLLATION(\'abc\');\n -> \'latin1_swedish_ci\'\nMariaDB> SELECT COLLATION(_utf8\'abc\');\n -> \'utf8_general_ci\'\n','https://mariadb.com/kb/en/collation/'),(504,'COALESCE',18,'Syntax:\nCOALESCE(value,...)\n\nReturns the first non-NULL value in the list, or NULL if there are no\nnon-NULL values.\n\nURL: https://mariadb.com/kb/en/coalesce/\n\n','MariaDB> SELECT COALESCE(NULL,1);\n -> 1\nMariaDB> SELECT COALESCE(NULL,NULL,NULL);\n -> NULL\n','https://mariadb.com/kb/en/coalesce/'),(505,'VERSION',17,'Syntax:\nVERSION()\n\nReturns a string that indicates the MySQL server version. The string\nuses the utf8 character set. The value might have a suffix in addition\nto the version number. See the description of the version system\nvariable in\nhttps://mariadb.com/kb/en/server-system-variables#version.\n\nURL: https://mariadb.com/kb/en/version/\n\n','MariaDB> SELECT VERSION();\n -> \'5.5.29-standard\'\n','https://mariadb.com/kb/en/version/'),(506,'MAKE_SET',37,'Syntax:\nMAKE_SET(bits,str1,str2,...)\n\nReturns a set value (a string containing substrings separated by \",\"\ncharacters) consisting of the strings that have the corresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL\nvalues in str1, str2, ... are not appended to the result.\n\nURL: https://mariadb.com/kb/en/make_set/\n\n','MariaDB> SELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n -> \'a\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n -> \'hello,world\'\nMariaDB> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n -> \'hello\'\nMariaDB> SELECT MAKE_SET(0,\'a\',\'b\',\'c\');\n -> \'\'\n','https://mariadb.com/kb/en/make_set/'),(507,'FIND_IN_SET',37,'Syntax:\nFIND_IN_SET(str,strlist)\n\nReturns a value in the range of 1 to N if the string str is in the\nstring list strlist consisting of N substrings. A string list is a\nstring composed of substrings separated by \",\" characters. If the first\nargument is a constant string and the second is a column of type SET,\nthe FIND_IN_SET() function is optimized to use bit arithmetic. Returns\n0 if str is not in strlist or if strlist is the empty string. Returns\nNULL if either argument is NULL. This function does not work properly\nif the first argument contains a comma (\",\") character.\n\nURL: https://mariadb.com/kb/en/find_in_set/\n\n','MariaDB> SELECT FIND_IN_SET(\'b\',\'a,b,c,d\');\n -> 2\n','https://mariadb.com/kb/en/find_in_set/'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `host` +-- + +DROP TABLE IF EXISTS `host`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `host` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `host` +-- + +LOCK TABLES `host` WRITE; +/*!40000 ALTER TABLE `host` DISABLE KEYS */; +/*!40000 ALTER TABLE `host` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `index_stats` +-- + +DROP TABLE IF EXISTS `index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `index_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `prefix_arity` int(11) unsigned NOT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `index_stats` +-- + +LOCK TABLES `index_stats` WRITE; +/*!40000 ALTER TABLE `index_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_index_stats` +-- + +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_index_stats` +-- + +LOCK TABLES `innodb_index_stats` WRITE; +/*!40000 ALTER TABLE `innodb_index_stats` DISABLE KEYS */; +INSERT INTO `innodb_index_stats` VALUES ('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:16:25','n_diff_pfx01',0,1,'domain_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:16:25','n_diff_pfx02',0,1,'domain_id,sub_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:16:25','n_leaf_pages',1,NULL,'Number of leaf pages in the index'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:16:25','size',1,NULL,'Number of pages in the index'); +/*!40000 ALTER TABLE `innodb_index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_table_stats` +-- + +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_table_stats` +-- + +LOCK TABLES `innodb_table_stats` WRITE; +/*!40000 ALTER TABLE `innodb_table_stats` DISABLE KEYS */; +INSERT INTO `innodb_table_stats` VALUES ('mysql','gtid_slave_pos','2020-05-31 16:16:25',0,1,0); +/*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +INSERT INTO `proc` VALUES ('mysql','AddGeometryColumn','PROCEDURE','AddGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64), t_srid int','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:16:25','2020-05-31 16:16:25','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','NONE'),('mysql','DropGeometryColumn','PROCEDURE','DropGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64)','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','root@localhost','2020-05-31 16:16:25','2020-05-31 16:16:25','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','NONE'); +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') COLLATE utf8_bin NOT NULL, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT 0, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 16:16:25'),('asus','root','','',1,'','2020-05-31 16:16:25'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_mapping` +-- + +DROP TABLE IF EXISTS `roles_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_mapping` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Admin_option` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + UNIQUE KEY `Host` (`Host`,`User`,`Role`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Granted roles'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_mapping` +-- + +LOCK TABLES `roles_mapping` WRITE; +/*!40000 ALTER TABLE `roles_mapping` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_mapping` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` varchar(2048) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(80) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT 0, + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` varchar(512) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `table_stats` +-- + +DROP TABLE IF EXISTS `table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `table_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `cardinality` bigint(21) unsigned DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `table_stats` +-- + +LOCK TABLES `table_stats` WRITE; +/*!40000 ALTER TABLE `table_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT 0, + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT 0, + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', + `ssl_cipher` blob NOT NULL, + `x509_issuer` blob NOT NULL, + `x509_subject` blob NOT NULL, + `max_questions` int(11) unsigned NOT NULL DEFAULT 0, + `max_updates` int(11) unsigned NOT NULL DEFAULT 0, + `max_connections` int(11) unsigned NOT NULL DEFAULT 0, + `max_user_connections` int(11) NOT NULL DEFAULT 0, + `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, + `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, + PRIMARY KEY (`Host`,`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0.000000),('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000),('asus','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'','','N','N','',0.000000); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transaction_registry` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `transaction_registry` ( + `transaction_id` bigint(20) unsigned NOT NULL, + `commit_id` bigint(20) unsigned NOT NULL, + `begin_timestamp` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `commit_timestamp` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `isolation_level` enum('READ-UNCOMMITTED','READ-COMMITTED','REPEATABLE-READ','SERIALIZABLE') COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`transaction_id`), + UNIQUE KEY `commit_id` (`commit_id`), + KEY `begin_timestamp` (`begin_timestamp`), + KEY `commit_timestamp` (`commit_timestamp`,`transaction_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 19:16:46 diff --git a/mysql-test/std_data/mysql_database_10.4.dump b/mysql-test/std_data/mysql_database_10.4.dump new file mode 100644 index 00000000000..f396f4ebf76 --- /dev/null +++ b/mysql-test/std_data/mysql_database_10.4.dump @@ -0,0 +1,923 @@ +-- MariaDB dump 10.17 Distrib 10.4.13-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 10.4.13-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `column_stats` +-- + +DROP TABLE IF EXISTS `column_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, + `nulls_ratio` decimal(12,4) DEFAULT NULL, + `avg_length` decimal(12,4) DEFAULT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + `hist_size` tinyint(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `column_stats` +-- + +LOCK TABLES `column_stats` WRITE; +/*!40000 ALTER TABLE `column_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `column_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + PRIMARY KEY (`db`,`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT 0, + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `global_priv` +-- + +DROP TABLE IF EXISTS `global_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `global_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + PRIMARY KEY (`Host`,`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `global_priv` +-- + +LOCK TABLES `global_priv` WRITE; +/*!40000 ALTER TABLE `global_priv` DISABLE KEYS */; +INSERT INTO `global_priv` VALUES ('localhost','mariadb.sys','{\"access\":0,\"plugin\":\"mysql_native_password\",\"authentication_string\":\"\",\"account_locked\":true,\"password_last_changed\":0}'),('localhost','root','{\"access\":18446744073709551615,\"plugin\":\"mysql_native_password\",\"authentication_string\":\"\",\"auth_or\":[{},{\"plugin\":\"unix_socket\"}],\"password_last_changed\":1590943617}'),('localhost','','{}'),('asus','','{}'); +/*!40000 ALTER TABLE `global_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gtid_slave_pos` +-- + +DROP TABLE IF EXISTS `gtid_slave_pos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gtid_slave_pos` ( + `domain_id` int(10) unsigned NOT NULL, + `sub_id` bigint(20) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `seq_no` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`domain_id`,`sub_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Replication slave GTID position'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gtid_slave_pos` +-- + +LOCK TABLES `gtid_slave_pos` WRITE; +/*!40000 ALTER TABLE `gtid_slave_pos` DISABLE KEYS */; +/*!40000 ALTER TABLE `gtid_slave_pos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon Properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control Flow Functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point Properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString Properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical Operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison Operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry Constructors',34,''),(25,'GeometryCollection Properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry Relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry Properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''),(40,'Sequences',35,''),(41,'JSON Functions',38,''),(42,'Window Functions',38,''),(43,'Spider Functions',38,''),(44,'Dynamic Column Functions',38,''),(45,'Storage Engines',35,''),(46,'InnoDB',45,''),(47,'Optimization and Indexes',35,''),(48,'Full-text Indexes',47,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (1,'account'),(2,'aggregate'),(3,'add'),(4,'after'),(5,'alter'),(6,'completion'),(7,'schedule'),(8,'server'),(9,'columns'),(10,'drop'),(11,'analyze'),(12,'json'),(13,'value'),(14,'master_ssl_ca'),(15,'master_ssl_verify_cert'),(16,'nchar'),(17,'action'),(18,'create'),(19,'at'),(20,'starts'),(21,'returns'),(22,'host'),(23,'row_format'),(24,'deallocate prepare'),(25,'drop prepare'),(26,'against'),(27,'fulltext'),(28,'escape'),(29,'mode'),(30,'repeat'),(31,'sql_big_result'),(32,'isolation'),(33,'read committed'),(34,'read uncommitted'),(35,'repeatable read'),(36,'serializable'),(37,'work'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (116,1),(118,1),(119,1),(183,2),(184,2),(185,2),(186,2),(187,2),(188,2),(189,2),(190,2),(191,2),(192,2),(193,2),(194,2),(196,2),(197,2),(199,2),(258,2),(724,2),(652,3),(751,3),(652,4),(119,5),(645,5),(646,5),(647,5),(648,5),(649,5),(650,5),(652,5),(653,5),(654,5),(646,6),(657,6),(646,7),(657,7),(651,8),(357,9),(652,9),(665,9),(97,10),(120,10),(259,10),(652,10),(669,10),(670,10),(671,10),(672,10),(673,10),(674,10),(675,10),(676,10),(677,10),(678,10),(680,10),(681,10),(251,11),(444,11),(446,11),(447,11),(280,12),(447,12),(448,12),(449,12),(264,13),(317,13),(320,13),(419,13),(435,13),(95,14),(95,15),(271,16),(655,17),(665,17),(118,18),(127,18),(258,18),(656,18),(657,18),(658,18),(659,18),(660,18),(661,18),(662,18),(663,18),(664,18),(665,18),(666,18),(667,18),(668,18),(657,19),(657,20),(258,21),(664,22),(665,23),(97,24),(97,25),(614,26),(752,26),(752,27),(753,27),(607,28),(436,29),(614,29),(316,30),(625,30),(436,31),(108,32),(108,33),(108,34),(108,35),(108,36),(110,37); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (1,'HELP_DATE',9,'This help information was generated from the MariaDB Knowledge Base\non 2 September 2019.','',''),(2,'AREA',2,'A synonym for ST_AREA.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/polygon-properties-area/','','https://mariadb.com/kb/en/polygon-properties-area/'),(3,'CENTROID',2,'A synonym for ST_CENTROID.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/centroid/','','https://mariadb.com/kb/en/centroid/'),(4,'ExteriorRing',2,'A synonym for ST_ExteriorRing.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/polygon-properties-exteriorring/','','https://mariadb.com/kb/en/polygon-properties-exteriorring/'),(5,'InteriorRingN',2,'A synonym for ST_InteriorRingN.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/polygon-properties-interiorringn/','','https://mariadb.com/kb/en/polygon-properties-interiorringn/'),(6,'NumInteriorRings',2,'A synonym for ST_NumInteriorRings.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/polygon-properties-numinteriorrings/','','https://mariadb.com/kb/en/polygon-properties-numinteriorrings/'),(7,'ST_AREA',2,'Syntax\n------ \nST_Area(poly)\nArea(poly)\n \nDescription\n----------- \nReturns as a double-precision number the area of the Polygon\nvalue poly, as measured in its spatial reference system.\n \nST_Area() and Area() are synonyms.\n \nExamples\n-------- \nSET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1\n1))\';\n \nSELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_area/','','https://mariadb.com/kb/en/st_area/'),(8,'ST_CENTROID',2,'Syntax\n------ \nST_Centroid(mpoly)\nCentroid(mpoly)\n \nDescription\n----------- \nReturns a point reflecting the mathematical centroid\n(geometric center) for the MultiPolygon mpoly. The resulting\npoint will not necessarily be on the MultiPolygon. \n \nST_Centroid() and Centroid() are synonyms.\n \nExamples\n-------- \nSET @poly = ST_GeomFromText(\'POLYGON((0 0,20 0,20 20,0 20,0\n0))\');\nSELECT ST_AsText(ST_Centroid(@poly)) AS center;\n \n+--------------+\n| center |\n+--------------+\n| POINT(10 10) |\n+--------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_centroid/','','https://mariadb.com/kb/en/st_centroid/'),(9,'ST_ExteriorRing',2,'Syntax\n------ \nST_ExteriorRing(poly)\nExteriorRing(poly)\n \nDescription\n----------- \nReturns the exterior ring of the Polygon value poly as a\nLineString.\n \nST_ExteriorRing() and ExteriorRing() are synonyms.\n \nExamples\n-------- \nSET @poly = \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2\n1,1 1))\';\n \nSELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_exteriorring/','','https://mariadb.com/kb/en/st_exteriorring/'),(10,'ST_InteriorRingN',2,'Syntax\n------ \nST_InteriorRingN(poly,N)\nInteriorRingN(poly,N)\n \nDescription\n----------- \nReturns the N-th interior ring for the Polygon value poly as\na LineString. Rings are numbered beginning with 1.\n \nST_InteriorRingN() and InteriorRingN() are synonyms.\n \nExamples\n-------- \nSET @poly = \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2\n1,1 1))\';\n \nSELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_interiorringn/','','https://mariadb.com/kb/en/st_interiorringn/'),(11,'ST_NumInteriorRings',2,'Syntax\n------ \nST_NumInteriorRings(poly)\nNumInteriorRings(poly)\n \nDescription\n----------- \nReturns an integer containing the number of interior rings\nin the Polygon value poly.\n \nNote that according the the OpenGIS standard, a POLYGON\nshould have exactly one ExteriorRing and all other rings\nshould lie within that ExteriorRing and thus be the\nInteriorRings. Practically, however, some systems, including\nMariaDB\'s, permit polygons to have several\n\'ExteriorRings\'. In the case of there being multiple,\nnon-overlapping exterior rings ST_NumInteriorRings() will\nreturn 1.\n \nST_NumInteriorRings() and NumInteriorRings() are synonyms.\n \nExamples\n-------- \nSET @poly = \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2\n1,1 1))\';\n \nSELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n \nNon-overlapping \'polygon\':\n \nSELECT ST_NumInteriorRings(ST_PolyFromText(\'POLYGON((0 0,10\n0,10 10,0 10,0 0),\n (-1 -1,-5 -1,-5 -5,-1 -5,-1 -1))\')) AS NumInteriorRings;\n \n+------------------+\n| NumInteriorRings |\n+------------------+\n| 1 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_numinteriorrings/','','https://mariadb.com/kb/en/st_numinteriorrings/'),(12,'WKT Definition',3,'Description\n----------- \nThe Well-Known Text (WKT) representation of Geometry is\ndesigned to exchange geometry data in ASCII form. Examples\nof the basic geometry types include:\n \nGeometry Types | \n \nPOINT | \n \nLINESTRING | \n \nPOLYGON | \n \nMULTIPOINT | \n \nMULTILINESTRING | \n \nMULTIPOLYGON | \n \nGEOMETRYCOLLECTION | \n \nGEOMETRY | \n \n\n\nURL: https://mariadb.com/kb/en/wkt-definition/','','https://mariadb.com/kb/en/wkt-definition/'),(13,'AsText',3,'A synonym for ST_AsText().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-astext/','','https://mariadb.com/kb/en/wkt-astext/'),(14,'AsWKT',3,'A synonym for ST_AsText().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-aswkt/','','https://mariadb.com/kb/en/wkt-aswkt/'),(15,'GeomCollFromText',3,'A synonym for ST_GeomCollFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-geomcollfromtext/','','https://mariadb.com/kb/en/wkt-geomcollfromtext/'),(16,'GeometryCollectionFromText',3,'A synonym for ST_GeomCollFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometrycollectionfromtext/','','https://mariadb.com/kb/en/geometrycollectionfromtext/'),(17,'GeometryFromText',3,'A synonym for ST_GeomFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometryfromtext/','','https://mariadb.com/kb/en/geometryfromtext/'),(18,'GeomFromText',3,'A synonym for ST_GeomFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-geomfromtext/','','https://mariadb.com/kb/en/wkt-geomfromtext/'),(19,'LineFromText',3,'A synonym for ST_LineFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-linefromtext/','','https://mariadb.com/kb/en/wkt-linefromtext/'),(20,'LineStringFromText',3,'A synonym for ST_LineFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/linestringfromtext/','','https://mariadb.com/kb/en/linestringfromtext/'),(21,'MLineFromText',3,'Syntax\n------ \nMLineFromText(wkt[,srid])\nMultiLineStringFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a MULTILINESTRING value using its WKT\nrepresentation and SRID.\n \nMLineFromText() and MultiLineStringFromText() are synonyms.\n \nExamples\n-------- \nCREATE TABLE gis_multi_line (g MULTILINESTRING);\nSHOW FIELDS FROM gis_multi_line;\n \nINSERT INTO gis_multi_line VALUES\n (MultiLineStringFromText(\'MULTILINESTRING((10 48,10 21,10\n0),(16 0,16 23,16 48))\')),\n (MLineFromText(\'MULTILINESTRING((10 48,10 21,10 0))\')),\n (MLineFromWKB(AsWKB(MultiLineString(LineString(Point(1, 2),\nPoint(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21,\n7))))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mlinefromtext/','','https://mariadb.com/kb/en/mlinefromtext/'),(22,'MPointFromText',3,'Syntax\n------ \nMPointFromText(wkt[,srid])\nMultiPointFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a MULTIPOINT value using its WKT representation\nand SRID.\n \nMPointFromText() and MultiPointFromText() are synonyms.\n \nExamples\n-------- \nCREATE TABLE gis_multi_point (g MULTIPOINT);\nSHOW FIELDS FROM gis_multi_point;\n \nINSERT INTO gis_multi_point VALUES\n (MultiPointFromText(\'MULTIPOINT(0 0,10 10,10 20,20\n20)\')),\n (MPointFromText(\'MULTIPOINT(1 1,11 11,11 21,21 21)\')),\n (MPointFromWKB(AsWKB(MultiPoint(Point(3, 6), Point(4,\n10)))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mpointfromtext/','','https://mariadb.com/kb/en/mpointfromtext/'),(23,'MPolyFromText',3,'Syntax\n------ \nMPolyFromText(wkt[,srid])\nMultiPolygonFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a MULTIPOLYGON value using its WKT representation\nand SRID.\n \nMPolyFromText() and MultiPolygonFromText() are synonyms.\n \nExamples\n-------- \nCREATE TABLE gis_multi_polygon (g MULTIPOLYGON);\nSHOW FIELDS FROM gis_multi_polygon;\n \nINSERT INTO gis_multi_polygon VALUES\n (MultiPolygonFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84\n42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67\n13,59 13,59 18)))\')),\n (MPolyFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28\n26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59\n13,59 18)))\')),\n (MPolyFromWKB(AsWKB(MultiPolygon(Polygon(LineString(Point(0,\n3), Point(3, 3), Point(3, 0), Point(0, 3)))))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mpolyfromtext/','','https://mariadb.com/kb/en/mpolyfromtext/'),(24,'MultiLineStringFromText',3,'A synonym for MLineFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multilinestringfromtext/','','https://mariadb.com/kb/en/multilinestringfromtext/'),(25,'MultiPointFromText',3,'A synonym for MPointFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipointfromtext/','','https://mariadb.com/kb/en/multipointfromtext/'),(26,'MultiPolygonFromText',3,'A synonym for MPolyFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipolygonfromtext/','','https://mariadb.com/kb/en/multipolygonfromtext/'),(27,'PointFromText',3,'A synonym for ST_PointFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-pointfromtext/','','https://mariadb.com/kb/en/wkt-pointfromtext/'),(28,'PolyFromText',3,'A synonym for ST_PolyFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkt-polyfromtext/','','https://mariadb.com/kb/en/wkt-polyfromtext/'),(29,'PolygonFromText',3,'A synonym for ST_PolyFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/polygonfromtext/','','https://mariadb.com/kb/en/polygonfromtext/'),(30,'ST_AsText',3,'Syntax\n------ \nST_AsText(g)\nAsText(g)\nST_AsWKT(g)\nAsWKT(g)\n \nDescription\n----------- \nConverts a value in internal geometry format to its WKT\nrepresentation and returns the string result.\n \nST_AsText(), AsText(), ST_AsWKT() and AsWKT() are all\nsynonyms.\n \nExamples\n-------- \nSET @g = \'LineString(1 1,4 4,6 6)\';\n \nSELECT ST_AsText(ST_GeomFromText(@g));\n+--------------------------------+\n| ST_AsText(ST_GeomFromText(@g)) |\n+--------------------------------+\n| LINESTRING(1 1,4 4,6 6) |\n+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_astext/','','https://mariadb.com/kb/en/st_astext/'),(31,'ST_ASWKT',3,'A synonym for ST_ASTEXT().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_aswkt/','','https://mariadb.com/kb/en/st_aswkt/'),(32,'ST_GeomCollFromText',3,'Syntax\n------ \nST_GeomCollFromText(wkt[,srid])\nST_GeometryCollectionFromText(wkt[,srid])\nGeomCollFromText(wkt[,srid])\nGeometryCollectionFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a GEOMETRYCOLLECTION value using its WKT \nrepresentation and SRID.\n \nST_GeomCollFromText(), ST_GeometryCollectionFromText(),\nGeomCollFromText() and GeometryCollectionFromText() are all\nsynonyms.\n \nExample\n \nCREATE TABLE gis_geometrycollection (g GEOMETRYCOLLECTION);\nSHOW FIELDS FROM gis_geometrycollection;\n \nINSERT INTO gis_geometrycollection VALUES\n (GeomCollFromText(\'GEOMETRYCOLLECTION(POINT(0 0),\nLINESTRING(0 0,10 10))\')),\n (GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6),\nLineString(Point(3, 6), Point(7, 9)))))),\n (GeomFromText(\'GeometryCollection()\')),\n (GeomFromText(\'GeometryCollection EMPTY\'));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geomcollfromtext/','','https://mariadb.com/kb/en/st_geomcollfromtext/'),(33,'ST_GeometryCollectionFromText',3,'A synonym for ST_GeomCollFromText.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/st_geometrycollectionfromtext/','','https://mariadb.com/kb/en/st_geometrycollectionfromtext/'),(34,'ST_GeometryFromText',3,'A synonym for ST_GeomFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geometryfromtext/','','https://mariadb.com/kb/en/st_geometryfromtext/'),(35,'ST_GeomFromText',3,'Syntax\n------ \nST_GeomFromText(wkt[,srid])\nST_GeometryFromText(wkt[,srid])\nGeomFromText(wkt[,srid])\nGeometryFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a geometry value of any type using its WKT\nrepresentation and SRID.\n \nGeomFromText(), GeometryFromText(), ST_GeomFromText() and\nST_GeometryFromText() are all synonyms.\n \nExample\n \nSET @g = ST_GEOMFROMTEXT(\'POLYGON((1 1,1 5,4 9,6 9,9 3,7\n2,1 1))\');\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geomfromtext/','','https://mariadb.com/kb/en/st_geomfromtext/'),(36,'ST_LineFromText',3,'Syntax\n------ \nST_LineFromText(wkt[,srid])\nST_LineStringFromText(wkt[,srid])\nLineFromText(wkt[,srid])\nLineStringFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a LINESTRING value using its WKT representation\nand SRID.\n \nST_LineFromText(), ST_LineStringFromText(),\nST_LineFromText() and ST_LineStringFromText() are all\nsynonyms.\n \nExamples\n-------- \nCREATE TABLE gis_line (g LINESTRING);\nSHOW FIELDS FROM gis_line;\n \nINSERT INTO gis_line VALUES\n (LineFromText(\'LINESTRING(0 0,0 10,10 0)\')),\n (LineStringFromText(\'LINESTRING(10 10,20 10,20 20,10 20,10\n10)\')),\n (LineStringFromWKB(AsWKB(LineString(Point(10, 10),\nPoint(40, 10)))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_linefromtext/','','https://mariadb.com/kb/en/st_linefromtext/'),(37,'ST_LineStringFromText',3,'A synonym for ST_LineFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_linestringfromtext/','','https://mariadb.com/kb/en/st_linestringfromtext/'),(38,'ST_PointFromText',3,'Syntax\n------ \nST_PointFromText(wkt[,srid])\nPointFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a POINT value using its WKT representation and\nSRID.\n \nST_PointFromText() and PointFromText() are synonyms.\n \nExamples\n-------- \nCREATE TABLE gis_point (g POINT);\nSHOW FIELDS FROM gis_point;\n \nINSERT INTO gis_point VALUES\n (PointFromText(\'POINT(10 10)\')),\n (PointFromText(\'POINT(20 10)\')),\n (PointFromText(\'POINT(20 20)\')),\n (PointFromWKB(AsWKB(PointFromText(\'POINT(10 20)\'))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_pointfromtext/','','https://mariadb.com/kb/en/st_pointfromtext/'),(39,'ST_PolyFromText',3,'Syntax\n------ \nST_PolyFromText(wkt[,srid])\nST_PolygonFromText(wkt[,srid])\nPolyFromText(wkt[,srid])\nPolygonFromText(wkt[,srid])\n \nDescription\n----------- \nConstructs a POLYGON value using its WKT representation and\nSRID.\n \nST_PolyFromText(), ST_PolygonFromText(), PolyFromText() and\nST_PolygonFromText() are all synonyms.\n \nExamples\n-------- \nCREATE TABLE gis_polygon (g POLYGON);\nINSERT INTO gis_polygon VALUES\n (PolygonFromText(\'POLYGON((10 10,20 10,20 20,10 20,10\n10))\')),\n (PolyFromText(\'POLYGON((0 0,50 0,50 50,0 50,0 0), (10\n10,20 10,20 20,10 20,10 10))\'));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_polyfromtext/','','https://mariadb.com/kb/en/st_polyfromtext/'),(40,'ST_PolygonFromText',3,'A synonym for ST_PolyFromText.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_polygonfromtext/','','https://mariadb.com/kb/en/st_polygonfromtext/'),(41,'Addition Operator (+)',4,'Syntax\n------ \n+\n \nDescription\n----------- \nAddition.\n \nIf both operands are integers, the result is calculated with\nBIGINT precision. If either integer is unsigned, the result\nis also an unsigned integer.\n \nFor real or string operands, the operand with the highest\nprecision determines the result precision.\n \nExamples\n-------- \nSELECT 3+5;\n \n+-----+\n| 3+5 |\n+-----+\n| 8 |\n+-----+\n \n\n\nURL: https://mariadb.com/kb/en/addition-operator/','','https://mariadb.com/kb/en/addition-operator/'),(42,'Subtraction Operator (-)',4,'Syntax\n------ \n-\n \nDescription\n----------- \nSubtraction. The operator is also used as the unary minus\nfor changing sign.\n \nIf both operands are integers, the result is calculated with\nBIGINT precision. If either integer is unsigned, the result\nis also an unsigned integer, unless the\nNO_UNSIGNED_SUBTRACTION SQL_MODE is enabled, in which case\nthe result is always signed.\n \nFor real or string operands, the operand with the highest\nprecision determines the result precision.\n \nExamples\n-------- \nSELECT 96-9;\n \n+------+\n| 96-9 |\n+------+\n| 87 |\n+------+\n \nSELECT 15-17;\n \n+-------+\n| 15-17 |\n+-------+\n| -2 |\n+-------+\n \nSELECT 3.66 + 1.333;\n \n+--------------+\n| 3.66 + 1.333 |\n+--------------+\n| 4.993 |\n+--------------+\n \nUnary minus:\n \n SELECT - (3+5);\n+---------+\n| - (3+5) |\n+---------+\n| -8 |\n+---------+\n \n\n\nURL: https://mariadb.com/kb/en/subtraction-operator-/','','https://mariadb.com/kb/en/subtraction-operator-/'),(43,'Division Operator (/)',4,'Syntax\n------ \n/\n \nDescription\n----------- \nDivision operator. Dividing by zero will return NULL. By\ndefault, returns four digits after the decimal. This is\ndetermined by the server system variable\ndiv_precision_increment which by default is four. It can be\nset from 0 to 30.\n \nDividing by zero returns NULL. If the\nERROR_ON_DIVISION_BY_ZERO SQL_MODE is used (the default\nsince MariaDB 10.2.4), a division by zero also produces a\nwarning.\n \nExamples\n-------- \nSELECT 4/5;\n \n+--------+\n| 4/5 |\n+--------+\n| 0.8000 |\n+--------+\n \nSELECT 300/(2-2);\n+-----------+\n| 300/(2-2) |\n+-----------+\n| NULL |\n+-----------+\n \nSELECT 300/7;\n \n+---------+\n| 300/7 |\n+---------+\n| 42.8571 |\n+---------+\n \nChanging div_precision_increment for the session from the\ndefault of four to six:\n \nSET div_precision_increment = 6;\n \nSELECT 300/7;\n \n+-----------+\n| 300/7 |\n+-----------+\n| 42.857143 |\n+-----------+\n \nSELECT 300/7;\n \n+-----------+\n| 300/7 |\n+-----------+\n| 42.857143 |\n+-----------+\n \n\n\nURL: https://mariadb.com/kb/en/division-operator/','','https://mariadb.com/kb/en/division-operator/'),(44,'Multiplication Operator (*)',4,'Syntax\n------ \n*\n \nDescription\n----------- \nMultiplication operator.\n \nExamples\n-------- \nSELECT 7*6;\n \n+-----+\n| 7*6 |\n+-----+\n| 42 |\n+-----+\n \nSELECT 1234567890*9876543210;\n \n+-----------------------+\n| 1234567890*9876543210 |\n+-----------------------+\n| -6253480962446024716 |\n+-----------------------+\n \nSELECT 18014398509481984*18014398509481984.0;\n \n+---------------------------------------+\n| 18014398509481984*18014398509481984.0 |\n+---------------------------------------+\n| 324518553658426726783156020576256.0 |\n+---------------------------------------+\n \nSELECT 18014398509481984*18014398509481984;\n \n+-------------------------------------+\n| 18014398509481984*18014398509481984 |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/multiplication-operator/','','https://mariadb.com/kb/en/multiplication-operator/'),(45,'Modulo Operator (%)',4,'Syntax\n------ \nN % M\n \nDescription\n----------- \nModulo operator. Returns the remainder of N divided by M.\nSee also MOD.\n \nExamples\n-------- \nSELECT 1042 % 50;\n \n+-----------+\n| 1042 % 50 |\n+-----------+\n| 42 |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/modulo-operator/','','https://mariadb.com/kb/en/modulo-operator/'),(46,'DIV',4,'Syntax\n------ \nDIV\n \nDescription\n----------- \nInteger division. Similar to FLOOR(), but is safe with\nBIGINT values.\nIncorrect results may occur for non-integer operands that\nexceed BIGINT range.\n \nIf the ERROR_ON_DIVISION_BY_ZERO SQL_MODE is used, a\ndivision by zero produces an error. Otherwise, it returns\nNULL.\n \nThe remainder of a division can be obtained using the MOD\noperator.\n \nExamples\n-------- \nSELECT 300 DIV 7;\n \n+-----------+\n| 300 DIV 7 |\n+-----------+\n| 42 |\n+-----------+\n \nSELECT 300 DIV 0;\n \n+-----------+\n| 300 DIV 0 |\n+-----------+\n| NULL |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/div/','','https://mariadb.com/kb/en/div/'),(47,'ABS',4,'Syntax\n------ \nABS(X)\n \nDescription\n----------- \nReturns the absolute (non-negative) value of X. If X is not\na number, it is converted to a numeric type.\n \nExamples\n-------- \nSELECT ABS(42);\n+---------+\n| ABS(42) |\n+---------+\n| 42 |\n+---------+\n \nSELECT ABS(-42);\n+----------+\n| ABS(-42) |\n+----------+\n| 42 |\n+----------+\n \nSELECT ABS(DATE \'1994-01-01\');\n+------------------------+\n| ABS(DATE \'1994-01-01\') |\n+------------------------+\n| 19940101 |\n+------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/abs/','','https://mariadb.com/kb/en/abs/'),(48,'ACOS',4,'Syntax\n------ \nACOS(X)\n \nDescription\n----------- \nReturns the arc cosine of X, that is, the value whose cosine\nis X.\nReturns NULL if X is not in the range -1 to 1.\n \nExamples\n-------- \nSELECT ACOS(1);\n+---------+\n| ACOS(1) |\n+---------+\n| 0 |\n+---------+\n \nSELECT ACOS(1.0001);\n+--------------+\n| ACOS(1.0001) |\n+--------------+\n| NULL |\n+--------------+\n \nSELECT ACOS(0);\n+-----------------+\n| ACOS(0) |\n+-----------------+\n| 1.5707963267949 |\n+-----------------+\n \nSELECT ACOS(0.234);\n+------------------+\n| ACOS(0.234) |\n+------------------+\n| 1.33460644244679 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/acos/','','https://mariadb.com/kb/en/acos/'),(49,'ASIN',4,'Syntax\n------ \nASIN(X)\n \nDescription\n----------- \nReturns the arc sine of X, that is, the value whose sine is\nX. Returns\nNULL if X is not in the range -1 to 1.\n \nExamples\n-------- \nSELECT ASIN(0.2);\n+--------------------+\n| ASIN(0.2) |\n+--------------------+\n| 0.2013579207903308 |\n+--------------------+\n \nSELECT ASIN(\'foo\');\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n \nSHOW WARNINGS;\n \n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\'\n|\n+---------+------+-----------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/asin/','','https://mariadb.com/kb/en/asin/'),(50,'ATAN',4,'Syntax\n------ \nATAN(X)\n \nDescription\n----------- \nReturns the arc tangent of X, that is, the value whose\ntangent is X.\n \nExamples\n-------- \nSELECT ATAN(2);\n+--------------------+\n| ATAN(2) |\n+--------------------+\n| 1.1071487177940904 |\n+--------------------+\n \nSELECT ATAN(-2);\n+---------------------+\n| ATAN(-2) |\n+---------------------+\n| -1.1071487177940904 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/atan/','','https://mariadb.com/kb/en/atan/'),(51,'ATAN2',4,'Syntax\n------ \nATAN(Y,X), ATAN2(Y,X)\n \nDescription\n----------- \nReturns the arc tangent of the two variables X and Y. It is\nsimilar to\ncalculating the arc tangent of Y / X, except that the signs\nof both\narguments are used to determine the quadrant of the result.\n \nExamples\n-------- \nSELECT ATAN(-2,2);\n+---------------------+\n| ATAN(-2,2) |\n+---------------------+\n| -0.7853981633974483 |\n+---------------------+\n \nSELECT ATAN2(PI(),0);\n+--------------------+\n| ATAN2(PI(),0) |\n+--------------------+\n| 1.5707963267948966 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/atan2/','','https://mariadb.com/kb/en/atan2/'),(52,'CEIL',4,'Syntax\n------ \nCEIL(X)\n \nDescription\n----------- \nCEIL() is a synonym for CEILING().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ceil/','','https://mariadb.com/kb/en/ceil/'),(53,'CEILING',4,'Syntax\n------ \nCEILING(X)\n \nDescription\n----------- \nReturns the smallest integer value not less than X.\n \nExamples\n-------- \nSELECT CEILING(1.23);\n+---------------+\n| CEILING(1.23) |\n+---------------+\n| 2 |\n+---------------+\n \nSELECT CEILING(-1.23);\n+----------------+\n| CEILING(-1.23) |\n+----------------+\n| -1 |\n+----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ceiling/','','https://mariadb.com/kb/en/ceiling/'),(54,'CONV',4,'Syntax\n------ \nCONV(N,from_base,to_base)\n \nDescription\n----------- \nConverts numbers between different number bases. Returns a\nstring\nrepresentation of the number N, converted from base\nfrom_base\nto base to_base.\n \nReturns NULL if any argument is NULL, or if the second or\nthird argument are not in the allowed range.\n \nThe argument N is interpreted as an integer, but may be\nspecified as an\ninteger or a string. The minimum base is 2 and the maximum\nbase is 36. If\nto_base is a negative number, N is regarded as a signed\nnumber.\nOtherwise, N is treated as unsigned. CONV() works with\n64-bit\nprecision.\n \nSome shortcuts for this function are also available: BIN(),\nOCT(), HEX(), UNHEX(). Also, MariaDB allows binary literal\nvalues and hexadecimal literal values.\n \nExamples\n-------- \nSELECT CONV(\'a\',16,2);\n+----------------+\n| CONV(\'a\',16,2) |\n+----------------+\n| 1010 |\n+----------------+\n \nSELECT CONV(\'6E\',18,8);\n+-----------------+\n| CONV(\'6E\',18,8) |\n+-----------------+\n| 172 |\n+-----------------+\n \nSELECT CONV(-17,10,-18);\n+------------------+\n| CONV(-17,10,-18) |\n+------------------+\n| -H |\n+------------------+\n \nSELECT CONV(12+\'10\'+\'10\'+0xa,10,10);\n+------------------------------+\n| CONV(12+\'10\'+\'10\'+0xa,10,10) |\n+------------------------------+\n| 42 |\n+------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/conv/','','https://mariadb.com/kb/en/conv/'),(55,'COS',4,'Syntax\n------ \nCOS(X)\n \nDescription\n----------- \nReturns the cosine of X, where X is given in radians.\n \nExamples\n-------- \nSELECT COS(PI());\n+-----------+\n| COS(PI()) |\n+-----------+\n| -1 |\n+-----------\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/cos/','','https://mariadb.com/kb/en/cos/'),(56,'COT',4,'Syntax\n------ \nCOT(X)\n \nDescription\n----------- \nReturns the cotangent of X.\n \nExamples\n-------- \nSELECT COT(42);\n+--------------------+\n| COT(42) |\n+--------------------+\n| 0.4364167060752729 |\n+--------------------+\n \nSELECT COT(12);\n+---------------------+\n| COT(12) |\n+---------------------+\n| -1.5726734063976893 |\n+---------------------+\n \nSELECT COT(0);\nERROR 1690 (22003): DOUBLE value is out of range in\n\'cot(0)\'\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/cot/','','https://mariadb.com/kb/en/cot/'),(57,'CRC32',4,'Syntax\n------ \nCRC32(expr)\n \nDescription\n----------- \nComputes a cyclic redundancy check value and returns a\n32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The\nargument is\nexpected to be a string and (if possible) is treated as one\nif it is\nnot.\n \nExamples\n-------- \nSELECT CRC32(\'MariaDB\');\n+------------------+\n| CRC32(\'MariaDB\') |\n+------------------+\n| 4227209140 |\n+------------------+\n \nSELECT CRC32(\'mariadb\');\n+------------------+\n| CRC32(\'mariadb\') |\n+------------------+\n| 2594253378 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/crc32/','','https://mariadb.com/kb/en/crc32/'),(58,'DEGREES',4,'Syntax\n------ \nDEGREES(X)\n \nDescription\n----------- \nReturns the argument X, converted from radians to degrees.\n \nThis is the converse of the RADIANS() function.\n \nExamples\n-------- \nSELECT DEGREES(PI());\n+---------------+\n| DEGREES(PI()) |\n+---------------+\n| 180 |\n+---------------+\n \nSELECT DEGREES(PI() / 2);\n+-------------------+\n| DEGREES(PI() / 2) |\n+-------------------+\n| 90 |\n+-------------------+\n \nSELECT DEGREES(45);\n+-----------------+\n| DEGREES(45) |\n+-----------------+\n| 2578.3100780887 |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/degrees/','','https://mariadb.com/kb/en/degrees/'),(59,'EXP',4,'Syntax\n------ \nEXP(X)\n \nDescription\n----------- \nReturns the value of e (the base of natural logarithms)\nraised to the\npower of X. The inverse of this function is LOG() (using a\nsingle\nargument only) or LN().\n \nIf X is NULL, this function returns NULL.\n \nExamples\n-------- \nSELECT EXP(2);\n+------------------+\n| EXP(2) |\n+------------------+\n| 7.38905609893065 |\n+------------------+\n \nSELECT EXP(-2);\n+--------------------+\n| EXP(-2) |\n+--------------------+\n| 0.1353352832366127 |\n+--------------------+\n \nSELECT EXP(0);\n+--------+\n| EXP(0) |\n+--------+\n| 1 |\n+--------+\n \nSELECT EXP(NULL);\n+-----------+\n| EXP(NULL) |\n+-----------+\n| NULL |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/exp/','','https://mariadb.com/kb/en/exp/'),(60,'FLOOR',4,'Syntax\n------ \nFLOOR(X)\n \nDescription\n----------- \nReturns the largest integer value not greater than X.\n \nExamples\n-------- \nSELECT FLOOR(1.23);\n+-------------+\n| FLOOR(1.23) |\n+-------------+\n| 1 |\n+-------------+\n \nSELECT FLOOR(-1.23);\n+--------------+\n| FLOOR(-1.23) |\n+--------------+\n| -2 |\n+--------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/floor/','','https://mariadb.com/kb/en/floor/'),(61,'LN',4,'Syntax\n------ \nLN(X)\n \nDescription\n----------- \nReturns the natural logarithm of X; that is, the base-e\nlogarithm of X.\nIf X is less than or equal to 0, or NULL, then NULL is\nreturned.\n \nThe inverse of this function is EXP().\n \nExamples\n-------- \nSELECT LN(2);\n+-------------------+\n| LN(2) |\n+-------------------+\n| 0.693147180559945 |\n+-------------------+\n \nSELECT LN(-2);\n+--------+\n| LN(-2) |\n+--------+\n| NULL |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ln/','','https://mariadb.com/kb/en/ln/'),(62,'LOG',4,'Syntax\n------ \nLOG(X), LOG(B,X)\n \nDescription\n----------- \nIf called with one parameter, this function returns the\nnatural\nlogarithm of X. If X is less than or equal to 0, then NULL\nis\nreturned.\n \nIf called with two parameters, it returns the logarithm of X\nto the base B. If B is \n\nURL: https://mariadb.com/kb/en/log/','','https://mariadb.com/kb/en/log/'),(63,'LOG10',4,'Syntax\n------ \nLOG10(X)\n \nDescription\n----------- \nReturns the base-10 logarithm of X.\n \nExamples\n-------- \nSELECT LOG10(2);\n+-------------------+\n| LOG10(2) |\n+-------------------+\n| 0.301029995663981 |\n+-------------------+\n \nSELECT LOG10(100);\n+------------+\n| LOG10(100) |\n+------------+\n| 2 |\n+------------+\n \nSELECT LOG10(-100);\n+-------------+\n| LOG10(-100) |\n+-------------+\n| NULL |\n+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/log10/','','https://mariadb.com/kb/en/log10/'),(64,'LOG2',4,'Syntax\n------ \nLOG2(X)\n \nDescription\n----------- \nReturns the base-2 logarithm of X.\n \nExamples\n-------- \nSELECT LOG2(4398046511104);\n+---------------------+\n| LOG2(4398046511104) |\n+---------------------+\n| 42 |\n+---------------------+\n \nSELECT LOG2(65536);\n+-------------+\n| LOG2(65536) |\n+-------------+\n| 16 |\n+-------------+\n \nSELECT LOG2(-100);\n+------------+\n| LOG2(-100) |\n+------------+\n| NULL |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/log2/','','https://mariadb.com/kb/en/log2/'),(66,'OCT',4,'Syntax\n------ \nOCT(N)\n \nDescription\n----------- \nReturns a string representation of the octal value of N,\nwhere N is a longlong (BIGINT) number. This is equivalent to\nCONV(N,10,8). Returns NULL if N is NULL.\n \nExamples\n-------- \nSELECT OCT(34);\n+---------+\n| OCT(34) |\n+---------+\n| 42 |\n+---------+\n \nSELECT OCT(12);\n+---------+\n| OCT(12) |\n+---------+\n| 14 |\n+---------+\n \n\n\nURL: https://mariadb.com/kb/en/oct/','','https://mariadb.com/kb/en/oct/'),(65,'MOD',4,'Syntax\n------ \nMOD(N,M), N % M, N MOD M\n \nDescription\n----------- \nModulo operation. Returns the remainder of N divided by M.\nSee also Modulo Operator.\n \nIf the ERROR_ON_DIVISION_BY_ZERO SQL_MODE is used, any\nnumber modulus zero produces an error. Otherwise, it returns\nNULL.\n \nThe integer part of a division can be obtained using DIV.\n \nExamples\n-------- \nSELECT 1042 % 50;\n \n+-----------+\n| 1042 % 50 |\n+-----------+\n| 42 |\n+-----------+\n \nSELECT MOD(234, 10);\n+--------------+\n| MOD(234, 10) |\n+--------------+\n| 4 |\n+--------------+\n \nSELECT 253 % 7;\n \n+---------+\n| 253 % 7 |\n+---------+\n| 1 |\n+---------+\n \nSELECT MOD(29,9);\n+-----------+\n| MOD(29,9) |\n+-----------+\n| 2 |\n+-----------+\n \nSELECT 29 MOD 9;\n \n+----------+\n| 29 MOD 9 |\n+----------+\n| 2 |\n+----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mod/','','https://mariadb.com/kb/en/mod/'),(67,'PI',4,'Syntax\n------ \nPI()\n \nDescription\n----------- \nReturns the value of π (pi). The default number of decimal\nplaces\ndisplayed is six, but MariaDB uses the full double-precision\nvalue\ninternally.\n \nExamples\n-------- \nSELECT PI();\n+----------+\n| PI() |\n+----------+\n| 3.141593 |\n+----------+\n \nSELECT PI()+0.0000000000000000000000;\n \n+-------------------------------+\n| PI()+0.0000000000000000000000 |\n+-------------------------------+\n| 3.1415926535897931159980 |\n+-------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/pi/','','https://mariadb.com/kb/en/pi/'),(68,'POW',4,'Syntax\n------ \nPOW(X,Y)\n \nDescription\n----------- \nReturns the value of X raised to the power of Y.\n \nPOWER() is a synonym.\n \nExamples\n-------- \nSELECT POW(2,3);\n+----------+\n| POW(2,3) |\n+----------+\n| 8 |\n+----------+\n \nSELECT POW(2,-2);\n+-----------+\n| POW(2,-2) |\n+-----------+\n| 0.25 |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/pow/','','https://mariadb.com/kb/en/pow/'),(69,'POWER',4,'Syntax\n------ \nPOWER(X,Y)\n \nDescription\n----------- \nThis is a synonym for POW(), which returns the value of X\nraised to the power of Y.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/power/','','https://mariadb.com/kb/en/power/'),(70,'RADIANS',4,'Syntax\n------ \nRADIANS(X)\n \nDescription\n----------- \nReturns the argument X, converted from degrees to radians.\nNote that\nπ radians equals 180 degrees. \n \nThis is the converse of the DEGREES() function.\n \nExamples\n-------- \nSELECT RADIANS(45);\n+-------------------+\n| RADIANS(45) |\n+-------------------+\n| 0.785398163397448 |\n+-------------------+\n \nSELECT RADIANS(90);\n+-----------------+\n| RADIANS(90) |\n+-----------------+\n| 1.5707963267949 |\n+-----------------+\n \nSELECT RADIANS(PI());\n+--------------------+\n| RADIANS(PI()) |\n+--------------------+\n| 0.0548311355616075 |\n+--------------------+\n \nSELECT RADIANS(180);\n+------------------+\n| RADIANS(180) |\n+------------------+\n| 3.14159265358979 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/radians/','','https://mariadb.com/kb/en/radians/'),(71,'RAND',4,'Syntax\n------ \nRAND(), RAND(N)\n \nDescription\n----------- \nReturns a random DOUBLE precision floating point value v in\nthe range 0 \n\nURL: https://mariadb.com/kb/en/rand/','','https://mariadb.com/kb/en/rand/'),(72,'ROUND',4,'Syntax\n------ \nROUND(X), ROUND(X,D)\n \nDescription\n----------- \nRounds the argument X to D decimal places. The rounding\nalgorithm\ndepends on the data type of X. D defaults to 0 if not\nspecified.\nD can be negative to cause D digits left of the decimal\npoint of the\nvalue X to become zero.\n \nExamples\n-------- \nSELECT ROUND(-1.23);\n+--------------+\n| ROUND(-1.23) |\n+--------------+\n| -1 |\n+--------------+\n \nSELECT ROUND(-1.58);\n+--------------+\n| ROUND(-1.58) |\n+--------------+\n| -2 |\n+--------------+\n \nSELECT ROUND(1.58); \n+-------------+\n| ROUND(1.58) |\n+-------------+\n| 2 |\n+-------------+\n \nSELECT ROUND(1.298, 1);\n+-----------------+\n| ROUND(1.298, 1) |\n+-----------------+\n| 1.3 |\n+-----------------+\n \nSELECT ROUND(1.298, 0);\n+-----------------+\n| ROUND(1.298, 0) |\n+-----------------+\n| 1 |\n+-----------------+\n \nSELECT ROUND(23.298, -1);\n+-------------------+\n| ROUND(23.298, -1) |\n+-------------------+\n| 20 |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/round/','','https://mariadb.com/kb/en/round/'),(73,'SIGN',4,'Syntax\n------ \nSIGN(X)\n \nDescription\n----------- \nReturns the sign of the argument as -1, 0, or 1, depending\non whether\nX is negative, zero, or positive.\n \nExamples\n-------- \nSELECT SIGN(-32);\n+-----------+\n| SIGN(-32) |\n+-----------+\n| -1 |\n+-----------+\n \nSELECT SIGN(0);\n+---------+\n| SIGN(0) |\n+---------+\n| 0 |\n+---------+\n \nSELECT SIGN(234);\n+-----------+\n| SIGN(234) |\n+-----------+\n| 1 |\n+-----------+\n \n\n\nURL: https://mariadb.com/kb/en/sign/','','https://mariadb.com/kb/en/sign/'),(74,'SIN',4,'Syntax\n------ \nSIN(X)\n \nDescription\n----------- \nReturns the sine of X, where X is given in radians.\n \nExamples\n-------- \nSELECT SIN(1.5707963267948966);\n+-------------------------+\n| SIN(1.5707963267948966) |\n+-------------------------+\n| 1 |\n+-------------------------+\n \nSELECT SIN(PI());\n+----------------------+\n| SIN(PI()) |\n+----------------------+\n| 1.22460635382238e-16 |\n+----------------------+\n \nSELECT ROUND(SIN(PI()));\n+------------------+\n| ROUND(SIN(PI())) |\n+------------------+\n| 0 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sin/','','https://mariadb.com/kb/en/sin/'),(75,'SQRT',4,'Syntax\n------ \nSQRT(X)\n \nDescription\n----------- \nReturns the square root of X. If X is negative, NULL is\nreturned.\n \nExamples\n-------- \nSELECT SQRT(4);\n+---------+\n| SQRT(4) |\n+---------+\n| 2 |\n+---------+\n \nSELECT SQRT(20);\n+------------------+\n| SQRT(20) |\n+------------------+\n| 4.47213595499958 |\n+------------------+\n \nSELECT SQRT(-16);\n+-----------+\n| SQRT(-16) |\n+-----------+\n| NULL |\n+-----------+\n \nSELECT SQRT(1764);\n+------------+\n| SQRT(1764) |\n+------------+\n| 42 |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sqrt/','','https://mariadb.com/kb/en/sqrt/'),(76,'TAN',4,'Syntax\n------ \nTAN(X)\n \nDescription\n----------- \nReturns the tangent of X, where X is given in radians.\n \nExamples\n-------- \nSELECT TAN(0.7853981633974483);\n+-------------------------+\n| TAN(0.7853981633974483) |\n+-------------------------+\n| 0.9999999999999999 |\n+-------------------------+\n \nSELECT TAN(PI());\n+-----------------------+\n| TAN(PI()) |\n+-----------------------+\n| -1.22460635382238e-16 |\n+-----------------------+\n \nSELECT TAN(PI()+1);\n+-----------------+\n| TAN(PI()+1) |\n+-----------------+\n| 1.5574077246549 |\n+-----------------+\n \nSELECT TAN(RADIANS(PI()));\n+--------------------+\n| TAN(RADIANS(PI())) |\n+--------------------+\n| 0.0548861508080033 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/tan/','','https://mariadb.com/kb/en/tan/'),(78,'Plugin Overview',5,'Plugins are server components that enhance MariaDB in some\nway. These can be anything from new storage engines, plugins\nfor enhancing full-text parsing, or even small enhancements,\nsuch as a plugin to get a timestamp as an integer.\n \nQuerying Plugin Information\n \nThere are a number of ways to see which plugins are\ncurrently active.\n \nA server almost always has a large number of active plugins,\nbecause the server contains a large number of built-in\nplugins, which are active by default and cannot be\nuninstalled.\n \nQuerying Plugin Information with SHOW PLUGINS\n \nThe SHOW PLUGINS statement can be used to query information\nabout all active plugins.\n \nFor example:\n \nSHOW PLUGINS;\n \n+----------------------------+----------+--------------------+---------+---------+\n| Name | Status | Type | Library | License |\n+----------------------------+----------+--------------------+---------+---------+\n...\n| mysql_native_password | ACTIVE | AUTHENTICATION | NULL |\nGPL |\n| mysql_old_password | ACTIVE | AUTHENTICATION | NULL | GPL\n|\n| MRG_MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |\n...\n+----------------------------+----------+--------------------+---------+---------+\n \nIf a plugin\'s Library column has the NULL value, then the\nplugin is built-in, and it cannot be uninstalled.\n \nQuerying Plugin Information with information_schema.PLUGINS\n \nThe information_schema.PLUGINS table can be queried to get\nmore detailed information about plugins.\n \nFor example:\n \nSELECT * FROM information_schema.PLUGINS\\G\n...\n*************************** 6. row\n***************************\n PLUGIN_NAME: CSV\n PLUGIN_VERSION: 1.0\n PLUGIN_STATUS: ACTIVE\n PLUGIN_TYPE: STORAGE ENGINE\n PLUGIN_TYPE_VERSION: 100003.0\n PLUGIN_LIBRARY: NULL\nPLUGIN_LIBRARY_VERSION: NULL\n PLUGIN_AUTHOR: Brian Aker, MySQL AB\n PLUGIN_DESCRIPTION: CSV storage engine\n PLUGIN_LICENSE: GPL\n LOAD_OPTION: FORCE\n PLUGIN_MATURITY: Stable\n PLUGIN_AUTH_VERSION: 1.0\n*************************** 7. row\n***************************\n PLUGIN_NAME: MEMORY\n PLUGIN_VERSION: 1.0\n PLUGIN_STATUS: ACTIVE\n PLUGIN_TYPE: STORAGE ENGINE\n PLUGIN_TYPE_VERSION: 100003.0\n PLUGIN_LIBRARY: NULL\nPLUGIN_LIBRARY_VERSION: NULL\n PLUGIN_AUTHOR: MySQL AB\n PLUGIN_DESCRIPTION: Hash based, stored in memory, useful\nfor temporary tables\n PLUGIN_LICENSE: GPL\n LOAD_OPTION: FORCE\n PLUGIN_MATURITY: Stable\n PLUGIN_AUTH_VERSION: 1.0\n...\n \nIf a plugin\'s PLUGIN_LIBRARY column has the NULL value,\nthen the plugin is built-in, and it cannot be uninstalled.\n \nQuerying Plugin Information with mysql.plugin\n \nThe mysql.plugin table can be queried to get information\nabout installed plugins.\n \nThis table only contains information about plugins that have\nbeen installed via the following methods:\nThe INSTALL SONAME statement.\nThe INSTALL PLUGIN statement.\nThe mysql_plugin utility.\n \nThis table does not contain information about:\nBuilt-in plugins.\nPlugins loaded with the --plugin-load-add option.\nPlugins loaded with the --plugin-load option.\n \nThis table only contains enough information to reload the\nplugin when the server is restarted, which means it only\ncontains the plugin name and the plugin library.\n \nFor example:\n \nSELECT * FROM mysql.plugin;\n \n+------+------------+\n| name | dl |\n+------+------------+\n| PBXT | libpbxt.so |\n+------+------------+\n \nInstalling a Plugin\n \nThere are three primary ways to install a plugin:\nA plugin can be installed dynamically with an SQL statement.\nA plugin can be installed with a mysqld option, but it\nrequires a server restart.\nA plugin can be installed with the mysql_plugin utility,\nwhile the server is completely offline.\n \nWhen you are installing a plugin, you also have to ensure\nthat:\nThe server\'s plugin directory is properly configured, and\nthe plugin\'s library is in the plugin directory.\nThe server\'s minimum plugin maturity is properly\nconfigured, and the plugin is mature enough to be installed.\n \nInstalling a Plugin Dynamically\n \nA plugin can be installed dynamically by executing either\nthe INSTALL SONAME or the INSTALL PLUGIN statement.\n \nIf a plugin is installed with one of these statements, then\na record will be added to the mysql.plugins table for the\nplugin. This means that the plugin will automatically be\nloaded every time the server restarts, unless specifically\nuninstalled or deactivated.\n \nInstalling a Plugin with INSTALL SONAME\n \nYou can install a plugin dynamically by executing the\nINSTALL SONAME statement. INSTALL SONAME installs all\nplugins from the given plugin library. This could be\nrequired for some plugin libraries.\n \nFor example, to install all plugins in the server_audit\nplugin library (which is currently only the server_audit\naudit plugin), you could execute the following:\n \nINSTALL SONAME \'server_audit\';\n \nInstalling a Plugin with INSTALL PLUGIN\n \nYou can install a plugin dynamically by executing the\nINSTALL PLUGIN statement. INSTALL PLUGIN installs a single\nplugin from the given plugin library.\n \nFor example, to install the server_audit audit plugin from\nthe server_audit plugin library, you could execute the\nfollowing:\n \nINSTALL PLUGIN server_audit SONAME \'server_audit\';\n \nInstalling a Plugin with Plugin Load Options\n \nA plugin can be installed with a mysqld option by providing\neither the --plugin-load-add or the --plugin-load option.\n \nIf a plugin is installed with one of these options, then a\nrecord will not be added to the mysql.plugins table for the\nplugin. This means that if the server is restarted without\nthe same option set, then the plugin will not automatically\nbe loaded.\n \nInstalling a Plugin with --plugin-load-add\n \nYou can install a plugin with the --plugin-load-add option\nby specifying the option as a command-line argument to\nmysqld or by specifying the option in a relevant server\noption group in an option file.\n \nThe --plugin-load-add option uses the following format:\nPlugins can be specified in the format name=library, where\nname is the plugin name and library is the plugin library.\nThis format installs a single plugin from the given plugin\nlibrary.\nPlugins can also be specified in the format library, where\nlibrary is the plugin library. This format installs all\nplugins from the given plugin library.\nMultiple plugins can be specified by separating them with\nsemicolons.\n \nFor example, to install all plugins in the server_audit\nplugin library (which is currently only the server_audit\naudit plugin) and also the ed25519 authentication plugin\nfrom the auth_ed25519 plugin library, you could set the\noption to the following values on the command-line:\n \n$ mysqld --user=mysql --plugin-load-add=\'server_audit\'\n--plugin-load-add=\'ed25519=auth_ed25519\'\n \nYou could also set the option to the same values in an\noption file:\n \n[mariadb]\n...\nplugin_load_add = server_audit\nplugin_load_add = ed25519=auth_ed25519\n \nSpecial care must be taken when specifying both the\n--plugin-load option and the --plugin-load-add option\ntogether. The --plugin-load option resets the plugin load\nlist, and this can cause unexpected problems if you are not\naware. The --plugin-load-add option does not reset the\nplugin load list, so it is much safer to use. See Specifying\nMultiple Plugin Load Options for more information.\n \nInstalling a Plugin with --plugin-load\n \nYou can install a plugin with the --plugin-load option by\nspecifying the option as a command-line argument to mysqld\nor by specifying the option in a relevant server option\ngroup in an option file.\n \nThe --plugin-load option uses the following format:\nPlugins can be specified in the format name=library, where\nname is the plugin name and library is the plugin library.\nThis format installs a single plugin from the given plugin\nlibrary.\nPlugins can also be specified in the format library, where\nlibrary is the plugin library. This format installs all\nplugins from the given plugin library.\nMultiple plugins can be specified by separating them with\nsemicolons.\n \nFor example, to install all plugins in the server_audit\nplugin library (which is currently only the server_audit\naudit plugin) and also the ed25519 authentication plugin\nfrom the auth_ed25519 plugin library, you could set the\noption to the following values on the command-line:\n \n$ mysqld --user=mysql\n--plugin-load=\'server_audit;ed25519=auth_ed25519\'\n \nYou could also set the option to the same values in an\noption file:\n \n[mariadb]\n...\nplugin_load = server_audit;ed25519=auth_ed25519\n \nSpecial care must be taken when specifying the --plugin-load\noption multiple times, or when specifying both the\n--plugin-load option and the --plugin-load-add option\ntogether. The --plugin-load option resets the plugin load\nlist, and this can cause unexpected problems if you are not\naware. The --plugin-load-add option does not reset the\nplugin load list, so it is much safer to use. See Specifying\nMultiple Plugin Load Options for more information.\n \nSpecifying Multiple Plugin Load Options\n \nSpecial care must be taken when specifying the --plugin-load\noption multiple times, or when specifying both the\n--plugin-load option and the --plugin-load-add option. The\n--plugin-load option resets the plugin load list, and this\ncan cause unexpected problems if you are not aware. The\n--plugin-load-add option does not reset the plugin load\nlist, so it is much safer to use.\n \nThis can have the following consequences:\nIf the --plugin-load option is specified multiple times,\nthen only the last instance will have any effect. For\nexample, in the following case, the first instance of the\noption is reset:\n \n[mariadb]\n...\nplugin_load = server_audit\nplugin_load = ed25519=auth_ed25519\nIf the --plugin-load option is specified after the\n--plugin-load-add option, then it will also reset the\nchanges made by that option. For example, in the following\ncase, the --plugin-load-add option does not do anything,\nbecause the subsequent --plugin-load option resets the\nplugin load list:\n \n[mariadb]\n...\nplugin_load_add = server_audit\nplugin_load = ed25519=auth_ed25519\nIn contrast, if the --plugin-load option is specified before\nthe --plugin-load-add option, then it will work fine,\nbecause the --plugin-load-add option does not reset the\nplugin load list. For example, in the following case, both\nplugins are properly loaded:\n \n[mariadb]\n...\nplugin_load = server_audit\nplugin_load_add = ed25519=auth_ed25519\n \nInstalling a Plugin with mysql_plugin\n \nA plugin can be installed with the mysql_plugin utility if\nthe server is completely offline. \n \nThe syntax is:\n \nmysql_plugin [options] \n ENABLE|DISABLE\n \nFor example, to install the server_audit audit plugin, you\ncould execute the following:\n \nmysql_plugin server_audit ENABLE\n \nIf a plugin is installed with this utility, then a record\nwill be added to the mysql.plugins table for the plugin.\nThis means that the plugin will automatically be loaded\nevery time the server restarts, unless specifically\nuninstalled or deactivated.\n \nConfiguring the Plugin Directory\n \nWhen a plugin is being installed, the server looks for the\nplugin\'s library in the server\'s plugin directory. This\ndirectory is configured by the plugin_dir system variable.\nThis can be specified as a command-line argument to mysqld\nor it can be specified in a relevant server option group in\nan option file. For example:\n \n[mariadb]\n...\nplugin_dir = /usr/lib64/mysql/plugin\n \nConfiguring the Minimum Plugin Maturity\n \nWhen a plugin is being installed, the server compares the\nplugin\'s maturity level against the server\'s minimum\nallowed plugin maturity. This can help prevent users from\nusing unstable plugins on production servers. This minimum\nplugin maturity is configured by the plugin_maturity system\nvariable. This can be specified as a command-line argument\nto mysqld or it can be specified in a relevant server option\ngroup in an option file. For example:\n \n[mariadb]\n...\nplugin_maturity = stable\n \nConfiguring Plugin Activation at Server Startup\n \nA plugin will be loaded by default when the server starts\nif:\nThe plugin was installed with the INSTALL SONAME statement.\nThe plugin was installed with the INSTALL PLUGIN statement.\nThe plugin was installed with the mysql_plugin utility.\nThe server is configured to load the plugin with the\n--plugin-load-add option.\nThe server is configured to load the plugin with the\n--plugin-load option.\n \nThis behavior can be changed with special options that take\nthe form --plugin-name. For example, for the server_audit\naudit plugin, the special option is called --server-audit.\n \nThe possible values for these special options are:\n \nOption Value | Description | \n \nOFF | Disables the plugin without removing it from the\nmysql.plugins table. | \n \nON | Enables the plugin. If the plugin cannot be\ninitialized, then the server will still continue starting\nup, but the plugin will be disabled. | \n \nFORCE | Enables the plugin. If the plugin cannot be\ninitialized, then the server will fail to start with an\nerror. | \n \nFORCE_PLUS_PERMANENT | Enables the plugin. If the plugin\ncannot be initialized, then the server will fail to start\nwith an error. In addition, the plugin cannot be uninstalled\nwith UNINSTALL SONAME or UNINSTALL PLUGIN while the server\nis running. | \n \nA plugin\'s status can be found by looking at the\nPLUGIN_STATUS column of the information_schema.PLUGINS\ntable.\n \nUninstalling Plugins\n \nPlugins that are found in the mysql.plugin table, that is\nthose that were installed with INSTALL SONAME, INSTALL\nPLUGIN or mysql_plugin can be uninstalled in one of two\nways:\nThe UNINSTALL SONAME or the UNINSTALL PLUGIN statement while\nthe server is running\nWith mysql_plugin while the server is offline.\n \nPlugins that were enabled as a --plugin-load option do not\nneed to be uninstalled. If --plugin-load is omitted the next\ntime the server starts, or the plugin is not listed as one\nof the --plugin-load entries, the plugin will not be loaded.\n \nUNINSTALL PLUGIN uninstalls a single installed plugin, while\nUNINSTALL SONAME uninstalls all plugins belonging to a given\nlibrary.\n \n\n\nURL: https://mariadb.com/kb/en/plugin-overview/','','https://mariadb.com/kb/en/plugin-overview/'),(83,'MBR Definition',6,'Description\n----------- \nThe MBR (Minimum Bounding Rectangle), or Envelope is the\nbounding\ngeometry, formed by the minimum and maximum (X,Y)\ncoordinates:\n \nExamples\n-------- \n((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbr-definition/','','https://mariadb.com/kb/en/mbr-definition/'),(84,'MBRContains',6,'Syntax\n------ \nMBRContains(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangle of\ng1 contains the Minimum Bounding Rectangle of g2. This tests\nthe\nopposite relationship as MBRWithin().\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\n \nSET @g2 = GeomFromText(\'Point(1 1)\');\n \nSELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n+----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrcontains/','','https://mariadb.com/kb/en/mbrcontains/'),(77,'TRUNCATE',4,'This page documents the TRUNCATE function. See TRUNCATE\nTABLE for the DDL statement.\n \nSyntax\n------ \nTRUNCATE(X,D)\n \nDescription\n----------- \nReturns the number X, truncated to D decimal places. If D is\n0, the\nresult has no decimal point or fractional part. D can be\nnegative to\ncause D digits left of the decimal point of the value X to\nbecome\nzero.\n \nExamples\n-------- \nSELECT TRUNCATE(1.223,1);\n+-------------------+\n| TRUNCATE(1.223,1) |\n+-------------------+\n| 1.2 |\n+-------------------+\n \nSELECT TRUNCATE(1.999,1);\n+-------------------+\n| TRUNCATE(1.999,1) |\n+-------------------+\n| 1.9 |\n+-------------------+\n \nSELECT TRUNCATE(1.999,0); \n+-------------------+\n| TRUNCATE(1.999,0) |\n+-------------------+\n| 1 |\n+-------------------+\n \nSELECT TRUNCATE(-1.999,1);\n+--------------------+\n| TRUNCATE(-1.999,1) |\n+--------------------+\n| -1.9 |\n+--------------------+\n \nSELECT TRUNCATE(122,-2);\n+------------------+\n| TRUNCATE(122,-2) |\n+------------------+\n| 100 |\n+------------------+\n \nSELECT TRUNCATE(10.28*100,0);\n+-----------------------+\n| TRUNCATE(10.28*100,0) |\n+-----------------------+\n| 1028 |\n+-----------------------+\n \n\n\nURL: https://mariadb.com/kb/en/truncate/','','https://mariadb.com/kb/en/truncate/'),(79,'INSTALL PLUGIN',5,'Syntax\n------ \nINSTALL PLUGIN [IF NOT EXISTS] plugin_name SONAME\n\'plugin_library\'\n \nDescription\n----------- \nThis statement installs an individual plugin from the\nspecified library. To install the whole library (which could\nbe required), use INSTALL SONAME.\n \nplugin_name is the name of the plugin as defined in the\nplugin declaration structure contained in the library file.\nPlugin names are\nnot case sensitive. For maximal compatibility, plugin names\nshould be limited\nto ASCII letters, digits, and underscore, because they are\nused in C source\nfiles, shell command lines, M4 and Bourne shell scripts, and\nSQL environments.\n \nplugin_library is the name of the shared library that\ncontains the plugin code. Before MariaDB 5.5.21, the name\nshould include the file name extension (for\nexample, libmyplugin.so or libmyplugin.dll). Starting from\nMariaDB 5.5.21, the file name extension can be omitted\n(which makes the statement look the same on all\narchitectures).\n \nThe shared library must be located in the plugin directory\n(that is,\nthe directory named by the plugin_dir system variable). The\nlibrary must be in the plugin directory itself, not in a\nsubdirectory. By\ndefault, plugin_dir is plugin directory under the directory\nnamed by\nthe pkglibdir configuration variable, but it can be changed\nby setting\nthe value of plugin_dir at server startup. For example, set\nits value in a my.cnf file:\n \n[mysqld]\nplugin_dir=/path/to/plugin/directory\nIf the value of plugin_dir is a relative path name, it is\ntaken to be relative to the MySQL base directory (the value\nof the basedir\nsystem variable).\n \nINSTALL PLUGIN adds a line to the mysql.plugin table that\ndescribes the plugin. This table contains the plugin name\nand library file\nname.\n \nINSTALL PLUGIN causes the server to read\noption (my.cnf) files just as during server startup. This\nenables the plugin to\npick up any relevant options from those files. It is\npossible to add plugin\noptions to an option file even before loading a plugin (if\nthe loose prefix is\nused). It is also possible to uninstall a plugin, edit\nmy.cnf, and install the\nplugin again. Restarting the plugin this way enables it to\nthe new option\nvalues without a server restart.\n \nBefore MySQL 5.1.33, a plugin was started with each option\nset to its\ndefault value.\n \nINSTALL PLUGIN also loads and initializes the plugin code to\nmake the plugin available for use. A plugin is initialized\nby executing its\ninitialization function, which handles any setup that the\nplugin must perform\nbefore it can be used.\n \nTo use INSTALL PLUGIN, you must have the\nINSERT privilege for the mysql.plugin table.\n \nAt server startup, the server loads and initializes any\nplugin that is\nlisted in the mysql.plugin table. This means that a plugin\nis installed\nwith INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the\nserver is started with\nthe --skip-grant-tables option.\n \nWhen the server shuts down, it executes the deinitialization\nfunction\nfor each plugin that is loaded so that the plugin has a\nchance to\nperform any final cleanup.\n \nIf you need to load plugins for a single server startup when\nthe\n--skip-grant-tables option is given (which tells the server\nnot to read system tables), use the \n--plugin-load mysqld option.\n \nIF NOT EXISTS\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nnote instead of an error if the specified plugin already\nexists. See SHOW WARNINGS.\n \nExamples\n-------- \nINSTALL PLUGIN sphinx SONAME \'ha_sphinx.so\';\n \nStarting from MariaDB 5.5.21, the extension can be omitted:\n \nINSTALL PLUGIN innodb SONAME \'ha_xtradb\';\n \nFrom MariaDB 10.4.0:\n \nINSTALL PLUGIN IF NOT EXISTS example SONAME \'ha_example\';\n \nQuery OK, 0 rows affected (0.104 sec)\n \nINSTALL PLUGIN IF NOT EXISTS example SONAME \'ha_example\';\n \nQuery OK, 0 rows affected, 1 warning (0.000 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------------------+\n| Level | Code | Message |\n+-------+------+------------------------------------+\n| Note | 1968 | Plugin \'example\' already installed |\n+-------+------+------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/install-plugin/','','https://mariadb.com/kb/en/install-plugin/'),(86,'MBREqual',6,'Syntax\n------ \nMBREqual(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangles of\nthe two geometries g1 and g2 are the same.\n \nExamples\n-------- \nSET @g1=GEOMFROMTEXT(\'LINESTRING(0 0, 1 2)\');\nSET @g2=GEOMFROMTEXT(\'POLYGON((0 0, 0 2, 1 2, 1 0, 0\n0))\');\nSELECT MbrEqual(@g1,@g2);\n+-------------------+\n| MbrEqual(@g1,@g2) |\n+-------------------+\n| 1 |\n+-------------------+\n \nSET @g1=GEOMFROMTEXT(\'LINESTRING(0 0, 1 3)\');\nSET @g2=GEOMFROMTEXT(\'POLYGON((0 0, 0 2, 1 4, 1 0, 0\n0))\');\nSELECT MbrEqual(@g1,@g2);\n+-------------------+\n| MbrEqual(@g1,@g2) |\n+-------------------+\n| 0 |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrequal/','','https://mariadb.com/kb/en/mbrequal/'),(90,'MBRWithin',6,'Syntax\n------ \nMBRWithin(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangle of\ng1 is within the Minimum Bounding Rectangle of g2. This\ntests the\nopposite relationship as MBRContains().\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nSELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrwithin/','','https://mariadb.com/kb/en/mbrwithin/'),(92,'IF Function',7,'Syntax\n------ \nIF(expr1,expr2,expr3)\n \nDescription\n----------- \nIf expr1 is TRUE (expr1 0 and expr1 NULL) then IF()\nreturns expr2; otherwise it returns expr3. IF() returns a\nnumeric\nor string value, depending on the context in which it is\nused.\n \nNote: There is also an IF statement which differs from the\nIF() function described here.\n \nExamples\n-------- \nSELECT IF(1>2,2,3);\n+-------------+\n| IF(1>2,2,3) |\n+-------------+\n| 3 |\n+-------------+\n \nSELECT IF(1\n\nURL: https://mariadb.com/kb/en/if-function/','','https://mariadb.com/kb/en/if-function/'),(80,'UNINSTALL PLUGIN',5,'Syntax\n------ \nUNINSTALL PLUGIN [IF EXISTS] plugin_name\n \nDescription\n----------- \nThis statement removes a single installed plugin. To\nuninstall the whole library which contains the plugin, use\nUNINSTALL SONAME. You cannot uninstall a plugin if any table\nthat uses it is open.\n \nplugin_name must be the name of some plugin that is listed\nin the mysql.plugin table. The server executes the plugin\'s\ndeinitialization\nfunction and removes the row for the plugin from the\nmysql.plugin\ntable, so that subsequent server restarts will not load and\ninitialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s\nshared library file.\n \nTo use UNINSTALL PLUGIN, you must have the\nDELETE privilege for the mysql.plugin table.\n \nIF EXISTS\n \nIf the IF EXISTS clause is used, MariaDB will return a note\ninstead of an error if the plugin does not exist. See SHOW\nWARNINGS.\n \nExamples\n-------- \nUNINSTALL PLUGIN example;\n \nFrom MariaDB 10.4.0:\n \nUNINSTALL PLUGIN IF EXISTS example;\n \nQuery OK, 0 rows affected (0.099 sec)\n \nUNINSTALL PLUGIN IF EXISTS example;\n \nQuery OK, 0 rows affected, 1 warning (0.000 sec)\n \nSHOW WARNINGS;\n \n+-------+------+-------------------------------+\n| Level | Code | Message |\n+-------+------+-------------------------------+\n| Note | 1305 | PLUGIN example does not exist |\n+-------+------+-------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/uninstall-plugin/','','https://mariadb.com/kb/en/uninstall-plugin/'),(81,'INSTALL SONAME',5,'INSTALL SONAME has been supported since MariaDB 5.5.21.\n \nSyntax\n------ \nINSTALL SONAME \'plugin_library\'\n \nDescription\n----------- \nThis statement is a variant of INSTALL PLUGIN. It installs\nall plugins from a given plugin_library. See INSTALL PLUGIN\nfor details.\n \nplugin_library is the name of the shared library that\ncontains the plugin code. The file name extension (for\nexample, libmyplugin.so or libmyplugin.dll) can be omitted\n(which makes the statement look the same on all\narchitectures).\n \nThe shared library must be located in the plugin directory\n(that is,\nthe directory named by the plugin_dir system variable). The\nlibrary must be in the plugin directory itself, not in a\nsubdirectory. By\ndefault, plugin_dir is plugin directory under the directory\nnamed by\nthe pkglibdir configuration variable, but it can be changed\nby setting\nthe value of plugin_dir at server startup. For example, set\nits value in a my.cnf file:\n \n[mysqld]\nplugin_dir=/path/to/plugin/directory\nIf the value of plugin_dir is a relative path name, it is\ntaken to be relative to the MySQL base directory (the value\nof the basedir\nsystem variable).\n \nINSTALL SONAME adds one or more lines to the mysql.plugin\ntable that\ndescribes the plugin. This table contains the plugin name\nand library file\nname.\n \nINSTALL SONAME causes the server to read\noption (my.cnf) files just as during server startup. This\nenables the plugin to\npick up any relevant options from those files. It is\npossible to add plugin\noptions to an option file even before loading a plugin (if\nthe loose prefix is\nused). It is also possible to uninstall a plugin, edit\nmy.cnf, and install the\nplugin again. Restarting the plugin this way enables it to\nthe new option\nvalues without a server restart.\n \nINSTALL SONAME also loads and initializes the plugin code to\nmake the plugin available for use. A plugin is initialized\nby executing its\ninitialization function, which handles any setup that the\nplugin must perform\nbefore it can be used.\n \nTo use INSTALL SONAME, you must have the\nINSERT privilege for the mysql.plugin table.\n \nAt server startup, the server loads and initializes any\nplugin that is\nlisted in the mysql.plugin table. This means that a plugin\nis installed\nwith INSTALL SONAME only once, not every time the server\nstarts. Plugin loading at startup does not occur if the\nserver is started with\nthe --skip-grant-tables option.\n \nWhen the server shuts down, it executes the deinitialization\nfunction\nfor each plugin that is loaded so that the plugin has a\nchance to\nperform any final cleanup.\n \nIf you need to load plugins for a single server startup when\nthe\n--skip-grant-tables option is given (which tells the server\nnot to read system tables), use the \n--plugin-load mysqld option.\n \nIf you need to install only one plugin from a library, use\nthe INSTALL PLUGIN statement.\n \nExamples\n-------- \nTo load the XtraDB storage engine and all of its\ninformation_schema tables with one statement, use\n \nINSTALL SONAME \'ha_xtradb\';\n \nThis statement can be used instead of INSTALL PLUGIN even\nwhen the library contains only one plugin:\n \nINSTALL SONAME \'ha_sequence\';\n \n\n\nURL: https://mariadb.com/kb/en/install-soname/','','https://mariadb.com/kb/en/install-soname/'),(82,'UNINSTALL SONAME',5,'UNINSTALL SONAME has been supported since MariaDB 5.5.21.\n \nSyntax\n------ \nUNINSTALL SONAME [IF EXISTS] \'plugin_library\'\n \nDescription\n----------- \nThis statement is a variant of UNINSTALL PLUGIN statement,\nthat removes all plugins belonging to a specified\nplugin_library. See UNINSTALL PLUGIN for details.\n \nplugin_library is the name of the shared library that\ncontains the plugin code. The file name extension (for\nexample, libmyplugin.so or libmyplugin.dll) can be omitted\n(which makes the statement look the same on all\narchitectures).\n \nTo use UNINSTALL SONAME, you must have the\nDELETE privilege for the mysql.plugin table.\n \nIF EXISTS\n \nIf the IF EXISTS clause is used, MariaDB will return a note\ninstead of an error if the plugin library does not exist.\nSee SHOW WARNINGS.\n \nExamples\n-------- \nTo uninstall the XtraDB plugin and all of its\ninformation_schema tables with one statement, use\n \nUNINSTALL SONAME \'ha_xtradb\';\n \nFrom MariaDB 10.4.0:\n \nUNINSTALL SONAME IF EXISTS \'ha_example\';\n \nQuery OK, 0 rows affected (0.099 sec)\n \nUNINSTALL SONAME IF EXISTS \'ha_example\';\n \nQuery OK, 0 rows affected, 1 warning (0.000 sec)\n \nSHOW WARNINGS;\n \n+-------+------+-------------------------------------+\n| Level | Code | Message |\n+-------+------+-------------------------------------+\n| Note | 1305 | SONAME ha_example.so does not exist |\n+-------+------+-------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/uninstall-soname/','','https://mariadb.com/kb/en/uninstall-soname/'),(93,'IFNULL',7,'Syntax\n------ \nIFNULL(expr1,expr2)\n \nDescription\n----------- \nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it\nreturns\nexpr2. IFNULL() returns a numeric or string value, depending\non the\ncontext in which it is used.\n \nExamples\n-------- \nSELECT IFNULL(1,0); \n+-------------+\n| IFNULL(1,0) |\n+-------------+\n| 1 |\n+-------------+\n \nSELECT IFNULL(NULL,10);\n+-----------------+\n| IFNULL(NULL,10) |\n+-----------------+\n| 10 |\n+-----------------+\n \nSELECT IFNULL(1/0,10);\n+----------------+\n| IFNULL(1/0,10) |\n+----------------+\n| 10.0000 |\n+----------------+\n \nSELECT IFNULL(1/0,\'yes\');\n+-------------------+\n| IFNULL(1/0,\'yes\') |\n+-------------------+\n| yes |\n+-------------------+\n \n\n\nURL: https://mariadb.com/kb/en/ifnull/','','https://mariadb.com/kb/en/ifnull/'),(94,'NULLIF',7,'Syntax\n------ \nNULLIF(expr1,expr2)\n \nDescription\n----------- \nReturns NULL if expr1 = expr2 is true, otherwise returns\nexpr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1\nEND.\n \nExamples\n-------- \nSELECT NULLIF(1,1);\n+-------------+\n| NULLIF(1,1) |\n+-------------+\n| NULL |\n+-------------+\n \nSELECT NULLIF(1,2);\n+-------------+\n| NULLIF(1,2) |\n+-------------+\n| 1 |\n+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/nullif/','','https://mariadb.com/kb/en/nullif/'),(85,'MBRDisjoint',6,'Syntax\n------ \nMBRDisjoint(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangles of the two geometries g1 and g2 are disjoint. Two\ngeometries are disjoint if they do not intersect, that is\ntouch or overlap.\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((4 4,4 7,7 7,7 4,4 4))\');\nSELECTmbrdisjoint(@g1,@g2);\n+----------------------+\n| mbrdisjoint(@g1,@g2) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbrdisjoint(@g1,@g2);\n+----------------------+\n| mbrdisjoint(@g1,@g2) |\n+----------------------+\n| 0 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrdisjoint/','','https://mariadb.com/kb/en/mbrdisjoint/'),(87,'MBRIntersects',6,'Syntax\n------ \nMBRIntersects(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangles of the two geometries g1 and g2 intersect.\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbrintersects(@g1,@g2);\n+------------------------+\n| mbrintersects(@g1,@g2) |\n+------------------------+\n| 1 |\n+------------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((4 4,4 7,7 7,7 4,4 4))\');\nSELECT mbrintersects(@g1,@g2);\n+------------------------+\n| mbrintersects(@g1,@g2) |\n+------------------------+\n| 0 |\n+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrintersects/','','https://mariadb.com/kb/en/mbrintersects/'),(88,'MBROverlaps',6,'Syntax\n------ \nMBROverlaps(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangles of\nthe two geometries g1 and g2 overlap. The term spatially\noverlaps is\nused if two geometries intersect and their intersection\nresults in a\ngeometry of the same dimension but not equal to either of\nthe given\ngeometries.\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((4 4,4 7,7 7,7 4,4 4))\');\nSELECT mbroverlaps(@g1,@g2);\n+----------------------+\n| mbroverlaps(@g1,@g2) |\n+----------------------+\n| 0 |\n+----------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbroverlaps(@g1,@g2);\n+----------------------+\n| mbroverlaps(@g1,@g2) |\n+----------------------+\n| 0 |\n+----------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 4,4 4,4 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbroverlaps(@g1,@g2);\n+----------------------+\n| mbroverlaps(@g1,@g2) |\n+----------------------+\n| 1 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbroverlaps/','','https://mariadb.com/kb/en/mbroverlaps/'),(89,'MBRTouches',6,'Syntax\n------ \nMBRTouches(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether the Minimum Bounding\nRectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially\ntouch if\nthe interiors of the geometries do not intersect, but the\nboundary of\none of the geometries intersects either the boundary or the\ninterior\nof the other.\n \nExamples\n-------- \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((4 4,4 7,7 7,7 4,4 4))\');\nSELECT mbrtouches(@g1,@g2);\n+---------------------+\n| mbrtouches(@g1,@g2) |\n+---------------------+\n| 0 |\n+---------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbrtouches(@g1,@g2);\n+---------------------+\n| mbrtouches(@g1,@g2) |\n+---------------------+\n| 1 |\n+---------------------+\n \nSET @g1 = GeomFromText(\'Polygon((0 0,0 4,4 4,4 0,0 0))\');\nSET @g2 = GeomFromText(\'Polygon((3 3,3 6,6 6,6 3,3 3))\');\nSELECT mbrtouches(@g1,@g2);\n+---------------------+\n| mbrtouches(@g1,@g2) |\n+---------------------+\n| 0 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mbrtouches/','','https://mariadb.com/kb/en/mbrtouches/'),(91,'CASE OPERATOR',7,'Syntax\n------ \nCASE value WHEN [compare_value] THEN result [WHEN\n[compare_value] THEN\nresult ...] [ELSE result] END\n \nCASE WHEN [condition] THEN result [WHEN [condition] THEN\nresult ...]\n[ELSE result] END\n \nDescription\n----------- \nThe first version returns the result where\nvalue=compare_value. The\nsecond version returns the result for the first condition\nthat is\ntrue. If there was no matching result value, the result\nafter ELSE is\nreturned, or NULL if there is no ELSE part.\n \nThere is also a CASE statement, which differs from the CASE\noperator described here.\n \nExamples\n-------- \nSELECT CASE 1 WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE\n\'more\' END;\n \n+------------------------------------------------------------+\n| CASE 1 WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE\n\'more\' END |\n+------------------------------------------------------------+\n| one |\n+------------------------------------------------------------+\n \nSELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n \n+--------------------------------------------+\n| CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END |\n+--------------------------------------------+\n| true |\n+--------------------------------------------+\n \nSELECT CASE BINARY \'B\' WHEN \'a\' THEN 1 WHEN \'b\' THEN 2\nEND;\n \n+-----------------------------------------------------+\n| CASE BINARY \'B\' WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END\n|\n+-----------------------------------------------------+\n| NULL |\n+-----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/case-operator/','','https://mariadb.com/kb/en/case-operator/'),(95,'CHANGE MASTER TO',8,'Syntax\n------ \nCHANGE MASTER [\'connection_name\'] TO master_def [,\nmaster_def] ...\n \nmaster_def:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'[\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_DELAY = interval\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_CRL = \'crl_file_name\'\n | MASTER_SSL_CRLPATH = \'crl_directory_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | MASTER_USE_GTID = {current_pos|slave_pos|no}\n | IGNORE_SERVER_IDS = (server_id_list)\n | DO_DOMAIN_IDS = ([N,..])\n | IGNORE_DOMAIN_IDS = ([N,..])\n \nDescription\n----------- \nThe CHANGE MASTER statement sets the options that a\nreplication slave uses to connect to and replicate from a\nreplication master. \n \nMariaDB until 10.0.7\n \nIn MariaDB 10.0.7 and before, the relay_log_purge system\nvariable was silently set to 0 when CHANGE MASTER was\nexecuted.\n \nMulti-Source Replication\n \nMulti-source replication was added in MariaDB 10.0.1.\n \nIf you are using multi-source replication, then you need to\nspecify a connection name when you execute CHANGE MASTER.\nThere are two ways to do this:\nSetting the default_master_connection system variable prior\nto executing CHANGE MASTER.\nSetting the connection_name parameter when executing CHANGE\nMASTER.\n \ndefault_master_connection\n \nSET default_master_connection = \'gandalf\';\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n MASTER_PASSWORD=\'new3cret\';\n \nSTART SLAVE;\n \nconnection_name\n \nSTOP SLAVE \'gandalf\';\n \nCHANGE MASTER \'gandalf\' TO \n MASTER_PASSWORD=\'new3cret\';\n \nSTART SLAVE \'gandalf\';\n \nOptions\n \nConnection Options\n \nMASTER_USER\n \nThe MASTER_USER option for CHANGE MASTER defines the user\naccount that the replication slave will use to connect to\nthe replication master.\n \nThis user account will need the REPLICATION SLAVE privilege\non the master.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_USER=\'repl\',\n MASTER_PASSWORD=\'new3cret\';\n \nSTART SLAVE;\n \nMASTER_PASSWORD\n \nThe MASTER_USER option for CHANGE MASTER defines the\npassword that the replication slave will use to connect to\nthe replication master as the user account defined by the\nMASTER_USER option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n MASTER_PASSWORD=\'new3cret\';\n \nSTART SLAVE;\n \nMASTER_HOST\n \nThe MASTER_HOST option for CHANGE MASTER defines the\nhostname or IP address of the replication master.\n \nIf you set the value of the MASTER_HOST option to the empty\nstring, then that is not the same as not setting the\noption\'s value at all. In MariaDB 5.5 and later, if you set\nthe value of the MASTER_HOST option to the empty string,\nthen the CHANGE MASTER command will fail with an error. In\nMariaDB 5.3 and before, if you set the value of the\nMASTER_HOST option to the empty string, then the CHANGE\nMASTER command would succeed, but the subsequent START SLAVE\ncommand would fail.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_HOST=\'dbserver1.example.com\',\n MASTER_USER=\'repl\',\n MASTER_PASSWORD=\'new3cret\',\n MASTER_USE_GTID=slave_pos;\n \nSTART SLAVE;\n \nIf you set the value of the MASTER_HOST option in a CHANGE\nMASTER command, then the slave assumes that the master is\ndifferent from before, even if you set the value of this\noption to the same value it had previously. In this\nscenario, the slave will consider the old values for the\nmaster\'s binary\nlog file name and position to be invalid for the new master.\nAs a side effect, if you do not explicitly set the values of\nthe MASTER_LOG_FILE and MASTER_LOG_POS options in the\nstatement, then the statement will be implicitly appended\nwith MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4. However, if\nyou enable GTID mode for replication by setting the\nMASTER_USE_GTID option to some value other than no in the\nstatement, then these values will effectively be ignored\nanyway.\n \nReplication slaves cannot connect to replication masters\nusing Unix socket files or Windows named pipes. The\nreplication slave must connect to the replication master\nusing TCP/IP.\n \nMASTER_PORT\n \nThe MASTER_PORT option for CHANGE MASTER defines the TCP/IP\nport of the replication master.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_HOST=\'dbserver1.example.com\',\n MASTER_PORT=3307,\n MASTER_USER=\'repl\',\n MASTER_PASSWORD=\'new3cret\',\n MASTER_USE_GTID=slave_pos;\n \nSTART SLAVE;\n \nIf you set the value of the MASTER_PORT option in a CHANGE\nMASTER command, then the slave assumes that the master is\ndifferent from before, even if you set the value of this\noption to the same value it had previously. In this\nscenario, the slave will consider the old values for the\nmaster\'s binary\nlog file name and position to be invalid for the new master.\nAs a side effect, if you do not explicitly set the values of\nthe MASTER_LOG_FILE and MASTER_LOG_POS options in the\nstatement, then the statement will be implicitly appended\nwith MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4. However, if\nyou enable GTID mode for replication by setting the\nMASTER_USE_GTID option to some value other than no in the\nstatement, then these values will effectively be ignored\nanyway.\n \nReplication slaves cannot connect to replication masters\nusing Unix socket files or Windows named pipes. The\nreplication slave must connect to the replication master\nusing TCP/IP.\n \nMASTER_CONNECT_RETRY\n \nThe MASTER_CONNECT_RETRY option for CHANGE MASTER defines\nhow many seconds that the slave will wait between connection\nretries. The default is 60.\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n MASTER_CONNECT_RETRY=20;\n \nSTART SLAVE;\n \nThe number of connection attempts is limited by the\nmaster_retry_count option. It can be set either on the\ncommand-line or in a server option group in an option file\nprior to starting up the server. For example:\n \n[mariadb]\n...\nmaster_retry_count=4294967295\n \nMASTER_BIND\n \nThe MASTER_BIND option for CHANGE MASTER is only supported\nby MySQL 5.6.2 and later and by MySQL NDB Cluster 7.3.1 and\nlater. This option is not yet supported by MariaDB. See\nMDEV-19248 for more information.\n \nThe MASTER_BIND option for CHANGE MASTER can be used on\nreplication slaves that have multiple network interfaces to\nchoose which network interface the slave will use to connect\nto the master.\n \nMASTER_HEARTBEAT_PERIOD\n \nThe MASTER_HEARTBEAT_PERIOD option for CHANGE MASTER can be\nused to set the interval in seconds between replication\nheartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is\nreset.\n \nThis option\'s interval argument has the following\ncharacteristics:\nIt is a decimal value with a range of 0 to 4294967 seconds.\nIt has a resolution of hundredths of a second.\nIts smallest valid non-zero value is 0.001.\nIts default value is the value of the slave_net_timeout\nsystem variable divided by 2.\nIf it\'s set to 0, then heartbeats are disabled.\n \nHeartbeats are sent by the master only if there are no\nunsent events in the binary log file for a period longer\nthan the interval.\n \nIf the RESET SLAVE statement is executed, then the heartbeat\ninterval is reset to the default.\n \nIf the slave_net_timeout system variable is set to a value\nthat is lower than the current heartbeat interval, then a\nwarning will be issued.\n \nTLS Options\n \nThe TLS options are used for providing information about\nTLS. The options can be set even on slaves that are compiled\nwithout TLS support. The TLS options are saved to either the\ndefault master.info file or the file that is configured by\nthe master_info_file option, but these TLS options are\nignored unless the slave supports TLS.\n \nSee Replication with Secure Connections for more\ninformation.\n \nMASTER_SSL\n \nThe MASTER_SSL option for CHANGE MASTER tells the slave\nwhether to force TLS for the connection. The valid values\nare 0 or 1.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL=1;\n \nSTART SLAVE;\n \nMASTER_SSL_CA\n \nThe MASTER_SSL_CA option for CHANGE MASTER defines a path to\na PEM file that should contain one or more X509 certificates\nfor trusted Certificate Authorities (CAs) to use for TLS.\nThis option requires that you use the absolute path, not a\nrelative path. This option implies the MASTER_SSL option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1;\n \nSTART SLAVE;\n \nSee Secure Connections Overview: Certificate Authorities\n(CAs) for more information.\n \nMASTER_SSL_CAPATH\n \nThe MASTER_SSL_CAPATH option for CHANGE MASTER defines a\npath to a directory that contains one or more PEM files that\nshould each contain one X509 certificate for a trusted\nCertificate Authority (CA) to use for TLS. This option\nrequires that you use the absolute path, not a relative\npath. The directory specified by this option needs to be run\nthrough the openssl rehash command. This option implies the\nMASTER_SSL option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CAPATH=\'/etc/my.cnf.d/certificates/ca/\',\n MASTER_SSL_VERIFY_SERVER_CERT=1;\n \nSTART SLAVE;\n \nSee Secure Connections Overview: Certificate Authorities\n(CAs) for more information.\n \nMASTER_SSL_CERT\n \nThe MASTER_SSL_CERT option for CHANGE MASTER defines a path\nto the X509 certificate file to use for TLS. This option\nrequires that you use the absolute path, not a relative\npath. This option implies the MASTER_SSL option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1;\n \nSTART SLAVE;\n \nMASTER_SSL_CRL\n \nThe MASTER_SSL_CRL option for CHANGE MASTER defines a path\nto a PEM file that should contain one or more revoked X509\ncertificates to use for TLS. This option requires that you\nuse the absolute path, not a relative path.\n \nThis option is only supported if the server was built with\nOpenSSL. If the server was built with yaSSL, then this\noption is not supported. See TLS and Cryptography Libraries\nUsed by MariaDB for more information about which libraries\nare used on which platforms.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1,\n MASTER_SSL_CRL=\'/etc/my.cnf.d/certificates/crl.pem\';\n \nSTART SLAVE;\n \nSee Secure Connections Overview: Certificate Revocation\nLists (CRLs) for more information.\n \nMASTER_SSL_CRLPATH\n \nThe MASTER_SSL_CRLPATH option for CHANGE MASTER defines a\npath to a directory that contains one or more PEM files that\nshould each contain one revoked X509 certificate to use for\nTLS. This option requires that you use the absolute path,\nnot a relative path. The directory specified by this\nvariable needs to be run through the openssl rehash command.\n \nThis option is only supported if the server was built with\nOpenSSL. If the server was built with yaSSL, then this\noption is not supported. See TLS and Cryptography Libraries\nUsed by MariaDB for more information about which libraries\nare used on which platforms.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1,\n MASTER_SSL_CRLPATH=\'/etc/my.cnf.d/certificates/crl/\';\n \nSTART SLAVE;\n \nSee Secure Connections Overview: Certificate Revocation\nLists (CRLs) for more information.\n \nMASTER_SSL_KEY\n \nThe MASTER_SSL_KEY option for CHANGE MASTER defines a path\nto a private key file to use for TLS. This option requires\nthat you use the absolute path, not a relative path. This\noption implies the MASTER_SSL option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1;\n \nSTART SLAVE;\n \nMASTER_SSL_CIPHER\n \nThe MASTER_SSL_CIPHER option for CHANGE MASTER defines the\nlist of permitted ciphers or cipher suites to use for TLS.\nBesides cipher names, if MariaDB was compiled with OpenSSL,\nthis option could be set to \"SSLv3\" or \"TLSv1.2\" to\nallow all SSLv3 or all TLSv1.2 ciphers. Note that the\nTLSv1.3 ciphers cannot be excluded when using OpenSSL, even\nby using this option. See Using TLSv1.3 for details. This\noption implies the MASTER_SSL option.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1,\n MASTER_SSL_CIPHER=\'TLSv1.2\';\n \nSTART SLAVE;\n \nMASTER_SSL_VERIFY_SERVER_CERT\n \nThe MASTER_SSL_VERIFY_SERVER_CERT option for CHANGE MASTER\nenables server certificate verification. This option is\ndisabled by default.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_SSL_CERT=\'/etc/my.cnf.d/certificates/server-cert.pem\',\n MASTER_SSL_KEY=\'/etc/my.cnf.d/certificates/server-key.pem\',\n MASTER_SSL_CA=\'/etc/my.cnf.d/certificates/ca.pem\',\n MASTER_SSL_VERIFY_SERVER_CERT=1;\n \nSTART SLAVE;\n \nSee Secure Connections Overview: Server Certificate\nVerification for more information.\n \nBinary Log Options\n \nThese options are related to the binary log position on the\nmaster.\n \nMASTER_LOG_FILE\n \nThe MASTER_LOG_FILE option for CHANGE MASTER can be used\nalong with MASTER_LOG_POS to specify the coordinates at\nwhich the slave\'s I/O thread should begin reading from the\nmaster\'s binary logs the next time the thread starts.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4;\n \nSTART SLAVE;\n \nThe MASTER_LOG_FILE and MASTER_LOG_POS options cannot be\nspecified if the RELAY_LOG_FILE and RELAY_LOG_POS options\nwere also specified.\n \nThe MASTER_LOG_FILE and MASTER_LOG_POS options are\neffectively ignored if you enable GTID mode for replication\nby setting the MASTER_USE_GTID option to some value other\nthan no in the statement.\n \nMASTER_LOG_POS\n \nThe MASTER_LOG_POS option for CHANGE MASTER can be used\nalong with MASTER_LOG_FILE to specify the coordinates at\nwhich the slave\'s I/O thread should begin reading from the\nmaster\'s binary logs the next time the thread starts.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4;\n \nSTART SLAVE;\n \nThe MASTER_LOG_FILE and MASTER_LOG_POS options cannot be\nspecified if the RELAY_LOG_FILE and RELAY_LOG_POS options\nwere also specified.\n \nThe MASTER_LOG_FILE and MASTER_LOG_POS options are\neffectively ignored if you enable GTID mode for replication\nby setting the MASTER_USE_GTID option to some value other\nthan no in the statement.\n \nRelay Log Options\n \nThese options are related to the relay log position on the\nslave.\n \nRELAY_LOG_FILE\n \nThe RELAY_LOG_FILE option for CHANGE MASTER can be used\nalong with the RELAY_LOG_POS option to specify the\ncoordinates at which the slave\'s SQL thread should begin\nreading from the relay log the next time the thread starts.\n \nThe CHANGE MASTER statement usually deletes all relay log\nfiles. However, if the RELAY_LOG_FILE and/or RELAY_LOG_POS\noptions are specified, then existing relay log files are\nkept.\n \nWhen you want to change the relay log position, you only\nneed to stop the slave\'s SQL thread. The slave\'s I/O\nthread can continue running. The STOP SLAVE and START SLAVE\nstatements support the SQL_THREAD option for this scenario.\nFor example:\n \nSTOP SLAVE SQL_THREAD;\n \nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n \nSTART SLAVE SQL_THREAD;\n \nWhen the value of this option is changed, the metadata about\nthe slave\'s SQL thread\'s position in the relay logs will\nalso be changed in the relay-log.info file or the file that\nis configured by the relay_log_info_file system variable.\n \nThe RELAY_LOG_FILE and RELAY_LOG_POS options cannot be\nspecified if the MASTER_LOG_FILE and MASTER_LOG_POS options\nwere also specified.\n \nRELAY_LOG_POS\n \nThe RELAY_LOG_POS option for CHANGE MASTER can be used along\nwith the RELAY_LOG_FILE option to specify the coordinates at\nwhich the slave\'s SQL thread should begin reading from the\nrelay log the next time the thread starts.\n \nThe CHANGE MASTER statement usually deletes all relay log\nfiles. However, if the RELAY_LOG_FILE and/or RELAY_LOG_POS\noptions are specified, then existing relay log files are\nkept.\n \nWhen you want to change the relay log position, you only\nneed to stop the slave\'s SQL thread. The slave\'s I/O\nthread can continue running. The STOP SLAVE and START SLAVE\nstatements support the SQL_THREAD option for this scenario.\nFor example:\n \nSTOP SLAVE SQL_THREAD;\n \nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n \nSTART SLAVE SQL_THREAD;\n \nWhen the value of this option is changed, the metadata about\nthe slave\'s SQL thread\'s position in the relay logs will\nalso be changed in the relay-log.info file or the file that\nis configured by the relay_log_info_file system variable.\n \nThe RELAY_LOG_FILE and RELAY_LOG_POS options cannot be\nspecified if the MASTER_LOG_FILE and MASTER_LOG_POS options\nwere also specified.\n \nGTID Options\n \nMASTER_USE_GTID\n \nThe MASTER_USE_GTID option for CHANGE MASTER was first added\nin MariaDB 10.0.2 to enable replication with Global\nTransaction IDs (GTIDs).\n \nThe MASTER_USE_GTID option for CHANGE MASTER can be used to\nconfigure the slave to use the global transaction ID (GTID)\nwhen connecting to a master. The possible values are:\ncurrent_pos - Replicate in GTID mode and use\ngtid_current_pos as the position to start downloading\ntransactions from the master.\nslave_pos - Replicate in GTID mode and use gtid_slave_pos as\nthe position to start downloading transactions from the\nmaster.\nno - Don\'t replicate in GTID mode.\n \nFor example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO\n MASTER_USE_GTID = current_pos;\n \nSTART SLAVE;\n \nOr:\n \nSTOP SLAVE;\n \nSET GLOBAL gtid_slave_pos=\'0-1-153\';\n \nCHANGE MASTER TO\n MASTER_USE_GTID = slave_pos;\n \nSTART SLAVE;\n \nReplication Filter Options\n \nIGNORE_SERVER_IDS\n \nThe IGNORE_SERVER_IDS option for CHANGE MASTER can be used\nto configure a replication slave to ignore binary log events\nthat originated from certain servers. Filtered binary log\nevents will not get logged to the slave’s relay log, and\nthey will not be applied by the slave.\n \nThe option\'s value can be specified by providing a\ncomma-separated list of server_id values. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n IGNORE_SERVER_IDS = (3,5);\nSTART SLAVE;\n \nIf you would like to clear a previously set list, then you\ncan set the value to an empty list. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n IGNORE_SERVER_IDS = ();\nSTART SLAVE;\n \nDO_DOMAIN_IDS\n \nThe DO_DOMAIN_IDS option for CHANGE MASTER was first added\nin MariaDB 10.1.2.\n \nThe DO_DOMAIN_IDS option for CHANGE MASTER can be used to\nconfigure a replication slave to only apply binary log\nevents if the transaction\'s GTID is in a specific\ngtid_domain_id value. Filtered binary log events will not\nget logged to the slave’s relay log, and they will not be\napplied by the slave.\n \nThe option\'s value can be specified by providing a\ncomma-separated list of gtid_domain_id values. Duplicate\nvalues are automatically ignored. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n DO_DOMAIN_IDS = (1,2);\nSTART SLAVE;\n \nIf you would like to clear a previously set list, then you\ncan set the value to an empty list. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n DO_DOMAIN_IDS = ();\nSTART SLAVE;\n \nThe DO_DOMAIN_IDS option and the IGNORE_DOMAIN_IDS option\ncannot both be set to non-empty values at the same time. If\nyou want to set the DO_DOMAIN_IDS option, and the\nIGNORE_DOMAIN_IDS option was previously set, then you need\nto clear the value of the IGNORE_DOMAIN_IDS option. For\nexample:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n IGNORE_DOMAIN_IDS = (), \n DO_DOMAIN_IDS = (1,2);\nSTART SLAVE;\n \nThe DO_DOMAIN_IDS option can only be specified if the slave\nis replicating in GTID mode. Therefore, the MASTER_USE_GTID\noption must also be set to some value other than no in order\nto use this option.\n \nIGNORE_DOMAIN_IDS\n \nThe IGNORE_DOMAIN_IDS option for CHANGE MASTER was first\nadded in MariaDB 10.1.2.\n \nThe IGNORE_DOMAIN_IDS option for CHANGE MASTER can be used\nto configure a replication slave to ignore binary log events\nif the transaction\'s GTID is in a specific gtid_domain_id\nvalue. Filtered binary log events will not get logged to the\nslave’s relay log, and they will not be applied by the\nslave.\n \nThe option\'s value can be specified by providing a\ncomma-separated list of gtid_domain_id values. Duplicate\nvalues are automatically ignored. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n IGNORE_DOMAIN_IDS = (1,2);\nSTART SLAVE;\n \nIf you would like to clear a previously set list, then you\ncan set the value to an empty list. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n IGNORE_DOMAIN_IDS = ();\nSTART SLAVE;\n \nThe DO_DOMAIN_IDS option and the IGNORE_DOMAIN_IDS option\ncannot both be set to non-empty values at the same time. If\nyou want to set the IGNORE_DOMAIN_IDS option, and the\nDO_DOMAIN_IDS option was previously set, then you need to\nclear the value of the DO_DOMAIN_IDS option. For example:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n DO_DOMAIN_IDS = (), \n IGNORE_DOMAIN_IDS = (1,2);\nSTART SLAVE;\n \nThe IGNORE_DOMAIN_IDS option can only be specified if the\nslave is replicating in GTID mode. Therefore, the\nMASTER_USE_GTID option must also be set to some value other\nthan no in order to use this option.\n \nDelayed Replication Options\n \nMASTER_DELAY\n \nThe MASTER_DELAY option for CHANGE MASTER was first added in\nMariaDB 10.2.3 to enable delayed replication.\n \nThe MASTER_DELAY option for CHANGE MASTER can be used to\nenable delayed replication. This option specifies the time\nin seconds (at least) that a replication slave should lag\nbehind the master. Before executing an event, the slave will\nfirst wait, if necessary, until the given time has passed\nsince the event was created on the master. The result is\nthat the slave will reflect the state of the master some\ntime back in the past. The default is zero, no delay.\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n MASTER_DELAY=3600;\n \nSTART SLAVE;\n \nChanging Option Values\n \nIf you don\'t specify a given option when executing the\nCHANGE MASTER statement, then the option keeps its old value\nin most cases. Most of the time, there is no need to specify\nthe options that do not need to change. For example, if the\npassword for the user account that the slave uses to connect\nto its master has changed, but no other options need to\nchange, then you can just change the MASTER_PASSWORD option\nby executing the following commands:\n \nSTOP SLAVE;\n \nCHANGE MASTER TO \n MASTER_PASSWORD=\'new3cret\';\n \nSTART SLAVE;\n \nThere are some cases where options are implicitly reset,\nsuch as when the MASTER_HOST and MASTER_PORT options are\nchanged.\n \nOption Persistence\n \nThe values of the MASTER_LOG_FILE and MASTER_LOG_POS options\n(i.e. the binary log position on the master) and most other\noptions are written to either the default master.info file\nor the file that is configured by the master_info_file\noption. The slave\'s I/O thread keeps this binary log\nposition updated as it downloads events only when\nMASTER_USE_GTID option\n is set to NO. Otherwise the file is not updated on a per\nevent basis.\n \nThe master_info_file option can be set either on the\ncommand-line or in a server option group in an option file\nprior to starting up the server. For example:\n \n[mariadb]\n...\nmaster_info_file=/mariadb/myserver1-master.info\n \nThe values of the RELAY_LOG_FILE and RELAY_LOG_POS options\n(i.e. the relay log position) are written to either the\ndefault relay-log.info file or the file that is configured\nby the relay_log_info_file system variable. The slave\'s SQL\nthread keeps this relay log position updated as it applies\nevents.\n \nThe relay_log_info_file system variable can be set either on\nthe command-line or in a server option group in an option\nfile prior to starting up the server. For example:\n \n[mariadb]\n...\nrelay_log_info_file=/mariadb/myserver1-relay-log.info\n \nGTID Persistence\n \nIf the slave is replicating binary log events that contain\nGTIDs, then the slave\'s SQL thread will write every GTID\nthat it applies to the mysql.gtid_slave_pos table. This GTID\ncan be inspected and modified through the gtid_slave_pos\nsystem variable.\n \nIf the slave has the log_slave_updates system variable\nenabled and if the slave has the binary log enabled, then\nevery write by the slave\'s SQL thread will also go into the\nslave\'s binary log. This means that GTIDs of replicated\ntransactions would be reflected in the value of the\ngtid_binlog_pos system variable.\n \nCreating a Slave from a Backup\n \nThe CHANGE MASTER statement is useful for setting up a slave\nwhen you have a backup of the master and you also have the\nbinary log position or GTID position corresponding to the\nbackup.\n \nAfter restoring the backup on the slave, you could execute\nsomething like this to use the binary log position:\n \nCHANGE MASTER TO\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4;\n \nSTART SLAVE;\n \nOr you could execute something like this to use the GTID\nposition:\n \nSET GLOBAL gtid_slave_pos=\'0-1-153\';\n \nCHANGE MASTER TO\n MASTER_USE_GTID=slave_pos;\n \nSTART SLAVE;\n \nSee Setting up a Replication Slave with Mariabackup for more\ninformation on how to do this with Mariabackup.\n \nExample\n \nThe following example changes the master and master\'s\nbinary log coordinates.\nThis is used when you want to set up the slave to replicate\nthe master:\n \nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n \nSTART SLAVE;\n \n\n\nURL: https://mariadb.com/kb/en/change-master-to/','','https://mariadb.com/kb/en/change-master-to/'),(106,'RESET MASTER',8,'RESET MASTER [TO #]\n \nDeletes all binary log files listed in the index file,\nresets the\nbinary log index file to be empty, and creates a new binary\nlog file with a suffix of .000001.\n \nIf TO # is given, then the first new binary log file will\nstart from number #.\n \nThis statement is for use only when the master is started\nfor the first time, and should never be used if any slaves\nare actively replicating from the binary log.\n \n\n\nURL: https://mariadb.com/kb/en/reset-master/','','https://mariadb.com/kb/en/reset-master/'),(113,'UNLOCK TABLES',8,'Syntax\n------ \nUNLOCK TABLES\n \nDescription\n----------- \nUNLOCK TABLES explicitly releases any table locks held by\nthe\ncurrent session. See LOCK TABLES for more information.\n \nIn addition to releasing table locks acquired by the LOCK\nTABLES statement, the UNLOCK TABLES statement also releases\nthe global read lock acquired by the FLUSH TABLES WITH READ\nLOCK statement. The FLUSH TABLES WITH READ LOCK statement is\nvery useful for performing backups. See FLUSH for more\ninformation about FLUSH TABLES WITH READ LOCK.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/transactions-unlock-tables/','','https://mariadb.com/kb/en/transactions-unlock-tables/'),(115,'XA Transactions',8,'Overview\n \nThe MariaDB XA implementation is based on the X/Open CAE\ndocument Distributed Transaction Processing: The XA\nSpecification. This document is published by The Open Group\nand available at\nhttp://www.opengroup.org/public/pubs/catalog/c193.htm.\n \nXA transactions are designed to allow distributed\ntransactions, where a transaction manager (the application)\ncontrols a transaction which involves multiple resources.\nSuch resources are usually DBMSs, but could be resources of\nany type. The whole set of required transactional operations\nis called a global transaction. Each subset of operations\nwhich involve a single resource is called a local\ntransaction. XA used a 2-phases commit (2PC). With the first\ncommit, the transaction manager tells each resource to\nprepare an effective commit, and waits for a confirm\nmessage. The changes are not still made effective at this\npoint. If any of the resources encountered an error, the\ntransaction manager will rollback the global transaction. If\nall resources communicate that the first commit is\nsuccessful, the transaction manager can require a second\ncommit, which makes the changes effective.\n \nIn MariaDB, XA transactions can only be used with storage\nengines that support them. At least InnoDB, TokuDB, SPIDER\nand MyRocks support them. For InnoDB, XA transactions can be\ndisabled by setting the innodb_support_xa server system\nvariable to 0. \n \nLike regular transactions, XA transactions create metadata\nlocks on accessed tables.\n \nXA transactions require REPEATABLE READ as a minimum\nisolation level. However, distributed transactions should\nalways use SERIALIZABLE.\n \nTrying to start more than one XA transaction at the same\ntime produces a 1400 error (SQLSTATE \'XAE09\'). The same\nerror is produced when attempting to start an XA transaction\nwhile a regular transaction is in effect. Trying to start a\nregular transaction while an XA transaction is in effect\nproduces a 1399 error (SQLSTATE \'XAE07\').\n \nThe statements that cause an implicit COMMIT for regular\ntransactions produce a 1400 error (SQLSTATE \'XAE09\') if a\nXA transaction is in effect.\n \nInternal XA vs External XA\n \nXA transactions are an overloaded term in MariaDB. If a\nstorage engine is XA-capable, it can mean one or both of\nthese:\nIt supports MariaDB\'s internal two-phase commit API. This\nis transparent to the user. Sometimes this is called\n\"internal XA\", since MariaDB\'s internal transaction\ncoordinator log can handle coordinating these transactions.\n \nIt supports XA transactions, with the XA START, XA PREPARE,\nXA COMMIT, etc. statements. Sometimes this is called\n\"external XA\", since it requires the use of an external\ntransaction coordinator to use this feature properly.\n \nTransaction Coordinator Log\n \nIf you have two or more XA-capable storage engines enabled,\nthen a transaction coordinator log must be available.\n \nThere are currently two implementations of the transaction\ncoordinator log:\nBinary log-based transaction coordinator log\nMemory-mapped file-based transaction coordinator log\n \nIf the binary log is enabled on a server, then the server\nwill use the binary log-based transaction coordinator log.\nOtherwise, it will use the memory-mapped file-based\ntransaction coordinator log.\n \nSee Transaction Coordinator Log for more information.\n \nSyntax\n------ \nXA {START|BEGIN} xid [JOIN|RESUME]\n \nXA END xid [SUSPEND [FOR MIGRATE]]\n \nXA PREPARE xid\n \nXA COMMIT xid [ONE PHASE]\n \nXA ROLLBACK xid\n \nXA RECOVER [FORMAT=[\'RAW\'|\'SQL\']]\n \nxid: gtrid [, bqual [, formatID ]]\n \nThe interface to XA transactions is a set of SQL statements\nstarting with XA. Each statement changes a transaction\'s\nstate, determining which actions it can perform. A\ntransaction which does not exist is in the NON-EXISTING\nstate.\n \nXA START (or BEGIN) starts a transaction and defines its xid\n(a transaction identifier). The JOIN or RESUME keywords have\nno effect. The new transaction will be in ACTIVE state.\n \nThe xid can have 3 components, though only the first one is\nmandatory. gtrid is a quoted string representing a global\ntransaction identifier. bqual is a quoted string\nrepresenting a local transaction identifier. formatID is an\nunsigned integer indicating the format used for the first\ntwo components; if not specified, defaults to 1. MariaDB\ndoes not interpret in any way these components, and only\nuses them to identify a transaction. xids of transactions in\neffect must be unique.\n \nXA END declares that the specified ACTIVE transaction is\nfinished and it changes its state to IDLE. SUSPEND [FOR\nMIGRATE] has no effect.\n \nXA PREPARE prepares an IDLE transaction for commit, changing\nits state to PREPARED. This is the first commit.\n \nXA COMMIT definitely commits and terminates a transaction\nwhich has already been PREPARED. If the ONE PHASE clause is\nspecified, this statements performs a 1-phase commit on an\nIDLE transaction.\n \nXA ROLLBACK rolls back and terminates an IDLE or PREPARED\ntransaction.\n \nXA RECOVER shows information about all PREPARED\ntransactions.\n \nWhen trying to execute an operation which is not allowed for\nthe transaction\'s current state, an error is produced:\n \nXA COMMIT \'test\' ONE PHASE;\n \nERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be\nexecuted when global transaction is in the ACTIVE state\n \nXA COMMIT \'test2\';\n \nERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be\nexecuted when global transaction is in the NON-EXISTING\nstate\n \nXA RECOVER\n \nThe XA RECOVER statement shows information about all\ntransactions which are in the PREPARED state. It does not\nmatter which connection created the transaction: if it has\nbeen PREPARED, it appears. But this does not mean that a\nconnection can commit or rollback a transaction which was\nstarted by another connection. Note that transactions using\na 1-phase commit are never in the PREPARED state, so they\ncannot be shown by XA RECOVER.\n \nXA RECOVER produces four columns:\n \nXA RECOVER;\n \n+----------+--------------+--------------+------+\n| formatID | gtrid_length | bqual_length | data |\n+----------+--------------+--------------+------+\n| 1 | 4 | 0 | test |\n+----------+--------------+--------------+------+\n \nYou can use XA RECOVER FORMAT=\'SQL\' to get the data in a\nhuman readable\nform that can be directly copy-pasted into XA COMMIT or XA\nROLLBACK. This is particularly useful for binary xid\ngenerated by some transaction coordinators.\n \nformatID is the formatID part of xid.\n \ndata are the gtrid and bqual parts of xid, concatenated.\n \ngtrid_length and bqual_length are the lengths of gtrid and\nbqual, respectevely.\n \nExamples\n-------- \n2-phases commit:\n \nXA START \'test\';\n \nINSERT INTO t VALUES (1,2);\n \nXA END \'test\';\n \nXA PREPARE \'test\';\n \nXA COMMIT \'test\';\n \n1-phase commit:\n \nXA START \'test\';\n \nINSERT INTO t VALUES (1,2);\n \nXA END \'test\';\n \nXA COMMIT \'test\' ONE PHASE;\n \nHuman-readable:\n \nxa start \'12\\r34\\t67\\v78\', \'abc\\ndef\', 3;\n \ninsert t1 values (40);\n \nxa end \'12\\r34\\t67\\v78\', \'abc\\ndef\', 3;\n \nxa prepare \'12\\r34\\t67\\v78\', \'abc\\ndef\', 3;\n \nxa recover format=\'RAW\';\n \n+----------+--------------+--------------+--------------------+\n| formatID | gtrid_length | bqual_length | data |\n+----------+--------------+--------------+--------------------+\n34 67v78abc 11 | 7 | 12\ndef |\n+----------+--------------+--------------+--------------------+\n \nxa recover format=\'SQL\';\n \n+----------+--------------+--------------+-----------------------------------------------+\n| formatID | gtrid_length | bqual_length | data |\n+----------+--------------+--------------+-----------------------------------------------+\n| 3 | 11 | 7 |\nX\'31320d3334093637763738\',X\'6162630a646566\',3 |\n+----------+--------------+--------------+-----------------------------------------------+\n \nxa rollback\nX\'31320d3334093637763738\',X\'6162630a646566\',3;\n \nKnown Issues\n \nMariaDB Galera Cluster\n \nMariaDB Galera Cluster does not support XA transactions. See\nMDEV-10532 for more information on that. The request to\nimplement that feature is being tracked at MDEV-17099.\n \nHowever, MariaDB Galera Cluster builds include a built-in\nplugin called wsrep. Prior to MariaDB 10.4.3, this plugin\nwas internally considered an XA-capable storage engine.\nConsequently, these MariaDB Galera Cluster builds have\nmultiple XA-capable storage engines by default, even if the\nonly \"real\" storage engine that supports external XA\ntransactions enabled on these builds by default is InnoDB.\nTherefore, when using one these builds MariaDB would be\nforced to use a transaction coordinator log by default,\nwhich could have performance implications.\n \nSee Transaction Coordinator Log Overview: MariaDB Galera\nCluster for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/xa-transactions/','','https://mariadb.com/kb/en/xa-transactions/'),(117,'Authentication from MariaDB 10.4',10,'MariaDB 10.4 introduces a number of changes to the\nauthentication process, intended to make things easier and\nmore intuitive.\n \nOverview\n \nThere are four main changes relating to authentication:\nIt is possible to use more than one authentication plugin\nfor each user account. For example, this can be useful to\nslowly migrate users to the more secure ed25519\nauthentication plugin over time, while allowing the old\nmysql_native_password authentication plugin as an\nalternative for the transitional period.\nThe root@localhost user account created by mysql_install_db\nis created with the ability to use two authentication\nplugins.\nFirst, it is configured to try to use the unix_socket\nauthentication plugin. This allows the the root@localhost\nuser to login without a password via the local Unix socket\nfile defined by the socket system variable, as long as the\nlogin is attempted from a process owned by the operating\nsystem root user account.\nSecond, if authentication fails with the unix_socket\nauthentication plugin, then it is configured to try to use\nthe mysql_native_password authentication plugin. However, an\ninvalid password is initially set, so in order to\nauthenticate this way, a password must be set with SET\nPASSWORD.\nHowever, just using the unix_socket authentication plugin\nmay be fine for many users, and it is very secure. You may\nwant to try going without password authentication to see how\nwell it works for you. Remember, the best way to keep your\npassword safe is not to have one!\n \nAll user accounts, passwords, and global privileges are now\nstored in the mysql.global_priv table. The mysql.user table\nstill exists and has exactly the same set of columns as\nbefore, but it’s now a view that references the\nmysql.global_priv table. Tools that analyze the mysql.user\ntable should continue to workas before.\nMariaDB 10.4 supports User Password Expiry, which is not\nactive by default.\n \nDescription\n----------- \nAs a result of the above changes, the open-for-everyone\nall-powerful root account is finally gone. And installation\nscripts will no longer demand that you “PLEASE REMEMBER TO\nSET A PASSWORD FOR THE MariaDB root USER !”, because the\nroot account is securely created automatically.\n \nTwo all-powerful accounts are created by default — root\nand the OS user that owns the data directory, typically\nmysql. They are created as:\n \nCREATE USER root@localhost IDENTIFIED VIA unix_socket OR\nmysql_native_password USING \'invalid\'\nCREATE USER mysql@localhost IDENTIFIED VIA unix_socket OR\nmysql_native_password USING \'invalid\'\n \nUsing unix_socket means that if you are the system root\nuser, you can login as root@locahost without a password.\nThis technique was pioneered by Otto Kekäläinen in Debian\nMariaDB packages and has been successfully used in Debian\nsince as early as MariaDB 10.0. \n \nIt is based on a simple fact that asking the system root for\na password adds no extra security — root has full access\nto all the data files and all process memory anyway. But not\nasking for a password means, there is no root password to\nforget (no need for the numerous tutorials on “how to\nreset MariaDB root password”). And if you want to script\nsome tedious database work, there is no need to store the\nroot password in plain text for the scipt to use (no need\nfor debian-sys-maint user).\n \nStill, some users may wish to log in as MariaDB root without\nusing sudo. Hence the old authentication method —\nconventional MariaDB password — is still available. By\ndefault it is disabled (“invalid” is not a valid\npassword hash), but one can set the password with a usual\nSET PASSWORD statement. And still retain the password-less\naccess via sudo.\n \nIf you install MariaDB locally (say from a tarball, you\nwould not want to use sudo to be able to login. This is why\nMariaDB creates a second all-powerful user with the same\nname as a system user that owns the data directory. In local\n(not system-wide) installations, this will be the user who\ninstalled MariaDB — they automatically get convenient\npassword-less root-like access, because they can access all\nthe data files anyway.\n \nEven if MariaDB is installed system-wide, you may not want\nto run your database maintenance scripts as system root —\nnow you can run them as system mysql user. And you will know\nthat they will never destroy your entire system, even if you\nmake a typo in a shell script.\n \nHowever, seasoned MariaDB DBAs who are used to the old ways\ndo need to makes some changes. See the examples below for\ncommon tasks. \n \nCookbook\n \nAfter installing MariaDB system-wide the first thing\nyou’ve got used to doing is logging in into the\nunprotected root account and protecting it, that is, setting\nthe root password:\n \n$ sudo dnf install MariaDB-server\n$ mysql -uroot\n...\nMariaDB> set password = password(\"XH4VmT3_jt\");\n \nThis is not only unnecessary now, it will simply not work\n— there is no unprotected root account. To login as root\nuse\n \n$ sudo dnf install MariaDB-server\n$ sudo mysql\n \nNote that it implies you are connecting via the unix socket,\nnot tcp. If you happen to have protocol=tcp in a system-wide\n/etc/my.cnf file, use sudo mysql --protocol=socket.\n \nAfter installing MariaDB locally you’ve also used to\nconnect to the unprotected root account using mysql -uroot.\nThis will not work either, simply use mysql without\nspecifying a username.\n \nIf you\'ve forgotten your root password, no problem — you\ncan still connect using sudo and change the password. And if\nyou\'ve also removed unix_socket authentication, to restore\naccess do as follows:\nrestart MariaDB with --skip-grant-tables\nlogin into the unprotected server\nrun FLUSH PRIVILEGES (note, before 10.4 this would’ve been\nthe last step, not anymore). This disables\n--skip-grant-tables and allows you to change the stored\nauthentication method.\nrun SET PASSWORD FOR root@localhost to change the root\npassword\n \nTo view inside privilege tables, the old mysql.user table\nstill exists. You can select from it as before, although you\ncannot update it anymore. It doesn’t show alternative\nauthentication plugins and this was one of the reasons for\nswitching to the mysql.global_priv table — complex\nauthentication rules did not fit into rigid structure of a\nrelational table. You can select from the new table, for\nexample: \n \nselect concat(user, \'@\', host, \' => \',\njson_detailed(priv)) from mysql.global_priv;\n \nReverting to the Previous Authentication Method for\nroot@localhost\n \nIf you don\'t want the root@localhost user account created\nby mysql_install_db to use unix_socket authentication by\ndefault, then there are a few ways to revert to the previous\nmysql_native_password authentication method for this user\naccount.\n \nConfiguring mysql_install_db to Revert to the Previous\nAuthentication Method\n \nOne way to revert to the previous mysql_native_password\nauthentication method for the root@localhost user account is\nto execute mysql_install_db with a special option. If\nmysql_install_db is executed while\n--auth-root-authentication-method=normal is specified, then\nit will create the default user accounts using the default\nbehavior of MariaDB 10.3 and before.\n \nThis means that the root@localhost user account will use\nmysql_native_password authentication by default. There are\nsome other differences as well. See mysql_install_db: User\nAccounts Created by Default for more information.\n \nFor example, the option can be set on the command-line while\nrunning mysql_install_db:\n \nmysql_install_db --user=mysql --datadir=/var/lib/mysql\n--auth-root-authentication-method=normal\n \nThe option can also be set in an option file in an option\ngroup supported by mysql_install_db. For example:\n \n[mysql_install_db]\nauth_root_authentication_method=normal\n \nIf the option is set in an option file and if\nmysql_install_db is executed, then mysql_install_db will\nread this option from the option file, and it will\nautomatically set this option.\n \nAltering the User Account to Revert to the Previous\nAuthentication Method\n \nIf you have already installed MariaDB, and if the\nroot@localhost user account is already using unix_socket\nauthentication, then you can revert to the old\nmysql_native_password authentication method for the user\naccount by executing the following:\n \nALTER USER root@localhost IDENTIFIED VIA\nmysql_native_password USING PASSWORD(\"verysecret\")\n \n\n\nURL:\nhttps://mariadb.com/kb/en/authentication-from-mariadb-104/','','https://mariadb.com/kb/en/authentication-from-mariadb-104/'),(118,'CREATE USER',10,'Syntax\n------ \nCREATE [OR REPLACE] USER [IF NOT EXISTS] \n user_specification [,user_specification ...] \n [REQUIRE {NONE | tls_option [[AND] tls_option ...] }]\n [WITH resource_option [resource_option ...] ]\n [password_option | lock_option] \n \nuser_specification:\n username [authentication_option]\n \nauthentication_option:\n IDENTIFIED BY \'password\' \n | IDENTIFIED BY PASSWORD \'password_hash\'\n | IDENTIFIED {VIA|WITH} authentication_rule [OR\nauthentication_rule ...]\n \nauthentication_rule:\n authentication_plugin\n | authentication_plugin {USING|AS}\n\'authentication_string\'\n | authentication_plugin {USING|AS} PASSWORD(\'password\')\n \ntls_option:\n SSL \n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n \nresource_option:\n MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n | MAX_STATEMENT_TIME time\n \npassword_option:\n PASSWORD EXPIRE\n | PASSWORD EXPIRE DEFAULT\n | PASSWORD EXPIRE NEVER\n | PASSWORD EXPIRE INTERVAL N DAY\n \nlock_option:\n ACCOUNT LOCK\n | ACCOUNT UNLOCK\n}\n \nDescription\n----------- \nThe CREATE USER statement creates new MariaDB accounts. To\nuse it, you must have the global CREATE USER privilege or\nthe INSERT privilege for the mysql database. For each\naccount, CREATE USER creates a new row in\nthe mysql.user table that has no privileges.\n \nIf any of the specified accounts, or any permissions for the\nspecified accounts, already exist, then the server returns\nERROR 1396 (HY000). If an error occurs, CREATE USER will\nstill create the accounts that do not result in an error.\nOnly one error is produced for all users which have not been\ncreated:\n \nERROR 1396 (HY000): \n Operation CREATE USER failed for \'u1\'@\'%\',\'u2\'@\'%\'\n \nCREATE USER, DROP USER, CREATE ROLE, and DROP ROLE all\nproduce the\nsame error code when they fail.\n \nSee Account Names below for details on how account names are\nspecified. \n \nOR REPLACE\n \nIf the optional OR REPLACE clause is used, it is basically a\nshortcut for:\n \nDROP USER IF EXISTS name;\n \nCREATE USER name ...;\n \nFor example:\n \nCREATE USER foo2@test IDENTIFIED BY \'password\';\n \nERROR 1396 (HY000): Operation CREATE USER failed for\n\'foo2\'@\'test\'\n \nCREATE OR REPLACE USER foo2@test IDENTIFIED BY \'password\';\n \nQuery OK, 0 rows affected (0.00 sec)\n \nIF NOT EXISTS\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the specified user already\nexists.\n \nFor example:\n \nCREATE USER foo2@test IDENTIFIED BY \'password\';\n \nERROR 1396 (HY000): Operation CREATE USER failed for\n\'foo2\'@\'test\'\n \nCREATE USER IF NOT EXISTS foo2@test IDENTIFIED BY\n\'password\';\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+----------------------------------------------------+\n| Level | Code | Message |\n+-------+------+----------------------------------------------------+\n| Note | 1973 | Can\'t create user \'foo2\'@\'test\';\n it already exists |\n+-------+------+----------------------------------------------------+\n1 row in set (0.00 sec\n \nAuthentication Options\n \nIDENTIFIED BY \'password\'\n \nThe optional IDENTIFIED BY clause can be used to provide an\naccount with a password. The password should be specified in\nplain text. It will be hashed by the PASSWORD function prior\nto being stored to the mysql.user table.\n \nFor example, if our password is mariadb, then we can create\nthe user with:\n \nCREATE USER foo2@test IDENTIFIED BY \'mariadb\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED BY PASSWORD \'password_hash\'\n \nThe optional IDENTIFIED BY PASSWORD clause can be used to\nprovide an account with a password that has already been\nhashed. The password should be specified as a hash that was\nprovided by the PASSWORD function. It will be stored to the\nmysql.user table as-is.\n \nFor example, if our password is mariadb, then we can find\nthe hash with:\n \nSELECT PASSWORD(\'mariadb\');\n+-------------------------------------------+\n| PASSWORD(\'mariadb\') |\n+-------------------------------------------+\n| *54958E764CE10E50764C2EECBB71D01F08549980 |\n+-------------------------------------------+\n1 row in set (0.00 sec)\n \nAnd then we can create a user with the hash:\n \nCREATE USER foo2@test IDENTIFIED BY PASSWORD\n\'*54958E764CE10E50764C2EECBB71D01F08549980\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED {VIA|WITH} authentication_plugin\n \nThe optional IDENTIFIED VIA authentication_plugin allows you\nto specify that the account should be authenticated by a\nspecific authentication plugin. The plugin name must be an\nactive authentication plugin as per SHOW PLUGINS. If it\ndoesn\'t show up in that output, then you will need to\ninstall it with INSTALL PLUGIN or INSTALL SONAME.\n \nFor example, this could be used with the PAM authentication\nplugin:\n \nCREATE USER foo2@test IDENTIFIED VIA pam;\n \nSome authentication plugins allow additional arguments to be\nspecified after a USING or AS keyword. For example, the PAM\nauthentication plugin accepts a service name:\n \nCREATE USER foo2@test IDENTIFIED VIA pam USING \'mariadb\';\n \nThe exact meaning of the additional argument would depend on\nthe specific authentication plugin.\n \nThe USING or AS keyword can also be used to provide a\nplain-text password to a plugin if it\'s provided as an\nargument to the PASSWORD() function. This is only valid for\nauthentication plugins that have implemented a hook for the\nPASSWORD() function. For example, the ed25519 authentication\nplugin supports this:\n \nCREATE USER safe@\'%\' IDENTIFIED VIA ed25519 USING\nPASSWORD(\'secret\');\n \nOne can specify many authentication plugins, they all works\nas alternatives ways of authenticating a user:\n \nCREATE USER safe@\'%\' IDENTIFIED VIA ed25519 USING\nPASSWORD(\'secret\') OR unix_socket;\n \nTLS Options\n \nBy default, MariaDB transmits data between the server and\nclients without encrypting it. This is generally acceptable\nwhen the server and client run on the same host or in\nnetworks where security is guaranteed through other means.\nHowever, in cases where the server and client exist on\nseparate networks or they are in a high-risk network, the\nlack of encryption does introduce security concerns as a\nmalicious actor could potentially eavesdrop on the traffic\nas it is sent over the network between them.\n \nTo mitigate this concern, MariaDB allows you to encrypt data\nin transit between the server and clients using the\nTransport Layer Security (TLS) protocol. TLS was formerly\nknown as Secure Socket Layer (SSL), but strictly speaking\nthe SSL protocol is a predecessor to TLS and, that version\nof the protocol is now considered insecure. The\ndocumentation still uses the term SSL often and for\ncompatibility reasons TLS-related server system and status\nvariables still use the prefix ssl_, but internally, MariaDB\nonly supports its secure successors.\n \nSee Secure Connections Overview for more information about\nhow to determine whether your MariaDB server has TLS\nsupport.\n \nYou can set certain TLS-related restrictions for specific\nuser accounts. For instance, you might use this with user\naccounts that require access to sensitive data while sending\nit across networks that you do not control. These\nrestrictions can be enabled for a user account with the\nCREATE USER, ALTER USER, or GRANT statements. The following\noptions are available:\n \nOption | Description | \n \nREQUIRE NONE | TLS is not required for this account, but can\nstill be used. | \n \nREQUIRE SSL | The account must use TLS, but no valid X509\ncertificate is required. This option cannot be combined with\nother TLS options. | \n \nREQUIRE X509 | The account must use TLS and must have a\nvalid X509 certificate. This option implies REQUIRE SSL.\nThis option cannot be combined with other TLS options. | \n \nREQUIRE ISSUER \'issuer\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the Certificate\nAuthority must be the one specified via the string issuer.\nThis option implies REQUIRE X509. This option can be\ncombined with the SUBJECT, and CIPHER options in any order.\n| \n \nREQUIRE SUBJECT \'subject\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the certificate\'s\nSubject must be the one specified via the string subject.\nThis option implies REQUIRE X509. This option can be\ncombined with the ISSUER, and CIPHER options in any order. |\n\n \nREQUIRE CIPHER \'cipher\' | The account must use TLS, but no\nvalid X509 certificate is required. Also, the encryption\nused for the connection must use one of the methods\nspecified in the string cipher. This option implies REQUIRE\nSSL. This option can be combined with the ISSUER, and\nSUBJECT options in any order. | \n \nThe REQUIRE keyword must be used only once for all specified\noptions, and the AND keyword can be used to separate\nindividual options, but it is not required.\n \nFor example, you can create a user account that requires\nthese TLS options with the following:\n \nCREATE USER \'alice\'@\'%\'\n REQUIRE SUBJECT \'/CN=alice/O=My Dom,\nInc./C=US/ST=Oregon/L=Portland\'\n AND ISSUER \'/C=FI/ST=Somewhere/L=City/ O=Some\nCompany/CN=Peter Parker/emailAddress=p.parker@marvel.com\'\n AND CIPHER \'TLSv1.2\';\n \nIf any of these options are set for a specific user account,\nthen any client who tries to connect with that user account\nwill have to be configured to connect with TLS.\n \nSee Securing Connections for Client and Server for\ninformation on how to enable TLS on the client and server.\n \nResource Limit Options\n \nMariaDB 10.2.0 introduced a number of resource limit\noptions.\n \nIt is possible to set per-account limits for certain server\nresources. The following table shows the values that can be\nset per account:\n \nLimit Type | Decription | \n \nMAX_QUERIES_PER_HOUR | Number of statements that the account\ncan issue per hour (including updates) | \n \nMAX_UPDATES_PER_HOUR | Number of updates (not queries) that\nthe account can issue per hour | \n \nMAX_CONNECTIONS_PER_HOUR | Number of connections that the\naccount can start per hour | \n \nMAX_USER_CONNECTIONS | Number of simultaneous connections\nthat can be accepted from the same account; if it is 0,\nmax_connections will be used instead; if max_connections is\n0, there is no limit for this account\'s simultaneous\nconnections. | \n \nMAX_STATEMENT_TIME | Timeout, in seconds, for statements\nexecuted by the user. See also Aborting Statements that\nExceed a Certain Time to Execute. | \n \nIf any of these limits are set to 0, then there is no limit\nfor that resource for that user.\n \nHere is an example showing how to create a user with\nresource limits:\n \nCREATE USER \'someone\'@\'localhost\' WITH\n MAX_USER_CONNECTIONS 10\n MAX_QUERIES_PER_HOUR 200;\n \nThe resources are tracked per account, which means\n\'user\'@\'server\'; not per user name or per connection.\n \nThe count can be reset for all users using FLUSH\nUSER_RESOURCES, FLUSH PRIVILEGES or mysqladmin reload.\n \nPer account resource limits are stored in the user table, in\nthe mysql database. Columns used for resources limits are\nnamed max_questions, max_updates, max_connections (for\nMAX_CONNECTIONS_PER_HOUR), and max_user_connections (for\nMAX_USER_CONNECTIONS).\n \nAccount Names\n \nAccount names have both a user name component and a host\nname component, and are specified as\n\'user_name\'@\'host_name\'.\n \nThe user name and host name may be unquoted, quoted as\nstrings using double quotes (\") or\nsingle quotes (\'), or quoted as identifiers using backticks\n(`). You must use quotes\nwhen using special characters (such as a hyphen) or wildcard\ncharacters. If you quote, you \nmust quote the user name and host name separately (for\nexample \'user_name\'@\'host_name\').\n \nHost Name Component\n \nIf the host name is not provided, it is assumed to be \'%\'.\n \nHost names may contain the wildcard characters % and _. They\nare matched as if by\nthe LIKE clause. If you need to use a wildcard character\nliterally (for example, to\nmatch a domain name with an underscore), prefix the\ncharacter with a backslash. See LIKE\nfor more information on escaping wildcard characters.\n \nHost name matches are case-insensitive. Host names can match\neither domain names or IP\naddresses. Use \'localhost\' as the host name to allow only\nlocal client connections.\n \nYou can use a netmask to match a range of IP addresses using\n\'base_ip/netmask\' as the\nhost name. A user with an IP address ip_addr will be allowed\nto connect if the following\ncondition is true:\n \nip_addr & netmask = base_ip\n \nYou can only use netmasks that specify a multiple of 8 bits\nof the address to match. That is,\nonly the following netmasks are allowed:\n \n255.0.0.0\n255.255.0.0\n255.255.255.0\n255.255.255.255\n \nUsing 255.255.255.255 is equivalent to not using a netmask\nat all.\n \nUser Name Component\n \nUser names must match exactly, including case. A user name\nthat is empty is known as an anonymous account and is\nallowed to match a login attempt with any user name\ncomponent. These are described more in the next section.\n \nFor valid identifiers to use as user names, see Identifier\nNames.\n \nIt is possible for more than one account to match when a\nuser connects. MariaDB selects\nthe first matching account after sorting according to the\nfollowing criteria:\nAccounts with an exact host name are sorted before accounts\nusing a wildcard in the\nhost name. Host names using a netmask are considered to be\nexact for sorting.\nAccounts with a wildcard in the host name are sorted\naccording to the position of\nthe first wildcard character. Those with a wildcard\ncharacter later in the host name\nsort before those with a wildcard character earlier in the\nhost name.\nAccounts with a non-empty user name sort before accounts\nwith an empty user name.\nAccounts with an empty user name are sorted last. As\nmentioned previously, these are known as anonymous accounts.\nThese are described more in the next section.\n \nThe following table shows a list of example account as\nsorted by these criteria:\n \n+---------+-------------+\n| User | Host |\n+---------+-------------+\n| joffrey | 192.168.0.3 |\n| | 192.168.0.% |\n| joffrey | 192.168.% |\n| | 192.168.% |\n+---------+-------------+\n \nOnce connected, you only have the privileges granted to the\naccount that matched,\nnot all accounts that could have matched. For example,\nconsider the following\ncommands:\n \nCREATE USER \'joffrey\'@\'192.168.0.3\';\n \nCREATE USER \'joffrey\'@\'%\';\n \nGRANT SELECT ON test.t1 to \'joffrey\'@\'192.168.0.3\';\n \nGRANT SELECT ON test.t2 to \'joffrey\'@\'%\';\n \nIf you connect as joffrey from 192.168.0.3, you will have\nthe SELECT\nprivilege on the table test.t1, but not on the table\ntest.t2. If you connect as joffrey from any other IP\naddress, you will have the SELECT privilege on the table\ntest.t2, but not\non the table test.t1.\n \nBeginning with MariaDB 5.5.31, usernames can be up to 80\ncharacters long. From MariaDB 10.0 the system tables are all\nby default this length. However, in order to enable this\nfeature in MariaDB 5.5, the following schema changes must be\nmade:\n \nALTER TABLE mysql.user MODIFY User CHAR(80) BINARY NOT NULL\nDEFAULT \'\';\n \nALTER TABLE mysql.db MODIFY User CHAR(80) BINARY NOT NULL\nDEFAULT \'\';\n \nALTER TABLE mysql.tables_priv MODIFY User CHAR(80) BINARY\nNOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.columns_priv MODIFY User CHAR(80) BINARY\nNOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.procs_priv MODIFY User CHAR(80) BINARY NOT\nNULL DEFAULT \'\';\n \nALTER TABLE mysql.proc MODIFY definer CHAR(141) COLLATE\nutf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.event MODIFY definer CHAR(141) COLLATE\nutf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.proxies_priv MODIFY User CHAR(80) COLLATE\nutf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.proxies_priv MODIFY Proxied_user CHAR(80)\nCOLLATE utf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.proxies_priv MODIFY Grantor CHAR(141)\nCOLLATE utf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.servers MODIFY Username CHAR(80) NOT NULL\nDEFAULT \'\';\n \nALTER TABLE mysql.procs_priv MODIFY Grantor CHAR(141)\nCOLLATE utf8_bin NOT NULL DEFAULT \'\';\n \nALTER TABLE mysql.tables_priv MODIFY Grantor CHAR(141)\nCOLLATE utf8_bin NOT NULL DEFAULT \'\';\n \nFLUSH PRIVILEGES;\n \nAnonymous Accounts\n \nAnonymous accounts are accounts where the user name portion\nof the account name is empty. These accounts act as special\ncatch-all accounts. If a user attempts to log into the\nsystem from a host, and an anonymous account exists with a\nhost name portion that matches the user\'s host, then the\nuser will log in as the anonymous account if there is no\nmore specific account match for the user name that the user\nentered.\n \nFor example, here are some anonymous accounts:\n \nCREATE USER \'\'@\'localhost\';\n \nCREATE USER \'\'@\'192.168.0.3\';\n \nFixing a Legacy Default Anonymous Account\n \nOn some systems, the mysql.db table has some entries for the\n\'\'@\'%\' anonymous account by default. Unfortunately,\nthere is no matching entry in the mysql.user table, which\nmeans that this anonymous account doesn\'t exactly exist,\nbut it does have privileges--usually on the default test\ndatabase created by mysql_install_db. These account-less\nprivileges are a legacy that is leftover from a time when\nMySQL\'s privilege system was less advanced.\n \nThis situation means that you will run into errors if you\ntry to create a \'\'@\'%\' account. For example:\n \nCREATE USER \'\'@\'%\';\n \nERROR 1396 (HY000): Operation CREATE USER failed for\n\'\'@\'%\'\n \nThe fix is to DELETE the row in the mysql.db table and then\nexecute FLUSH PRIVILEGES:\n \nDELETE FROM mysql.db WHERE User=\'\' AND Host=\'%\';\n \nFLUSH PRIVILEGES;\n \nAnd then the account can be created:\n \nCREATE USER \'\'@\'%\';\n \nQuery OK, 0 rows affected (0.01 sec)\n \nSee MDEV-13486 for more information.\n \nPassword Expiry\n \nBesides automatic password expiry, as determined by\ndefault_password_lifetime, password expiry times can be set\non an individual user basis, overriding the global setting,\nfor example:\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nSee User Password Expiry for more details.\n \nAccount Locking\n \nAccount locking permits privileged administrators to\nlock/unlock user accounts. No new client connections will be\npermitted if an account is locked (existing connections are\nnot affected). For example:\n \nCREATE USER \'marijn\'@\'localhost\' ACCOUNT LOCK;\n \nSee Account Locking for more details.\n \n\n\nURL: https://mariadb.com/kb/en/create-user/','','https://mariadb.com/kb/en/create-user/'),(119,'ALTER USER',10,'The ALTER USER statement was introduced in MariaDB 10.2.0.\n \nSyntax\n------ \nALTER USER [IF EXISTS] \n user_specification [,user_specification] ...\n [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]\n [WITH resource_option [resource_option] ...]\n [password_option | lock_option] \n \nuser_specification:\n username [authentication_option]\n \nauthentication_option:\n IDENTIFIED BY \'password\' \n | IDENTIFIED BY PASSWORD \'password_hash\'\n | IDENTIFIED {VIA|WITH} authentication_plugin\n | IDENTIFIED {VIA|WITH} authentication_plugin {USING|AS}\n\'authentication_string\'\n | IDENTIFIED {VIA|WITH} authentication_plugin {USING|AS}\nPASSWORD(\'password\')\n \ntls_option\n SSL \n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n \nresource_option\n MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n | MAX_STATEMENT_TIME time\n \npassword_option:\n PASSWORD EXPIRE\n | PASSWORD EXPIRE DEFAULT\n | PASSWORD EXPIRE NEVER\n | PASSWORD EXPIRE INTERVAL N DAY\n \nlock_option:\n ACCOUNT LOCK\n | ACCOUNT UNLOCK\n}\n \nDescription\n----------- \nThe ALTER USER statement modifies existing MariaDB accounts.\nTo use it, you must have the global CREATE USER privilege or\nthe UPDATE privilege for the mysql database. The global\nSUPER privilege is also required if the read_only system\nvariable is enabled.\n \nIf any of the specified user accounts do not yet exist, an\nerror results. If an error occurs, ALTER USER will still\nmodify the accounts that do not result in an error. Only one\nerror is produced for all users which have not been\nmodified.\n \nIF EXISTS\n \nWhen the IF EXISTS clause is used, MariaDB will return a\nwarning instead of an error for each specified user that\ndoes not exist.\n \nAccount Names\n \nFor ALTER USER statements, account names are specified as\nthe username argument in the same way as they are for CREATE\nUSER statements. See account names from the CREATE USER page\nfor details on how account names are specified.\n \nCURRENT_USER or CURRENT_USER() can also be used to alter the\naccount logged into the current session. For example, to\nchange the current user\'s password to mariadb:\n \nALTER USER CURRENT_USER() IDENTIFIED BY \'mariadb\';\n \nAuthentication Options\n \nIDENTIFIED BY \'password\'\n \nThe optional IDENTIFIED BY clause can be used to provide an\naccount with a password. The password should be specified in\nplain text. It will be hashed by the PASSWORD function prior\nto being stored to the mysql.user table.\n \nFor example, if our password is mariadb, then we can set the\naccount\'s password with:\n \nALTER USER foo2@test IDENTIFIED BY \'mariadb\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED BY PASSWORD \'password_hash\'\n \nThe optional IDENTIFIED BY PASSWORD clause can be used to\nprovide an account with a password that has already been\nhashed. The password should be specified as a hash that was\nprovided by the PASSWORD function. It will be stored to the\nmysql.user table as-is.\n \nFor example, if our password is mariadb, then we can find\nthe hash with:\n \nSELECT PASSWORD(\'mariadb\');\n+-------------------------------------------+\n| PASSWORD(\'mariadb\') |\n+-------------------------------------------+\n| *54958E764CE10E50764C2EECBB71D01F08549980 |\n+-------------------------------------------+\n1 row in set (0.00 sec)\n \nAnd then we can set an account\'s password with the hash:\n \nALTER USER foo2@test IDENTIFIED BY PASSWORD\n\'*54958E764CE10E50764C2EECBB71D01F08549980\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED {VIA|WITH} authentication_plugin\n \nThe optional IDENTIFIED VIA authentication_plugin allows you\nto specify that the account should be authenticated by a\nspecific authentication plugin. The plugin name must be an\nactive authentication plugin as per SHOW PLUGINS. If it\ndoesn\'t show up in that output, then you will need to\ninstall it with INSTALL PLUGIN or INSTALL SONAME.\n \nFor example, this could be used with the PAM authentication\nplugin:\n \nALTER USER foo2@test IDENTIFIED VIA pam;\n \nSome authentication plugins allow additional arguments to be\nspecified after a USING or AS keyword. For example, the PAM\nauthentication plugin accepts a service name:\n \nALTER USER foo2@test IDENTIFIED VIA pam USING \'mariadb\';\n \nThe exact meaning of the additional argument would depend on\nthe specific authentication plugin.\n \nIn MariaDB 10.4 and later, the USING or AS keyword can also\nbe used to provide a plain-text password to a plugin if\nit\'s provided as an argument to the PASSWORD() function.\nThis is only valid for authentication plugins that have\nimplemented a hook for the PASSWORD() function. For example,\nthe ed25519 authentication plugin supports this:\n \nALTER USER safe@\'%\' IDENTIFIED VIA ed25519 USING\nPASSWORD(\'secret\');\n \nTLS Options\n \nBy default, MariaDB transmits data between the server and\nclients without encrypting it. This is generally acceptable\nwhen the server and client run on the same host or in\nnetworks where security is guaranteed through other means.\nHowever, in cases where the server and client exist on\nseparate networks or they are in a high-risk network, the\nlack of encryption does introduce security concerns as a\nmalicious actor could potentially eavesdrop on the traffic\nas it is sent over the network between them.\n \nTo mitigate this concern, MariaDB allows you to encrypt data\nin transit between the server and clients using the\nTransport Layer Security (TLS) protocol. TLS was formerly\nknown as Secure Socket Layer (SSL), but strictly speaking\nthe SSL protocol is a predecessor to TLS and, that version\nof the protocol is now considered insecure. The\ndocumentation still uses the term SSL often and for\ncompatibility reasons TLS-related server system and status\nvariables still use the prefix ssl_, but internally, MariaDB\nonly supports its secure successors.\n \nSee Secure Connections Overview for more information about\nhow to determine whether your MariaDB server has TLS\nsupport.\n \nYou can set certain TLS-related restrictions for specific\nuser accounts. For instance, you might use this with user\naccounts that require access to sensitive data while sending\nit across networks that you do not control. These\nrestrictions can be enabled for a user account with the\nCREATE USER, ALTER USER, or GRANT statements. The following\noptions are available:\n \nOption | Description | \n \nREQUIRE NONE | TLS is not required for this account, but can\nstill be used. | \n \nREQUIRE SSL | The account must use TLS, but no valid X509\ncertificate is required. This option cannot be combined with\nother TLS options. | \n \nREQUIRE X509 | The account must use TLS and must have a\nvalid X509 certificate. This option implies REQUIRE SSL.\nThis option cannot be combined with other TLS options. | \n \nREQUIRE ISSUER \'issuer\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the Certificate\nAuthority must be the one specified via the string issuer.\nThis option implies REQUIRE X509. This option can be\ncombined with the SUBJECT, and CIPHER options in any order.\n| \n \nREQUIRE SUBJECT \'subject\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the certificate\'s\nSubject must be the one specified via the string subject.\nThis option implies REQUIRE X509. This option can be\ncombined with the ISSUER, and CIPHER options in any order. |\n\n \nREQUIRE CIPHER \'cipher\' | The account must use TLS, but no\nvalid X509 certificate is required. Also, the encryption\nused for the connection must use one of the methods\nspecified in the string cipher. This option implies REQUIRE\nSSL. This option can be combined with the ISSUER, and\nSUBJECT options in any order. | \n \nThe REQUIRE keyword must be used only once for all specified\noptions, and the AND keyword can be used to separate\nindividual options, but it is not required.\n \nFor example, you can alter a user account to require these\nTLS options with the following:\n \nALTER USER \'alice\'@\'%\'\n REQUIRE SUBJECT \'/CN=alice/O=My Dom,\nInc./C=US/ST=Oregon/L=Portland\'\n AND ISSUER \'/C=FI/ST=Somewhere/L=City/ O=Some\nCompany/CN=Peter Parker/emailAddress=p.parker@marvel.com\'\n AND CIPHER \'TLSv1.2\';\n \nIf any of these options are set for a specific user account,\nthen any client who tries to connect with that user account\nwill have to be configured to connect with TLS.\n \nSee Securing Connections for Client and Server for\ninformation on how to enable TLS on the client and server.\n \nResource Limit Options\n \nMariaDB 10.2.0 introduced a number of resource limit\noptions.\n \nIt is possible to set per-account limits for certain server\nresources. The following table shows the values that can be\nset per account:\n \nLimit Type | Decription | \n \nMAX_QUERIES_PER_HOUR | Number of statements that the account\ncan issue per hour (including updates) | \n \nMAX_UPDATES_PER_HOUR | Number of updates (not queries) that\nthe account can issue per hour | \n \nMAX_CONNECTIONS_PER_HOUR | Number of connections that the\naccount can start per hour | \n \nMAX_USER_CONNECTIONS | Number of simultaneous connections\nthat can be accepted from the same account; if it is 0,\nmax_connections will be used instead; if max_connections is\n0, there is no limit for this account\'s simultaneous\nconnections. | \n \nMAX_STATEMENT_TIME | Timeout, in seconds, for statements\nexecuted by the user. See also Aborting Statements that\nExceed a Certain Time to Execute. | \n \nIf any of these limits are set to 0, then there is no limit\nfor that resource for that user.\n \nHere is an example showing how to set an account\'s resource\nlimits:\n \nALTER USER \'someone\'@\'localhost\' WITH\n MAX_USER_CONNECTIONS 10\n MAX_QUERIES_PER_HOUR 200;\n \nThe resources are tracked per account, which means\n\'user\'@\'server\'; not per user name or per connection.\n \nThe count can be reset for all users using FLUSH\nUSER_RESOURCES, FLUSH PRIVILEGES or mysqladmin reload.\n \nPer account resource limits are stored in the user table, in\nthe mysql database. Columns used for resources limits are\nnamed max_questions, max_updates, max_connections (for\nMAX_CONNECTIONS_PER_HOUR), and max_user_connections (for\nMAX_USER_CONNECTIONS).\n \nPassword Expiry\n \nBesides automatic password expiry, as determined by\ndefault_password_lifetime, password expiry times can be set\non an individual user basis, overriding the global setting,\nfor example:\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE NEVER;\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE DEFAULT;\n \nSee User Password Expiry for more details.\n \nAccount Locking\n \nAccount locking permits privileged administrators to\nlock/unlock user accounts. No new client connections will be\npermitted if an account is locked (existing connections are\nnot affected). For example:\n \nALTER USER \'marijn\'@\'localhost\' ACCOUNT LOCK;\n \nSee Account Locking for more details.\n \n\n\nURL: https://mariadb.com/kb/en/alter-user/','','https://mariadb.com/kb/en/alter-user/'),(96,'COMMIT',8,'The COMMIT statement ends a transaction, saving any changes\nto the data so that they become visible to subsequent\ntransactions. Also, unlocks metadata changed by current\ntransaction. If autocommit is set to 1, an implicit commit\nis performed after each statement. Otherwise, all\ntransactions which don\'t end with an explicit COMMIT are\nimplicitly rollbacked and the changes are lost. The ROLLBACK\nstatement can be used to do this explicitly.\n \nThe required syntax for the COMMIT statement is as follows:\n \nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\n \nCOMMIT is the more important transaction terminator, as well\nas the more interesting one. The basic form of the COMMIT\nstatement is simply the keyword COMMIT (the keyword WORK is\nsimply noise and can be omitted without changing the\neffect).\n \nThe optional AND CHAIN clause is a convenience for\ninitiating a new transaction as soon as the old transaction\nterminates. If AND CHAIN is specified, then there is\neffectively nothing between the old and new transactions,\nalthough they remain separate. The characteristics of the\nnew transaction will be the same as the characteristics of\nthe old one — that is, the new transaction will have the\nsame access mode, isolation level and diagnostics area size\n(we\'ll discuss all of these shortly) as the transaction\njust terminated. \n \nRELEASE tells the server to disconnect the client\nimmediately after the current transaction.\n \nThere are NO RELEASE and AND NO CHAIN options. By default,\ncommits do not RELEASE or CHAIN, but it\'s possible to\nchange this default behavior with the completion_type server\nsystem variable. In this case, the AND NO CHAIN and NO\nRELEASE options override the server default.\n \n\n\nURL: https://mariadb.com/kb/en/commit/','','https://mariadb.com/kb/en/commit/'),(97,'DEALLOCATE / DROP PREPARE',8,'Syntax\n------ \n{DEALLOCATE | DROP} PREPARE stmt_name\n \nDescription\n----------- \nTo deallocate a prepared statement produced with PREPARE,\nuse a\nDEALLOCATE PREPARE statement that refers to the prepared\nstatement\nname.\n \nA prepared statement is implicitly deallocated when a new\nPREPARE command is issued. In that case, there is no need to\nuse DEALLOCATE.\n \nAttempting to execute a prepared statement after\ndeallocating it\nresults in an error, as if it was not prepared at all:\n \nERROR 1243 (HY000): Unknown prepared statement handler\n(stmt_name) given to EXECUTE\n \nIf the specified statement has not been PREPAREd, an error\nsimilar to the following will be produced:\n \nERROR 1243 (HY000): Unknown prepared statement handler\n(stmt_name) given to DEALLOCATE PREPARE\n \nExample\n \nSee example in PREPARE.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/deallocate-drop-prepared-statement/','','https://mariadb.com/kb/en/deallocate-drop-prepared-statement/'),(98,'EXECUTE Statement',8,'Syntax\n------ \nEXECUTE stmt_name\n [USING expression[, expression] ...]\n \nEXECUTE with expression as parameters was introduced in\nMariaDB 10.2.3. Before that one could only use variables\n(@var_name) as parameters.\n \nDescription\n----------- \nAfter preparing a statement with PREPARE, you execute it\nwith an\nEXECUTE statement that refers to the prepared statement\nname. If the\nprepared statement contains any parameter markers, you must\nsupply a\nUSING clause that lists user variables containing the values\nto be\nbound to the parameters. Parameter values can be supplied\nonly by user\nvariables, and the USING clause must name exactly as many\nvariables as\nthe number of parameter markers in the statement.\n \nYou can execute a given prepared statement multiple times,\npassing\ndifferent variables to it or setting the variables to\ndifferent values\nbefore each execution.\n \nIf the specified statement has not been PREPAREd, an error\nsimilar to the following is produced:\n \nERROR 1243 (HY000): Unknown prepared statement handler\n(stmt_name) given to EXECUTE\n \nExample\n \nSee example in PREPARE.\n \n\n\nURL: https://mariadb.com/kb/en/execute-statement/','','https://mariadb.com/kb/en/execute-statement/'),(102,'SAVEPOINT',8,'Syntax\n------ \nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n \nDescription\n----------- \nInnoDB supports the SQL statements SAVEPOINT,\nROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT\nand the optional WORK keyword for\nROLLBACK.\n \nEach savepoint must have a legal MariaDB identifier. A\nsavepoint is a named sub-transaction.\n \nNormally ROLLBACK undoes the changes performed by the whole\ntransaction. When used with the TO clause, it undoes the\nchanges performed after the specified savepoint, and erases\nall subsequent savepoints. However, all locks that have been\nacquired after the save point will survive. RELEASE\nSAVEPOINT does not rollback or commit any changes, but\nremoves the specified savepoint.\n \nWhen the execution of a trigger or a stored function begins,\nit is not possible to use statements which reference a\nsavepoint which was defined from out of that stored program.\n \nWhen a COMMIT (including implicit commits) or a ROLLBACK\nstatement (with no TO clause) is performed, they act on the\nwhole transaction, and all savepoints are removed.\n \nErrors\n \nIf COMMIT or ROLLBACK is issued and no transaction was\nstarted, no error is reported.\n \nIf SAVEPOINT is issued and no transaction was started, no\nerror is reported but no savepoint is created. When ROLLBACK\nTO SAVEPOINT or RELEASE SAVEPOINT is called for a savepoint\nthat does not exist, an error like this is issued:\n \nERROR 1305 (42000): SAVEPOINT svp_name does not exist\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/savepoint/','','https://mariadb.com/kb/en/savepoint/'),(121,'GRANT',10,'Syntax\n------ \nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [ user_options ...]\n \nuser_specification:\n username [authentication_option]\n \nauthentication_option:\n IDENTIFIED BY \'password\' \n | IDENTIFIED BY PASSWORD \'password_hash\'\n | IDENTIFIED {VIA|WITH} authentication_rule [OR\nauthentication_rule ...]\n \nauthentication_rule:\n authentication_plugin\n | authentication_plugin {USING|AS}\n\'authentication_string\'\n | authentication_plugin {USING|AS} PASSWORD(\'password\')\n \nGRANT PROXY ON username\n TO username [, username] ...\n [WITH GRANT OPTION]\n \nuser_options:\n [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]\n [WITH with_option [with_option] ...]\n \nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n \npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n \nwith_option:\n GRANT OPTION\n | resource_option\n \nresource_option:\n MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n | MAX_STATEMENT_TIME time\n \ntls_option:\n SSL \n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n \nDescription\n----------- \nThe GRANT statement allows you to grant privileges or roles\nto accounts. To use GRANT, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are\ngranting.\n \nUse the REVOKE statement to revoke privileges granted with\nthe GRANT statement.\n \nUse the SHOW GRANTS statement to determine what privileges\nan account has.\n \nAccount Names\n \nFor GRANT statements, account names are specified as the\nusername argument in the same way as they are for CREATE\nUSER statements. See account names from the CREATE USER page\nfor details on how account names are specified.\n \nImplicit Account Creation\n \nThe GRANT statement also allows you to implicitly create\naccounts in some cases.\n \nIf the account does not yet exist, then GRANT can implicitly\ncreate it. To implicitly create an account with GRANT, a\nuser is required to have the same privileges that would be\nrequired to explicitly create the account with the CREATE\nUSER statement.\n \nIf the NO_AUTO_CREATE_USER SQL_MODE is set, then accounts\ncan only be created if authentication information is\nspecified, or with a CREATE USER statement. If no\nauthentication information is provided, GRANT will produce\nan error when the specified account does not exist, for\nexample:\n \nshow variables like \'%sql_mode%\' ;\n+---------------+--------------------------------------------+\n| Variable_name | Value |\n+---------------+--------------------------------------------+\n| sql_mode | NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |\n+---------------+--------------------------------------------+\n \nGRANT USAGE ON *.* TO \'user123\'@\'%\' IDENTIFIED BY \'\';\nERROR 1133 (28000): Can\'t find any matching row in the user\ntable\n \nGRANT USAGE ON *.* TO \'user123\'@\'%\' IDENTIFIED VIA PAM\nusing \'mariadb\' require ssl ;\nQuery OK, 0 rows affected (0.00 sec)\n \nselect host, user from mysql.user where user=\'user123\' ;\n \n+------+----------+\n| host | user |\n+------+----------+\n| % | user123 |\n+------+----------+\n \nPrivilege Levels\n \nPrivileges can be set globally, for an entire database, for\na table or routine,\nor for individual columns in a table. Certain privileges can\nonly be set at\ncertain levels.\nGlobal privileges are granted using *.* for\npriv_level. Global privileges include privileges to\nadminister the database\nand manage user accounts, as well as privileges for all\ntables, functions, and\nprocedures. Global privileges are stored in the mysql.user\ntable.\nDatabase privileges are granted using db_name.*\nfor priv_level, or using just * to use default database.\nDatabase\nprivileges include privileges to create tables and\nfunctions, as well as\nprivileges for all tables, functions, and procedures in the\ndatabase. Database privileges are stored in the mysql.db\ntable.\nTable privileges are granted using db_name.tbl_name\nfor priv_level, or using just tbl_name to specify a table in\nthe default\ndatabase. The TABLE keyword is optional. Table privileges\ninclude the\nability to select and change data in the table. Certain\ntable privileges can\nbe granted for individual columns.\nColumn privileges are granted by specifying a table for\npriv_level and providing a column list after the privilege\ntype. They allow\nyou to control exactly which columns in a table users can\nselect and change.\nFunction privileges are granted using FUNCTION\ndb_name.routine_name\nfor priv_level, or using just FUNCTION routine_name to\nspecify a function\nin the default database.\nProcedure privileges are granted using PROCEDURE\ndb_name.routine_name\nfor priv_level, or using just PROCEDURE routine_name to\nspecify a procedure\nin the default database.\n \nThe USAGE Privilege\n \nThe USAGE privilege grants no real privileges. The SHOW\nGRANTS\nstatement will show a global USAGE privilege for a\nnewly-created user. You\ncan use USAGE with the GRANT statement to change options\nlike GRANT OPTION\nand MAX_USER_CONNECTIONS without changing any account\nprivileges.\n \nThe ALL PRIVILEGES Privilege\n \nThe ALL PRIVILEGES privilege grants all available\nprivileges. Granting all\nprivileges only affects the given privilege level. For\nexample, granting all\nprivileges on a table does not grant any privileges on the\ndatabase or globally.\n \nUsing ALL PRIVILEGES does not grant the special GRANT OPTION\nprivilege.\n \nYou can use ALL instead of ALL PRIVILEGES.\n \nThe GRANT OPTION Privilege\n \nUse the WITH GRANT OPTION clause to give users the ability\nto grant privileges\nto other users at the given privilege level. Users with the\nGRANT OPTION privilege can\nonly grant privileges they have. They cannot grant\nprivileges at a higher privilege level than\nthey have the GRANT OPTION privilege.\n \nThe GRANT OPTION privilege cannot be set for individual\ncolumns.\nIf you use WITH GRANT OPTION when specifying column\nprivileges,\nthe GRANT OPTION privilege will be granted for the entire\ntable.\n \nUsing the WITH GRANT OPTION clause is equivalent to listing\nGRANT OPTION\nas a privilege.\n \nGlobal Privileges\n \nThe following table lists the privileges that can be granted\nglobally. You can\nalso grant all database, table, and function privileges\nglobally. When granted\nglobally, these privileges apply to all databases, tables,\nor functions,\nincluding those created later.\n \nTo set a global privilege, use *.* for priv_level.\n \nPrivilege | Description | \n \nCREATE USER | Create a user using the CREATE USER statement,\nor implicitly create a user with the GRANT statement. | \n \nFILE | Read and write files on the server, using statements\nlike LOAD DATA INFILE or functions like LOAD_FILE(). Also\nneeded to create CONNECT outward tables. MariaDB server must\nhave the permissions to access those files. | \n \nGRANT OPTION | Grant global privileges. You can only grant\nprivileges that you have. | \n \nPROCESS | Show information about the active processes, via\nSHOW PROCESSLIST or mysqladmin processlist. | \n \nRELOAD | Execute FLUSH statements or equivalent mysqladmin\ncommands. | \n \nREPLICATION CLIENT | Execute SHOW MASTER STATUS and SHOW\nSLAVE STATUS informative statements. | \n \nREPLICATION SLAVE | Accounts used by slave servers on the\nmaster need this privilege. This is needed to get the\nupdates made on the master. | \n \nSHOW DATABASES | List all databases using the SHOW DATABASES\nstatement. Without the SHOW DATABASES privilege, you can\nstill issue the SHOW DATABASES statement, but it will only\nlist databases containing tables on which you have\nprivileges. | \n \nSHUTDOWN | Shut down the server using SHUTDOWN or the\nmysqladmin shutdown command. | \n \nSUPER | Execute superuser statements: CHANGE MASTER TO, KILL\n(users who do not have this privilege can only KILL their\nown threads), PURGE LOGS, SET global system variables, or\nthe mysqladmin debug command. Also, this permission allows\nthe user to write data even if the read_only startup option\nis set, enable or disable logging, enable or disable\nreplication on slaves, specify a DEFINER for statements that\nsupport that clause, connect once after reaching the\nMAX_CONNECTIONS. If a statement has been specified for the\ninit-connect mysqld option, that command will not be\nexecuted when a user with SUPER privileges connects to the\nserver. | \n \nDatabase Privileges\n \nThe following table lists the privileges that can be granted\nat the database\nlevel. You can also grant all table and function privileges\nat the database\nlevel. Table and function privileges on a database apply to\nall tables or\nfunctions in that database, including those created later.\n \nTo set a privilege for a database, specify the database\nusing\ndb_name.* for priv_level, or just use *\nto specify the default database.\n \nPrivilege | Description | \n \nCREATE | Create a database using the CREATE DATABASE\nstatement, when the privilege is granted for a database. You\ncan grant the CREATE privilege on databases that do not yet\nexist. This also grants the CREATE privilege on all tables\nin the database. | \n \nCREATE ROUTINE | Create Stored Programs using the CREATE\nPROCEDURE and CREATE FUNCTION statements. | \n \nCREATE TEMPORARY TABLES | Create temporary tables with the\nCREATE TEMPORARY TABLE statement. This privilege enable\nwriting and dropping those temporary tables | \n \nDROP | Drop a database using the DROP DATABASE statement,\nwhen the privilege is granted for a database. This also\ngrants the DROP privilege on all tables in the database. | \n \nEVENT | Create, drop and alter EVENTs. Added in MySQL 5.1.6.\n| \n \nGRANT OPTION | Grant database privileges. You can only grant\nprivileges that you have. | \n \nLOCK TABLES | Acquire explicit locks using the LOCK TABLES\nstatement; you also need to have the SELECT privilege on a\ntable, in order to lock it. | \n \nTable Privileges\n \nPrivilege | Description | \n \nALTER | Change the structure of an existing table using the\nALTER TABLE statement. | \n \nCREATE | Create a table using the CREATE TABLE statement.\nYou can grant the CREATE privilege on tables that do not yet\nexist. | \n \nCREATE VIEW | Create a view using the CREATE_VIEW statement.\n| \n \nDELETE | Remove rows from a table using the DELETE\nstatement. | \n \nDELETE HISTORY | Remove historical rows from a table using\nthe DELETE HISTORY statement. Displays as DELETE VERSIONING\nROWS when running SHOW GRANTS until MariaDB 10.3.15 and\nuntil MariaDB 10.4.5 (MDEV-17655), or when running SHOW\nPRIVILEGES (MDEV-20382). From MariaDB 10.3.4. From MariaDB\n10.3.5, if a user has the SUPER privilege but not this\nprivilege, running mysql_upgrade will grant this privilege\nas well. | \n \nDROP | Drop a table using the DROP TABLE statement or a view\nusing the DROP VIEW statement. Also required to execute the\nTRUNCATE TABLE statement. | \n \nGRANT OPTION | Grant table privileges. You can only grant\nprivileges that you have. | \n \nINDEX | Create an index on a table using the CREATE INDEX\nstatement. Without the INDEX privilege, you can still create\nindexes when creating a table using the CREATE TABLE\nstatement if the you have the CREATE privilege, and you can\ncreate indexes using the ALTER TABLE statement if you have\nthe ALTER privilege. | \n \nINSERT | Add rows to a table using the INSERT statement. The\nINSERT privilege can also be set on individual columns; see\nColumn Privileges below for details. | \n \nREFERENCES | Unused. | \n \nSELECT | Read data from a table using the SELECT statement.\nThe SELECT privilege can also be set on individual columns;\nsee Column Privileges below for details. | \n \nSHOW VIEW | Show the CREATE VIEW statement to create a view\nusing the SHOW CREATE VIEW statement. | \n \nTRIGGER | Execute triggers associated to tables you update,\nexecute the CREATE TRIGGER and DROP TRIGGER statements. You\nwill still be able to see triggers. | \n \nUPDATE | Update existing rows in a table using the UPDATE\nstatement. UPDATE statements usually include a WHERE clause\nto update only certain rows. You must have SELECT privileges\non the table or the appropriate columns for the WHERE\nclause. The UPDATE privilege can also be set on individual\ncolumns; see Column Privileges below for details. | \n \nColumn Privileges\n \nSome table privileges can be set for individual columns of a\ntable. To use\ncolumn privileges, specify the table explicitly and provide\na list of column\nnames after the privilege type. For example, the following\nstatement would allow\nthe user to read the names and positions of employees, but\nnot other information\nfrom the same table, such as salaries.\n \nGRANT SELECT (name, position) on Employee to\n\'jeffrey\'@\'localhost\';\n \nPrivilege | Description | \n \nINSERT (column_list) | Add rows specifying values in columns\nusing the INSERT statement. If you only have column-level\nINSERT privileges, you must specify the columns you are\nsetting in the INSERT statement. All other columns will be\nset to their default values, or NULL. | \n \nREFERENCES (column_list) | Unused. | \n \nSELECT (column_list) | Read values in columns using the\nSELECT statement. You cannot access or query any columns for\nwhich you do not have SELECT privileges, including in WHERE,\nON, GROUP BY, and ORDER BY clauses. | \n \nUPDATE (column_list) | Update values in columns of existing\nrows using the UPDATE statement. UPDATE statements usually\ninclude a WHERE clause to update only certain rows. You must\nhave SELECT privileges on the table or the appropriate\ncolumns for the WHERE clause. | \n \nFunction Privileges\n \nPrivilege | Description | \n \nALTER ROUTINE | Change the characteristics of a stored\nfunction using the ALTER FUNCTION statement. | \n \nEXECUTE | Use a stored function. You need SELECT privileges\nfor any tables or columns accessed by the function. | \n \nGRANT OPTION | Grant function privileges. You can only grant\nprivileges that you have. | \n \nProcedure Privileges\n \nPrivilege | Description | \n \nALTER ROUTINE | Change the characteristics of a stored\nprocedure using the ALTER PROCEDURE statement. | \n \nEXECUTE | Execute a stored procedure using the CALL\nstatement. The privilege to call a procedure may allow you\nto perform actions you wouldn\'t otherwise be able to do,\nsuch as insert rows into a table. | \n \nGRANT OPTION | Grant procedure privileges. You can only\ngrant privileges that you have. | \n \nProxy Privileges\n \nPrivilege | Description | \n \nPROXY | Permits one user to be a proxy for another. | \n \nThe PROXY privilege allows one user to proxy as another\nuser, which means their privileges change to that of the\nproxy user, and the CURRENT_USER() function returns the user\nname of the proxy user.\n \nThe PROXY privilege only works with authentication plugins\nthat support it. The default mysql_native_password\nauthentication plugin does not support proxy users.\n \nThe pam authentication plugin is the only plugin included\nwith MariaDB that currently supports proxy users. The PROXY\nprivilege is commonly used with the pam authentication\nplugin to enable user and group mapping with PAM.\n \nFor example, to grant the PROXY privilege to an anonymous\naccount that authenticates with the pam authentication\nplugin, you could execute the following:\n \nCREATE USER \'dba\'@\'%\' IDENTIFIED BY \'strongpassword\';\n \nGRANT ALL PRIVILEGES ON *.* TO \'dba\'@\'%\' ;\n \nCREATE USER \'\'@\'%\' IDENTIFIED VIA pam USING \'mariadb\';\n \nGRANT PROXY ON \'dba\'@\'%\' TO \'\'@\'%\';\n \nA user account can only grant the PROXY privilege for a\nspecific user account if the granter also has the PROXY\nprivilege for that specific user account, and if that\nprivilege is defined WITH GRANT OPTION. For example, the\nfollowing example fails because the granter does not have\nthe PROXY privilege for that specific user account at all:\n \nSELECT USER(), CURRENT_USER();\n+-----------------+-----------------+\n| USER() | CURRENT_USER() |\n+-----------------+-----------------+\n| alice@localhost | alice@localhost |\n+-----------------+-----------------+\n \nSHOW GRANTS;\n \n+-----------------------------------------------------------------------------------------------------------------------+\n| Grants for alice@localhost |\n+-----------------------------------------------------------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'alice\'@\'localhost\'\nIDENTIFIED BY PASSWORD\n\'*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19\' |\n+-----------------------------------------------------------------------------------------------------------------------+\n \nGRANT PROXY ON \'dba\'@\'localhost\' TO\n\'bob\'@\'localhost\';\n \nERROR 1698 (28000): Access denied for user\n\'alice\'@\'localhost\'\n \nAnd the following example fails because the granter does\nhave the PROXY privilege for that specific user account, but\nit is not defined WITH GRANT OPTION:\n \nSELECT USER(), CURRENT_USER();\n+-----------------+-----------------+\n| USER() | CURRENT_USER() |\n+-----------------+-----------------+\n| alice@localhost | alice@localhost |\n+-----------------+-----------------+\n \nSHOW GRANTS;\n \n+-----------------------------------------------------------------------------------------------------------------------+\n| Grants for alice@localhost |\n+-----------------------------------------------------------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'alice\'@\'localhost\'\nIDENTIFIED BY PASSWORD\n\'*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19\' |\n| GRANT PROXY ON \'dba\'@\'localhost\' TO\n\'alice\'@\'localhost\' |\n+-----------------------------------------------------------------------------------------------------------------------+\n \nMariaDB [(none)]> GRANT PROXY ON \'dba\'@\'localhost\' TO\n\'bob\'@\'localhost\';\n \nERROR 1698 (28000): Access denied for user\n\'alice\'@\'localhost\'\n \nBut the following example succeeds because the granter does\nhave the PROXY privilege for that specific user account, and\nit is defined WITH GRANT OPTION:\n \nSELECT USER(), CURRENT_USER();\n+-----------------+-----------------+\n| USER() | CURRENT_USER() |\n+-----------------+-----------------+\n| alice@localhost | alice@localhost |\n+-----------------+-----------------+\n \nSHOW GRANTS;\n \n+-----------------------------------------------------------------------------------------------------------------------------------------+\n| Grants for alice@localhost |\n+-----------------------------------------------------------------------------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'alice\'@\'localhost\'\nIDENTIFIED BY PASSWORD\n\'*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19\' WITH GRANT\nOPTION |\n| GRANT PROXY ON \'dba\'@\'localhost\' TO\n\'alice\'@\'localhost\' WITH GRANT OPTION |\n+-----------------------------------------------------------------------------------------------------------------------------------------+\n \nGRANT PROXY ON \'dba\'@\'localhost\' TO\n\'bob\'@\'localhost\';\n \nQuery OK, 0 rows affected (0.004 sec)\n \nA user account can grant the PROXY privilege for any other\nuser account if the granter has the PROXY privilege for the\n\'\'@\'%\' anonymous user account, like this:\n \nGRANT PROXY ON \'\'@\'%\' TO \'dba\'@\'localhost\' WITH\nGRANT OPTION;\n \nFor example, the following example succeeds because the user\ncan grant the PROXY privilege for any other user account:\n \nSELECT USER(), CURRENT_USER();\n+-----------------+-----------------+\n| USER() | CURRENT_USER() |\n+-----------------+-----------------+\n| alice@localhost | alice@localhost |\n+-----------------+-----------------+\n \nSHOW GRANTS;\n \n+-----------------------------------------------------------------------------------------------------------------------------------------+\n| Grants for alice@localhost |\n+-----------------------------------------------------------------------------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'alice\'@\'localhost\'\nIDENTIFIED BY PASSWORD\n\'*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19\' WITH GRANT\nOPTION |\n| GRANT PROXY ON \'\'@\'%\' TO \'alice\'@\'localhost\' WITH\nGRANT OPTION |\n+-----------------------------------------------------------------------------------------------------------------------------------------+\n \nGRANT PROXY ON \'app1_dba\'@\'localhost\' TO\n\'bob\'@\'localhost\';\n \nQuery OK, 0 rows affected (0.004 sec)\n \nGRANT PROXY ON \'app2_dba\'@\'localhost\' TO\n\'carol\'@\'localhost\';\n \nQuery OK, 0 rows affected (0.004 sec)\n \nThe default root user accounts created by mysql_install_db\nhave this privilege. For example:\n \nGRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH\nGRANT OPTION;\n \nGRANT PROXY ON \'\'@\'%\' TO \'root\'@\'localhost\' WITH\nGRANT OPTION;\n \nThis allows the default root user accounts to grant the\nPROXY privilege for any other user account, and it also\nallows the default root user accounts to grant others the\nprivilege to do the same.\n \nAuthentication Options\n \nThe authentication options for the GRANT statement are the\nsame as those for the CREATE USER statement.\n \nIDENTIFIED BY \'password\'\n \nThe optional IDENTIFIED BY clause can be used to provide an\naccount with a password. The password should be specified in\nplain text. It will be hashed by the PASSWORD function prior\nto being stored to the mysql.user table.\n \nFor example, if our password is mariadb, then we can create\nthe user with:\n \nGRANT USAGE ON *.* TO foo2@test IDENTIFIED BY \'mariadb\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nIf the user account already exists and if you provide the\nIDENTIFIED BY clause, then the user\'s password will be\nchanged. You must have the privileges needed for the SET\nPASSWORD\nstatement to change a user\'s password with GRANT.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED BY PASSWORD \'password_hash\'\n \nThe optional IDENTIFIED BY PASSWORD clause can be used to\nprovide an account with a password that has already been\nhashed. The password should be specified as a hash that was\nprovided by the PASSWORD function. It will be stored to the\nmysql.user table as-is.\n \nFor example, if our password is mariadb, then we can find\nthe hash with:\n \nSELECT PASSWORD(\'mariadb\');\n+-------------------------------------------+\n| PASSWORD(\'mariadb\') |\n+-------------------------------------------+\n| *54958E764CE10E50764C2EECBB71D01F08549980 |\n+-------------------------------------------+\n1 row in set (0.00 sec)\n \nAnd then we can create a user with the hash:\n \nGRANT USAGE ON *.* TO foo2@test IDENTIFIED BY PASSWORD\n\'*54958E764CE10E50764C2EECBB71D01F08549980\';\n \nIf you do not specify a password with the IDENTIFIED BY\nclause, the user\nwill be able to connect without a password. A blank password\nis not a wildcard\nto match any password. The user must connect without\nproviding a password if no\npassword is set.\n \nIf the user account already exists and if you provide the\nIDENTIFIED BY clause, then the user\'s password will be\nchanged. You must have the privileges needed for the SET\nPASSWORD\nstatement to change a user\'s password with GRANT.\n \nThe only authentication plugins that this clause supports\nare mysql_native_password and mysql_old_password.\n \nIDENTIFIED {VIA|WITH} authentication_plugin\n \nThe optional IDENTIFIED VIA authentication_plugin allows you\nto specify that the account should be authenticated by a\nspecific authentication plugin. The plugin name must be an\nactive authentication plugin as per SHOW PLUGINS. If it\ndoesn\'t show up in that output, then you will need to\ninstall it with INSTALL PLUGIN or INSTALL SONAME.\n \nFor example, this could be used with the PAM authentication\nplugin:\n \nGRANT USAGE ON *.* TO foo2@test IDENTIFIED VIA pam;\n \nSome authentication plugins allow additional arguments to be\nspecified after a USING or AS keyword. For example, the PAM\nauthentication plugin accepts a service name:\n \nGRANT USAGE ON *.* TO foo2@test IDENTIFIED VIA pam USING\n\'mariadb\';\n \nThe exact meaning of the additional argument would depend on\nthe specific authentication plugin.\n \nThe USING or AS keyword can also be used to provide a\nplain-text password to a plugin if it\'s provided as an\nargument to the PASSWORD() function. This is only valid for\nauthentication plugins that have implemented a hook for the\nPASSWORD() function. For example, the ed25519 authentication\nplugin supports this:\n \nCREATE USER safe@\'%\' IDENTIFIED VIA ed25519 USING\nPASSWORD(\'secret\');\n \nOne can specify many authentication plugins, they all works\nas alternatives ways of authenticating a user:\n \nCREATE USER safe@\'%\' IDENTIFIED VIA ed25519 USING\nPASSWORD(\'secret\') OR unix_socket;\n \nResource Limit Options\n \nMariaDB 10.2.0 introduced a number of resource limit\noptions.\n \nIt is possible to set per-account limits for certain server\nresources. The following table shows the values that can be\nset per account:\n \nLimit Type | Decription | \n \nMAX_QUERIES_PER_HOUR | Number of statements that the account\ncan issue per hour (including updates) | \n \nMAX_UPDATES_PER_HOUR | Number of updates (not queries) that\nthe account can issue per hour | \n \nMAX_CONNECTIONS_PER_HOUR | Number of connections that the\naccount can start per hour | \n \nMAX_USER_CONNECTIONS | Number of simultaneous connections\nthat can be accepted from the same account; if it is 0,\nmax_connections will be used instead; if max_connections is\n0, there is no limit for this account\'s simultaneous\nconnections. | \n \nMAX_STATEMENT_TIME | Timeout, in seconds, for statements\nexecuted by the user. See also Aborting Statements that\nExceed a Certain Time to Execute. | \n \nIf any of these limits are set to 0, then there is no limit\nfor that resource for that user.\n \nTo set resource limits for an account, if you do not want to\nchange that account\'s privileges, you can issue a GRANT\nstatement with the USAGE privilege, which has no meaning.\nThe statement can name some or all limit types, in any\norder.\n \nHere is an example showing how to set resource limits:\n \nGRANT USAGE ON *.* TO \'someone\'@\'localhost\' WITH\n MAX_USER_CONNECTIONS 0\n MAX_QUERIES_PER_HOUR 200;\n \nThe resources are tracked per account, which means\n\'user\'@\'server\'; not per user name or per connection.\n \nThe count can be reset for all users using FLUSH\nUSER_RESOURCES, FLUSH PRIVILEGES or mysqladmin reload.\n \nPer account resource limits are stored in the user table, in\nthe mysql database. Columns used for resources limits are\nnamed max_questions, max_updates, max_connections (for\nMAX_CONNECTIONS_PER_HOUR), and max_user_connections (for\nMAX_USER_CONNECTIONS).\n \nTLS Options\n \nBy default, MariaDB transmits data between the server and\nclients without encrypting it. This is generally acceptable\nwhen the server and client run on the same host or in\nnetworks where security is guaranteed through other means.\nHowever, in cases where the server and client exist on\nseparate networks or they are in a high-risk network, the\nlack of encryption does introduce security concerns as a\nmalicious actor could potentially eavesdrop on the traffic\nas it is sent over the network between them.\n \nTo mitigate this concern, MariaDB allows you to encrypt data\nin transit between the server and clients using the\nTransport Layer Security (TLS) protocol. TLS was formerly\nknown as Secure Socket Layer (SSL), but strictly speaking\nthe SSL protocol is a predecessor to TLS and, that version\nof the protocol is now considered insecure. The\ndocumentation still uses the term SSL often and for\ncompatibility reasons TLS-related server system and status\nvariables still use the prefix ssl_, but internally, MariaDB\nonly supports its secure successors.\n \nSee Secure Connections Overview for more information about\nhow to determine whether your MariaDB server has TLS\nsupport.\n \nYou can set certain TLS-related restrictions for specific\nuser accounts. For instance, you might use this with user\naccounts that require access to sensitive data while sending\nit across networks that you do not control. These\nrestrictions can be enabled for a user account with the\nCREATE USER, ALTER USER, or GRANT statements. The following\noptions are available:\n \nOption | Description | \n \nREQUIRE NONE | TLS is not required for this account, but can\nstill be used. | \n \nREQUIRE SSL | The account must use TLS, but no valid X509\ncertificate is required. This option cannot be combined with\nother TLS options. | \n \nREQUIRE X509 | The account must use TLS and must have a\nvalid X509 certificate. This option implies REQUIRE SSL.\nThis option cannot be combined with other TLS options. | \n \nREQUIRE ISSUER \'issuer\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the Certificate\nAuthority must be the one specified via the string issuer.\nThis option implies REQUIRE X509. This option can be\ncombined with the SUBJECT, and CIPHER options in any order.\n| \n \nREQUIRE SUBJECT \'subject\' | The account must use TLS and\nmust have a valid X509 certificate. Also, the certificate\'s\nSubject must be the one specified via the string subject.\nThis option implies REQUIRE X509. This option can be\ncombined with the ISSUER, and CIPHER options in any order. |\n\n \nREQUIRE CIPHER \'cipher\' | The account must use TLS, but no\nvalid X509 certificate is required. Also, the encryption\nused for the connection must use one of the methods\nspecified in the string cipher. This option implies REQUIRE\nSSL. This option can be combined with the ISSUER, and\nSUBJECT options in any order. | \n \nThe REQUIRE keyword must be used only once for all specified\noptions, and the AND keyword can be used to separate\nindividual options, but it is not required.\n \nFor example, you can create a user account that requires\nthese TLS options with the following:\n \nGRANT USAGE ON *.* TO \'alice\'@\'%\'\n REQUIRE SUBJECT \'/CN=alice/O=My Dom,\nInc./C=US/ST=Oregon/L=Portland\'\n AND ISSUER \'/C=FI/ST=Somewhere/L=City/ O=Some\nCompany/CN=Peter Parker/emailAddress=p.parker@marvel.com\'\n AND CIPHER \'TLSv1.2\';\n \nIf any of these options are set for a specific user account,\nthen any client who tries to connect with that user account\nwill have to be configured to connect with TLS.\n \nSee Securing Connections for Client and Server for\ninformation on how to enable TLS on the client and server.\n \nRoles\n \nRoles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nGRANT role TO grantee [, grantee2 ... ]\n[ WITH ADMIN OPTION ]\n \nThe GRANT statement is also used to grant the use a role to\none or more users or other roles. In order to be able to\ngrant a role, the grantor doing so must have permission to\ndo so (see WITH ADMIN in the CREATE ROLE article).\n \nSpecifying the WITH ADMIN OPTION permits the grantee to in\nturn grant the role to another.\n \nFor example, the following commands show how to grant the\nsame role to a couple different users.\n \nGRANT journalist TO hulda;\n \nGRANT journalist TO berengar WITH ADMIN OPTION;\n \nIf a user has been granted a role, they do not automatically\nobtain all permissions associated with that role. These\npermissions are only in use when the user activates the role\nwith the SET ROLE statement.\n \nGrant Examples\n \nGranting Root-like Privileges\n \nYou can create a user that has privileges similar to the\ndefault root accounts by executing the following:\n \nCREATE USER \'alexander\'@\'localhost\';\n \nGRANT ALL PRIVILEGES ON *.* to \'alexander\'@\'localhost\'\nWITH GRANT OPTION;\n \n\n\nURL: https://mariadb.com/kb/en/grant/','','https://mariadb.com/kb/en/grant/'),(131,'ST_X',11,'Syntax\n------ \nST_X(p)\nX(p)\n \nDescription\n----------- \nReturns the X-coordinate value for the point p as a\ndouble-precision number.\n \nST_X() and X() are synonyms.\n \nExamples\n-------- \nSET @pt = \'Point(56.7 53.34)\';\n \nSELECT X(GeomFromText(@pt));\n+----------------------+\n| X(GeomFromText(@pt)) |\n+----------------------+\n| 56.7 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_x/','','https://mariadb.com/kb/en/st_x/'),(132,'ST_Y',11,'Syntax\n------ \nST_Y(p)\nY(p)\n \nDescription\n----------- \nReturns the Y-coordinate value for the point p as a\ndouble-precision number.\n \nST_Y() and Y() are synonyms.\n \nExamples\n-------- \nSET @pt = \'Point(56.7 53.34)\';\n \nSELECT Y(GeomFromText(@pt));\n+----------------------+\n| Y(GeomFromText(@pt)) |\n+----------------------+\n| 53.34 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_y/','','https://mariadb.com/kb/en/st_y/'),(133,'X',11,'A synonym for ST_X.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/point-properties-x/','','https://mariadb.com/kb/en/point-properties-x/'),(134,'Y',11,'A synonym for ST_Y.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/point-properties-y/','','https://mariadb.com/kb/en/point-properties-y/'),(135,'AES_DECRYPT',12,'Syntax\n------ \nAES_DECRYPT(crypt_str,key_str)\n \nDescription\n----------- \nThis function allows decryption of data using the official\nAES\n(Advanced Encryption Standard) algorithm. For more\ninformation, see\nthe description of AES_ENCRYPT().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/aes_decrypt/','','https://mariadb.com/kb/en/aes_decrypt/'),(138,'DECODE',12,'Syntax\n------ \nDECODE(crypt_str,pass_str)\n \nDescription\n----------- \nDecrypts the encrypted string crypt_str using pass_str as\nthe\npassword. crypt_str should be a string returned from\nENCODE(). The resulting string will be the original string\nonly if pass_str is the same.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/decode/','','https://mariadb.com/kb/en/decode/'),(99,'EXECUTE IMMEDIATE',8,'EXECUTE IMMEDIATE was introduced in MariaDB 10.2.3.\n \nSyntax\n------ \nEXECUTE IMMEDIATE statement\n \nDescription\n----------- \nEXECUTE IMMEDIATE executes a dynamic SQL statement created\non the fly, which can reduce performance overhead.\n \nFor example:\n \nEXECUTE IMMEDIATE \'SELECT 1\' \n \nwhich is shorthand for:\n \nprepare stmt from \"select 1\";\n \nexecute stmt;\n \ndeallocate prepare stmt;\n \nEXECUTE IMMEDIATE supports complex expressions as prepare\nsource and parameters:\n \nEXECUTE IMMEDIATE CONCAT(\'SELECT COUNT(*) FROM \', \'t1\',\n\' WHERE a=?\') USING 5+5;\n \nLimitations: subselects and stored function calls are not\nsupported as a prepare source.\n \nThe following examples return an error:\n \nCREATE OR REPLACE FUNCTION f1() RETURNS VARCHAR(64) RETURN\n\'SELECT * FROM t1\';\nEXECUTE IMMEDIATE f1();\nERROR 1970 (42000): EXECUTE IMMEDIATE does not support\nsubqueries or stored functions\n \nEXECUTE IMMEDIATE (SELECT \'SELECT * FROM t1\');\nERROR 1064 (42000): You have an error in your SQL syntax;\ncheck the manual that \n corresponds to your MariaDB server version for the right\nsyntax to use near \n \'SELECT \'SELECT * FROM t1\')\' at line 1\n \nCREATE OR REPLACE FUNCTION f1() RETURNS INT RETURN 10;\nEXECUTE IMMEDIATE \'SELECT * FROM t1 WHERE a=?\' USING f1();\nERROR 1970 (42000): EXECUTE..USING does not support\nsubqueries or stored functions\n \nEXECUTE IMMEDIATE \'SELECT * FROM t1 WHERE a=?\' USING\n(SELECT 10);\nERROR 1064 (42000): You have an error in your SQL syntax;\ncheck the manual that \n corresponds to your MariaDB server version for the right\nsyntax to use near \n \'SELECT 10)\' at line 1\n \nOne can use a user or an SP variable as a workaround:\n \nCREATE OR REPLACE FUNCTION f1() RETURNS VARCHAR(64) RETURN\n\'SELECT * FROM t1\';\nSET @stmt=f1();\nEXECUTE IMMEDIATE @stmt;\n \nSET @stmt=(SELECT \'SELECT 1\');\nEXECUTE IMMEDIATE @stmt;\n \nCREATE OR REPLACE FUNCTION f1() RETURNS INT RETURN 10;\nSET @param=f1();\nEXECUTE IMMEDIATE \'SELECT * FROM t1 WHERE a=?\' USING\n@param;\n \nSET @param=(SELECT 10);\nEXECUTE IMMEDIATE \'SELECT * FROM t1 WHERE a=?\' USING\n@param;\n \nEXECUTE IMMEDIATE supports user variables and SP variables\nas OUT parameters\n \nDELIMITER $$\nCREATE OR REPLACE PROCEDURE p1(OUT a INT)\nBEGIN\n SET a:= 10;\nEND;\n$$\nDELIMITER ;\nSET @a=2;\nEXECUTE IMMEDIATE \'CALL p1(?)\' USING @a;\nSELECT @a;\n+------+\n| @a |\n+------+\n| 10 |\n+------+\n \nSimilar to PREPARE, EXECUTE IMMEDIATE is allowed in stored\nprocedures but is not allowed in stored functions.\n \nThis example uses EXECUTE IMMEDIATE inside a stored\nprocedure:\n \nDELIMITER $$\nCREATE OR REPLACE PROCEDURE p1()\nBEGIN\n EXECUTE IMMEDIATE \'SELECT 1\';\nEND;\n$$\nDELIMITER ;\nCALL p1;\n+---+\n| 1 |\n+---+\n| 1 |\n+---+\n \nThis script returns an error:\n \nDELIMITER $$\nCREATE FUNCTION f1() RETURNS INT\nBEGIN\n EXECUTE IMMEDIATE \'DO 1\';\n RETURN 1;\nEND;\n$$\nERROR 1336 (0A000): Dynamic SQL is not allowed in stored\nfunction or trigger\n \nEXECUTE IMMEDIATE can use DEFAULT and IGNORE indicators as\nbind parameters:\n \nCREATE OR REPLACE TABLE t1 (a INT DEFAULT 10);\nEXECUTE IMMEDIATE \'INSERT INTO t1 VALUES (?)\' USING\nDEFAULT;\nSELECT * FROM t1;\n+------+\n| a |\n+------+\n| 10 |\n+------+\n \nEXECUTE IMMEDIATE increments the Com_execute_immediate\nstatus variable, as well as the Com_stmt_prepare,\nCom_stmt_execute and Com_stmt_close status variables.\n \nNote, EXECUTE IMMEDIATE does not increment the\nCom_execute_sql status variable. Com_execute_sql is used\nonly for PREPARE..EXECUTE.\n \nThis session screenshot demonstrates how EXECUTE IMMEDIATE\naffects status variables:\n \nSELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE\nVARIABLE_NAME RLIKE \n (\'COM_(EXECUTE|STMT_PREPARE|STMT_EXECUTE|STMT_CLOSE)\');\n \n+-----------------------+----------------+\n| VARIABLE_NAME | VARIABLE_VALUE |\n+-----------------------+----------------+\n| COM_EXECUTE_IMMEDIATE | 0 |\n| COM_EXECUTE_SQL | 0 |\n| COM_STMT_CLOSE | 0 |\n| COM_STMT_EXECUTE | 0 |\n| COM_STMT_PREPARE | 0 |\n+-----------------------+----------------+\n \nEXECUTE IMMEDIATE \'SELECT 1\';\n+---+\n| 1 |\n+---+\n| 1 |\n+---+\n \nSELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE\nVARIABLE_NAME RLIKE \n (\'COM_(EXECUTE|STMT_PREPARE|STMT_EXECUTE|STMT_CLOSE)\');\n+-----------------------+----------------+\n| VARIABLE_NAME | VARIABLE_VALUE |\n+-----------------------+----------------+\n| COM_EXECUTE_IMMEDIATE | 1 |\n| COM_EXECUTE_SQL | 0 |\n| COM_STMT_CLOSE | 1 |\n| COM_STMT_EXECUTE | 1 |\n| COM_STMT_PREPARE | 1 |\n+-----------------------+----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/execute-immediate/','','https://mariadb.com/kb/en/execute-immediate/'),(103,'Metadata Locking',8,'Metadata locking has been supported since MariaDB 5.5. This\nmeans that when a transaction (including XA transactions)\nuses a table, it locks its metadata until the end of\ntransaction. Non-transactional tables are also locked, as\nwell as views and objects which are related to locked\ntables/views (stored functions, triggers, etc). When a\nconnection tries to use a DDL statement (like an ALTER\nTABLE) which modifies a table that is locked, that\nconnection is queued, and has to wait until it\'s unlocked.\nUsing savepoints and performing a partial rollback does not\nrelease metadata locks.\n \nLOCK TABLES ... WRITE are also queued. Some wrong statements\nwhich produce an error may not need to wait for the lock to\nbe freed.\n \nMetadata lock\'s timeout is determined by the value of the\nlock_wait_timeout server system variable (in seconds).\nHowever, note that its default value is 31536000 (1 year).\nIf this timeout exceeds, the following error is returned:\n \nERROR 1205 (HY000): Lock wait timeout exceeded;\n try restarting transaction\n \nIf the metadata_lock_info plugin is installed, the\nInformation Schema metadata_lock_info table stores\ninformation about existing metadata locks.\n \nExample\n \nLet\'s use the following MEMORY (non-transactional) table:\n \nCREATE TABLE t (a INT) ENGINE = MEMORY;\n \nConnection 1 starts a transaction, and INSERTs a row into t:\n \nSTART TRANSACTION;\n \nINSERT INTO t SET a=1;\n \nt\'s metadata is now locked by connection 1. Connection 2\ntries to alter t, but has to wait:\n \nALTER TABLE t ADD COLUMN b INT;\n \nConnection 2\'s prompt is blocked now.\n \nNow connection 1 ends the transaction:\n \nCOMMIT;\n \n...and connection 2 finally gets the output of its command:\n \nQuery OK, 1 row affected (35.23 sec)\nRecords: 1 Duplicates: 0 Warnings: 0\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/metadata-locking/','','https://mariadb.com/kb/en/metadata-locking/'),(143,'MD5',12,'Syntax\n------ \nMD5(str)\n \nDescription\n----------- \nCalculates an MD5 128-bit checksum for the string. \n \nThe return value is a 32-hex digit string, and as of MariaDB\n5.5, is a nonbinary string in the connection character set\nand collation, determined by the values of the\ncharacter_set_connection and collation_connection system\nvariables. Before 5.5, the return value was a binary string.\n \nNULL is returned if the argument was NULL. \n \nExamples\n-------- \nSELECT MD5(\'testing\');\n+----------------------------------+\n| MD5(\'testing\') |\n+----------------------------------+\n| ae2b1fca515949e5d54fb22b8ed95575 |\n+----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/md5/','','https://mariadb.com/kb/en/md5/'),(145,'PASSWORD',12,'Syntax\n------ \nPASSWORD(str)\n \nDescription\n----------- \nThe PASSWORD() function is used for hashing passwords for\nuse in authentication by the MariaDB server. It is not\nintended for use in other applications.\n \nCalculates and returns a hashed password string from the\nplaintext password str. Returns an empty string (>= MariaDB\n10.0.4) or NULL (\n\nURL: https://mariadb.com/kb/en/password/','','https://mariadb.com/kb/en/password/'),(100,'LOCK TABLES',8,'Syntax\n------ \nLOCK TABLE[S]\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n [WAIT n|NOWAIT]\n \nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n | WRITE CONCURRENT\n \nUNLOCK TABLES\n \nDescription\n----------- \nThe lock_type can be one of:\n \nOption | Description | \n \nREAD | Read lock, no writes allowed | \n \nREAD LOCAL | Read lock, but allow concurrent inserts | \n \nWRITE | Exclusive write lock. No other connections can read\nor write to this table | \n \nLOW_PRIORITY WRITE | Exclusive write lock, but allow new\nread locks on the table until we get the write lock. | \n \nWRITE CONCURRENT | Exclusive write lock, but allow READ\nLOCAL locks to the table. | \n \nMariaDB enables client sessions to acquire table locks\nexplicitly for the\npurpose of cooperating with other sessions for access to\ntables, or to\nprevent other sessions from modifying tables during periods\nwhen a\nsession requires exclusive access to them. A session can\nacquire or\nrelease locks only for itself. One session cannot acquire\nlocks for\nanother session or release locks held by another session.\n \nLocks may be used to emulate transactions or to get more\nspeed when\nupdating tables.\n \nLOCK TABLES explicitly acquires table locks for the current\nclient session.\nTable locks can be acquired for base tables or views. To use\nLOCK TABLES,\nyou must have the LOCK TABLES privilege, and the SELECT\nprivilege for\neach object to be locked. See GRANT\n \nFor view locking, LOCK TABLES adds all base tables used in\nthe view to the\nset of tables to be locked and locks them automatically. If\nyou lock a table\nexplicitly with LOCK TABLES, any tables used in triggers are\nalso locked\nimplicitly, as described in Triggers and Implicit Locks.\n \nUNLOCK TABLES explicitly releases any table locks held by\nthe\ncurrent session.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nLimitations\n \nLOCK TABLES doesn\'t work when using Galera cluster. You may\nexperience crashes or locks when used with Galera.\n \nLOCK TABLES works on XtraDB/InnoDB tables only if the\ninnodb_table_locks system variable is set to 1 (the default)\nand autocommit is set to 0 (1 is default). Please note that\nno error message will be returned on LOCK TABLES with\ninnodb_table_locks = 0.\n \nLOCK TABLES implicitly commits the active transaction, if\nany. Also, starting a transaction always releases all table\nlocks acquired with LOCK TABLES. This means that there is no\nway to have table locks and an active transaction at the\nsame time. The only exceptions are the transactions in\nautocommit mode. To preserve the data integrity between\ntransactional and non-transactional tables, the GET_LOCK()\nfunction can be used.\n \nWhile a connection holds an explicit read lock on a table,\nit cannot modify it. If you try, the following error will be\nproduced:\n \nERROR 1099 (HY000): Table \'tab_name\' was locked with a\nREAD lock and can\'t be updated\n \nWhile a connection holds an explicit lock on a table, it\ncannot access a non-locked table. If you try, the following\nerror will be produced:\n \nERROR 1100 (HY000): Table \'tab_name\' was not locked with\nLOCK TABLES\n \nWhile a connection holds an explicit lock on a table, it\ncannot issue the following: INSERT DELAYED, CREATE TABLE,\nCREATE TABLE ... LIKE, and DDL statements involving stored\nprograms and views (except for triggers). If you try, the\nfollowing error will be produced:\n \nERROR 1192 (HY000): Can\'t execute the given command because\nyou have active locked tables or an active transaction\n \nLOCK TABLES can not be used in stored routines - if you try,\nthe following error will be produced on creation:\n \nERROR 1314 (0A000): LOCK is not allowed in stored procedures\n \n\n\nURL: https://mariadb.com/kb/en/lock-tables/','','https://mariadb.com/kb/en/lock-tables/'),(105,'PURGE BINARY LOGS',8,'Syntax\n------ \nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n \nDescription\n----------- \nThe PURGE BINARY LOGS statement deletes all the binary log\nfiles listed in the log index file prior to the specified\nlog file name or\ndate. BINARY and MASTER are synonyms.\nDeleted log files also are removed from the list recorded in\nthe index file, so\nthat the given log file becomes the first in the list.\n \nThe datetime expression is in the format \'YYYY-MM-DD\nhh:mm:ss\'. \n \nIf a slave is active but has yet to read from a binary log\nfile you attempt to delete, the statement will fail with an\nerror. However, if the slave is not connected and has yet to\nread from a log file you delete, the file will be deleted,\nbut the slave will be unable to continue replicating once it\nconnects again.\n \nThis statement has no effect if the server was not started\nwith the\n--log-bin option to enable binary logging.\n \nTo list the binary log files on the server, use SHOW BINARY\nLOGS. To see which files they are reading, use SHOW SLAVE\nSTATUS. You can only delete the files that are older than\nthe oldest file that is used by the slaves.\n \nTo delete all binary log files, use RESET MASTER.\nTo move to a new log file (for example if you want to remove\nthe current log file), use FLUSH LOGS before you execute\nPURGE LOGS.\n \nIf the expire_logs_days server system variable is not set to\n0, the server automatically deletes binary log files after\nthe given number of days.\n \nExamples\n-------- \nPURGE BINARY LOGS TO \'mariadb-bin.000063\';\n \nPURGE BINARY LOGS BEFORE \'2013-04-21\';\n \nPURGE BINARY LOGS BEFORE \'2013-04-22 09:55:22\';\n \n\n\nURL: https://mariadb.com/kb/en/purge-binary-logs/','','https://mariadb.com/kb/en/purge-binary-logs/'),(150,'ENDPOINT',13,'A synonym for ST_ENDPOINT.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/linestring-properties-endpoint/','','https://mariadb.com/kb/en/linestring-properties-endpoint/'),(151,'GLENGTH',13,'Syntax\n------ \nGLength(ls)\n \nDescription\n----------- \nReturns as a double-precision number the length of the\nLineString value ls in its associated spatial reference.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.82842712474619 |\n+----------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/glength/','','https://mariadb.com/kb/en/glength/'),(152,'NumPoints',13,'A synonym for ST_NumPoints.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/linestring-properties-numpoints/','','https://mariadb.com/kb/en/linestring-properties-numpoints/'),(153,'PointN',13,'A synonym for ST_PointN.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/linestring-properties-pointn/','','https://mariadb.com/kb/en/linestring-properties-pointn/'),(154,'STARTPOINT',13,'A synonym for ST_STARTPOINT.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/linestring-properties-startpoint/','','https://mariadb.com/kb/en/linestring-properties-startpoint/'),(155,'ST_ENDPOINT',13,'Syntax\n------ \nST_EndPoint(ls)\nEndPoint(ls)\n \nDescription\n----------- \nReturns the Point that is the endpoint of the\nLineString value ls.\n \nST_EndPoint() and EndPoint() are synonyms.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_endpoint/','','https://mariadb.com/kb/en/st_endpoint/'),(101,'ROLLBACK',8,'The ROLLBACK statement rolls back (ends) a transaction,\ndestroying any changes to SQL-data so that they never become\nvisible to subsequent transactions. The required syntax for\nthe ROLLBACK statement is as follows. \n \nROLLBACK [ WORK ] [ AND [ NO ] CHAIN ] \n[ TO [ SAVEPOINT ] { | } ]\n \nThe ROLLBACK statement will either end a transaction,\ndestroying all data changes that happened during any of the\ntransaction, or it will just destroy any data changes that\nhappened since you established a savepoint. The basic form\nof the ROLLBACK statement is just the keyword ROLLBACK (the\nkeyword WORK is simply noise and can be omitted without\nchanging the effect). \n \nThe optional AND CHAIN clause is a convenience for\ninitiating a new transaction as soon as the old transaction\nterminates. If AND CHAIN is specified, then there is\neffectively nothing between the old and new transactions,\nalthough they remain separate. The characteristics of the\nnew transaction will be the same as the characteristics of\nthe old one — that is, the new transaction will have the\nsame access mode, isolation level and diagnostics area size\n(we\'ll discuss all of these shortly) as the transaction\njust terminated. The AND NO CHAIN option just tells your\nDBMS to end the transaction — that is, these four SQL\nstatements are equivalent: \n \nROLLBACK;\n \nROLLBACK WORK;\n \nROLLBACK AND NO CHAIN;\n \nROLLBACK WORK AND NO CHAIN;\n \nAll of them end a transaction without saving any transaction\ncharacteristics. The only other options, the equivalent\nstatements: \n \nROLLBACK AND CHAIN;\n \nROLLBACK WORK AND CHAIN;\n \nboth tell your DBMS to end a transaction, but to save that\ntransaction\'s characteristics for the next transaction. \n \nROLLBACK is much simpler than COMMIT: it may involve no more\nthan a few deletions (of Cursors, locks, prepared SQL\nstatements and log-file entries). It\'s usually assumed that\nROLLBACK can\'t fail, although such a thing is conceivable\n(for example, an encompassing transaction might reject an\nattempt to ROLLBACK because it\'s lining up for a COMMIT). \n \nROLLBACK cancels all effects of a transaction. It does not\ncancel effects on objects outside the DBMS\'s control (for\nexample the values in host program variables or the settings\nmade by some SQL/CLI function calls). But in general, it is\na convenient statement for those situations when you say\n\"oops, this isn\'t working\" or when you simply don\'t care\nwhether your temporary work becomes permanent or not.\n \nHere is a moot question. If all you\'ve been doing is\nSELECTs, so that there have been no data changes, should you\nend the transaction with ROLLBACK or COMMIT? It shouldn\'t\nreally matter because both ROLLBACK and COMMIT do the same\ntransaction-terminating job. However, the popular conception\nis that ROLLBACK implies failure, so after a successful\nseries of SELECT statements the convention is to end the\ntransaction with COMMIT rather than ROLLBACK.\n \nMariaDB (and most other DBMSs) supports rollback of SQL-data\nchange statements, but not of SQL-Schema statements. This\nmeans that if you use any of CREATE, ALTER, DROP, GRANT,\nREVOKE, you are implicitly committing at execution time.\n \nINSERT INTO Table_2 VALUES(5); \nDROP TABLE Table_3 CASCADE;\n \nROLLBACK;\n \nThe result will be that both the INSERT and the DROP will go\nthrough as separate transactions so the ROLLBACK will have\nno effect. \n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/rollback/','','https://mariadb.com/kb/en/rollback/'),(107,'RESET SLAVE',8,'RESET SLAVE [\"connection_name\"] [ALL] \n \nRESET SLAVE makes the slave forget its replication position\nin the\nmaster\'s binary log. This statement is meant to be used for\na clean\nstart. It deletes the master.info and relay-log.info files,\nall the\nrelay log files, and starts a new relay log file. To use\nRESET SLAVE,\nthe slave replication threads must be stopped (use STOP\nSLAVE if\nnecessary).\n \nNote: All relay log files are deleted, even if they have not\nbeen\ncompletely executed by the slave SQL thread. (This is a\ncondition\nlikely to exist on a replication slave if you have issued a\nSTOP SLAVE\nstatement or if the slave is highly loaded.)\n \nConnection information stored in the master.info file is\nimmediately\nreset using any values specified in the corresponding\nstartup options.\nThis information includes values such as master host, master\nport,\nmaster user, and master password. If the slave SQL thread\nwas in the\nmiddle of replicating temporary tables when it was stopped,\nand RESET\nSLAVE is issued, these replicated temporary tables are\ndeleted on the\nslave.\n \nThe ALL also resets the PORT, HOST, USER and PASSWORD\nparameters for the slave. If you are using a connection\nname, it will permanently delete it and it will not show up\nanymore in SHOW ALL SLAVES STATUS.\n \nconnection_name\n \nThe connection_name option was added as part of multi-source\nreplication added in MariaDB 10.0\n \nIf there is only one nameless master, or the default master\n(as specified by the default_master_connection system\nvariable) is intended, connection_name can be omitted. If\nprovided, the RESET SLAVE statement will apply to the\nspecified master. connection_name is case-insensitive.\n \n\n\nURL: https://mariadb.com/kb/en/reset-slave-connection_name/','','https://mariadb.com/kb/en/reset-slave-connection_name/'),(156,'ST_NUMPOINTS',13,'Syntax\n------ \nST_NumPoints(ls)\nNumPoints(ls)\n \nDescription\n----------- \nReturns the number of Point objects in the LineString\nvalue ls.\n \nST_NumPoints() and NumPoints() are synonyms.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_numpoints/','','https://mariadb.com/kb/en/st_numpoints/'),(157,'ST_POINTN',13,'Syntax\n------ \nST_PointN(ls,N)\nPointN(ls,N)\n \nDescription\n----------- \nReturns the N-th Point in the LineString value ls.\nPoints are numbered beginning with 1.\n \nST_PointN() and PointN() are synonyms.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_pointn/','','https://mariadb.com/kb/en/st_pointn/'),(161,'INET_ATON',14,'Syntax\n------ \nINET_ATON(expr)\n \nDescription\n----------- \nGiven the dotted-quad representation of an IPv4 network\naddress as a string,\nreturns an integer that represents the numeric value of the\naddress.\nAddresses may be 4- or 8-byte addresses.\n \nReturns NULL if the argument is not understood.\n \nExamples\n-------- \nSELECT INET_ATON(\'192.168.1.1\');\n+--------------------------+\n| INET_ATON(\'192.168.1.1\') |\n+--------------------------+\n| 3232235777 |\n+--------------------------+\n \nThis is calculated as follows: 192 x 2563 + 168 x 256 2 + 1\nx 256 + 1\n \n\n\nURL: https://mariadb.com/kb/en/inet_aton/','','https://mariadb.com/kb/en/inet_aton/'),(162,'INET_NTOA',14,'Syntax\n------ \nINET_NTOA(expr)\n \nDescription\n----------- \nGiven a numeric IPv4 network address in network byte order\n(4 or 8 byte),\nreturns the dotted-quad representation of the address as a\nstring.\n \nExamples\n-------- \nSELECT INET_NTOA(3232235777);\n+-----------------------+\n| INET_NTOA(3232235777) |\n+-----------------------+\n| 192.168.1.1 |\n+-----------------------+\n \n192.168.1.1 corresponds to 3232235777 since 192 x 2563 + 168\nx 256 2 + 1 x 256 + 1 = 3232235777\n \n\n\nURL: https://mariadb.com/kb/en/inet_ntoa/','','https://mariadb.com/kb/en/inet_ntoa/'),(104,'PREPARE Statement',8,'Syntax\n------ \nPREPARE stmt_name FROM preparable_stmt\n \nDescription\n----------- \nThe PREPARE statement prepares a statement and assigns it a\nname,\nstmt_name, by which to refer to the statement later.\nStatement names\nare not case sensitive. preparable_stmt is either a string\nliteral or a user variable (not a local variable, an SQL\nexpression or a subquery) that contains the text of the\nstatement. The text must \nrepresent a single SQL statement, not multiple statements.\nWithin the\nstatement, \"?\" characters can be used as parameter markers\nto indicate\nwhere data values are to be bound to the query later when\nyou execute\nit. The \"?\" characters should not be enclosed within\nquotes, even if\nyou intend to bind them to string values. Parameter markers\ncan be used\nonly where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n \nThe scope of a prepared statement is the session within\nwhich it is\ncreated. Other sessions cannot see it.\n \nIf a prepared statement with the given name already exists,\nit is\ndeallocated implicitly before the new statement is prepared.\nThis means\nthat if the new statement contains an error and cannot be\nprepared, an\nerror is returned and no statement with the given name\nexists.\n \nPrepared statements can be PREPAREd and EXECUTEd in a stored\nprocedure, but not in a stored function or trigger. Also,\neven if the statement is PREPAREd in a procedure, it will\nnot be deallocated when the procedure execution ends.\n \nA prepared statement can access user-defined variables, but\nnot local variables or procedure\'s parameters.\n \nIf the prepared statement contains a syntax error, PREPARE\nwill fail. As a side effect, stored procedures can use it to\ncheck if a statement is valid. For example:\n \nCREATE PROCEDURE `test_stmt`(IN sql_text TEXT)\nBEGIN\n DECLARE EXIT HANDLER FOR SQLEXCEPTION\n BEGIN\n SELECT CONCAT(sql_text, \' is not valid\');\n END;\n SET @SQL := sql_text;\n PREPARE stmt FROM @SQL;\n DEALLOCATE PREPARE stmt;\nEND;\n \nThe FOUND_ROWS() and ROW_COUNT() functions, if called\nimmediatly after EXECUTE, return the number of rows read or\naffected by the prepared statements; however, if they are\ncalled after DEALLOCATE PREPARE, they provide information\nabout this statement. If the prepared statement produces\nerrors or warnings, GET DIAGNOSTICS return information about\nthem. DEALLOCATE PREPARE shouldn\'t clear the diagnostics\narea, unless it produces an error.\n \nA prepared statement is executed with EXECUTE and released \nwith DEALLOCATE PREPARE.\n \nThe max_prepared_stmt_count server system variable\ndetermines the number of allowed prepared statements that\ncan be prepared on the server. If it is set to 0, prepared\nstatements are not allowed. If the limit is reached, an\nerror similar to the following will be produced:\n \nERROR 1461 (42000): Can\'t create more than\nmax_prepared_stmt_count statements \n (current value: 0)\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, PREPARE stmt FROM \'SELECT\n:1, :2\' is used, instead of ?.\n \nPermitted Statements\n \nNot all statements can be prepared. Only the following SQL\ncommands are permitted:\nALTER TABLE\nANALYZE TABLE\nBINLOG\nCACHE INDEX\nCALL\nCHANGE MASTER\nCHECKSUM {TABLE | TABLES}\nCOMMIT\n{CREATE | DROP} DATABASE\n{CREATE | DROP} INDEX\n{CREATE | RENAME | DROP} TABLE\n{CREATE | RENAME | DROP} USER\n{CREATE | DROP} VIEW\nDELETE\nDESCRIBE\nDO\nEXPLAIN\nFLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS |\nPRIVILEGES | LOGS | STATUS | \n MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES | QUERY\nCACHE | TABLE_STATISTICS | \n INDEX_STATISTICS | USER_STATISTICS | CLIENT_STATISTICS}\nGRANT\nINSERT\nINSTALL {PLUGIN | SONAME}\nHANDLER READ\nKILL\nLOAD INDEX INTO CACHE\nOPTIMIZE TABLE\nREPAIR TABLE\nREPLACE\nRESET {MASTER | SLAVE | QUERY CACHE}\nREVOKE\nROLLBACK\nSELECT\nSET\nSET GLOBAL SQL_SLAVE_SKIP_COUNTER\nSET ROLE\nSET SQL_LOG_BIN\nSET TRANSACTION ISOLATION LEVEL\nSHOW EXPLAIN\nSHOW {DATABASES | TABLES | OPEN TABLES | TABLE STATUS |\nCOLUMNS | INDEX | TRIGGERS | \n EVENTS | GRANTS | CHARACTER SET | COLLATION | ENGINES |\nPLUGINS [SONAME] | PRIVILEGES | \n PROCESSLIST | PROFILE | PROFILES | VARIABLES | STATUS |\nWARNINGS | ERRORS | \n TABLE_STATISTICS | INDEX_STATISTICS | USER_STATISTICS |\nCLIENT_STATISTICS | AUTHORS | \n CONTRIBUTORS}\nSHOW CREATE {DATABASE | TABLE | VIEW | PROCEDURE | FUNCTION\n| TRIGGER | EVENT}\nSHOW {FUNCTION | PROCEDURE} CODE\nSHOW BINLOG EVENTS\nSHOW SLAVE HOSTS\nSHOW {MASTER | BINARY} LOGS\nSHOW {MASTER | SLAVE | TABLES | INNODB | FUNCTION |\nPROCEDURE} STATUS\nSLAVE {START | STOP}\nTRUNCATE TABLE\nSHUTDOWN\nUNINSTALL {PLUGIN | SONAME}\nUPDATE\n \nSynonyms are not listed here, but can be used. For example,\nDESC can be used instead of DESCRIBE.\n \nCompound statements can be prepared too.\n \nNote that if a statement can be run in a stored routine, it\nwill work even if it is called by a prepared statement. For\nexample, SIGNAL can\'t be directly prepared. However, it is\nallowed in stored routines. If the x() procedure contains\nSIGNAL, you can still prepare and execute the \'CALL x();\'\nprepared statement.\n \nPREPARE now supports most kinds of expressions as well, for\nexample:\n \nPREPARE stmt FROM CONCAT(\'SELECT * FROM \', table_name);\n \nWhen PREPARE is used with a statement which is not\nsupported, the following error is produced:\n \nERROR 1295 (HY000): This command is not supported in the\nprepared statement protocol yet\n \nExample\n \ncreate table t1 (a int,b char(10));\ninsert into t1 values (1,\"one\"),(2,\n\"two\"),(3,\"three\");\nprepare test from \"select * from t1 where a=?\";\nset @param=2;\nexecute test using @param;\n+------+------+\n| a | b |\n+------+------+\n| 2 | two |\n+------+------+\nset @param=3;\nexecute test using @param;\n+------+-------+\n| a | b |\n+------+-------+\n| 3 | three |\n+------+-------+\ndeallocate prepare test;\n \nSince identifiers are not permitted as prepared statements\nparameters, sometimes it is necessary to dynamically compose\nan SQL statement. This technique is called dynamic SQL). The\nfollowing example shows how to use dynamic SQL:\n \nCREATE PROCEDURE test.stmt_test(IN tab_name VARCHAR(64))\nBEGIN\n SET @sql = CONCAT(\'SELECT COUNT(*) FROM \', tab_name);\n PREPARE stmt FROM @sql;\n EXECUTE stmt;\n DEALLOCATE PREPARE stmt;\nEND;\n \nCALL test.stmt_test(\'mysql.user\');\n+----------+\n| COUNT(*) |\n+----------+\n| 4 |\n+----------+\n \nUse of variables in prepared statements:\n \nPREPARE stmt FROM \'SELECT @x;\';\n \nSET @x = 1;\n \nEXECUTE stmt;\n+------+\n| @x |\n+------+\n| 1 |\n+------+\n \nSET @x = 0;\n \nEXECUTE stmt;\n+------+\n| @x |\n+------+\n| 0 |\n+------+\n \nDEALLOCATE PREPARE stmt;\n \n\n\nURL: https://mariadb.com/kb/en/prepare-statement/','','https://mariadb.com/kb/en/prepare-statement/'),(163,'IS_FREE_LOCK',14,'Syntax\n------ \nIS_FREE_LOCK(str)\n \nDescription\n----------- \nChecks whether the lock named str is free to use (that is,\nnot locked).\nReturns 1 if the lock is free (no one is using the lock),\n 0 if the lock is in use, and NULL if an\nerror occurs (such as an incorrect argument, like an empty\nstring or NULL). str is case insensitive.\n \nIf the metadata_lock_info plugin is installed, the\nInformation Schema metadata_lock_info table contains\ninformation about locks of this kind (as well as metadata\nlocks).\n \nStatements using the IS_FREE_LOCK() function are not safe\nfor replication.\n \n\n\nURL: https://mariadb.com/kb/en/is_free_lock/','','https://mariadb.com/kb/en/is_free_lock/'),(167,'IS_IPV6',14,'IS_IPV6() has been available since MariaDB 10.0.12.\n \nSyntax\n------ \nIS_IPV6(expr)\n \nDescription\n----------- \nReturns 1 if the expression is a valid IPv6 address\nspecified as a string, otherwise returns 0. Does not\nconsider IPv4 addresses to be valid IPv6 addresses.\n \nExamples\n-------- \n SELECT IS_IPV6(\'48f3::d432:1431:ba23:846f\');\n+--------------------------------------+\n| IS_IPV6(\'48f3::d432:1431:ba23:846f\') |\n+--------------------------------------+\n| 1 |\n+--------------------------------------+\n1 row in set (0.02 sec)\n \nSELECT IS_IPV6(\'10.0.1.1\');\n+---------------------+\n| IS_IPV6(\'10.0.1.1\') |\n+---------------------+\n| 0 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/is_ipv6/','','https://mariadb.com/kb/en/is_ipv6/'),(108,'SET TRANSACTION',8,'Syntax\n------ \nSET [GLOBAL | SESSION] TRANSACTION\n transaction_property [, transaction_property] ...\n \ntransaction_property:\n ISOLATION LEVEL level\n | READ WRITE\n | READ ONLY\n \nlevel:\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n \nDescription\n----------- \nThis statement sets the transaction isolation level or the\ntransaction access mode globally, for the current session,\nor for the next transaction:\nWith the GLOBAL keyword, the statement sets the default\n transaction level globally for all subsequent sessions.\nExisting sessions are\n unaffected.\nWith the SESSION keyword, the statement sets the default\n transaction level for all subsequent transactions performed\nwithin the\n current session.\nWithout any SESSION or GLOBAL keyword,\n the statement sets the isolation level for the next (not\nstarted) transaction\n performed within the current session.\n \nA change to the global default isolation level requires the \nSUPER privilege. Any session is free to change its\nsession isolation level (even in the middle of a\ntransaction), or the isolation\nlevel for its next transaction.\n \nIsolation Level\n \nTo set the global default isolation level at server startup,\nuse the\n--transaction-isolation=level option on the command line or\nin an option file. Values of level for this option use\ndashes\nrather than spaces, so the allowable values are\nREAD-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or\nSERIALIZABLE. For example, to set the default isolation\nlevel to REPEATABLE READ, use these lines in the [mysqld]\nsection of an option file:\n \n[mysqld]\ntransaction-isolation = REPEATABLE-READ\nTo determine the global and session transaction isolation\nlevels at\nruntime, check the value of the tx_isolation system\nvariable:\n \nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\n \nInnoDB supports each of the translation isolation levels\ndescribed here\nusing different locking strategies. The default level is \nREPEATABLE READ. For additional information about InnoDB\nrecord-level locks and how it uses them to execute various\ntypes of statements,\nsee XtraDB/InnoDB Lock Modes,\nand\nhttp://dev.mysql.com/doc/refman/en/innodb-locks-set.html.\n \nIsolation Levels\n \nThe following sections describe how MariaDB supports the\ndifferent transaction levels.\n \nREAD UNCOMMITTED\n \nSELECT statements are performed in a non-locking fashion,\nbut a possible earlier version of a row might be used. Thus,\nusing this\nisolation level, such reads are not consistent. This is also\ncalled a \"dirty\nread.\" Otherwise, this isolation level works like \nREAD COMMITTED.\n \nREAD COMMITTED\n \nA somewhat Oracle-like isolation level with respect to\nconsistent\n(non-locking) reads: Each consistent read, even within the\nsame\ntransaction, sets and reads its own fresh snapshot. See\nhttp://dev.mysql.com/doc/refman/en/innodb-consistent-read.html.\n \nFor locking reads (SELECT with FOR UPDATE\nor LOCK IN SHARE MODE), InnoDB locks only index records, not\nthe gaps before them, and thus allows the free insertion of\nnew records next to\nlocked records. For UPDATE and DELETE\nstatements, locking depends on whether the statement uses a\nunique index with a\nunique search condition (such as WHERE id = 100), or a\nrange-type search condition (such as WHERE id > 100). For a\nunique index with a unique search condition, InnoDB locks\nonly the index record\nfound, not the gap before it. For range-type searches,\nInnoDB locks the index\nrange scanned, using gap locks or next-key (gap plus\nindex-record) locks to\nblock insertions by other sessions into the gaps covered by\nthe range. This is\nnecessary because \"phantom rows\" must be blocked for MySQL\nreplication and\nrecovery to work.\n \nNote: Since MariaDB 5.1, if the READ COMMITTED isolation\nlevel is used or the innodb_locks_unsafe_for_binlog system\nvariable is enabled,\nthere is no InnoDB gap locking except for foreign-key\nconstraint checking and\nduplicate-key checking. Also, record locks for non-matching\nrows are released\nafter MariaDB has evaluated the WHERE condition. As of\nMariaDB/MySQL\n5.1, if you use READ COMMITTED or enable\ninnodb_locks_unsafe_for_binlog, you must use row-based\nbinary logging.\n \nREPEATABLE READ\n \nThis is the default isolation level for InnoDB. For\nconsistent reads,\nthere is an important difference from the READ COMMITTED\nisolation level: All consistent reads within the same\ntransaction read the\nsnapshot established by the first read. This convention\nmeans that if you issue\nseveral plain (non-locking) SELECT statements within the\nsame transaction, these SELECT statements are consistent\nalso with respect to each other. See\nhttp://dev.mysql.com/doc/refman/en/innodb-consistent-read.html.\n \nFor locking reads (SELECT with FOR UPDATE or LOCK IN SHARE\nMODE),\nUPDATE, and DELETE statements, locking depends on whether\nthe\nstatement uses a unique index with a unique search\ncondition, or a\nrange-type search condition. For a unique index with a\nunique search\ncondition, InnoDB locks only the index record found, not the\ngap\nbefore it. For other search conditions, InnoDB locks the\nindex range\nscanned, using gap locks or next-key (gap plus index-record)\nlocks to\nblock insertions by other sessions into the gaps covered by\nthe range.\n \nThis is the minimum isolation level for non-distributed XA\ntransactions.\n \nSERIALIZABLE\n \nThis level is like REPEATABLE READ, but InnoDB implicitly\nconverts all\nplain SELECT statements to SELECT ... LOCK IN SHARE MODE if\nautocommit\nis disabled. If autocommit is enabled, the SELECT is its own\ntransaction. It therefore is known to be read only and can\nbe\nserialized if performed as a consistent (non-locking) read\nand need\nnot block for other transactions. (This means that to force\na plain\nSELECT to block if other transactions have modified the\nselected rows,\nyou should disable autocommit.)\n \nDistributed XA transactions should always use this isolation\nlevel.\n \nAccess Mode\n \nThese clauses appeared in MariaDB 10.0.\n \nThe access mode specifies whether the transaction is allowed\nto write data or not. By default, transactions are in READ\nWRITE mode (see the tx_read_only system variable). READ ONLY\nmode allows the storage engine to apply optimizations that\ncannot be used for transactions which write data. The only\nexception to this rule is that read only transactions can\nperform DDL statements on temporary tables.\n \nIt is not permitted to specify both READ WRITE and READ ONLY\nin the same statement.\n \nREAD WRITE and READ ONLY can also be specified in the START\nTRANSACTION statement, in which case the specified mode is\nonly valid for one transaction.\n \nExamples\n-------- \nSET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;\n \nAttempting to set the isolation level within an existing\ntransaction without specifying GLOBAL or SESSION.\n \nSTART TRANSACTION;\n \nSET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction characteristics can\'t be\nchanged while a transaction is in progress\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/set-transaction/','','https://mariadb.com/kb/en/set-transaction/'),(168,'IS_USED_LOCK',14,'Syntax\n------ \nIS_USED_LOCK(str)\n \nDescription\n----------- \nChecks whether the lock named str is in use (that is,\nlocked). If so,\nit returns the connection identifier of the client that\nholds the\nlock. Otherwise, it returns NULL. str is case insensitive.\n \nIf the metadata_lock_info plugin is installed, the\nInformation Schema metadata_lock_info table contains\ninformation about locks of this kind (as well as metadata\nlocks).\n \nStatements using the IS_USED_LOCK() function are not safe\nfor replication.\n \n\n\nURL: https://mariadb.com/kb/en/is_used_lock/','','https://mariadb.com/kb/en/is_used_lock/'),(109,'START SLAVE',8,'Syntax\n------ \nSTART SLAVE [\"connection_name\"] [thread_type [,\nthread_type] ... ]\nSTART SLAVE [\"connection_name\"] [SQL_THREAD] UNTIL \n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\nSTART SLAVE [\"connection_name\"] [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\nSTART SLAVE [\"connection_name\"] [SQL_THREAD] UNTIL\n MASTER_GTID_POS = \nSTART ALL SLAVES [thread_type [, thread_type]]\nthread_type: IO_THREAD | SQL_THREAD\n \nDescription\n----------- \nSTART SLAVE with no thread_type options starts both of the\nslave\nthreads (see replication). The I/O thread reads events from\nthe master server and stores\nthem in the relay log. The SQL thread reads events from the\nrelay log\nand executes them. START SLAVE requires the SUPER privilege.\n \nIf START SLAVE succeeds in starting the slave threads, it\nreturns\nwithout any error. However, even in that case, it might be\nthat the\nslave threads start and then later stop (for example,\nbecause they do\nnot manage to connect to the master or read its binary log,\nor some\nother problem). START SLAVE does not warn you about this.\nYou must\ncheck the slave\'s error log for error messages generated by\nthe slave\nthreads, or check that they are running satisfactorily with\nSHOW SLAVE\nSTATUS.\n \nSTART SLAVE UNTIL\n \nSTART SLAVE UNTIL refers to the SQL_THREAD slave position at\nwhich the SQL_THREAD replication will halt. If SQL_THREAD\nisn\'t specified both threads are started.\n \nSince version 10.0.2, START SLAVE UNTIL master_gtid_pos=xxx\nhas also been supported. See Global Transaction ID/START\nSLAVE UNTIL master_gtid_pos=xxx for more details.\n \nconnection_name\n \nThe connection_name option was added as part of multi-source\nreplication added in MariaDB 10.0\n \nIf there is only one nameless master, or the default master\n(as specified by the default_master_connection system\nvariable) is intended, connection_name can be omitted. If\nprovided, the START SLAVE statement will apply to the\nspecified master. connection_name is case-insensitive.\n \nSTART ALL SLAVES\n \nSTART ALL SLAVES starts all configured slaves (slaves with\nmaster_host not empty) that were not started before. It will\ngive a note for all started connections. You can check the\nnotes with SHOW WARNINGS.\n \n\n\nURL: https://mariadb.com/kb/en/start-slave/','','https://mariadb.com/kb/en/start-slave/'),(110,'START TRANSACTION',8,'Syntax\n------ \nSTART TRANSACTION [transaction_property [,\ntransaction_property] ...] | BEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n \ntransaction_property:\n WITH CONSISTENT SNAPSHOT\n | READ WRITE\n | READ ONLY\n \nDescription\n----------- \nThe START TRANSACTION or BEGIN statement\nbegins a new transaction. COMMIT commits the current\ntransaction, making its changes permanent. ROLLBACK rolls\nback the current transaction, canceling its changes. The SET\nautocommit statement disables or enables the default\nautocommit mode for the current session.\n \nSTART TRANSACTION and SET autocommit = 1 implicitly commit\nthe current transaction, if any.\n \nThe optional WORK keyword is supported for\nCOMMIT and ROLLBACK, as are the\nCHAIN and RELEASE clauses.\nCHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of\nthe\ncompletion_type system variable determines the default\ncompletion behavior.\n \nThe AND CHAIN clause causes a new transaction to begin as\nsoon as the current one ends, and the new transaction has\nthe same isolation\nlevel as the just-terminated transaction. The RELEASE clause\ncauses the server to disconnect the current client session\nafter terminating\nthe current transaction. Including the NO keyword suppresses\nCHAIN or RELEASE completion, which can be\nuseful if the completion_type system variable is set to\ncause chaining or release completion by default.\n \nAccess Mode\n \nThese clauses appeared in MariaDB 10.0.\n \nThe access mode specifies whether the transaction is allowed\nto write data or not. By default, transactions are in READ\nWRITE mode (see the tx_read_only system variable). READ ONLY\nmode allows the storage engine to apply optimizations that\ncannot be used for transactions which write data. The only\nexception to this rule is that read only transactions can\nperform DDL statements on temporary tables.\n \nIt is not permitted to specify both READ WRITE and READ ONLY\nin the same statement.\n \nREAD WRITE and READ ONLY can also be specified in the SET\nTRANSACTION statement, in which case the specified mode is\nvalid for all sessions, or for all subsequent transaction\nused by the current session.\n \nautocommit\n \nBy default, MariaDB runs with autocommit mode enabled. This\nmeans that as soon as you execute a statement that updates\n(modifies) a table, MariaDB stores the update on disk to\nmake it permanent. To disable autocommit mode, use the\nfollowing statement:\n \nSET autocommit=0;\n \nAfter disabling autocommit mode by setting the autocommit\nvariable to zero, changes to transaction-safe tables (such\nas those for InnoDB or\nNDBCLUSTER) are not made permanent immediately. You must use\nCOMMIT to store your changes to disk or ROLLBACK to ignore\nthe changes.\n \nTo disable autocommit mode for a single series of\nstatements, use the START TRANSACTION statement.\n \nDDL Statements\n \nDDL statements (CREATE, ALTER, DROP) and administrative\nstatements (FLUSH, RESET, OPTIMIZE, ANALYZE, CHECK, REPAIR,\nCACHE INDEX), and LOAD DATA INFILE, cause an implicit COMMIT\nand start a new transaction. An exception to this rule are\nthe DDL that operate on temporary tables: you can CREATE,\nALTER and DROP them without causing any COMMIT, but those\nactions cannot be rolled back. This means that if you call\nROLLBACK, the temporary tables you created in the\ntransaction will remain, while the rest of the transaction\nwill be rolled back.\n \nTransactions cannot be used in Stored Functions or Triggers.\nIn Stored Procedures and Events BEGIN is not allowed, so you\nshould use START TRANSACTION instead.\n \nA transaction acquires a metadata lock on every table it\naccesses to prevent other connections from altering their\nstructure. The lock is released at the end of the\ntransaction. This happens even with non-transactional\nstorage engines (like MEMORY or CONNECT), so it makes sense\nto use transactions with non-transactional tables.\n \nin_transaction\n \nThe in_transaction system variable appeared in MariaDB 5.3.\n \nIt is a session-only, read-only variable that returns 1\ninside a transaction, and 0 if not in a transaction.\n \nWITH CONSISTENT SNAPSHOT\n \nThe WITH CONSISTENT SNAPSHOT option starts a consistent read\nfor storage engines such as XtraDB and InnoDB that can do\nso, the same as if a START TRANSACTION followed by a SELECT\nfrom any InnoDB table was issued. \n \nMariaDB 5.3 introduced enhancements to this feature. See\nEnhancements for START TRANSACTION WITH CONSISTENT SNAPSHOT.\n \nExamples\n-------- \nSTART TRANSACTION;\n \nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\n \nUPDATE table2 SET summary=@A WHERE type=1;\n \nCOMMIT;\n \n\n\nURL: https://mariadb.com/kb/en/start-transaction/','','https://mariadb.com/kb/en/start-transaction/'),(171,'NAME_CONST',14,'Syntax\n------ \nNAME_CONST(name,value)\n \nDescription\n----------- \nReturns the given value. When used to produce a result set\ncolumn,\n NAME_CONST() causes the column to have the given name. The\narguments should be constants.\n \nThis function is used internally when replicating stored\nprocedures. It makes little sense to use it explicitly in\nSQL statements, and it was not supposed to be used like\nthat.\n \nSELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/name_const/','','https://mariadb.com/kb/en/name_const/'),(111,'STOP SLAVE',8,'Syntax\n------ \nSTOP SLAVE [\"connection_name\"] [thread_type [,\nthread_type] ... ]\n \nSTOP ALL SLAVES [thread_type [, thread_type]]\n \nthread_type: IO_THREAD | SQL_THREAD\n \nDescription\n----------- \nStops the slave threads. STOP SLAVE requires the SUPER\nprivilege.\n \nLike START SLAVE, this statement may be used with the\nIO_THREAD and\nSQL_THREAD options to name the thread or threads to be\nstopped. In almost all cases, one never need to use the\nthread_type options.\n \nSTOP SLAVE waits until any current replication event group\naffecting\none or more non-transactional tables has finished executing\n(if there\nis any such replication group), or until the user issues a\nKILL QUERY or KILL CONNECTION statement.\n \nNote that STOP SLAVE doesn\'t delete the connection\npermanently. Next time you execute START SLAVE or the\nMariaDB server restarts, the slave connection is restored\nwith it\'s original arguments. If you want to delete a\nconnection, you should execute RESET SLAVE.\n \nSTOP ALL SLAVES\n \nSTOP ALL SLAVES stops all your running slaves. It will give\nyou a note for every stopped connection. You can check the\nnotes with SHOW WARNINGS.\n \nconnection_name\n \nThe connection_name option was added as part of multi-source\nreplication added in MariaDB 10.0\n \nIf there is only one nameless master, or the default master\n(as specified by the default_master_connection system\nvariable) is intended, connection_name can be omitted. If\nprovided, the STOP SLAVE statement will apply to the\nspecified master. connection_name is case-insensitive.\n \n\n\nURL: https://mariadb.com/kb/en/stop-slave/','','https://mariadb.com/kb/en/stop-slave/'),(112,'Transaction Timeouts',8,'MariaDB has always had the wait_timeout and\ninteractive_timeout settings, which close connections after\na certain period of inactivity.\n \nHowever, these are by default set to a long wait period. In\nsituations where transactions may be started, but not\ncommitted or rolled back, more granular control and a\nshorter timeout may be desirable so as to avoid locks being\nheld for too long.\n \nMariaDB 10.3 introduced three new variables to handle this\nsituation.\nidle_transaction_timeout (all transactions)\nidle_write_transaction_timeout (write transactions - called\nidle_readwrite_transaction_timeout until MariaDB 10.3.2)\nidle_readonly_transaction_timeout (read transactions)\n \nThese accept a time in seconds to time out, by closing the\nconnection, transactions that are idle for longer than this\nperiod. By default all are set to zero, or no timeout.\n \nidle_transaction_timeout affects all transactions,\nidle_write_transaction_timeout affects write transactions\nonly and idle_readonly_transaction_timeout affects read\ntransactions only. The latter two variables work\nindependently. However, if either is set along with\nidle_transaction_timeout, the settings for\nidle_write_transaction_timeout or\nidle_readonly_transaction_timeout will take precedence.\n \nExamples\n-------- \nSET SESSION idle_transaction_timeout=2;\n \nBEGIN;\n \nSELECT * FROM t;\n \nEmpty set (0.000 sec)\n## wait 3 seconds\nSELECT * FROM t;\n \nERROR 2006 (HY000): MySQL server has gone away\n \nSET SESSION idle_write_transaction_timeout=2;\n \nBEGIN;\n \nSELECT * FROM t;\n \nEmpty set (0.000 sec)\n## wait 3 seconds\nSELECT * FROM t;\n \nEmpty set (0.000 sec)\nINSERT INTO t VALUES(1);\n## wait 3 seconds\nSELECT * FROM t;\n \nERROR 2006 (HY000): MySQL server has gone away\n \nSET SESSION idle_transaction_timeout=2, SESSION\nidle_readonly_transaction_timeout=10;\n \nBEGIN;\n \nSELECT * FROM t;\n \nEmpty set (0.000 sec)\n ## wait 3 seconds\nSELECT * FROM t;\n \nEmpty set (0.000 sec)\n## wait 11 seconds\nSELECT * FROM t;\n \nERROR 2006 (HY000): MySQL server has gone away\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/transaction-timeouts/','','https://mariadb.com/kb/en/transaction-timeouts/'),(114,'WAIT and NOWAIT',8,'MariaDB 10.3.0 introduced extended syntax so that it is\npossible to set innodb_lock_wait_timeout and\nlock_wait_timeout for the following statements:\n \nSyntax\n------ \nALTER TABLE tbl_name [WAIT n|NOWAIT] ...\nCREATE ... INDEX ON tbl_name (index_col_name, ...) [WAIT\nn|NOWAIT] ...\nDROP INDEX ... [WAIT n|NOWAIT]\nDROP TABLE tbl_name [WAIT n|NOWAIT] ...\nLOCK TABLE ... [WAIT n|NOWAIT]\nOPTIMIZE TABLE tbl_name [WAIT n|NOWAIT]\nRENAME TABLE tbl_name [WAIT n|NOWAIT] ...\nSELECT ... FOR UPDATE [WAIT n|NOWAIT]\nSELECT ... LOCK IN SHARE MODE [WAIT n|NOWAIT]\nTRUNCATE TABLE tbl_name [WAIT n|NOWAIT]\n \nDescription\n----------- \nThe lock wait timeout can be explicitly set in the statement\nby using either WAIT n (to set the wait in seconds) or\nNOWAIT, in which case the statement will immediately fail if\nthe lock cannot be obtained. WAIT 0 is equivalent to NOWAIT.\n \n\n\nURL: https://mariadb.com/kb/en/wait-and-nowait/','','https://mariadb.com/kb/en/wait-and-nowait/'),(116,'Account Locking',10,'Account locking was introduced in MariaDB 10.4.2.\n \nDescription\n----------- \nAccount locking permits privileged administrators to\nlock/unlock user accounts. No new client connections will be\npermitted if an account is locked (existing connections are\nnot affected).\n \nUser accounts can be locked at creation, with the CREATE\nUSER statement, or modified after creation with the ALTER\nUSER statement. For example:\n \nCREATE USER \'lorin\'@\'localhost\' ACCOUNT LOCK;\n \nor\n \nALTER USER \'marijn\'@\'localhost\' ACCOUNT LOCK;\n \nThe server will return an ER_ACCOUNT_HAS_BEEN_LOCKED error\nwhen locked users attempt to connect:\n \nmysql -ulorin\n ERROR 4151 (HY000): Access denied, this account is locked\n \nThe ALTER USER statement is also used to unlock a user:\n \nALTER USER \'lorin\'@\'localhost\' ACCOUNT UNLOCK;\n \nThe SHOW CREATE USER statement will show whether the account\nis locked:\n \nSHOW CREATE USER \'marijn\'@\'localhost\';\n \n+-----------------------------------------------+\n| CREATE USER for marijn@localhost |\n+-----------------------------------------------+\n| CREATE USER \'marijn\'@\'localhost\' ACCOUNT LOCK |\n+-----------------------------------------------+\n \nas well as querying the mysql.global_priv table:\n \nSELECT CONCAT(user, \'@\', host, \' => \',\nJSON_DETAILED(priv)) FROM mysql.global_priv \n WHERE user=\'marijn\';\n+--------------------------------------------------------------------------------------+\n| CONCAT(user, \'@\', host, \' => \', JSON_DETAILED(priv)) |\n+--------------------------------------------------------------------------------------+\n| marijn@localhost => {\n \"access\": 0,\n \"plugin\": \"mysql_native_password\",\n \"authentication_string\": \"\",\n \"account_locked\": true,\n \"password_last_changed\": 1558017158\n} |\n+--------------------------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/account-locking/','','https://mariadb.com/kb/en/account-locking/'),(173,'SLEEP',14,'Syntax\n------ \nSLEEP(duration)\n \nDescription\n----------- \nSleeps (pauses) for the number of seconds given by the\nduration argument, then\nreturns 0. If SLEEP() is interrupted, it\nreturns 1. The duration may have a fractional part given in\nmicroseconds.\n \nStatements using the SLEEP() function are not safe for\nreplication.\n \nExample\n \nSELECT SLEEP(5.5);\n+------------+\n| SLEEP(5.5) |\n+------------+\n| 0 |\n+------------+\n1 row in set (5.50 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sleep/','','https://mariadb.com/kb/en/sleep/'),(175,'UUID_SHORT',14,'Syntax\n------ \nUUID_SHORT()\n \nDescription\n----------- \nReturns a \"short\" universal identifier as a 64-bit\nunsigned integer (rather\nthan a string-form 128-bit identifier as returned by the\nUUID() function).\n \nThe value of UUID_SHORT() is guaranteed to be unique if the\nfollowing conditions hold:\nThe server_id of the current host is unique among your set\nof master and\n slave servers\nserver_id is between 0 and 255\nYou don\'t set back your system time for your server between\nmysqld restarts\nYou do not invoke UUID_SHORT() on average more than 16\n million times per second between mysqld restarts\n \nThe UUID_SHORT() return value is constructed this way:\n \n (server_id & 255) \n\nURL: https://mariadb.com/kb/en/uuid_short/','','https://mariadb.com/kb/en/uuid_short/'),(120,'DROP USER',10,'Syntax\n------ \nDROP USER [IF EXISTS] user_name [, user_name] ...\n \nDescription\n----------- \nThe DROP USER statement removes one or more MariaDB\naccounts. It removes\nprivilege rows for the account from all grant tables. To use\nthis statement,\nyou must have the global CREATE USER privilege\nor the DELETE privilege for the mysql database.\nEach account is named using the same format as for the\nCREATE USER\nstatement; for example, \'jeffrey\'@\'localhost\'. If you\nspecify\nonly the user name part of the account name, a host name\npart of \'%\' is\nused. For additional information about specifying account\nnames, see\nCREATE USER.\n \nNote that, if you specify an account that is currently\nconnected, it will not\nbe deleted until the connection is closed. The connection\nwill not be\nautomatically closed.\n \nIf any of the specified user accounts do not exist, ERROR\n1396 (HY000)\nresults. If an error occurs, DROP USER will still drop the\naccounts that do\nnot result in an error. Only one error is produced for all\nusers which have not\nbeen dropped:\n \nERROR 1396 (HY000): Operation DROP USER failed for\n\'u1\'@\'%\',\'u2\'@\'%\'\n \nFailed CREATE or DROP operations, for both users and roles,\nproduce the\nsame error code.\n \nIF EXISTS\n \nThe IF EXISTS clause was added in MariaDB 10.1.3\n \nIf the IF EXISTS clause is used, MariaDB will return a note\ninstead of an error if the user does not exist.\n \nExamples\n-------- \nDROP USER bob;\n \nIF EXISTS:\n \nDROP USER bob;\n \nERROR 1396 (HY000): Operation DROP USER failed for\n\'bob\'@\'%\'\n \nDROP USER IF EXISTS bob;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+---------------------------------------------+\n| Level | Code | Message |\n+-------+------+---------------------------------------------+\n| Note | 1974 | Can\'t drop user \'bob\'@\'%\'; it doesn\'t\nexist |\n+-------+------+---------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-user/','','https://mariadb.com/kb/en/drop-user/'),(122,'User Password Expiry',10,'User password expiry was introduced in MariaDB 10.4.3.\n \nPassword expiry permits administrators to expire user\npasswords, either manually or automatically. \n \nSystem Variables\n \nThere are two system variables which affect password expiry:\ndefault_password_lifetime, which determines the amount of\ntime between requiring the user to change their password. 0,\nthe default, means automatic password expiry is not active.\n \nThe second variable, disconnect_on_expired_password\ndetermines whether a client is permitted to connect if their\npassword has expired, or whether they are permitted to\nconnect in sandbox mode, able to perform a limited subset of\nqueries related to resetting the password, in particular SET\nPASSWORD and SET.\n \nSetting a Password Expiry Limit for a User\n \nBesides automatic password expiry, as determined by\ndefault_password_lifetime, password expiry times can be set\non an individual user basis, overriding the global using the\nCREATE USER or ALTER USER statements, for example:\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nLimits can be disabled by use of the NEVER keyword, for\nexample:\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE NEVER;\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE NEVER;\n \nA manually set limit can be restored the system default by\nuse of DEFAULT, for example:\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE DEFAULT;\n \nALTER USER \'monty\'@\'localhost\' PASSWORD EXPIRE DEFAULT;\n \nSHOW CREATE USER\n \nThe SHOW CREATE USER statement will display information\nabout the password expiry status of the user. Unlike MySQL,\nit will not display if the user is unlocked, or if the\npassword expiry is set to default.\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nCREATE USER \'konstantin\'@\'localhost\' PASSWORD EXPIRE\nNEVER;\n \nCREATE USER \'amse\'@\'localhost\' PASSWORD EXPIRE DEFAULT;\n \nSHOW CREATE USER \'monty\'@\'localhost\';\n \n+------------------------------------------------------------------+\n| CREATE USER for monty@localhost |\n+------------------------------------------------------------------+\n| CREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE\nINTERVAL 120 DAY |\n+------------------------------------------------------------------+\n \nSHOW CREATE USER \'konstantin\'@\'localhost\';\n \n+------------------------------------------------------------+\n| CREATE USER for konstantin@localhost |\n+------------------------------------------------------------+\n| CREATE USER \'konstantin\'@\'localhost\' PASSWORD EXPIRE\nNEVER |\n+------------------------------------------------------------+\n \nSHOW CREATE USER \'amse\'@\'localhost\';\n \n+--------------------------------+\n| CREATE USER for amse@localhost |\n+--------------------------------+\n| CREATE USER \'amse\'@\'localhost\' |\n+--------------------------------+\n \n--connect-expired-password Client Option\n \nThe mysql client --connect-expired-password option notifies\nthe server that the client is prepared to handle expired\npassword sandbox mode (even if the --batch option was\nspecified).\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/user-password-expiry/','','https://mariadb.com/kb/en/user-password-expiry/'),(177,'!',15,'Syntax\n------ \nNOT, !\n \nDescription\n----------- \nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the\noperand\nis non-zero, and NOT NULL returns NULL.\n \nBy default, the ! operator has a higher precedence. If the\nHIGH_NOT_PRECEDENCE SQL_MODE flag is set, NOT and ! have the\nsame precedence.\n \nExamples\n-------- \nSELECT NOT 10;\n \n+--------+\n| NOT 10 |\n+--------+\n| 0 |\n+--------+\n \nSELECT NOT 0;\n \n+-------+\n| NOT 0 |\n+-------+\n| 1 |\n+-------+\n \nSELECT NOT NULL;\n \n+----------+\n| NOT NULL |\n+----------+\n| NULL |\n+----------+\n \nSELECT ! (1+1);\n+---------+\n| ! (1+1) |\n+---------+\n| 0 |\n+---------+\n \nSELECT ! 1+1;\n \n+-------+\n| ! 1+1 |\n+-------+\n| 1 |\n+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not/','','https://mariadb.com/kb/en/not/'),(178,'&&',15,'Syntax\n------ \nAND, &&\n \nDescription\n----------- \nLogical AND. Evaluates to 1 if all operands are non-zero and\nnot NULL,\nto 0 if one or more operands are 0, otherwise NULL is\nreturned.\n \nFor this operator, short-circuit evaluation can be used.\n \nExamples\n-------- \nSELECT 1 && 1;\n \n+--------+\n| 1 && 1 |\n+--------+\n| 1 |\n+--------+\n \nSELECT 1 && 0;\n \n+--------+\n| 1 && 0 |\n+--------+\n| 0 |\n+--------+\n \nSELECT 1 && NULL;\n \n+-----------+\n| 1 && NULL |\n+-----------+\n| NULL |\n+-----------+\n \nSELECT 0 && NULL;\n \n+-----------+\n| 0 && NULL |\n+-----------+\n| 0 |\n+-----------+\n \nSELECT NULL && 0;\n \n+-----------+\n| NULL && 0 |\n+-----------+\n| 0 |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/and/','','https://mariadb.com/kb/en/and/'),(180,'XOR',15,'Syntax\n------ \nXOR\n \nDescription\n----------- \nXOR stands for eXclusive OR. Returns NULL if either operand\nis NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is\nnon-zero,\notherwise 0 is returned.\n \nExamples\n-------- \nSELECT 1 XOR 1;\n \n+---------+\n| 1 XOR 1 |\n+---------+\n| 0 |\n+---------+\n \nSELECT 1 XOR 0;\n \n+---------+\n| 1 XOR 0 |\n+---------+\n| 1 |\n+---------+\n \nSELECT 1 XOR NULL;\n \n+------------+\n| 1 XOR NULL |\n+------------+\n| NULL |\n+------------+\n \nIn the following example, the right 1 XOR 1 is evaluated\nfirst, and returns 0. Then, 1 XOR 0 is evaluated, and 1 is\nreturned.\n \nSELECT 1 XOR 1 XOR 1;\n \n+---------------+\n| 1 XOR 1 XOR 1 |\n+---------------+\n| 1 |\n+---------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/xor/','','https://mariadb.com/kb/en/xor/'),(123,'RENAME USER',10,'Syntax\n------ \nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n \nDescription\n----------- \nThe RENAME USER statement renames existing MariaDB accounts.\nTo use it,\nyou must have the global CREATE USER privilege\nor the UPDATE privilege for the mysql database.\nEach account is named using the same format as for the\nCREATE USER\nstatement; for example, \'jeffrey\'@\'localhost\'.\nIf you specify only the user name part of the account name,\na host\nname part of \'%\' is used.\n \nIf any of the old user accounts do not exist or any of the\nnew user accounts already\nexist, ERROR 1396 (HY000) results. If an error occurs,\nRENAME USER\nwill still rename the accounts that do not result in an\nerror.\n \nExamples\n-------- \nCREATE USER \'donald\', \'mickey\';\n \nRENAME USER \'donald\' TO \'duck\'@\'localhost\', \'mickey\'\nTO \'mouse\'@\'localhost\';\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/rename-user/','','https://mariadb.com/kb/en/rename-user/'),(124,'REVOKE',10,'Privileges\n \nSyntax\n------ \nREVOKE \n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n \nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n \nDescription\n----------- \nThe REVOKE statement enables system administrators to revoke\nprivileges (or roles - see section below) from MariaDB\naccounts. Each account is named using the same format\nas for the GRANT statement; for example,\n\'jeffrey\'@\'localhost\'. If you specify only the user name\npart\nof the account name, a host name part of \'%\' is used. For\ndetails on the levels at which privileges exist, the\nallowable\npriv_type and priv_level values, and the\nsyntax for specifying users and passwords, see GRANT.\n \nTo use the first REVOKE syntax, you must have the\nGRANT OPTION privilege, and you must have the privileges\nthat\nyou are revoking.\n \nTo revoke all privileges, use the second syntax, which drops\nall\nglobal, database, table, column, and routine privileges for\nthe named\nuser or users:\n \nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n \nTo use this REVOKE syntax, you must have the global\nCREATE USER privilege or the\nUPDATE privilege for the mysql database. See\nGRANT.\n \nExamples\n-------- \nREVOKE SUPER ON *.* FROM \'alexander\'@\'localhost\';\n \nRoles\n \nRoles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nREVOKE role [, role ...]\n FROM grantee [, grantee2 ... ]\n \nDescription\n----------- \nREVOKE is also used to remove a role from a user or another\nrole that it\'s previously been assigned to. If a role has\npreviously been set as a default role, REVOKE does not\nremove the record of the default role from the mysql.user\ntable. If the role is subsequently granted again, it will\nagain be the user\'s default. Use SET DEFAULT ROLE NONE to\nexplicitly remove this.\n \nBefore MariaDB 10.1.13, the REVOKE role statement was not\npermitted in prepared statements.\n \nExample\n \nREVOKE journalist FROM hulda\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/revoke/','','https://mariadb.com/kb/en/revoke/'),(127,'CREATE ROLE',10,'Roles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nCREATE [OR REPLACE] ROLE [IF NOT EXISTS] role \n [WITH ADMIN \n {CURRENT_USER | CURRENT_ROLE | user | role}]\n \nDescription\n----------- \nThe CREATE ROLE statement creates one or more MariaDB roles.\nTo\nuse it, you must have the global CREATE USER\nprivilege or the INSERT privilege for the mysql\ndatabase. For each account, CREATE ROLE creates a new row in\nthe\nmysql.user table that has no privileges, and with the\ncorresponding is_role field set to Y. It also creates a\nrecord in the\nmysql.roles_mapping table.\n \nIf any of the specified roles already exist, ERROR 1396\n(HY000) results. If\nan error occurs, CREATE ROLE will still create the roles\nthat do not result\nin an error. The maximum length for a role is 128\ncharacters. Role names can be\nquoted, as explained in the Identifier names page. Only\none error is produced for all roles which have not been\ncreated:\n \nERROR 1396 (HY000): Operation CREATE ROLE failed for\n\'a\',\'b\',\'c\'\n \nFailed CREATE or DROP operations, for both users and roles,\nproduce the\nsame error code.\n \nPUBLIC and NONE are reserved, and cannot be used as role\nnames.\n \nBefore MariaDB 10.1.13, the CREATE ROLE statement was not\npermitted in prepared statements.\n \nFor valid identifiers to use as role names, see Identifier\nNames.\n \nWITH ADMIN\n \nThe optional WITH ADMIN clause determines whether the\ncurrent user, the\ncurrent role or another user or role has use of the newly\ncreated role. If the\nclause is omitted, WITH ADMIN CURRENT_USER is treated as the\ndefault, which\nmeans that the current user will be able to GRANT this role\nto\nusers.\n \nOR REPLACE\n \nThe OR REPLACE clause was added in MariaDB 10.1.3\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP ROLE IF EXISTS name;\n \nCREATE ROLE name ...;\n \nIF NOT EXISTS\n \nThe IF NOT EXISTS clause was added in MariaDB 10.1.3\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the specified role already\nexists. Cannot be used together with the OR REPLACE clause.\n \nExamples\n-------- \nCREATE ROLE journalist;\n \nCREATE ROLE developer WITH ADMIN lorinda;\n \nThe OR REPLACE and IF NOT EXISTS clauses:\n \nCREATE ROLE journalist;\nERROR 1396 (HY000): Operation CREATE ROLE failed for\n\'journalist\'\n \nCREATE OR REPLACE ROLE journalist;\nQuery OK, 0 rows affected (0.00 sec)\n \nCREATE ROLE IF NOT EXISTS journalist;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n+-------+------+---------------------------------------------------+\n| Level | Code | Message |\n+-------+------+---------------------------------------------------+\n| Note | 1975 | Can\'t create role \'journalist\'; it\nalready exists |\n+-------+------+---------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-role/','','https://mariadb.com/kb/en/create-role/'),(182,'Assignment Operator (:=)',15,'Syntax\n------ \nvar_name := expr\n \nDescription\n----------- \nAssignment operator for assigning a value. The value on the\nright is assigned to the variable on left.\n \nUnlike the = operator, := can always be used to assign a\nvalue to a variable.\n \nThis operator works with both user-defined variables and\nlocal variables.\n \nWhen assigning the same value to several variables,\nLAST_VALUE() can be useful.\n \nExamples\n-------- \n SELECT @x := 10;\n \n+----------+\n| @x := 10 |\n+----------+\n| 10 |\n+----------+\n \nSELECT @x, @y := @x;\n \n+------+----------+\n| @x | @y := @x |\n+------+----------+\n| 10 | 10 |\n+------+----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/assignment-operator/','','https://mariadb.com/kb/en/assignment-operator/'),(189,'GROUP_CONCAT',16,'Syntax\n------ \nGROUP_CONCAT(expr)\n \nDescription\n----------- \nThis function returns a string result with the concatenated\nnon-NULL\nvalues from a group. It returns NULL if there are no\nnon-NULL values.\n \nThe maximum returned length in bytes is determined by the\ngroup_concat_max_len server system variable, which defaults\nto 1M (>= MariaDB 10.2.4) or 1K (\n\nURL: https://mariadb.com/kb/en/group_concat/','','https://mariadb.com/kb/en/group_concat/'),(195,'STDDEV_SAMP',16,'Syntax\n------ \nSTDDEV_SAMP(expr)\n \nDescription\n----------- \nReturns the sample standard deviation of expr (the square\nroot of VAR_SAMP()).\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, STDDEV_SAMP() can be used as a window\nfunction.\n \nSTDDEV_SAMP() returns NULL if there were no matching rows.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/stddev_samp/','','https://mariadb.com/kb/en/stddev_samp/'),(125,'SET PASSWORD',10,'Syntax\n------ \nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'some password\')\n | OLD_PASSWORD(\'some password\')\n | \'encrypted password\'\n }\n \nDescription\n----------- \nThe SET PASSWORD statement assigns a password to an existing\nMariaDB user\naccount.\n \nIf the password is specified using the PASSWORD() or\nOLD_PASSWORD()\nfunction, the literal text of the password should be given.\nIf the\npassword is specified without using either function, the\npassword\nshould be the already-encrypted password value as returned\nby\nPASSWORD().\n \nOLD_PASSWORD() should only be used if your MariaDB/MySQL\nclients are very old (< 4.0.0).\n \nWith no FOR clause, this statement sets the password for the\ncurrent\nuser. Any client that has connected to the server using a\nnon-anonymous\naccount can change the password for that account.\n \nWith a FOR clause, this statement sets the password for a\nspecific\naccount on the current server host. Only clients that have\nthe UPDATE\nprivilege for the mysql database can do this. The user value\nshould be\ngiven in user_name@host_name format, where user_name and\nhost_name are\nexactly as they are listed in the User and Host columns of\nthe\nmysql.user table entry. \n \nThe argument to PASSWORD() and the password given to MariaDB\nclients can be of arbitrary length.\n \nAuthentication Plugin Support\n \nIn MariaDB 10.4 and later, SET PASSWORD (with or without\nPASSWORD()) works for accounts authenticated via any\nauthentication plugin that supports passwords stored in the\nmysql.global_priv table.\n \nThe ed25519, mysql_native_password, and mysql_old_password\nauthentication plugins store passwords in the\nmysql.global_priv table.\n \nIf you run SET PASSWORD on an account that authenticates\nwith one of these authentication plugins that stores\npasswords in the mysql.global_priv table, then the\nPASSWORD() function is evaluated by the specific\nauthentication plugin used by the account. The\nauthentication plugin hashes the password with a method that\nis compatible with that specific authentication plugin.\n \nThe unix_socket, named_pipe, gssapi, and pam authentication\nplugins do not store passwords in the mysql.global_priv\ntable. These authentication plugins rely on other methods to\nauthenticate the user.\n \nIf you attempt to run SET PASSWORD on an account that\nauthenticates with one of these authentication plugins that\ndoesn\'t store a password in the mysql.global_priv table,\nthen MariaDB Server will raise a warning like the following:\n \nSET PASSWORD is ignored for users authenticating via\nunix_socket plugin\n \nSee Authentication from MariaDB 10.4 for an overview of\nauthentication changes in MariaDB 10.4.\n \nMariaDB until 10.3\n \nIn MariaDB 10.3 and before, SET PASSWORD (with or without\nPASSWORD()) only works for accounts authenticated via\nmysql_native_password or mysql_old_password authentication\nplugins\n \nPasswordless User Accounts\n \nUser accounts do not always require passwords to login.\n \nThe unix_socket , named_pipe and gssapi authentication\nplugins do not require a password to authenticate the user.\n \nThe pam authentication plugin may or may not require a\npassword to authenticate the user, depending on the specific\nconfiguration.\n \nThe mysql_native_password and mysql_old_password\nauthentication plugins require passwords for authentication,\nbut the password can be blank. In that case, no password is\nrequired.\n \nIf you provide a password while attempting to log into the\nserver as an account that doesn\'t require a password, then\nMariaDB server will simply ignore the password.\n \nIn MariaDB 10.4 and later, a user account can be defined to\nuse multiple authentication plugins in a specific order of\npreference. This specific scenario may be more noticeable in\nthese versions, since an account could be associated with\nsome authentication plugins that require a password, and\nsome that do not.\n \nExample\n \nFor example, if you had an entry with User and\nHost column values of \'bob\' and \n\'%.loc.gov\', you would write the\nstatement like this:\n \nSET PASSWORD FOR \'bob\'@\'%.loc.gov\' =\nPASSWORD(\'newpass\');\n \n\n\nURL: https://mariadb.com/kb/en/set-password/','','https://mariadb.com/kb/en/set-password/'),(128,'DROP ROLE',10,'Roles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nDROP ROLE [IF EXISTS] role_name [,role_name ...]\n \nDescription\n----------- \nThe DROP ROLE statement removes one or more MariaDB roles.\nTo use this\nstatement, you must have the global CREATE USER privilege or\nthe DELETE privilege for the mysql database.\n \nDROP ROLE does not disable roles for connections which\nselected them with SET ROLE. If a role has previously been\nset as a default role, DROP ROLE does not remove the record\nof the default role from the mysql.user table. If the role\nis subsequently recreated and granted, it will again be the\nuser\'s default. Use SET DEFAULT ROLE NONE to explicitly\nremove this.\n \nIf any of the specified user accounts do not exist, ERROR\n1396 (HY000)\nresults. If an error occurs, DROP ROLE will still drop the\nroles that\ndo not result in an error. Only one error is produced for\nall roles which have not been dropped:\n \nERROR 1396 (HY000): Operation DROP ROLE failed for\n\'a\',\'b\',\'c\'\n \nFailed CREATE or DROP operations, for both users and roles,\nproduce the same error code.\n \nBefore MariaDB 10.1.13, the DROP ROLE statement was not\npermitted in prepared statements.\n \nIF EXISTS\n \nThe IF EXISTS clause was added in MariaDB 10.1.3\n \nIf the IF EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the role does not exist.\n \nExamples\n-------- \nDROP ROLE journalist;\n \nThe same thing using the optional IF EXISTS clause:\n \nDROP ROLE journalist;\n \nERROR 1396 (HY000): Operation DROP ROLE failed for\n\'journalist\'\n \nDROP ROLE IF EXISTS journalist;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nNote (Code 1975): Can\'t drop role \'journalist\'; it\ndoesn\'t exist\n \n\n\nURL: https://mariadb.com/kb/en/drop-role/','','https://mariadb.com/kb/en/drop-role/'),(200,'BENCHMARK',17,'Syntax\n------ \nBENCHMARK(count,expr)\n \nDescription\n----------- \nThe BENCHMARK() function executes the expression expr\nrepeatedly count\ntimes. It may be used to time how quickly MariaDB processes\nthe\nexpression. The result value is always 0. The intended use\nis from\nwithin the mysql client, which reports query execution\ntimes.\n \nExamples\n-------- \nSELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (0.21 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/benchmark/','','https://mariadb.com/kb/en/benchmark/'),(201,'BINLOG_GTID_POS',17,'From version 10.0.2, MariaDB supports global transaction IDs\nfor replication.\n \nSyntax\n------ \nBINLOG_GTID_POS(binlog_filename,binlog_offset)\n \nDescription\n----------- \nThe BINLOG_GTID_POS() function takes as input an old-style\nbinary log position in the form of a file name and a file\noffset. It looks up the position in the current binlog, and\nreturns a string representation of the corresponding GTID\nposition. If the position is not found in the current\nbinlog, NULL is returned.\n \nExamples\n-------- \nSELECT BINLOG_GTID_POS(\"master-bin.000001\", 600);\n \n\n\nURL: https://mariadb.com/kb/en/binlog_gtid_pos/','','https://mariadb.com/kb/en/binlog_gtid_pos/'),(204,'COLLATION',17,'Syntax\n------ \nCOLLATION(str)\n \nDescription\n----------- \nReturns the collation of the string argument. If str is not\na string, it is considered as a binary string (so the\nfunction returns \'binary\'). This applies to NULL, too. The\nreturn value is a string in the utf8 character set.\n \nSee Character Sets and Collations.\n \nExamples\n-------- \nSELECT COLLATION(\'abc\');\n+-------------------+\n| COLLATION(\'abc\') |\n+-------------------+\n| latin1_swedish_ci |\n+-------------------+\n \nSELECT COLLATION(_utf8\'abc\');\n+-----------------------+\n| COLLATION(_utf8\'abc\') |\n+-----------------------+\n| utf8_general_ci |\n+-----------------------+\n \n\n\nURL: https://mariadb.com/kb/en/collation/','','https://mariadb.com/kb/en/collation/'),(126,'Roles Overview',10,'Roles were introduced in MariaDB 10.0.5.\n \nDescription\n----------- \nA role bundles a number of privileges together. It assists\nlarger organizations where, typically, a number of users\nwould have the same privileges, and, previously, the only\nway to change the privileges for a group of users was by\nchanging each user\'s privileges individually. \n \nAlternatively, multiple external users could have been\nassigned the same user, and there would have been no way to\nsee which actual user was responsible for which action.\n \nWith roles, managing this is easy. For example, there could\nbe a number of users assigned to a journalist role, with\nidentical privileges. Changing the privileges for all the\njournalists is a matter of simply changing the role\'s\nprivileges, while the individual user is still linked with\nany changes that take place.\n \nRoles are created with the CREATE ROLE statement, and\ndropped with the DROP ROLE statement. Roles are then\nassigned to a user with an extension to the GRANT statement,\nwhile privileges are assigned to a role in the regular way\nwith GRANT. Similarly, the REVOKE statement can be used to\nboth revoke a role from a user, or revoke a privilege from a\nrole.\n \nOnce a user has connected, he can obtain all privileges\nassociated with a role by setting a role with the SET ROLE\nstatement. The CURRENT_ROLE function returns the currently\nset role for the session, if any.\n \nOnly roles granted directly to a user can be set, roles\ngranted to other roles cannot. Instead the privileges\ngranted to a role, which is, in turn, granted to another\nrole (grantee), will be immediately available to any user\nwho sets this second grantee role.\n \nRoles were implemented as a GSoC 2013 project by Vicentiu\nCiorbaru. \n \nThe SET DEFAULT ROLE statement allows one to set a default\nrole for a user. A default role is automatically enabled\nwhen a user connects (an implicit SET ROLE statement is\nexecuted immediately after a connection is established).\n \nSystem Tables\n \nInformation about roles and who they\'ve been granted to can\nbe found in the Information Schema APPLICABLE_ROLES table as\nwell as the mysql.ROLES_MAPPING table.\n \nThe Information Schema ENABLED_ROLES table shows the enabled\nroles for the current session.\n \nExamples\n-------- \nCreating a role and granting a privilege:\n \nCREATE ROLE journalist;\n \nGRANT SHOW DATABASES ON *.* TO journalist;\n \nGRANT journalist to hulda;\n \nNote, that hulda has no SHOW DATABASES privilege, even\nthough she was granted the journalist role. She needs to set\nthe role first:\n \nSHOW DATABASES;\n \n+--------------------+\n| Database |\n+--------------------+\n| information_schema |\n+--------------------+\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| NULL |\n+--------------+\n \nSET ROLE journalist;\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| journalist |\n+--------------+\n \nSHOW DATABASES;\n \n+--------------------+\n| Database |\n+--------------------+\n| ... |\n| information_schema |\n| mysql |\n| performance_schema |\n| test |\n| ... |\n+--------------------+\n \nSET ROLE NONE;\n \nRoles can be granted to roles:\n \nCREATE ROLE writer;\n \nGRANT SELECT ON data.* TO writer;\n \nGRANT writer TO journalist;\n \nBut one does not need to set a role granted to a role. For\nexample, hulda will automatically get all writer privileges\nwhen she sets the journalist role:\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| NULL |\n+--------------+\n \nSHOW TABLES FROM data;\n \nEmpty set (0.01 sec)\n \nSET ROLE journalist;\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| journalist |\n+--------------+\n \nSHOW TABLES FROM data;\n \n+------------------------------+\n| Tables_in_data |\n+------------------------------+\n| set1 |\n| ... |\n+------------------------------+\n \nRoles and Views (and Stored Routines)\n \nWhen a user sets a role, he, in a sense, has two identities\nwith two associated sets of privileges.\nBut a view (or a stored routine) can have only one definer.\nSo, when a view (or a stored routine) is created with the\nSQL SECURITY DEFINER, one can specify whether the definer\nshould be CURRENT_USER (and the view will have none of the\nprivileges of the user\'s role) or CURRENT_ROLE (in this\ncase, the view will use role\'s privileges, but none of the\nuser\'s privileges). As a result, sometimes one can create a\nview that is impossible to use.\n \nCREATE ROLE r1;\n \nGRANT ALL ON db1.* TO r1;\n \nGRANT r1 TO foo@localhost;\n \nGRANT ALL ON db.* TO foo@localhost;\n \nSELECT CURRENT_USER\n+---------------+\n| current_user |\n+---------------+\n| foo@localhost |\n+---------------+\n \nSET ROLE r1;\n \nCREATE TABLE db1.t1 (i int);\n \nCREATE VIEW db.v1 AS SELECT * FROM db1.t1;\n \nSHOW CREATE VIEW db.v1;\n \n+------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n| View | Create View | character_set_client |\ncollation_connection |\n+------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n| v1 | CREATE ALGORITHM=UNDEFINED DEFINER=`foo`@`localhost`\nSQL SECURITY DEFINER VIEW `db`.`v1` AS SELECT `db1`.`t1`.`i`\nAS `i` from `db1`.`t1` | utf8 | utf8_general_ci |\n+------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n \nCREATE DEFINER=CURRENT_ROLE VIEW db.v2 AS SELECT * FROM\ndb1.t1;\n \nSHOW CREATE VIEW db.b2;\n \n+------+-----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n| View | Create View | character_set_client |\ncollation_connection |\n+------+-----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n| v2 | CREATE ALGORITHM=UNDEFINED DEFINER=`r1` SQL SECURITY\nDEFINER VIEW `db`.`v2` AS select `db1`.`t1`.`a` AS `a` from\n`db1`.`t1` | utf8 | utf8_general_ci |\n+------+-----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+\n \nOther Resources\n \nRoles Review by Peter Gulutzan\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/roles_overview/','','https://mariadb.com/kb/en/roles_overview/'),(205,'CONNECTION_ID',17,'Syntax\n------ \nCONNECTION_ID()\n \nDescription\n----------- \nReturns the connection ID (thread ID) for the connection.\nEvery\nthread (including events) has an ID that is unique among the\nset of currently\nconnected clients.\n \nUntil MariaDB 10.3.1, returns MYSQL_TYPE_LONGLONG, or\nbigint(10), in all cases. From MariaDB 10.3.1, returns\nMYSQL_TYPE_LONG, or int(10), when the result would fit\nwithin 32-bits.\n \nExamples\n-------- \nSELECT CONNECTION_ID();\n+-----------------+\n| CONNECTION_ID() |\n+-----------------+\n| 3 |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/connection_id/','','https://mariadb.com/kb/en/connection_id/'),(216,'SCHEMA',17,'Syntax\n------ \nSCHEMA()\n \nDescription\n----------- \nThis function is a synonym for DATABASE().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/schema/','','https://mariadb.com/kb/en/schema/'),(129,'SET ROLE',10,'Roles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nSET ROLE { role | NONE }\n \nDescription\n----------- \nThe SET ROLE statement enables a role, along with all of its\nassociated permissions, for the current session. To unset a\nrole, use NONE .\n \nIf a role that doesn\'t exist, or to which the user has not\nbeen assigned, is specified, an ERROR 1959 (OP000): Invalid\nrole specification error occurs.\n \nFrom MariaDB 10.1.1, an automatic SET ROLE is implicitly\nperformed when a user connects if that user has been\nassigned a default role. See SET DEFAULT ROLE.\n \nExample\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| NULL |\n+--------------+\n \nSET ROLE staff;\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| staff |\n+--------------+\n \nSET ROLE NONE;\n \nQuery OK, 0 rows affected (0.00 sec)\n \nSELECT CURRENT_ROLE();\n+----------------+\n| CURRENT_ROLE() |\n+----------------+\n| NULL |\n+----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/set-role/','','https://mariadb.com/kb/en/set-role/'),(130,'SET DEFAULT ROLE',10,'Default roles were implemented in MariaDB 10.1.1.\n \nSyntax\n------ \nSET DEFAULT ROLE { role | NONE } [ FOR user@host ]\n \nDescription\n----------- \nThe SET DEFAULT ROLE statement sets a default role for a\nspecified (or current) user. A default role is automatically\nenabled when a user connects (an implicit SET ROLE statement\nis executed immediately after a connection is established).\n \nTo be able to set a role as a default, one needs the\nprivileges to enable this role (if you cannot do SET ROLE X,\nyou won\'t be able to do SET DEFAULT ROLE X). To set a\ndefault role for another user one needs to have write access\nto the mysql database.\n \nTo remove a user\'s default role, use SET DEFAULT ROLE NONE\n[ FOR user@host ]. The record of the default role is not\nremoved if the role is dropped or revoked, so if the role is\nsubsequently re-created or granted, it will again be the\nuser\'s default role.\n \nThe default role is stored in a new column in the mysql.user\ntable, and currently viewing this table is the only way to\nsee which role has been assigned to a user as the default. \n \nExamples\n-------- \nSetting a default role for the current user:\n \nSET DEFAULT ROLE journalist;\n \nRemoving a default role from the current user:\n \nSET DEFAULT ROLE NONE;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/set-default-role/','','https://mariadb.com/kb/en/set-default-role/'),(136,'AES_ENCRYPT',12,'Syntax\n------ \nAES_ENCRYPT(str,key_str)\n \nDescription\n----------- \nAES_ENCRYPT() and AES_DECRYPT() allow encryption and\ndecryption of\ndata using the official AES (Advanced Encryption Standard)\nalgorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit\nkey length is\nused, but you can extend it up to 256 bits by modifying the\nsource. We\nchose 128 bits because it is much faster and it is secure\nenough for\nmost purposes.\n \nAES_ENCRYPT() encrypts a string str using the key key_str,\nand returns a binary string.\n \nAES_DECRYPT() decrypts the encrypted string and returns the\noriginal\nstring.\n \nThe input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n \nBecause AES is a block-level algorithm, padding is used to\nencode\nuneven length strings and so the result string length may be\ncalculated using this formula:\n \n16 x (trunc(string_length / 16) + 1)\n \nIf AES_DECRYPT() detects invalid data or incorrect padding,\nit returns\nNULL. However, it is possible for AES_DECRYPT() to return a\nnon-NULL\nvalue (possibly garbage) if the input data or the key is\ninvalid.\n \nExamples\n-------- \nINSERT INTO t VALUES\n(AES_ENCRYPT(\'text\',SHA2(\'password\',512)));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/aes_encrypt/','','https://mariadb.com/kb/en/aes_encrypt/'),(137,'COMPRESS',12,'Syntax\n------ \nCOMPRESS(string_to_compress)\n \nDescription\n----------- \nCompresses a string and returns the result as a binary\nstring. This\nfunction requires MariaDB to have been compiled with a\ncompression\nlibrary such as zlib. Otherwise, the return value is always\nNULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n \nThe have_compress server system variable indicates whether a\ncompression library is present. \n \nExamples\n-------- \nSELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n+------------------------------------+\n| LENGTH(COMPRESS(REPEAT(\'a\',1000))) |\n+------------------------------------+\n| 21 |\n+------------------------------------+\n \nSELECT LENGTH(COMPRESS(\'\'));\n+----------------------+\n| LENGTH(COMPRESS(\'\')) |\n+----------------------+\n| 0 |\n+----------------------+\n \nSELECT LENGTH(COMPRESS(\'a\'));\n+-----------------------+\n| LENGTH(COMPRESS(\'a\')) |\n+-----------------------+\n| 13 |\n+-----------------------+\n \nSELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n+----------------------------------+\n| LENGTH(COMPRESS(REPEAT(\'a\',16))) |\n+----------------------------------+\n| 15 |\n+----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/compress/','','https://mariadb.com/kb/en/compress/'),(217,'SESSION_USER',17,'Syntax\n------ \nSESSION_USER()\n \nDescription\n----------- \nSESSION_USER() is a synonym for USER().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/session_user/','','https://mariadb.com/kb/en/session_user/'),(218,'SYSTEM_USER',17,'Syntax\n------ \nSYSTEM_USER()\n \nDescription\n----------- \nSYSTEM_USER() is a synonym for USER().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/system_user/','','https://mariadb.com/kb/en/system_user/'),(222,'<',18,'Syntax\n------ \n\n\nURL: https://mariadb.com/kb/en/less-than/','','https://mariadb.com/kb/en/less-than/'),(223,'<=',18,'Syntax\n------ \n\n\nURL: https://mariadb.com/kb/en/less-than-or-equal/','','https://mariadb.com/kb/en/less-than-or-equal/'),(228,'BETWEEN AND',18,'Syntax\n------ \nexpr BETWEEN min AND max\n \nDescription\n----------- \nIf expr is greater than or equal to min and expr is less\nthan or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is\nequivalent\nto the expression (min \n\nURL: https://mariadb.com/kb/en/between-and/','','https://mariadb.com/kb/en/between-and/'),(230,'GREATEST',18,'Syntax\n------ \nGREATEST(value1,value2,...)\n \nDescription\n----------- \nWith two or more arguments, returns the largest\n(maximum-valued)\nargument. The arguments are compared using the same rules as\nfor\nLEAST().\n \nExamples\n-------- \nSELECT GREATEST(2,0);\n+---------------+\n| GREATEST(2,0) |\n+---------------+\n| 2 |\n+---------------+\n \nSELECT GREATEST(34.0,3.0,5.0,767.0);\n+------------------------------+\n| GREATEST(34.0,3.0,5.0,767.0) |\n+------------------------------+\n| 767.0 |\n+------------------------------+\n \nSELECT GREATEST(\'B\',\'A\',\'C\');\n+-----------------------+\n| GREATEST(\'B\',\'A\',\'C\') |\n+-----------------------+\n| C |\n+-----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/greatest/','','https://mariadb.com/kb/en/greatest/'),(232,'INTERVAL',18,'Syntax\n------ \nINTERVAL(N,N1,N2,N3,...)\n \nDescription\n----------- \nReturns the index of the last argument that is less than the\nfirst argument or is NULL. \n \nReturns 0 if N < N1, 1 if N < N2, 2 if N < N3 and so on or\n-1 if N is NULL. All\narguments are treated as integers. It is required that N1 <\nN2 < N3 \n\nURL: https://mariadb.com/kb/en/interval/','','https://mariadb.com/kb/en/interval/'),(235,'IS NOT NULL',18,'Syntax\n------ \nIS NOT NULL\n \nDescription\n----------- \nTests whether a value is not NULL. See also NULL Values in\nMariaDB.\n \nExamples\n-------- \nSELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n+---------------+---------------+------------------+\n| 1 IS NOT NULL | 0 IS NOT NULL | NULL IS NOT NULL |\n+---------------+---------------+------------------+\n| 1 | 1 | 0 |\n+---------------+---------------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/is-not-null/','','https://mariadb.com/kb/en/is-not-null/'),(139,'DES_DECRYPT',12,'Syntax\n------ \nDES_DECRYPT(crypt_str[,key_str])\n \nDescription\n----------- \nDecrypts a string encrypted with DES_ENCRYPT(). If an error\noccurs,\nthis function returns NULL.\n \nThis function works only if MariaDB has been configured with\nTLS\nsupport.\n \nIf no key_str argument is given, DES_DECRYPT() examines the\nfirst byte\nof the encrypted string to determine the DES key number that\nwas used\nto encrypt the original string, and then reads the key from\nthe DES\nkey file to decrypt the message. For this to work, the user\nmust have\nthe SUPER privilege. The key file can be specified with the\n--des-key-file server option.\n \nIf you pass this function a key_str argument, that string is\nused as\nthe key for decrypting the message.\n \nIf the crypt_str argument does not appear to be an encrypted\nstring,\nMariaDB returns the given crypt_str.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/des_decrypt/','','https://mariadb.com/kb/en/des_decrypt/'),(140,'DES_ENCRYPT',12,'Syntax\n------ \nDES_ENCRYPT(str[,{key_num|key_str}])\n \nDescription\n----------- \nEncrypts the string with the given key using the Triple-DES\nalgorithm.\n \nThis function works only if MariaDB has been configured with\nTLS support.\n \nThe encryption key to use is chosen based on the second\nargument to\nDES_ENCRYPT(), if one was given. With no argument, the first\nkey from\nthe DES key file is used. With a key_num argument, the given\nkey \nnumber (0-9) from the DES key file is used. With a key_str\nargument,\nthe given key string is used to encrypt str. \n \nThe key file can be specified with the --des-key-file server\noption.\n \nThe return string is a binary string where the first\ncharacter is \nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT()\nreturns NULL.\n \nThe 128 is added to make it easier to recognize an encrypted\nkey. If\nyou use a string key, key_num is 127.\n \nThe string length for the result is given by this formula:\n \nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n \nEach line in the DES key file has the following format:\n \nkey_num des_key_str\n \nEach key_num value must be a number in the range from 0 to\n9. Lines in\nthe file may be in any order. des_key_str is the string that\nis used\nto encrypt the message. There should be at least one space\nbetween the\nnumber and the key. The first key is the default key that is\nused if\nyou do not specify any key argument to DES_ENCRYPT().\n \nYou can tell MariaDB to read new key values from the key\nfile with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD\nprivilege.\n \nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted\ncolumn\nvalues, without giving the end user the right to decrypt\nthose values.\n \nExamples\n-------- \nSELECT customer_address FROM customer_table \n WHERE crypted_credit_card =\nDES_ENCRYPT(\'credit_card_number\');\n \n\n\nURL: https://mariadb.com/kb/en/des_encrypt/','','https://mariadb.com/kb/en/des_encrypt/'),(141,'ENCODE',12,'Syntax\n------ \nENCODE(str,pass_str)\n \nDescription\n----------- \nENCODE is not considered cryptographically secure, and\nshould not be used for password encryption.\n \nEncrypt str using pass_str as the password. To decrypt the\nresult, use\nDECODE().\n \nThe result is a binary string of the same length as str.\n \nThe strength of the encryption is based on how good the\nrandom generator is. \n \nIt is not recommended to rely on the encryption performed by\nthe ENCODE function. Using a salt value (changed when a\npassword is updated) will improve matters somewhat, but for\nstoring passwords, consider a more cryptographically secure\nfunction, such as SHA2().\n \nExamples\n-------- \nENCODE(\'not so secret text\',\nCONCAT(\'random_salt\',\'password\'))\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/encode/','','https://mariadb.com/kb/en/encode/'),(142,'ENCRYPT',12,'Syntax\n------ \nENCRYPT(str[,salt])\n \nDescription\n----------- \nEncrypts a string using the Unix crypt() system call,\nreturning an encrypted binary string. The salt argument\nshould be a string with at least two characters or the\nreturned result will be NULL. If no salt argument is given,\na random value of sufficient length is used.\n \nIt is not recommended to use ENCRYPT() with utf16, utf32 or\nucs2 multi-byte character sets because the crypt() system\ncall expects a string terminated with a zero byte.\n \nNote that the underlying crypt() system call may have some\nlimitations, such as ignoring all but the first eight\ncharacters.\n \nIf the have_crypt system variable is set to NO (because the\ncrypt() system call is not available), the ENCRYPT function\nwill always return NULL.\n \nExamples\n-------- \nSELECT ENCRYPT(\'encrypt me\');\n+-----------------------+\n| ENCRYPT(\'encrypt me\') |\n+-----------------------+\n| 4I5BsEx0lqTDk |\n+-----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/encrypt/','','https://mariadb.com/kb/en/encrypt/'),(144,'OLD_PASSWORD',12,'Syntax\n------ \nOLD_PASSWORD(str)\n \nDescription\n----------- \nOLD_PASSWORD() was added to MySQL when the implementation of\n\nPASSWORD() was changed to improve security. OLD_PASSWORD()\nreturns the\nvalue of the old (pre-MySQL 4.1) implementation of\nPASSWORD() as a\nstring, and is intended to permit you to reset passwords for\nany\npre-4.1 clients that need to connect to a more recent MySQL\nserver version, or any version of MariaDB,\nwithout locking them out.\n \nAs of MariaDB 5.5, the return value is a nonbinary string in\nthe connection character set and collation, determined by\nthe values of the character_set_connection and\ncollation_connection system variables. Before 5.5, the\nreturn value was a binary string.\n \nThe return value is 16 bytes in length, or NULL if the\nargument was NULL.\n \n\n\nURL: https://mariadb.com/kb/en/old_password/','','https://mariadb.com/kb/en/old_password/'),(237,'ISNULL',18,'Syntax\n------ \nISNULL(expr)\n \nDescription\n----------- \nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n \nSee also NULL Values in MariaDB.\n \nExamples\n-------- \nSELECT ISNULL(1+1);\n+-------------+\n| ISNULL(1+1) |\n+-------------+\n| 0 |\n+-------------+\n \nSELECT ISNULL(1/0);\n+-------------+\n| ISNULL(1/0) |\n+-------------+\n| 1 |\n+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/isnull/','','https://mariadb.com/kb/en/isnull/'),(241,'Operator Precedence',19,'The precedence is the order in which the SQL operators are\nevaluated.\n \nThe following list shows the SQL operator precedence.\nOperators that appear first in the list have a higher\nprecedence. Operators which are listed together have the\nsame precedence.\nINTERVAL\nBINARY, COLLATE\n!\n- (unary minus), [[bitwise-not|]] (unary bit inversion)\n|| (string concatenation)\n^\n*, /, DIV, %, MOD\n-, +\n \n&\n|\n= (comparison), , >=, >, \n\nURL: https://mariadb.com/kb/en/operator-precedence/','','https://mariadb.com/kb/en/operator-precedence/'),(242,'&',19,'Syntax\n------ \n&\n \nDescription\n----------- \nBitwise AND. Converts the values to binary and compares\nbits. Only if both the corresponding bits are 1 is the\nresulting bit also 1.\n \nSee also bitwise OR.\n \nExamples\n-------- \nSELECT 2&1;\n+-----+\n| 2&1 |\n+-----+\n| 0 |\n+-----+\n \nSELECT 3&1;\n+-----+\n| 3&1 |\n+-----+\n| 1 |\n+-----+\n \nSELECT 29 & 15;\n+---------+\n| 29 & 15 |\n+---------+\n| 13 |\n+---------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bitwise_and/','','https://mariadb.com/kb/en/bitwise_and/'),(243,'<<',19,'Syntax\n------ \nvalue1 \n\nURL: https://mariadb.com/kb/en/shift-left/','','https://mariadb.com/kb/en/shift-left/'),(146,'SHA1',12,'Syntax\n------ \nSHA1(str), SHA(str)\n \nDescription\n----------- \nCalculates an SHA-1 160-bit checksum for the string str, as\ndescribed in\nRFC 3174 (Secure Hash Algorithm).\n \nThe value is returned as a string of 40 hex digits, or NULL\nif the argument was NULL. As of MariaDB 5.5, the return\nvalue is a nonbinary string in the connection character set\nand collation, determined by the values of the\ncharacter_set_connection and collation_connection system\nvariables. Before 5.5, the return value was a binary string.\n \nExamples\n-------- \nSELECT SHA1(\'some boring text\');\n+------------------------------------------+\n| SHA1(\'some boring text\') |\n+------------------------------------------+\n| af969fc2085b1bb6d31e517d5c456def5cdd7093 |\n+------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sha1/','','https://mariadb.com/kb/en/sha1/'),(147,'SHA2',12,'SHA2() was introduced in MariaDB 5.5\n \nSyntax\n------ \nSHA2(str,hash_len)\n \nDescription\n----------- \nGiven a string str, calculates an SHA-2 checksum, which is\nconsidered more cryptographically secure than its SHA-1\nequivalent. The SHA-2 family includes SHA-224, SHA-256,\nSHA-384, and SHA-512, and the hash_len must correspond to\none of these, i.e. 224, 256, 384 or 512. 0 is equivalent to\n256.\n \nThe return value is a nonbinary string in the connection\ncharacter set and collation, determined by the values of the\ncharacter_set_connection and collation_connection system\nvariables. \n \nNULL is returned if the hash length is not valid, or the\nstring str is NULL.\n \nSHA2 will only work if MariaDB was has been configured with\nTLS support. \n \nExamples\n-------- \nSELECT SHA2(\'Maria\',224);\n+----------------------------------------------------------+\n| SHA2(\'Maria\',224) |\n+----------------------------------------------------------+\n| 6cc67add32286412efcab9d0e1675a43a5c2ef3cec8879f81516ff83 |\n+----------------------------------------------------------+\n \nSELECT SHA2(\'Maria\',256);\n+------------------------------------------------------------------+\n| SHA2(\'Maria\',256) |\n+------------------------------------------------------------------+\n|\n9ff18ebe7449349f358e3af0b57cf7a032c1c6b2272cb2656ff85eb112232f16\n|\n+------------------------------------------------------------------+\n \nSELECT SHA2(\'Maria\',0);\n+------------------------------------------------------------------+\n| SHA2(\'Maria\',0) |\n+------------------------------------------------------------------+\n|\n9ff18ebe7449349f358e3af0b57cf7a032c1c6b2272cb2656ff85eb112232f16\n|\n+------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sha2/','','https://mariadb.com/kb/en/sha2/'),(148,'UNCOMPRESS',12,'Syntax\n------ \nUNCOMPRESS(string_to_uncompress)\n \nDescription\n----------- \nUncompresses a string compressed by the COMPRESS() function.\nIf the\nargument is not a compressed value, the result is NULL. This\nfunction\nrequires MariaDB to have been compiled with a compression\nlibrary such\nas zlib. Otherwise, the return value is always NULL. The\nhave_compress server system variable indicates whether a\ncompression library is present. \n \nExamples\n-------- \nSELECT UNCOMPRESS(COMPRESS(\'a string\'));\n+----------------------------------+\n| UNCOMPRESS(COMPRESS(\'a string\')) |\n+----------------------------------+\n| a string |\n+----------------------------------+\n \nSELECT UNCOMPRESS(\'a string\');\n+------------------------+\n| UNCOMPRESS(\'a string\') |\n+------------------------+\n| NULL |\n+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/uncompress/','','https://mariadb.com/kb/en/uncompress/'),(149,'UNCOMPRESSED_LENGTH',12,'Syntax\n------ \nUNCOMPRESSED_LENGTH(compressed_string)\n \nDescription\n----------- \nReturns the length that the compressed string had before\nbeing\ncompressed with COMPRESS().\n \nUNCOMPRESSED_LENGTH() returns NULL or an incorrect result if\nthe string is not compressed.\n \nUntil MariaDB 10.3.1, returns MYSQL_TYPE_LONGLONG, or\nbigint(10), in all cases. From MariaDB 10.3.1, returns\nMYSQL_TYPE_LONG, or int(10), when the result would fit\nwithin 32-bits.\n \nExamples\n-------- \nSELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n+-----------------------------------------------+\n| UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30))) |\n+-----------------------------------------------+\n| 30 |\n+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/uncompressed_length/','','https://mariadb.com/kb/en/uncompressed_length/'),(159,'INET6_ATON',14,'INET6_ATON() has been available since MariaDB 10.0.12.\n \nSyntax\n------ \nINET6_ATON(expr)\n \nDescription\n----------- \nGiven an IPv6 or IPv4 network address as a string, returns a\nbinary string that represents the numeric value of the\naddress.\n \nNo trailing zone ID\'s or traling network masks are\npermitted. For IPv4 addresses, or IPv6 addresses with IPv4\naddress parts, no classful addresses or trailing port\nnumbers are permitted and octal numbers are not supported.\n \nThe returned binary string will be VARBINARY(16) or\nVARBINARY(4) for IPv6 and IPv4 addresses respectively.\n \nReturns NULL if the argument is not understood.\n \nExamples\n-------- \nSELECT HEX(INET6_ATON(\'10.0.1.1\'));\n+-----------------------------+\n| HEX(INET6_ATON(\'10.0.1.1\')) |\n+-----------------------------+\n| 0A000101 |\n+-----------------------------+\n \nSELECT HEX(INET6_ATON(\'48f3::d432:1431:ba23:846f\'));\n+----------------------------------------------+\n| HEX(INET6_ATON(\'48f3::d432:1431:ba23:846f\')) |\n+----------------------------------------------+\n| 48F3000000000000D4321431BA23846F |\n+----------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/inet6_aton/','','https://mariadb.com/kb/en/inet6_aton/'),(244,'>>',19,'Syntax\n------ \nvalue1 >> value2\n \nDescription\n----------- \nConverts a longlong (BIGINT) number (value1) to binary and\nshifts value2 units to the right.\n \nExamples\n-------- \nSELECT 4 >> 2;\n+--------+\n| 4 >> 2 |\n+--------+\n| 1 |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/shift-right/','','https://mariadb.com/kb/en/shift-right/'),(245,'BIT_COUNT',19,'Syntax\n------ \nBIT_COUNT(N)\n \nDescription\n----------- \nReturns the number of bits that are set in the argument N.\n \nExamples\n-------- \nSELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n+---------------+----------------------+\n| BIT_COUNT(29) | BIT_COUNT(b\'101010\') |\n+---------------+----------------------+\n| 4 | 3 |\n+---------------+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bit_count/','','https://mariadb.com/kb/en/bit_count/'),(246,'^',19,'Syntax\n------ \n^\n \nDescription\n----------- \nBitwise XOR. Converts the values to binary and compares\nbits. If one (and only one) of the corresponding bits is 1\nis the resulting bit also 1.\n \nExamples\n-------- \nSELECT 1 ^ 1;\n+-------+\n| 1 ^ 1 |\n+-------+\n| 0 |\n+-------+\n \nSELECT 1 ^ 0;\n+-------+\n| 1 ^ 0 |\n+-------+\n| 1 |\n+-------+\n \nSELECT 11 ^ 3;\n+--------+\n| 11 ^ 3 |\n+--------+\n| 8 |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bitwise-xor/','','https://mariadb.com/kb/en/bitwise-xor/'),(247,'|',19,'Syntax\n------ \n|\n \nDescription\n----------- \nBitwise OR. Converts the values to binary and compares bits.\nIf either of the corresponding bits has a value of 1, the\nresulting bit is also 1.\n \nSee also bitwise AND.\n \nExamples\n-------- \nSELECT 2|1;\n+-----+\n| 2|1 |\n+-----+\n| 3 |\n+-----+\n \nSELECT 29 | 15;\n+---------+\n| 29 | 15 |\n+---------+\n| 31 |\n+---------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bitwise-or/','','https://mariadb.com/kb/en/bitwise-or/'),(158,'GET_LOCK',14,'Syntax\n------ \nGET_LOCK(str,timeout)\n \nDescription\n----------- \nTries to obtain a lock with a name given by the string str,\nusing a timeout of timeout seconds. Returns 1 if the lock\nwas obtained successfully, 0 if the attempt timed out (for\nexample, because another client has previously locked the\nname), or NULL if an error occurred (such as running out of\nmemory or the thread was killed with mysqladmin kill).\n \nA lock is released with RELEASE_LOCK(), when the connection\nterminates (either normally or abnormally), or before\nMariaDB 10.0.2, when the connection executes another\nGET_LOCK statement. From MariaDB 10.0.2, a connection can\nhold multiple locks at the same time, so a lock that is no\nlonger needed needs to be explicitly released.\n \nThe IS_FREE_LOCK function returns whether a specified lock a\nfree or not, and the IS_USED_LOCK whether the function is in\nuse or not.\n \nLocks obtained with GET_LOCK() do not interact with\ntransactions. That is, committing a transaction does not\nrelease any such locks obtained during the transaction.\n \nFrom MariaDB 10.0.2, it is also possible to recursively set\nthe same lock. If a lock with the same name is set n times,\nit needs to be released n times as well. \n \nstr is case insensitive for GET_LOCK() and related\nfunctions. If str is an empty string or NULL, GET_LOCK()\nreturns NULL and does nothing. From MariaDB 10.2.2, timeout\nsupports microseconds. Before then, it was rounded to the\nclosest integer.\n \nIf the metadata_lock_info plugin is installed, locks\nacquired with this function are visible in the Information\nSchema METADATA_LOCK_INFO table.\n \nThis function can be used to implement application locks or\nto simulate record locks. Names are locked on a server-wide\nbasis. If a name has been locked by one client, GET_LOCK()\nblocks any request by another client for a lock with the\nsame name. This allows clients that agree on a given lock\nname to use the name to perform cooperative advisory\nlocking. But be aware that it also allows a client that is\nnot among the set of cooperating clients to lock a name,\neither inadvertently or deliberately, and thus prevent any\nof the cooperating clients from locking that name. One way\nto reduce the likelihood of this is to use lock names that\nare database-specific or application-specific. For example,\nuse lock names of the form db_name.str or app_name.str.\n \nStatements using the GET_LOCK() function are not safe for\nreplication.\n \nThe patch to permit multiple locks was contributed by\nKonstantin \"Kostja\" Osipov (MDEV-3917).\n \nExamples\n-------- \nSELECT GET_LOCK(\'lock1\',10);\n+----------------------+\n| GET_LOCK(\'lock1\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT IS_FREE_LOCK(\'lock1\'), IS_USED_LOCK(\'lock1\');\n+-----------------------+-----------------------+\n| IS_FREE_LOCK(\'lock1\') | IS_USED_LOCK(\'lock1\') |\n+-----------------------+-----------------------+\n| 0 | 46 |\n+-----------------------+-----------------------+\n \nSELECT IS_FREE_LOCK(\'lock2\'), IS_USED_LOCK(\'lock2\');\n+-----------------------+-----------------------+\n| IS_FREE_LOCK(\'lock2\') | IS_USED_LOCK(\'lock2\') |\n+-----------------------+-----------------------+\n| 1 | NULL |\n+-----------------------+-----------------------+\n \nFrom MariaDB 10.0.2, multiple locks can be held:\n \nSELECT GET_LOCK(\'lock2\',10);\n+----------------------+\n| GET_LOCK(\'lock2\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT IS_FREE_LOCK(\'lock1\'), IS_FREE_LOCK(\'lock2\');\n+-----------------------+-----------------------+\n| IS_FREE_LOCK(\'lock1\') | IS_FREE_LOCK(\'lock2\') |\n+-----------------------+-----------------------+\n| 0 | 0 |\n+-----------------------+-----------------------+\n \nSELECT RELEASE_LOCK(\'lock1\'), RELEASE_LOCK(\'lock2\');\n+-----------------------+-----------------------+\n| RELEASE_LOCK(\'lock1\') | RELEASE_LOCK(\'lock2\') |\n+-----------------------+-----------------------+\n| 1 | 1 |\n+-----------------------+-----------------------+\n \nBefore MariaDB 10.0.2, a connection could only hold a single\nlock:\n \nSELECT GET_LOCK(\'lock2\',10);\n+----------------------+\n| GET_LOCK(\'lock2\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT IS_FREE_LOCK(\'lock1\'), IS_FREE_LOCK(\'lock2\');\n+-----------------------+-----------------------+\n| IS_FREE_LOCK(\'lock1\') | IS_FREE_LOCK(\'lock2\') |\n+-----------------------+-----------------------+\n| 1 | 0 |\n+-----------------------+-----------------------+\n \nSELECT RELEASE_LOCK(\'lock1\'), RELEASE_LOCK(\'lock2\');\n+-----------------------+-----------------------+\n| RELEASE_LOCK(\'lock1\') | RELEASE_LOCK(\'lock2\') |\n+-----------------------+-----------------------+\n| NULL | 1 |\n+-----------------------+-----------------------+\n \nFrom MariaDB 10.0.2, it is possible to hold the same lock\nrecursively. This example is viewed using the\nmetadata_lock_info plugin:\n \nSELECT GET_LOCK(\'lock3\',10);\n+----------------------+\n| GET_LOCK(\'lock3\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT GET_LOCK(\'lock3\',10);\n+----------------------+\n| GET_LOCK(\'lock3\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \n+-----------+---------------------+---------------+-----------+--------------+------------+\n| THREAD_ID | LOCK_MODE | LOCK_DURATION | LOCK_TYPE |\nTABLE_SCHEMA | TABLE_NAME |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n| 46 | MDL_SHARED_NO_WRITE | NULL | User lock | lock3 | |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n \nSELECT RELEASE_LOCK(\'lock3\');\n+-----------------------+\n| RELEASE_LOCK(\'lock3\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \n+-----------+---------------------+---------------+-----------+--------------+------------+\n| THREAD_ID | LOCK_MODE | LOCK_DURATION | LOCK_TYPE |\nTABLE_SCHEMA | TABLE_NAME |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n| 46 | MDL_SHARED_NO_WRITE | NULL | User lock | lock3 | |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n \nSELECT RELEASE_LOCK(\'lock3\');\n+-----------------------+\n| RELEASE_LOCK(\'lock3\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \nEmpty set (0.000 sec)\n \nTimeout example: Connection 1:\n \nSELECT GET_LOCK(\'lock4\',10);\n+----------------------+\n| GET_LOCK(\'lock4\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nConnection 2:\n \nSELECT GET_LOCK(\'lock4\',10);\n \nAfter 10 seconds...\n \n+----------------------+\n| GET_LOCK(\'lock4\',10) |\n+----------------------+\n| 0 |\n+----------------------+\n \nDeadlocks are automatically detected and resolved.\nConnection 1:\n \nSELECT GET_LOCK(\'lock5\',10); \n+----------------------+\n| GET_LOCK(\'lock5\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nConnection 2:\n \nSELECT GET_LOCK(\'lock6\',10);\n+----------------------+\n| GET_LOCK(\'lock6\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nConnection 1:\n \nSELECT GET_LOCK(\'lock6\',10); \n+----------------------+\n| GET_LOCK(\'lock6\',10) |\n+----------------------+\n| 0 |\n+----------------------+\n \nConnection 2:\n \nSELECT GET_LOCK(\'lock5\',10);\nERROR 1213 (40001): Deadlock found when trying to get lock;\n try restarting transaction\n \n\n\nURL: https://mariadb.com/kb/en/get_lock/','','https://mariadb.com/kb/en/get_lock/'),(160,'INET6_NTOA',14,'INET6_NTOA() has been available from MariaDB 10.0.12.\n \nSyntax\n------ \nINET6_NTOA(expr)\n \nDescription\n----------- \nGiven an IPv6 or IPv4 network address as a numeric binary\nstring, returns the address as a nonbinary string in the\nconnection character set.\n \nThe return string is lowercase, and is platform independent,\nsince it does not use functions specific to the operating\nsystem. It has a maximum length of 39 characters.\n \nReturns NULL if the argument is not understood.\n \nExamples\n-------- \nSELECT INET6_NTOA(UNHEX(\'0A000101\'));\n+-------------------------------+\n| INET6_NTOA(UNHEX(\'0A000101\')) |\n+-------------------------------+\n| 10.0.1.1 |\n+-------------------------------+\n \nSELECT\nINET6_NTOA(UNHEX(\'48F3000000000000D4321431BA23846F\'));\n+-------------------------------------------------------+\n| INET6_NTOA(UNHEX(\'48F3000000000000D4321431BA23846F\')) |\n+-------------------------------------------------------+\n| 48f3::d432:1431:ba23:846f |\n+-------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/inet6_ntoa/','','https://mariadb.com/kb/en/inet6_ntoa/'),(164,'IS_IPV4',14,'IS_IPV4() has been available since MariaDB 10.0.12.\n \nSyntax\n------ \nIS_IPV4(expr)\n \nDescription\n----------- \nIf the expression is a valid IPv4 address, returns 1,\notherwise returns 0.\n \nIS_IPV4() is stricter than INET_ATON(), but as strict as\nINET6_ATON(), in determining the validity of an IPv4\naddress. This implies that if IS_IPV4 returns 1, the same\nexpression will always return a non-NULL result when passed\nto INET_ATON(), but that the reverse may not apply.\n \nExamples\n-------- \nSELECT IS_IPV4(\'1110.0.1.1\');\n+-----------------------+\n| IS_IPV4(\'1110.0.1.1\') |\n+-----------------------+\n| 0 |\n+-----------------------+\n \nSELECT IS_IPV4(\'48f3::d432:1431:ba23:846f\');\n+--------------------------------------+\n| IS_IPV4(\'48f3::d432:1431:ba23:846f\') |\n+--------------------------------------+\n| 0 |\n+--------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/is_ipv4/','','https://mariadb.com/kb/en/is_ipv4/'),(165,'IS_IPV4_COMPAT',14,'IS_IPV4_COMPAT() has been available since MariaDB 10.0.12.\n \nSyntax\n------ \nIS_IPV4_COMPAT(expr)\n \nDescription\n----------- \nReturns 1 if a given numeric binary string IPv6 address,\nsuch as returned by INET6_ATON(), is IPv4-compatible,\notherwise returns 0. \n \nExamples\n-------- \nSELECT IS_IPV4_COMPAT(INET6_ATON(\'::10.0.1.1\'));\n+------------------------------------------+\n| IS_IPV4_COMPAT(INET6_ATON(\'::10.0.1.1\')) |\n+------------------------------------------+\n| 1 |\n+------------------------------------------+\n \nSELECT\nIS_IPV4_COMPAT(INET6_ATON(\'::48f3::d432:1431:ba23:846f\'));\n+-----------------------------------------------------------+\n|\nIS_IPV4_COMPAT(INET6_ATON(\'::48f3::d432:1431:ba23:846f\'))\n|\n+-----------------------------------------------------------+\n| 0 |\n+-----------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/is_ipv4_compat/','','https://mariadb.com/kb/en/is_ipv4_compat/'),(166,'IS_IPV4_MAPPED',14,'IS_IPV4_MAPPED() has been available since MariaDB 10.0.12.\n \nSyntax\n------ \nIS_IPV4_MAPPED(expr)\n \nDescription\n----------- \nReturns 1 if a given a numeric binary string IPv6 address,\nsuch as returned by INET6_ATON(), is a valid IPv4-mapped\naddress, otherwise returns 0.\n \nExamples\n-------- \nSELECT IS_IPV4_MAPPED(INET6_ATON(\'::10.0.1.1\'));\n+------------------------------------------+\n| IS_IPV4_MAPPED(INET6_ATON(\'::10.0.1.1\')) |\n+------------------------------------------+\n| 0 |\n+------------------------------------------+\n \nSELECT IS_IPV4_MAPPED(INET6_ATON(\'::ffff:10.0.1.1\'));\n+-----------------------------------------------+\n| IS_IPV4_MAPPED(INET6_ATON(\'::ffff:10.0.1.1\')) |\n+-----------------------------------------------+\n| 1 |\n+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/is_ipv4_mapped/','','https://mariadb.com/kb/en/is_ipv4_mapped/'),(170,'MASTER_POS_WAIT',14,'MASTER_POS_WAIT was introduced in MariaDB 10.0.9.\n \nSyntax\n------ \nMASTER_POS_WAIT(log_name,log_pos[,timeout,[\"connection_name\"]])\n \nDescription\n----------- \nThis function is useful in replication for controlling\nmaster/slave synchronization. It blocks until the slave has\nread and applied all updates up to the specified position\n(log_name,log_pos) in the master log. The return value is\nthe number of log events the slave had to wait for to\nadvance to the specified position. The function returns NULL\nif\nthe slave SQL thread is not started, the slave\'s master\ninformation is not\ninitialized, the arguments are incorrect, or an error\noccurs. It returns -1 if\nthe timeout has been exceeded. If the slave SQL thread stops\nwhile\n MASTER_POS_WAIT() is waiting, the function returns NULL. If\nthe slave is past the specified position, the function\nreturns immediately.\n \nIf a timeout value is specified, MASTER_POS_WAIT() stops\nwaiting when timeout seconds have elapsed. timeout must be\ngreater than 0; a\nzero or negative timeout means no timeout.\n \nThe connection_name is used when you are using\nmulti-source-replication. If you don\'t specify it, it\'s\nset to the value of the default_master_connection system\nvariable.\n \nStatements using the MASTER_POS_WAIT() function are not safe\nfor replication.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/master_pos_wait/','','https://mariadb.com/kb/en/master_pos_wait/'),(248,'~',19,'Syntax\n------ \n~\n \nDescription\n----------- \nBitwise NOT. Converts the value to 4 bytes binary and\ninverts all bits.\n \nExamples\n-------- \nSELECT 3 & ~1;\n+--------+\n| 3 & ~1 |\n+--------+\n| 2 |\n+--------+\n \nSELECT 5 & ~1;\n+--------+\n| 5 & ~1 |\n+--------+\n| 4 |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bitwise-not/','','https://mariadb.com/kb/en/bitwise-not/'),(250,'TRUE FALSE',19,'Description\n----------- \nThe constants TRUE and FALSE evaluate to 1 and 0,\nrespectively. The\nconstant names can be written in any lettercase.\n \nExamples\n-------- \nSELECT TRUE, true, FALSE, false;\n \n+------+------+-------+-------+\n| TRUE | TRUE | FALSE | FALSE |\n+------+------+-------+-------+\n| 1 | 1 | 0 | 0 |\n+------+------+-------+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/true-false/','','https://mariadb.com/kb/en/true-false/'),(253,'CHECK VIEW',20,'CHECK VIEW was introduced in MariaDB 10.0.18.\n \nSyntax\n------ \nCHECK VIEW view_name\n \nDescription\n----------- \nThe CHECK VIEW statement was introduced in MariaDB 10.0.18\nto assist with fixing MDEV-6916, an issue introduced in\nMariaDB 5.2 where the view algorithms were swapped. It\nchecks whether the view algorithm is correct. It is run as\npart of mysql_upgrade, and should not normally be required\nin regular use.\n \n\n\nURL: https://mariadb.com/kb/en/check-view/','','https://mariadb.com/kb/en/check-view/'),(254,'',20,'URL: https://mariadb.com/kb/en/checksum-table/','','https://mariadb.com/kb/en/checksum-table/'),(269,'BLOB and TEXT Data Types',22,'Description\n----------- \nA BLOB is a binary large object that can hold a variable\namount of\ndata. The four BLOB types are \nTINYBLOB,\nBLOB, \nMEDIUMBLOB, and\nLONGBLOB.\n \nThese differ only in the maximum length of the values they\ncan hold. \n \nThe TEXT types are \nTINYTEXT,\nTEXT,\nMEDIUMTEXT, and\nLONGTEXT.\nJSON (alias for LONGTEXT)\n \nThese correspond to the four BLOB types and have the same\nmaximum lengths and storage requirements.\n \nStarting from MariaDB 10.2.1, BLOB and TEXT columns can have\na DEFAULT value.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/blob-and-text-data-types/','','https://mariadb.com/kb/en/blob-and-text-data-types/'),(169,'MASTER_GTID_WAIT',14,'MASTER_GTID_WAIT() was included in MariaDB 10.0.9.\n \nSyntax\n------ \nMASTER_GTID_WAIT(gtid-list[, timeout)\n \nDescription\n----------- \nThis function takes a string containing a comma-separated\nlist of global transaction id\'s\n(similar to the value of, for example, gtid_binlog_pos). It\nwaits until the value of gtid_slave_pos has the same or\nhigher seq_no within all replication domains specified in\nthe gtid-list; in other words, it waits until the slave has\nreached the specified GTID position.\n \nAn optional second argument gives a timeout in seconds. If\nthe timeout\nexpires before the specified GTID position is reached, then\nthe function\nreturns -1. Passing NULL or a negative number for the\ntimeout means no timeout, and the function will wait\nindefinitely.\n \n If the wait completes without a timeout, 0 is returned.\nPassing NULL for the\n gtid-list makes the function return NULL immediately,\nwithout waiting.\n \nThe gtid-list may be the empty string, in which case\nMASTER_GTID_WAIT()\nreturns immediately. If the gtid-list contains fewer domains\nthan\ngtid_slave_pos, then only those domains are waited upon. If\ngtid-list\ncontains a domain that is not present in @@gtid_slave_pos,\nthen\nMASTER_GTID_WAIT() will wait until an event containing such\ndomain_id arrives\non the slave (or until timed out or killed).\n \nMASTER_GTID_WAIT() can be useful to ensure that a slave has\ncaught up to\na master. Simply take the value of gtid_binlog_pos on the\nmaster, and use it in a MASTER_GTID_WAIT() call on the\nslave; when the call completes, the slave\nwill have caught up with that master position.\n \nMASTER_GTID_WAIT() can also be used in client applications\ntogether with the\nlast_gtid session variable. This is useful in a\nread-scaleout replication setup, where the application\nwrites to a single master but divides the\nreads out to a number of slaves to distribute the load. In\nsuch a setup, there\nis a risk that an application could first do an update on\nthe master, and then\na bit later do a read on a slave, and if the slave is not\nfast enough, the\ndata read from the slave might not include the update just\nmade, possibly\nconfusing the application and/or the end-user. One way to\navoid this is to\nrequest the value of last_gtid on the master just after the\nupdate. Then\nbefore doing the read on the slave, do a MASTER_GTID_WAIT()\non the value\nobtained from the master; this will ensure that the read is\nnot performed\nuntil the slave has replicated sufficiently far for the\nupdate to have become\nvisible.\n \nNote that MASTER_GTID_WAIT() can be used even if the slave\nis configured not\nto use GTID for connections (CHANGE MASTER TO\nmaster_use_gtid=no). This is\nbecause from MariaDB 10, GTIDs are always logged on the\nmaster server, and\nalways recorded on the slave servers.\n \nDifferences to MASTER_POS_WAIT()\n \nMASTER_GTID_WAIT() is global; it waits for any master\nconnection to reach\n the specified GTID position. MASTER_POS_WAIT() works only\nagainst a\n specific connection. This also means that while\nMASTER_POS_WAIT() aborts if\n its master connection is terminated with STOP SLAVE or due\nto an error,\n MASTER_GTID_WAIT() continues to wait while slaves are\nstopped.\n \nMASTER_GTID_WAIT() can take its timeout as a floating-point\nvalue, so a\n timeout in fractional seconds is supported, eg.\nMASTER_GTID_WAIT(\"0-1-100\",\n 0.5). (The minimum wait is one microsecond, 0.000001\nseconds).\n \nMASTER_GTID_WAIT() allows one to specify a timeout of zero\nin order to do a\n non-blocking check to see if the slaves have progressed to\na specific GTID position\n (MASTER_POS_WAIT() takes a zero timeout as meaning an\ninfinite wait). To do\n an infinite MASTER_GTID_WAIT(), specify a negative timeout,\nor omit the\n timeout argument.\n \nMASTER_GTID_WAIT() does not return the number of events\nexecuted since the\n wait started, nor does it return NULL if a slave thread is\nstopped. It\n always returns either 0 for successful wait completed, or\n-1 for timeout\n reached (or NULL if the specified gtid-pos is NULL).\n \nSince MASTER_GTID_WAIT() looks only at the seq_no part of\nthe GTIDs, not the\nserver_id, care is needed if a slave becomes diverged from\nanother server so\nthat two different GTIDs with the same seq_no (in the same\ndomain) arrive at\nthe same server. This situation is in any case best avoided;\nsetting\ngtid_strict_mode is recommended, as this will prevent any\nsuch out-of-order sequence numbers from ever being\nreplicated on a slave.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/master_gtid_wait/','','https://mariadb.com/kb/en/master_gtid_wait/'),(174,'UUID',14,'Syntax\n------ \nUUID()\n \nDescription\n----------- \nReturns a Universal Unique Identifier (UUID) generated\naccording to \"DCE 1.1:\nRemote Procedure Call\" (Appendix A) CAE (Common\nApplications Environment)\nSpecifications published by The Open Group in October\n1997 \n(Document Number C706).\n \nA UUID is designed as a number that is globally unique in\nspace and time. Two\ncalls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate\ncomputers that are\nnot connected to each other.\n \nA UUID is a 128-bit number represented by a utf8 string of\nfive\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\nformat:\nThe first three numbers are generated from a timestamp.\nThe fourth number preserves temporal uniqueness in case the\ntimestamp value\n loses monotonicity (for example, due to daylight saving\ntime).\nThe fifth number is an IEEE 802 node number that provides\nspatial uniqueness.\n A random number is substituted if the latter is not\navailable (for example,\n because the host computer has no Ethernet card, or we do\nnot know how to find\n the hardware address of an interface on your operating\nsystem). In this case,\n spatial uniqueness cannot be guaranteed. Nevertheless, a\ncollision should\n have very low probability.\n \nCurrently, the MAC address of an interface is taken into\naccount only on FreeBSD and Linux. On other operating\nsystems, MariaDB uses a randomly generated 48-bit number.\n \nStatements using the UUID() function are not safe for\nreplication.\n \nUUID() results are intended to be unique, but cannot always\nbe relied upon to unpredictable and unguessable, so should\nnot be relied upon for these purposes.\n \nExamples\n-------- \nSELECT UUID();\n+--------------------------------------+\n| UUID() |\n+--------------------------------------+\n| cd41294a-afb0-11df-bc9b-00241dd75637 |\n+--------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/uuid/','','https://mariadb.com/kb/en/uuid/'),(272,'CHAR BYTE',22,'Description\n----------- \nThe CHAR BYTE data type is an alias for the \nBINARY data type. This is a\ncompatibility feature.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/char-byte/','','https://mariadb.com/kb/en/char-byte/'),(281,'LONGBLOB',22,'Syntax\n------ \nLONGBLOB\n \nDescription\n----------- \nA BLOB column with a \nmaximum length of 4,294,967,295 bytes or 4GB (232 - 1). The\neffective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol\nand\navailable memory. Each LONGBLOB value is stored using a\nfour-byte\nlength prefix that indicates the number of bytes in the\nvalue.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, BLOB is a synonym for\nLONGBLOB.\n \n\n\nURL: https://mariadb.com/kb/en/longblob/','','https://mariadb.com/kb/en/longblob/'),(282,'LONGTEXT',22,'Syntax\n------ \nLONGTEXT [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA TEXT column with a maximum length of 4,294,967,295 or 4GB\n(232 - 1) characters. The effective maximum length is less\nif the value contains multi-byte characters. The effective\nmaximum length of LONGTEXT columns also depends on the\nconfigured maximum packet size in the client/server protocol\nand available memory. Each LONGTEXT value is stored using a\nfour-byte length prefix that indicates the number of bytes\nin the value.\n \nFrom MariaDB 10.2.7, JSON is an alias for LONGTEXT. See JSON\nData Type for details.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, CLOB is a synonym for\nLONGTEXT.\n \n\n\nURL: https://mariadb.com/kb/en/longtext/','','https://mariadb.com/kb/en/longtext/'),(172,'RELEASE_LOCK',14,'Syntax\n------ \nRELEASE_LOCK(str)\n \nDescription\n----------- \nReleases the lock named by the string str that was obtained\nwith GET_LOCK(). Returns 1 if the lock was released, 0 if\nthe lock was not established by this thread (in which case\nthe lock is not\nreleased), and NULL if the named lock did not exist. The\nlock does not exist if it was never obtained by a call to\nGET_LOCK() or if it has previously been released.\n \nMariaDB until 10.0.1\n \nBefore 10.0.2, GET_LOCK() released the existing lock, if\nany. Since 10.0.2 this does not happen, because multiple\nlocks are allowed.\n \nstr is case insensitive. If str is an empty string or NULL,\nRELEASE_LOCK() returns NULL and does nothing.\n \nStatements using the RELEASE_LOCK() function are not safe\nfor replication.\n \nThe DO statement is convenient to use with RELEASE_LOCK().\n \nExamples\n-------- \nConnection1:\n \nSELECT GET_LOCK(\'lock1\',10);\n+----------------------+\n| GET_LOCK(\'lock1\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nConnection 2:\n \nSELECT GET_LOCK(\'lock2\',10);\n+----------------------+\n| GET_LOCK(\'lock2\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nConnection 1:\n \nSELECT RELEASE_LOCK(\'lock1\'), RELEASE_LOCK(\'lock2\'),\nRELEASE_LOCK(\'lock3\');\n+-----------------------+-----------------------+-----------------------+\n| RELEASE_LOCK(\'lock1\') | RELEASE_LOCK(\'lock2\') |\nRELEASE_LOCK(\'lock3\') |\n+-----------------------+-----------------------+-----------------------+\n| 1 | 0 | NULL |\n+-----------------------+-----------------------+-----------------------+\n \nFrom MariaDB 10.0.2, it is possible to hold the same lock\nrecursively. This example is viewed using the\nmetadata_lock_info plugin:\n \nSELECT GET_LOCK(\'lock3\',10);\n+----------------------+\n| GET_LOCK(\'lock3\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT GET_LOCK(\'lock3\',10);\n+----------------------+\n| GET_LOCK(\'lock3\',10) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \n+-----------+---------------------+---------------+-----------+--------------+------------+\n| THREAD_ID | LOCK_MODE | LOCK_DURATION | LOCK_TYPE |\nTABLE_SCHEMA | TABLE_NAME |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n| 46 | MDL_SHARED_NO_WRITE | NULL | User lock | lock3 | |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n \nSELECT RELEASE_LOCK(\'lock3\');\n+-----------------------+\n| RELEASE_LOCK(\'lock3\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \n+-----------+---------------------+---------------+-----------+--------------+------------+\n| THREAD_ID | LOCK_MODE | LOCK_DURATION | LOCK_TYPE |\nTABLE_SCHEMA | TABLE_NAME |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n| 46 | MDL_SHARED_NO_WRITE | NULL | User lock | lock3 | |\n+-----------+---------------------+---------------+-----------+--------------+------------+\n \nSELECT RELEASE_LOCK(\'lock3\');\n+-----------------------+\n| RELEASE_LOCK(\'lock3\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;\n \nEmpty set (0.000 sec)\n \n\n\nURL: https://mariadb.com/kb/en/release_lock/','','https://mariadb.com/kb/en/release_lock/'),(176,'VALUES / VALUE',14,'Syntax\n------ \nVALUE(col_name) \n \nMariaDB until 10.3.2\n \nVALUES(col_name) \n \nDescription\n----------- \nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can\nuse the VALUES(col_name) function in the UPDATE clause to\nrefer to column values from the INSERT portion of the\nstatement. In other words, VALUES(col_name) in the UPDATE\nclause refers to the value of col_name that would be\ninserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts.\n \nThe VALUES() function is meaningful only in INSERT ... ON\nDUPLICATE KEY UPDATE statements and returns NULL otherwise.\n \nIn MariaDB 10.3.3 this function was renamed to VALUE(),\nbecause it\'s incompatible with the standard Table Value\nConstructors syntax, implemented in MariaDB 10.3.3.\n \nThe VALUES() function can still be used even from MariaDB\n10.3.3, but only in INSERT ... ON DUPLICATE KEY UPDATE\nstatements; it\'s a syntax error otherwise.\n \nExamples\n-------- \nINSERT INTO t (a,b,c) VALUES (1,2,3),(4,5,6)\n ON DUPLICATE KEY UPDATE c=VALUE(a)+VALUE(b);\n \nMariaDB until 10.3.2\n \nINSERT INTO t (a,b,c) VALUES (1,2,3),(4,5,6)\n ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/values-value/','','https://mariadb.com/kb/en/values-value/'),(179,'||',15,'Syntax\n------ \nOR, ||\n \nDescription\n----------- \nLogical OR. When both operands are non-NULL, the result is 1\nif any\noperand is non-zero, and 0 otherwise. With a NULL operand,\nthe result\nis 1 if the other operand is non-zero, and NULL otherwise.\nIf both\noperands are NULL, the result is NULL.\n \nFor this operator, short-circuit evaluation can be used.\n \nNote that, if the PIPES_AS_CONCAT SQL_MODE is set, || is\nused as a string concatenation operator. This means that a\n|| b is the same as CONCAT(a,b). See CONCAT() for details.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, || ignores NULL.\n \nExamples\n-------- \nSELECT 1 || 1;\n \n+--------+\n| 1 || 1 |\n+--------+\n| 1 |\n+--------+\n \nSELECT 1 || 0;\n \n+--------+\n| 1 || 0 |\n+--------+\n| 1 |\n+--------+\n \nSELECT 0 || 0;\n \n+--------+\n| 0 || 0 |\n+--------+\n| 0 |\n+--------+\n \nSELECT 0 || NULL;\n \n+-----------+\n| 0 || NULL |\n+-----------+\n| NULL |\n+-----------+\n \nSELECT 1 || NULL;\n \n+-----------+\n| 1 || NULL |\n+-----------+\n| 1 |\n+-----------+\n \nIn Oracle mode, from MariaDB 10.3:\n \nSELECT 0 || NULL;\n \n+-----------+\n| 0 || NULL |\n+-----------+\n| 0 |\n+-----------+\n \n\n\nURL: https://mariadb.com/kb/en/or/','','https://mariadb.com/kb/en/or/'),(283,'MEDIUMBLOB',22,'Syntax\n------ \nMEDIUMBLOB\n \nDescription\n----------- \nA BLOB column with a maximum\nlength of 16,777,215 (224 - 1) bytes.\nEach MEDIUMBLOB value is stored using a three-byte length\nprefix that\nindicates the number of bytes in the value. \n \n\n\nURL: https://mariadb.com/kb/en/mediumblob/','','https://mariadb.com/kb/en/mediumblob/'),(285,'MEDIUMTEXT',22,'Syntax\n------ \nMEDIUMTEXT [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA TEXT column with a \nmaximum length of 16,777,215 (224 - 1)\ncharacters. The effective maximum length is less if the\nvalue\ncontains multi-byte characters. Each MEDIUMTEXT value is\nstored using\na three-byte length prefix that indicates the number of\nbytes in the\nvalue.\n \n\n\nURL: https://mariadb.com/kb/en/mediumtext/','','https://mariadb.com/kb/en/mediumtext/'),(287,'ROW',22,'The ROW data type was introduced in MariaDB 10.3.0.\n \nSyntax\n------ \nROW ( [{, }... ])\n \nDescription\n----------- \nROW is a data type for stored procedure variables.\n \nFeatures\n \nROW fields as normal variables\n \nROW fields (members) act as normal variables, and are able\nto appear in all\nquery parts where a stored procedure variable is allowed:\nAssignment is using the := operator and the SET command:\n \na.x:= 10;\n \na.x:= b.x;\n \nSET a.x= 10, a.y=20, a.z= b.z;\n \nPassing to functions and operators:\n \nSELECT f1(rec.a), rec.a\n\nURL: https://mariadb.com/kb/en/row/','','https://mariadb.com/kb/en/row/'),(288,'SET Data Type',22,'Syntax\n------ \nSET(\'value1\',\'value2\',...) [CHARACTER SET charset_name]\n[COLLATE collation_name]\n \nDescription\n----------- \nA set. A string object that can have zero or more values,\neach of\nwhich must be chosen from the list of values \'value1\',\n\'value2\', ... A\nSET column can have a maximum of 64 members. SET values are\nrepresented internally as integers.\n \n\n\nURL: https://mariadb.com/kb/en/set-data-type/','','https://mariadb.com/kb/en/set-data-type/'),(181,'Assignment Operator (=)',15,'Syntax\n------ \nidentifier = expr\n \nDescription\n----------- \nThe equal sign is used as both an assignment operator in\ncertain contexts, and as a comparison operator. When used as\nassignment operator, the value on the right is assigned to\nthe variable (or column, in some contexts) on the left.\n \nSince its use can be ambiguous, unlike the := assignment\noperator, the = assignment operator cannot be used in all\ncontexts, and is only valid as part of a SET statement, or\nthe SET clause of an UPDATE statement\n \nThis operator works with both user-defined variables and\nlocal variables.\n \nExamples\n-------- \nUPDATE table_name SET x = 2 WHERE x > 100;\n \nSET @x = 1, @y := 2;\n \n\n \n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/assignment-operators-assignment-operator/','','https://mariadb.com/kb/en/assignment-operators-assignment-operator/'),(183,'Stored Aggregate Functions',16,'The ability to create stored aggregate functions was added\nin MariaDB 10.3.3.\n \nAggregate functions are functions that are computed over a\nsequence of rows and return one result for the sequence of\nrows.\n \nCreating a custom aggregate function is done using the\nCREATE FUNCTION statement with two main differences:\nThe addition of the AGGREGATE keyword, so CREATE AGGREGATE\nFUNCTION\nThe FETCH GROUP NEXT ROW instruction inside the loop\nOracle PL/SQL compatibility using SQL/PL is provided\n \nStandard Syntax\n \nCREATE AGGREGATE FUNCTION function_name (parameters) RETURNS\nreturn_type\nBEGIN\n All types of declarations\n DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN return_val;\n LOOP\n FETCH GROUP NEXT ROW; // fetches next row from table\n other instructions\n END LOOP;\nEND\n \nStored aggregate functions were a 2016 Google Summer of Code\nproject by Varun Gupta.\n \nUsing SQL/PL\n \nSET sql_mode=Oracle;\nDELIMITER //\n \nCREATE AGGREGATE FUNCTION function_name (parameters) RETURN\nreturn_type\n declarations\nBEGIN\n LOOP\n FETCH GROUP NEXT ROW; -- fetches next row from table\n -- other instructions\n \n END LOOP;\nEXCEPTION\n WHEN NO_DATA_FOUND THEN\n RETURN return_val;\nEND //\n \nDELIMITER ;\n \nExamples\n-------- \nFirst a simplified example:\n \nCREATE TABLE marks(stud_id INT, grade_count INT);\n \nINSERT INTO marks VALUES (1,6), (2,4), (3,7), (4,5), (5,8);\n \nSELECT * FROM marks;\n \n+---------+-------------+\n| stud_id | grade_count |\n+---------+-------------+\n| 1 | 6 |\n| 2 | 4 |\n| 3 | 7 |\n| 4 | 5 |\n| 5 | 8 |\n+---------+-------------+\n \nDELIMITER //\nCREATE AGGREGATE FUNCTION IF NOT EXISTS aggregate_count(x\nINT) RETURNS INT\nBEGIN\n DECLARE count_students INT DEFAULT 0;\n \n DECLARE CONTINUE HANDLER FOR NOT FOUND\n RETURN count_students;\n \n LOOP\n FETCH GROUP NEXT ROW;\n \n IF x THEN\n SET count_students = count_students+1;\n \n END IF;\n \n END LOOP;\n \nEND //\nDELIMITER ;\n \nA non-trivial example that cannot easily be rewritten using\nexisting functions:\n \nDELIMITER //\nCREATE AGGREGATE FUNCTION medi_int(x INT) RETURNS DOUBLE\nBEGIN\n DECLARE CONTINUE HANDLER FOR NOT FOUND\n BEGIN\n DECLARE res DOUBLE;\n \n DECLARE cnt INT DEFAULT (SELECT COUNT(*) FROM tt);\n DECLARE lim INT DEFAULT (cnt-1) DIV 2;\n \n IF cnt % 2 = 0 THEN\n SET res = (SELECT AVG(a) FROM (SELECT a FROM tt ORDER BY a\nLIMIT lim,2) ttt);\n ELSE\n SET res = (SELECT a FROM tt ORDER BY a LIMIT lim,1);\n END IF;\n \n DROP TEMPORARY TABLE tt;\n \n RETURN res;\n \n END;\n \n CREATE TEMPORARY TABLE tt (a INT);\n LOOP\n FETCH GROUP NEXT ROW;\n \n INSERT INTO tt VALUES (x);\n END LOOP;\n \nEND //\nDELIMITER ;\n \nSQL/PL Example\n \nThis uses the same marks table as created above.\n \nSET sql_mode=Oracle;\n \nDELIMITER //\n \nCREATE AGGREGATE FUNCTION aggregate_count(x INT) RETURN INT\nAS count_students INT DEFAULT 0;\n \nBEGIN\n LOOP\n FETCH GROUP NEXT ROW;\n \n IF x THEN\n SET count_students := count_students+1;\n \n END IF;\n \n END LOOP;\n \nEXCEPTION\n WHEN NO_DATA_FOUND THEN\n RETURN count_students;\n \nEND aggregate_count //\nDELIMITER ;\n \nSELECT aggregate_count(stud_id) FROM marks;\n \n\n\nURL: https://mariadb.com/kb/en/stored-aggregate-functions/','','https://mariadb.com/kb/en/stored-aggregate-functions/'),(184,'AVG',16,'Syntax\n------ \nAVG([DISTINCT] expr)\n \nDescription\n----------- \nReturns the average value of expr. The DISTINCT option can\nbe used to return the average of the distinct values of\nexpr. NULL values are ignored. It is an aggregate function,\nand so can be used with the GROUP BY clause.\n \nAVG() returns NULL if there were no matching rows.\n \nFrom MariaDB 10.2.0, AVG() can be used as a window function.\n \nExamples\n-------- \nCREATE TABLE sales (sales_value INT);\n \nINSERT INTO sales VALUES(10),(20),(20),(40);\n \nSELECT AVG(sales_value) FROM sales;\n \n+------------------+\n| AVG(sales_value) |\n+------------------+\n| 22.5000 |\n+------------------+\n \nSELECT AVG(DISTINCT(sales_value)) FROM sales;\n \n+----------------------------+\n| AVG(DISTINCT(sales_value)) |\n+----------------------------+\n| 23.3333 |\n+----------------------------+\n \nCommonly, AVG() is used with a GROUP BY clause:\n \nCREATE TABLE student (name CHAR(10), test CHAR(10), score\nTINYINT); \n \nINSERT INTO student VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nSELECT name, AVG(score) FROM student GROUP BY name;\n \n+---------+------------+\n| name | AVG(score) |\n+---------+------------+\n| Chun | 74.0000 |\n| Esben | 37.0000 |\n| Kaolin | 72.0000 |\n| Tatiana | 85.0000 |\n+---------+------------+\n \nBe careful to avoid this common mistake, not grouping\ncorrectly and returning mismatched data: \n \nSELECT name,test,AVG(score) FROM student;\n \n+------+------+------------+\n| name | test | MIN(score) |\n+------+------+------------+\n| Chun | SQL | 31 |\n+------+------+------------+\n \nAs a window function:\n \nCREATE TABLE student_test (name CHAR(10), test CHAR(10),\nscore TINYINT); \n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nSELECT name, test, score, AVG(score) OVER (PARTITION BY\ntest) \n AS average_by_test FROM student_test;\n \n+---------+--------+-------+-----------------+\n| name | test | score | average_by_test |\n+---------+--------+-------+-----------------+\n| Chun | SQL | 75 | 65.2500 |\n| Chun | Tuning | 73 | 68.7500 |\n| Esben | SQL | 43 | 65.2500 |\n| Esben | Tuning | 31 | 68.7500 |\n| Kaolin | SQL | 56 | 65.2500 |\n| Kaolin | Tuning | 88 | 68.7500 |\n| Tatiana | SQL | 87 | 65.2500 |\n| Tatiana | Tuning | 83 | 68.7500 |\n+---------+--------+-------+-----------------+\n \n\n\nURL: https://mariadb.com/kb/en/avg/','','https://mariadb.com/kb/en/avg/'),(293,'TIMESTAMP',22,'Syntax\n------ \nTIMESTAMP [(\n\nURL: https://mariadb.com/kb/en/timestamp/','','https://mariadb.com/kb/en/timestamp/'),(294,'TINYBLOB',22,'Syntax\n------ \nTINYBLOB\n \nDescription\n----------- \nA BLOB column with a maximum length of \n255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a one-byte length prefix that\nindicates\nthe number of bytes in the value.\n \n\n\nURL: https://mariadb.com/kb/en/tinyblob/','','https://mariadb.com/kb/en/tinyblob/'),(296,'TINYTEXT',22,'Syntax\n------ \nTINYTEXT [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA TEXT column with a maximum length of 255 (28 - 1)\ncharacters. The effective maximum length is less if the\nvalue contains multi-byte characters. Each TINYTEXT value is\nstored using a one-byte length prefix that indicates the\nnumber of bytes in the value.\n \n\n\nURL: https://mariadb.com/kb/en/tinytext/','','https://mariadb.com/kb/en/tinytext/'),(185,'BIT_AND',16,'Syntax\n------ \nBIT_AND(expr)\n \nDescription\n----------- \nReturns the bitwise AND of all bits in expr. The calculation\nis performed with 64-bit (BIGINT) precision. It is an\naggregate function, and so can be used with the GROUP BY\nclause.\n \nFrom MariaDB 10.2.0, BIT_AND() can be used as a window\nfunction.\n \nExamples\n-------- \nCREATE TABLE vals (x INT);\n \nINSERT INTO vals VALUES(111),(110),(100);\n \nSELECT BIT_AND(x), BIT_OR(x), BIT_XOR(x) FROM vals;\n \n+------------+-----------+------------+\n| BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+------------+-----------+------------+\n| 100 | 111 | 101 |\n+------------+-----------+------------+\n \nAs an aggregate function:\n \nCREATE TABLE vals2 (category VARCHAR(1), x INT);\n \nINSERT INTO vals2 VALUES\n (\'a\',111),(\'a\',110),(\'a\',100),\n (\'b\',\'000\'),(\'b\',001),(\'b\',011);\n \nSELECT category, BIT_AND(x), BIT_OR(x), BIT_XOR(x) \n FROM vals GROUP BY category;\n \n+----------+------------+-----------+------------+\n| category | BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+----------+------------+-----------+------------+\n| a | 100 | 111 | 101 |\n| b | 0 | 11 | 10 |\n+----------+------------+-----------+------------+\n \n\n\nURL: https://mariadb.com/kb/en/bit_and/','','https://mariadb.com/kb/en/bit_and/'),(186,'BIT_OR',16,'Syntax\n------ \nBIT_OR(expr)\n \nDescription\n----------- \nReturns the bitwise OR of all bits in expr. The calculation\nis performed with 64-bit (BIGINT) precision. It is an\naggregate function, and so can be used with the GROUP BY\nclause.\n \nFrom MariaDB 10.2.0, BIT_OR can be used as a window\nfunction.\n \nExamples\n-------- \nCREATE TABLE vals (x INT);\n \nINSERT INTO vals VALUES(111),(110),(100);\n \nSELECT BIT_AND(x), BIT_OR(x), BIT_XOR(x) FROM vals;\n \n+------------+-----------+------------+\n| BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+------------+-----------+------------+\n| 100 | 111 | 101 |\n+------------+-----------+------------+\n \nAs an aggregate function:\n \nCREATE TABLE vals2 (category VARCHAR(1), x INT);\n \nINSERT INTO vals2 VALUES\n (\'a\',111),(\'a\',110),(\'a\',100),\n (\'b\',\'000\'),(\'b\',001),(\'b\',011);\n \nSELECT category, BIT_AND(x), BIT_OR(x), BIT_XOR(x) \n FROM vals GROUP BY category;\n \n+----------+------------+-----------+------------+\n| category | BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+----------+------------+-----------+------------+\n| a | 100 | 111 | 101 |\n| b | 0 | 11 | 10 |\n+----------+------------+-----------+------------+\n \n\n\nURL: https://mariadb.com/kb/en/bit_or/','','https://mariadb.com/kb/en/bit_or/'),(187,'BIT_XOR',16,'Syntax\n------ \nBIT_XOR(expr)\n \nDescription\n----------- \nReturns the bitwise XOR of all bits in expr. The calculation\nis performed with 64-bit (BIGINT) precision. It is an\naggregate function, and so can be used with the GROUP BY\nclause.\n \nFrom MariaDB 10.2.0, BIT_XOR() can be used as a window\nfunction.\n \nExamples\n-------- \nCREATE TABLE vals (x INT);\n \nINSERT INTO vals VALUES(111),(110),(100);\n \nSELECT BIT_AND(x), BIT_OR(x), BIT_XOR(x) FROM vals;\n \n+------------+-----------+------------+\n| BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+------------+-----------+------------+\n| 100 | 111 | 101 |\n+------------+-----------+------------+\n \nAs an aggregate function:\n \nCREATE TABLE vals2 (category VARCHAR(1), x INT);\n \nINSERT INTO vals2 VALUES\n (\'a\',111),(\'a\',110),(\'a\',100),\n (\'b\',\'000\'),(\'b\',001),(\'b\',011);\n \nSELECT category, BIT_AND(x), BIT_OR(x), BIT_XOR(x) \n FROM vals GROUP BY category;\n \n+----------+------------+-----------+------------+\n| category | BIT_AND(x) | BIT_OR(x) | BIT_XOR(x) |\n+----------+------------+-----------+------------+\n| a | 100 | 111 | 101 |\n| b | 0 | 11 | 10 |\n+----------+------------+-----------+------------+\n \n\n\nURL: https://mariadb.com/kb/en/bit_xor/','','https://mariadb.com/kb/en/bit_xor/'),(188,'COUNT',16,'Syntax\n------ \nCOUNT(expr)\n \nDescription\n----------- \nReturns a count of the number of non-NULL values of expr in\nthe rows retrieved by a SELECT statement. The result is a\nBIGINT value. It is an aggregate function, and so can be\nused with the GROUP BY clause.\n \nCOUNT(*) counts the total number of rows in a table.\n \nCOUNT() returns 0 if there were no matching rows.\n \nFrom MariaDB 10.2.0, COUNT() can be used as a window\nfunction.\n \nExamples\n-------- \nCREATE TABLE student (name CHAR(10), test CHAR(10), score\nTINYINT); \n \nINSERT INTO student VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nSELECT COUNT(*) FROM student;\n \n+----------+\n| COUNT(*) |\n+----------+\n| 8 |\n+----------+\n \nCOUNT(DISTINCT) example:\n \nSELECT COUNT(DISTINCT (name)) FROM student;\n \n+------------------------+\n| COUNT(DISTINCT (name)) |\n+------------------------+\n| 4 |\n+------------------------+\n \nAs a window function\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, COUNT(score) OVER (PARTITION BY\nname) \n AS tests_written FROM student_test;\n \n+---------+--------+-------+---------------+\n| name | test | score | tests_written |\n+---------+--------+-------+---------------+\n| Chun | SQL | 75 | 2 |\n| Chun | Tuning | 73 | 2 |\n| Esben | SQL | 43 | 2 |\n| Esben | Tuning | 31 | 2 |\n| Kaolin | SQL | 56 | 2 |\n| Kaolin | Tuning | 88 | 2 |\n| Tatiana | SQL | 87 | 1 |\n+---------+--------+-------+---------------+\n \n\n\nURL: https://mariadb.com/kb/en/count/','','https://mariadb.com/kb/en/count/'),(302,'CLOSE',23,'Syntax\n------ \nCLOSE cursor_name\n \nDescription\n----------- \nThis statement closes a previously opened cursor. The cursor\nmust have been previously opened or else an error occurs.\n \nIf not closed explicitly, a cursor is closed at the end of\nthe\ncompound statement in which it was declared.\n \nSee Cursor Overview for an example.\n \n\n\nURL: https://mariadb.com/kb/en/close/','','https://mariadb.com/kb/en/close/'),(304,'DECLARE CURSOR',23,'Syntax\n------ \n\n\nURL: https://mariadb.com/kb/en/declare-cursor/','','https://mariadb.com/kb/en/declare-cursor/'),(307,'FETCH',23,'Syntax\n------ \nFETCH cursor_name INTO var_name [, var_name] ...\n \nDescription\n----------- \nThis statement fetches the next row (if a row exists) using\nthe\nspecified open cursor, and advances the cursor pointer.\n \nvar_name can be a local variable, but not a user-defined\nvariable.\n \nIf no more rows are available, a No Data condition occurs\nwith\nSQLSTATE value 02000. To detect this condition, you can set\nup a\nhandler for it (or for a NOT FOUND condition).\n \nSee Cursor Overview for an example.\n \n\n\nURL: https://mariadb.com/kb/en/fetch/','','https://mariadb.com/kb/en/fetch/'),(309,'GOTO',23,'The GOTO statement was introduced in MariaDB 10.3 for Oracle\ncompatibility.\n \nSyntax\n------ \nGOTO label\n \nDescription\n----------- \nThe GOTO statement causes the code to jump to the specified\nlabel, and continue operating from there. It is only\naccepted when in Oracle mode.\n \nExample\n \nSET sql_mode=ORACLE;\n \nDELIMITER //\n \nCREATE OR REPLACE PROCEDURE p1 AS\n \nBEGIN\n \n SELECT 1;\n \n GOTO label;\n \n SELECT 2;\n \n SELECT 3;\n \nEND;\n \n//\n \nDELIMITER \n \ncall p1();\n+---+\n| 1 |\n+---+\n| 1 |\n+---+\n1 row in set (0.000 sec)\n \n+---+\n| 3 |\n+---+\n| 3 |\n+---+\n1 row in set (0.000 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/goto/','','https://mariadb.com/kb/en/goto/'),(190,'MAX',16,'Syntax\n------ \nMAX([DISTINCT] expr)\n \nDescription\n----------- \nReturns the largest, or maximum, value of expr. MAX() can\nalso take a string\nargument in which case it returns the maximum string value.\nThe DISTINCT\nkeyword can be used to find the maximum of the distinct\nvalues of expr,\nhowever, this produces the same result as omitting DISTINCT.\n \nNote that SET and ENUM fields are currently compared by\ntheir string value rather than their relative position in\nthe set, so MAX() may produce a different highest result\nthan ORDER BY DESC.\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, MAX() can be used as a window function.\n \nMAX() returns NULL if there were no matching rows.\n \nExamples\n-------- \nCREATE TABLE student (name CHAR(10), test CHAR(10), score\nTINYINT); \n \nINSERT INTO student VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nSELECT name, MAX(score) FROM student GROUP BY name;\n \n+---------+------------+\n| name | MAX(score) |\n+---------+------------+\n| Chun | 75 |\n| Esben | 43 |\n| Kaolin | 88 |\n| Tatiana | 87 |\n+---------+------------+\n \nMAX string:\n \nSELECT MAX(name) FROM student;\n \n+-----------+\n| MAX(name) |\n+-----------+\n| Tatiana |\n+-----------+\n \nBe careful to avoid this common mistake, not grouping\ncorrectly and returning mismatched data: \n \nSELECT name,test,MAX(SCORE) FROM student;\n \n+------+------+------------+\n| name | test | MAX(SCORE) |\n+------+------+------------+\n| Chun | SQL | 88 |\n+------+------+------------+\n \nDifference between ORDER BY DESC and MAX():\n \nCREATE TABLE student2(name CHAR(10),grade\nENUM(\'b\',\'c\',\'a\'));\n \nINSERT INTO student2\nVALUES(\'Chun\',\'b\'),(\'Esben\',\'c\'),(\'Kaolin\',\'a\');\n \nSELECT MAX(grade) FROM student2;\n \n+------------+\n| MAX(grade) |\n+------------+\n| c |\n+------------+\n \nSELECT grade FROM student2 ORDER BY grade DESC LIMIT 1;\n \n+-------+\n| grade |\n+-------+\n| a |\n+-------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, MAX(score) \n OVER (PARTITION BY name) AS highest_score FROM\nstudent_test;\n \n+---------+--------+-------+---------------+\n| name | test | score | highest_score |\n+---------+--------+-------+---------------+\n| Chun | SQL | 75 | 75 |\n| Chun | Tuning | 73 | 75 |\n| Esben | SQL | 43 | 43 |\n| Esben | Tuning | 31 | 43 |\n| Kaolin | SQL | 56 | 88 |\n| Kaolin | Tuning | 88 | 88 |\n| Tatiana | SQL | 87 | 87 |\n+---------+--------+-------+---------------+\n \n\n\nURL: https://mariadb.com/kb/en/max/','','https://mariadb.com/kb/en/max/'),(191,'MIN',16,'Syntax\n------ \nMIN([DISTINCT] expr)\n \nDescription\n----------- \nReturns the minimum value of expr. MIN() may take a string\nargument, in which case it returns the minimum string value.\nThe DISTINCT\nkeyword can be used to find the minimum of the distinct\nvalues of expr,\nhowever, this produces the same result as omitting DISTINCT.\n \nNote that SET and ENUM fields are currently compared by\ntheir string value rather than their relative position in\nthe set, so MIN() may produce a different lowest result than\nORDER BY ASC.\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, MIN() can be used as a window function.\n \nMIN() returns NULL if there were no matching rows.\n \nExamples\n-------- \nCREATE TABLE student (name CHAR(10), test CHAR(10), score\nTINYINT); \n \nINSERT INTO student VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nSELECT name, MIN(score) FROM student GROUP BY name;\n \n+---------+------------+\n| name | MIN(score) |\n+---------+------------+\n| Chun | 73 |\n| Esben | 31 |\n| Kaolin | 56 |\n| Tatiana | 83 |\n+---------+------------+\n \nMIN() with a string:\n \nSELECT MIN(name) FROM student;\n \n+-----------+\n| MIN(name) |\n+-----------+\n| Chun |\n+-----------+\n \nBe careful to avoid this common mistake, not grouping\ncorrectly and returning mismatched data: \n \nSELECT name,test,MIN(score) FROM student;\n \n+------+------+------------+\n| name | test | MIN(score) |\n+------+------+------------+\n| Chun | SQL | 31 |\n+------+------+------------+\n \nDifference between ORDER BY ASC and MIN():\n \nCREATE TABLE student2(name CHAR(10),grade\nENUM(\'b\',\'c\',\'a\'));\n \nINSERT INTO student2\nVALUES(\'Chun\',\'b\'),(\'Esben\',\'c\'),(\'Kaolin\',\'a\');\n \nSELECT MIN(grade) FROM student2;\n \n+------------+\n| MIN(grade) |\n+------------+\n| a |\n+------------+\n \nSELECT grade FROM student2 ORDER BY grade ASC LIMIT 1;\n \n+-------+\n| grade |\n+-------+\n| b |\n+-------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, MIN(score) \n OVER (PARTITION BY name) AS lowest_score FROM student_test;\n \n+---------+--------+-------+--------------+\n| name | test | score | lowest_score |\n+---------+--------+-------+--------------+\n| Chun | SQL | 75 | 73 |\n| Chun | Tuning | 73 | 73 |\n| Esben | SQL | 43 | 31 |\n| Esben | Tuning | 31 | 31 |\n| Kaolin | SQL | 56 | 56 |\n| Kaolin | Tuning | 88 | 56 |\n| Tatiana | SQL | 87 | 87 |\n+---------+--------+-------+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/min/','','https://mariadb.com/kb/en/min/'),(310,'IF',23,'Syntax\n------ \nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF;\n \nDescription\n----------- \nIF implements a basic conditional construct. If the\nsearch_condition\nevaluates to true, the corresponding SQL statement list is\nexecuted.\nIf no search_condition matches, the statement list in the\nELSE clause\nis executed. Each statement_list consists of one or more\nstatements.\n \n\n\nURL: https://mariadb.com/kb/en/if/','','https://mariadb.com/kb/en/if/'),(311,'ITERATE',23,'Syntax\n------ \nITERATE label\n \nITERATE can appear only within LOOP, REPEAT, and WHILE\nstatements.\nITERATE means \"do the loop again\", and uses the\nstatement\'s label to determine which statements to repeat.\nThe label must be in the same stored program, not in a\ncaller procedure.\n \nIf you try to use ITERATE with a non-existing label, or if\nthe label is associated to a construct which is not a loop,\nthe following error will be produced:\n \nERROR 1308 (42000): ITERATE with no matching label: \n \nBelow is an example of how ITERATE might be used:\n \nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n \n IF p1 \n\nURL: https://mariadb.com/kb/en/iterate/','','https://mariadb.com/kb/en/iterate/'),(314,'LOOP',23,'Syntax\n------ \n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n \nDescription\n----------- \nLOOP implements a simple loop construct, enabling repeated\nexecution\nof the statement list, which consists of one or more\nstatements, each\nterminated by a semicolon (i.e., ;) statement delimiter. The\nstatements\nwithin the loop are repeated until the loop is exited;\nusually this is\naccomplished with a LEAVE statement.\n \nA LOOP statement can be labeled. end_label cannot be given\nunless\nbegin_label also is present. If both are present, they must\nbe the\nsame.\n \nSee Delimiters in the mysql client for more on delimiter\nusage in the client.\n \n\n\nURL: https://mariadb.com/kb/en/loop/','','https://mariadb.com/kb/en/loop/'),(192,'STD',16,'Syntax\n------ \nSTD(expr)\n \nDescription\n----------- \nReturns the population standard deviation of expr. This is\nan extension\nto standard SQL. The standard SQL function STDDEV_POP() can\nbe used instead. \n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, STD() can be used as a window function.\n \nThis function returns NULL if there were no matching rows.\n \nExamples\n-------- \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, STDDEV_POP(score) \n OVER (PARTITION BY test) AS stddev_results FROM\nstudent_test;\n \n+---------+--------+-------+----------------+\n| name | test | score | stddev_results |\n+---------+--------+-------+----------------+\n| Chun | SQL | 75 | 16.9466 |\n| Chun | Tuning | 73 | 24.1247 |\n| Esben | SQL | 43 | 16.9466 |\n| Esben | Tuning | 31 | 24.1247 |\n| Kaolin | SQL | 56 | 16.9466 |\n| Kaolin | Tuning | 88 | 24.1247 |\n| Tatiana | SQL | 87 | 16.9466 |\n+---------+--------+-------+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/std/','','https://mariadb.com/kb/en/std/'),(193,'STDDEV',16,'Syntax\n------ \nSTDDEV(expr)\n \nDescription\n----------- \nReturns the population standard deviation of expr. This\nfunction is\nprovided for compatibility with Oracle. The standard SQL\nfunction\nSTDDEV_POP() can be used instead.\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, STDDEV() can be used as a window\nfunction.\n \nThis function returns NULL if there were no matching rows.\n \nExamples\n-------- \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, STDDEV_POP(score) \n OVER (PARTITION BY test) AS stddev_results FROM\nstudent_test;\n \n+---------+--------+-------+----------------+\n| name | test | score | stddev_results |\n+---------+--------+-------+----------------+\n| Chun | SQL | 75 | 16.9466 |\n| Chun | Tuning | 73 | 24.1247 |\n| Esben | SQL | 43 | 16.9466 |\n| Esben | Tuning | 31 | 24.1247 |\n| Kaolin | SQL | 56 | 16.9466 |\n| Kaolin | Tuning | 88 | 24.1247 |\n| Tatiana | SQL | 87 | 16.9466 |\n+---------+--------+-------+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/stddev/','','https://mariadb.com/kb/en/stddev/'),(194,'STDDEV_POP',16,'Syntax\n------ \nSTDDEV_POP(expr)\n \nDescription\n----------- \nReturns the population standard deviation of expr (the\nsquare root of\nVAR_POP()). You can also use STD() or\nSTDDEV(), which are equivalent but not standard SQL.\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, STDDEV_POP() can be used as a window\nfunction.\n \nSTDDEV_POP() returns NULL if there were no matching rows.\n \nExamples\n-------- \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, STDDEV_POP(score) \n OVER (PARTITION BY test) AS stddev_results FROM\nstudent_test;\n \n+---------+--------+-------+----------------+\n| name | test | score | stddev_results |\n+---------+--------+-------+----------------+\n| Chun | SQL | 75 | 16.9466 |\n| Chun | Tuning | 73 | 24.1247 |\n| Esben | SQL | 43 | 16.9466 |\n| Esben | Tuning | 31 | 24.1247 |\n| Kaolin | SQL | 56 | 16.9466 |\n| Kaolin | Tuning | 88 | 24.1247 |\n| Tatiana | SQL | 87 | 16.9466 |\n+---------+--------+-------+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/stddev_pop/','','https://mariadb.com/kb/en/stddev_pop/'),(315,'OPEN',23,'Syntax\n------ \n\n\nURL: https://mariadb.com/kb/en/open/','','https://mariadb.com/kb/en/open/'),(318,'RETURN',23,'Syntax\n------ \nRETURN expr \n \nThe RETURN statement terminates execution of a stored\nfunction and\nreturns the value expr to the function caller. There must be\nat least\none RETURN statement in a stored function. If the function\nhas multiple exit points, all exit points must have a\nRETURN.\n \nThis statement is not used in stored procedures, triggers,\nor events. LEAVE can be used instead.\n \nThe following example shows that RETURN can return the\nresult of a scalar subquery:\n \nCREATE FUNCTION users_count() RETURNS BOOL\n READS SQL DATA\nBEGIN\n RETURN (SELECT COUNT(DISTINCT User) FROM mysql.user);\nEND;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/return/','','https://mariadb.com/kb/en/return/'),(321,'WHILE',23,'Syntax\n------ \n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n \nDescription\n----------- \nThe statement list within a WHILE statement is repeated as\nlong as the\nsearch_condition is true. statement_list consists of one or\nmore\nstatements. If the loop must be executed at least once,\nREPEAT ... LOOP can be used instead.\n \nA WHILE statement can be labeled. end_label cannot be given\nunless\nbegin_label also is present. If both are present, they must\nbe the\nsame.\n \nExamples\n-------- \nCREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n \n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n \n END WHILE;\n \nEND\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/while/','','https://mariadb.com/kb/en/while/'),(196,'SUM',16,'Syntax\n------ \nSUM([DISTINCT] expr)\n \nDescription\n----------- \nReturns the sum of expr. If the return set has no rows,\nSUM() returns\nNULL. The DISTINCT keyword can be used to sum only the\ndistinct values\nof expr.\n \nFrom MariaDB 10.2.0, SUM() can be used as a window function,\nalthough not with the DISTINCT specifier.\n \nExamples\n-------- \nCREATE TABLE sales (sales_value INT);\nINSERT INTO sales VALUES(10),(20),(20),(40);\n \nSELECT SUM(sales_value) FROM sales;\n \n+------------------+\n| SUM(sales_value) |\n+------------------+\n| 90 |\n+------------------+\n \nSELECT SUM(DISTINCT(sales_value)) FROM sales;\n \n+----------------------------+\n| SUM(DISTINCT(sales_value)) |\n+----------------------------+\n| 70 |\n+----------------------------+\n \nCommonly, SUM is used with a GROUP BY clause:\n \nCREATE TABLE sales (name CHAR(10), month CHAR(10), units\nINT);\n \nINSERT INTO sales VALUES \n (\'Chun\', \'Jan\', 75), (\'Chun\', \'Feb\', 73),\n (\'Esben\', \'Jan\', 43), (\'Esben\', \'Feb\', 31),\n (\'Kaolin\', \'Jan\', 56), (\'Kaolin\', \'Feb\', 88),\n (\'Tatiana\', \'Jan\', 87), (\'Tatiana\', \'Feb\', 83);\n \nSELECT name, SUM(units) FROM sales GROUP BY name;\n \n+---------+------------+\n| name | SUM(units) |\n+---------+------------+\n| Chun | 148 |\n| Esben | 74 |\n| Kaolin | 144 |\n| Tatiana | 170 |\n+---------+------------+\n \nThe GROUP BY clause is required when using an aggregate\nfunction along with regular column data, otherwise the\nresult will be a mismatch, as in the following common type\nof mistake:\n \nSELECT name,SUM(units) FROM sales\n;\n+------+------------+\n| name | SUM(units) |\n+------+------------+\n| Chun | 536 |\n+------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, SUM(score) OVER (PARTITION BY\nname) AS total_score FROM student_test;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Chun | SQL | 75 | 148 |\n| Chun | Tuning | 73 | 148 |\n| Esben | SQL | 43 | 74 |\n| Esben | Tuning | 31 | 74 |\n| Kaolin | SQL | 56 | 144 |\n| Kaolin | Tuning | 88 | 144 |\n| Tatiana | SQL | 87 | 87 |\n+---------+--------+-------+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/sum/','','https://mariadb.com/kb/en/sum/'),(197,'VARIANCE',16,'Syntax\n------ \nVARIANCE(expr) \n \nDescription\n----------- \nReturns the population standard variance of expr. This is an\nextension to\nstandard SQL. The standard SQL function VAR_POP() can be\nused\ninstead.\n \nVariance is calculated by\nworking out the mean for the set\nfor each number, subtracting the mean and squaring the\nresult\ncalculate the average of the resulting differences\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, VARIANCE() can be used as a window\nfunction.\n \nVARIANCE() returns NULL if there were no matching rows.\n \nExamples\n-------- \nCREATE TABLE v(i tinyint);\n \nINSERT INTO v VALUES(101),(99);\n \nSELECT VARIANCE(i) FROM v;\n \n+-------------+\n| VARIANCE(i) |\n+-------------+\n| 1.0000 |\n+-------------+\n \nINSERT INTO v VALUES(120),(80);\n \nSELECT VARIANCE(i) FROM v;\n \n+-------------+\n| VARIANCE(i) |\n+-------------+\n| 200.5000 |\n+-------------+\n \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, VAR_POP(score) \n OVER (PARTITION BY test) AS variance_results FROM\nstudent_test;\n \n+---------+--------+-------+------------------+\n| name | test | score | variance_results |\n+---------+--------+-------+------------------+\n| Chun | SQL | 75 | 287.1875 |\n| Chun | Tuning | 73 | 582.0000 |\n| Esben | SQL | 43 | 287.1875 |\n| Esben | Tuning | 31 | 582.0000 |\n| Kaolin | SQL | 56 | 287.1875 |\n| Kaolin | Tuning | 88 | 582.0000 |\n| Tatiana | SQL | 87 | 287.1875 |\n+---------+--------+-------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/variance/','','https://mariadb.com/kb/en/variance/'),(322,'BUFFER',24,'A synonym for ST_BUFFER.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/buffer/','','https://mariadb.com/kb/en/buffer/'),(323,'CONVEXHULL',24,'A synonym for ST_CONVEXHULL.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/convexhull/','','https://mariadb.com/kb/en/convexhull/'),(324,'GEOMETRYCOLLECTION',24,'Syntax\n------ \nGeometryCollection(g1,g2,...)\n \nDescription\n----------- \nConstructs a WKB GeometryCollection. If any argument is not\na well-formed WKB representation of a geometry, the return\nvalue is NULL.\n \nExamples\n-------- \nCREATE TABLE gis_geometrycollection (g GEOMETRYCOLLECTION);\nSHOW FIELDS FROM gis_geometrycollection;\n \nINSERT INTO gis_geometrycollection VALUES\n (GeomCollFromText(\'GEOMETRYCOLLECTION(POINT(0 0),\nLINESTRING(0 0,10 10))\')),\n (GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6),\nLineString(Point(3, 6), Point(7, 9)))))),\n (GeomFromText(\'GeometryCollection()\')),\n (GeomFromText(\'GeometryCollection EMPTY\'));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometrycollection/','','https://mariadb.com/kb/en/geometrycollection/'),(326,'MULTILINESTRING',24,'Syntax\n------ \nMultiLineString(ls1,ls2,...)\n \nDescription\n----------- \nConstructs a WKB MultiLineString value using WKB LineString\narguments. If any argument is not a WKB LineString, the\nreturn value is\nNULL.\n \nExample\n \nCREATE TABLE gis_multi_line (g MULTILINESTRING);\nINSERT INTO gis_multi_line VALUES\n (MultiLineStringFromText(\'MULTILINESTRING((10 48,10 21,10\n0),(16 0,16 23,16 48))\')),\n (MLineFromText(\'MULTILINESTRING((10 48,10 21,10 0))\')),\n (MLineFromWKB(AsWKB(MultiLineString(LineString(Point(1, 2),\nPoint(3, 5)), LineString(Point(2, 5),Point(5, 8),Point(21,\n7))))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multilinestring/','','https://mariadb.com/kb/en/multilinestring/'),(327,'MULTIPOINT',24,'Syntax\n------ \nMultiPoint(pt1,pt2,...)\n \nDescription\n----------- \nConstructs a WKB MultiPoint value using WKB Point arguments.\nIf any argument is not a WKB Point, the return value is\nNULL.\n \nExamples\n-------- \nSET @g = ST_GEOMFROMTEXT(\'MultiPoint( 1 1, 2 2, 5 3, 7 2, 9\n3, 8 4, 6 6, 6 9, 4 9, 1 5 )\');\n \nCREATE TABLE gis_multi_point (g MULTIPOINT);\nINSERT INTO gis_multi_point VALUES\n (MultiPointFromText(\'MULTIPOINT(0 0,10 10,10 20,20\n20)\')),\n (MPointFromText(\'MULTIPOINT(1 1,11 11,11 21,21 21)\')),\n (MPointFromWKB(AsWKB(MultiPoint(Point(3, 6), Point(4,\n10)))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipoint/','','https://mariadb.com/kb/en/multipoint/'),(198,'VAR_POP',16,'Syntax\n------ \nVAR_POP(expr)\n \nDescription\n----------- \nReturns the population standard variance of expr. It\nconsiders rows as\nthe whole population, not as a sample, so it has the number\nof rows as\nthe denominator. You can also use VARIANCE(), which is\nequivalent but\nis not standard SQL.\n \nVariance is calculated by\nworking out the mean for the set\nfor each number, subtracting the mean and squaring the\nresult\ncalculate the average of the resulting differences\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, VAR_POP() can be used as a window\nfunction.\n \nVAR_POP() returns NULL if there were no matching rows.\n \nExamples\n-------- \nCREATE TABLE v(i tinyint);\n \nINSERT INTO v VALUES(101),(99);\n \nSELECT VAR_POP(i) FROM v;\n \n+------------+\n| VAR_POP(i) |\n+------------+\n| 1.0000 |\n+------------+\n \nINSERT INTO v VALUES(120),(80);\n \nSELECT VAR_POP(i) FROM v;\n \n+------------+\n| VAR_POP(i) |\n+------------+\n| 200.5000 |\n+------------+\n \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, VAR_POP(score) \n OVER (PARTITION BY test) AS variance_results FROM\nstudent_test;\n \n+---------+--------+-------+------------------+\n| name | test | score | variance_results |\n+---------+--------+-------+------------------+\n| Chun | SQL | 75 | 287.1875 |\n| Chun | Tuning | 73 | 582.0000 |\n| Esben | SQL | 43 | 287.1875 |\n| Esben | Tuning | 31 | 582.0000 |\n| Kaolin | SQL | 56 | 287.1875 |\n| Kaolin | Tuning | 88 | 582.0000 |\n| Tatiana | SQL | 87 | 287.1875 |\n+---------+--------+-------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/var_pop/','','https://mariadb.com/kb/en/var_pop/'),(199,'VAR_SAMP',16,'Syntax\n------ \nVAR_SAMP(expr)\n \nDescription\n----------- \nReturns the sample variance of expr. That is, the\ndenominator is the number of rows minus one.\n \nIt is an aggregate function, and so can be used with the\nGROUP BY clause.\n \nFrom MariaDB 10.2.2, VAR_SAMP() can be used as a window\nfunction.\n \nVAR_SAMP() returns NULL if there were no matching rows.\n \nExamples\n-------- \nAs an aggregate function:\n \nCREATE OR REPLACE TABLE stats (category VARCHAR(2), x INT);\n \nINSERT INTO stats VALUES \n (\'a\',1),(\'a\',2),(\'a\',3),\n (\'b\',11),(\'b\',12),(\'b\',20),(\'b\',30),(\'b\',60);\n \nSELECT category, STDDEV_POP(x), STDDEV_SAMP(x), VAR_POP(x) \n FROM stats GROUP BY category;\n \n+----------+---------------+----------------+------------+\n| category | STDDEV_POP(x) | STDDEV_SAMP(x) | VAR_POP(x) |\n+----------+---------------+----------------+------------+\n| a | 0.8165 | 1.0000 | 0.6667 |\n| b | 18.0400 | 20.1693 | 325.4400 |\n+----------+---------------+----------------+------------+\n \nAs a window function:\n \nCREATE OR REPLACE TABLE student_test (name CHAR(10), test\nCHAR(10), score TINYINT);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, VAR_SAMP(score) \n OVER (PARTITION BY test) AS variance_results FROM\nstudent_test;\n \n+---------+--------+-------+------------------+\n| name | test | score | variance_results |\n+---------+--------+-------+------------------+\n| Chun | SQL | 75 | 382.9167 |\n| Chun | Tuning | 73 | 873.0000 |\n| Esben | SQL | 43 | 382.9167 |\n| Esben | Tuning | 31 | 873.0000 |\n| Kaolin | SQL | 56 | 382.9167 |\n| Kaolin | Tuning | 88 | 873.0000 |\n| Tatiana | SQL | 87 | 382.9167 |\n+---------+--------+-------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/var_samp/','','https://mariadb.com/kb/en/var_samp/'),(202,'CHARSET',17,'Syntax\n------ \nCHARSET(str)\n \nDescription\n----------- \nReturns the character set of the string argument. If str is\nnot a string, it is considered as a binary string (so the\nfunction returns \'binary\'). This applies to NULL, too. The\nreturn value is a string in the utf8 character set.\n \nExamples\n-------- \nSELECT CHARSET(\'abc\');\n+----------------+\n| CHARSET(\'abc\') |\n+----------------+\n| latin1 |\n+----------------+\n \nSELECT CHARSET(CONVERT(\'abc\' USING utf8));\n+------------------------------------+\n| CHARSET(CONVERT(\'abc\' USING utf8)) |\n+------------------------------------+\n| utf8 |\n+------------------------------------+\n \nSELECT CHARSET(USER());\n+-----------------+\n| CHARSET(USER()) |\n+-----------------+\n| utf8 |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/charset/','','https://mariadb.com/kb/en/charset/'),(328,'MULTIPOLYGON',24,'Syntax\n------ \nMultiPolygon(poly1,poly2,...)\n \nDescription\n----------- \nConstructs a WKB MultiPolygon value from a set of WKB\nPolygon arguments. If any argument is not a WKB Polygon, the\nreturn value is NULL.\n \nExample\n \nCREATE TABLE gis_multi_polygon (g MULTIPOLYGON);\nINSERT INTO gis_multi_polygon VALUES\n (MultiPolygonFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84\n42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67\n13,59 13,59 18)))\')),\n (MPolyFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28\n26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59\n13,59 18)))\')),\n (MPolyFromWKB(AsWKB(MultiPolygon(Polygon(LineString(Point(0,\n3), Point(3, 3), Point(3, 0), Point(0, 3)))))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipolygon/','','https://mariadb.com/kb/en/multipolygon/'),(329,'POINT',24,'Syntax\n------ \nPoint(x,y)\n \nDescription\n----------- \nConstructs a WKB Point using the given coordinates.\n \nExamples\n-------- \nSET @g = ST_GEOMFROMTEXT(\'Point(1 1)\');\n \nCREATE TABLE gis_point (g POINT);\nINSERT INTO gis_point VALUES\n (PointFromText(\'POINT(10 10)\')),\n (PointFromText(\'POINT(20 10)\')),\n (PointFromText(\'POINT(20 20)\')),\n (PointFromWKB(AsWKB(PointFromText(\'POINT(10 20)\'))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/point/','','https://mariadb.com/kb/en/point/'),(330,'PointOnSurface',24,'A synonym for ST_PointOnSurface.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/pointonsurface/','','https://mariadb.com/kb/en/pointonsurface/'),(334,'ST_INTERSECTION',24,'Syntax\n------ \nST_INTERSECTION(g1,g2)\n \nDescription\n----------- \nReturns a geometry that is the intersection, or shared\nportion, of geometry g1 and geometry g2.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(2 1)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(2 1, 0 2)\');\n \nSELECT ASTEXT(ST_INTERSECTION(@g1,@g2));\n+----------------------------------+\n| ASTEXT(ST_INTERSECTION(@g1,@g2)) |\n+----------------------------------+\n| POINT(2 1) |\n+----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_intersection/','','https://mariadb.com/kb/en/st_intersection/'),(203,'COERCIBILITY',17,'Syntax\n------ \nCOERCIBILITY(str)\n \nDescription\n----------- \nReturns the collation coercibility value of the string\nargument. Coercibility defines what will be converted to\nwhat in case of collation conflict, with an expression with\nhigher coercibility being converted to the collation of an\nexpression with lower coercibility.\n \nCoercibility | Description | Example | \n \n0 | Explicit | Value using a COLLATE clause | \n \n1 | No collation | Concatenated strings using different\ncollations | \n \n2 | Implicit | Column value | \n \n3 | Constant | USER() return value | \n \n4 | Coercible | Literal string | \n \n5 | Ignorable | NULL or derived from NULL | \n \nExamples\n-------- \nSELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n+-----------------------------------------------+\n| COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci) |\n+-----------------------------------------------+\n| 0 |\n+-----------------------------------------------+\n \nSELECT COERCIBILITY(USER());\n+----------------------+\n| COERCIBILITY(USER()) |\n+----------------------+\n| 3 |\n+----------------------+\n \nSELECT COERCIBILITY(\'abc\');\n+---------------------+\n| COERCIBILITY(\'abc\') |\n+---------------------+\n| 4 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/coercibility/','','https://mariadb.com/kb/en/coercibility/'),(206,'CURRENT_ROLE',17,'Roles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nCURRENT_ROLE, CURRENT_ROLE()\n \nDescription\n----------- \nReturns the current role name. This determines your access\nprivileges. The return value is a string in the\nutf8 character set.\n \nIf there is no current role, NULL is returned.\n \nThe output of SELECT CURRENT_ROLE is equivalent to the\ncontents of the ENABLED_ROLES Information Schema table.\n \nUSER() returns the combination of user and host used to\nlogin. CURRENT_USER() returns the account used to determine\ncurrent connection\'s privileges.\n \nExamples\n-------- \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| NULL |\n+--------------+\n \nSET ROLE staff;\n \nSELECT CURRENT_ROLE;\n \n+--------------+\n| CURRENT_ROLE |\n+--------------+\n| staff |\n+--------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/current_role/','','https://mariadb.com/kb/en/current_role/'),(207,'CURRENT_USER',17,'Syntax\n------ \nCURRENT_USER, CURRENT_USER()\n \nDescription\n----------- \nReturns the user name and host name combination for the\nMariaDB account\nthat the server used to authenticate the current client.\nThis account\ndetermines your access privileges. The return value is a\nstring in the\nutf8 character set.\n \nThe value of CURRENT_USER() can differ from the value of\nUSER(). CURRENT_ROLE() returns the current active role.\n \nExamples\n-------- \nshell> mysql --user=\"anonymous\"\n \nMariaDB [(none)]> select user(),current_user();\n+---------------------+----------------+\n| user() | current_user() |\n+---------------------+----------------+\n| anonymous@localhost | @localhost |\n+---------------------+----------------+\n \nWhen calling CURRENT_USER() in a stored procedure, it\nreturns the owner of the stored procedure, as defined with\nDEFINER.\n \n\n\nURL: https://mariadb.com/kb/en/current_user/','','https://mariadb.com/kb/en/current_user/'),(208,'DATABASE',17,'Syntax\n------ \nDATABASE()\n \nDescription\n----------- \nReturns the default (current) database name as a string in\nthe utf8 character set. If there is no default database,\nDATABASE() returns NULL. Within a stored routine, the\ndefault database is the database that the routine is\nassociated with, which is not necessarily the same as the\ndatabase that is the default in the calling context.\n \nSCHEMA() is a synonym for DATABASE().\n \nTo select a default database, the USE statement can be run.\nAnother way to set the default database is specifying its\nname at mysql command line client startup.\n \nExamples\n-------- \nSELECT DATABASE();\n+------------+\n| DATABASE() |\n+------------+\n| NULL |\n+------------+\n \nUSE test;\n \nDatabase changed\n \nSELECT DATABASE();\n+------------+\n| DATABASE() |\n+------------+\n| test |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/database/','','https://mariadb.com/kb/en/database/'),(210,'DEFAULT',17,'Syntax\n------ \nDEFAULT(col_name)\n \nDescription\n----------- \nReturns the default value for a table column. If the column\nhas no default value, NULL is returned.\nFor integer columns using AUTO_INCREMENT, 0 is returned.\n \nWhen using DEFAULT as a value to set in an INSERT or UPDATE\nstatement, you can use the bare keyword DEFAULT without the\nparentheses and argument to\nrefer to the column in context. You can only use DEFAULT as\na bare keyword if you are using it\nalone without a surrounding expression or function.\n \nExamples\n-------- \nSelect only non-default values for a column:\n \nSELECT i FROM t WHERE i != DEFAULT(i);\n \nUpdate values to be one greater than the default value:\n \nUPDATE t SET i = DEFAULT(i)+1 WHERE i \n\nURL: https://mariadb.com/kb/en/default/','','https://mariadb.com/kb/en/default/'),(335,'ST_POINTONSURFACE',24,'ST_POINTONSURFACE() was introduced in MariaDB 10.1.2\n \nSyntax\n------ \nST_PointOnSurface(g)\nPointOnSurface(g)\n \nDescription\n----------- \nGiven a geometry, returns a POINT guaranteed to intersect a\nsurface. However, see MDEV-7514.\n \nST_PointOnSurface() and PointOnSurface() are synonyms.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_pointonsurface/','','https://mariadb.com/kb/en/st_pointonsurface/'),(340,'BINLOG',26,'Syntax\n------ \nBINLOG \'str\'\n \nDescription\n----------- \nBINLOG is an internal-use statement. It is generated by the\nmysqlbinlog program as the printable representation of\ncertain events\nin binary log files. The \'str\' value is a base 64-encoded\nstring the that server decodes to determine the data change\nindicated by the\ncorresponding event. This statement requires the SUPER\nprivilege. It was added in MySQL 5.1.5.\n \n\n\nURL: https://mariadb.com/kb/en/binlog/','','https://mariadb.com/kb/en/binlog/'),(342,'FLUSH',26,'Syntax\n------ \nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n \nor when flushing tables:\n \nFLUSH [NO_WRITE_TO_BINLOG | LOCAL] TABLES [table_list]\n[table_flush_option]\n \nwhere table_list is a list of tables separated by , (comma).\n \nDescription\n----------- \nThe FLUSH statement clears or reloads various internal\ncaches used by\nMariaDB. To execute FLUSH, you must have the RELOAD\nprivilege. See GRANT.\n \nThe RESET statement is similar to FLUSH. See\nRESET.\n \nYou cannot issue a FLUSH statement from within a stored\nfunction or a trigger. Doing so within a stored procedure is\npermitted, as long as it is not called by a stored function\nor trigger. See Stored Routine Limitations, Stored Function\nLimitations and Trigger Limitations.\n \nIf a listed table is a view, an error like the following\nwill be produced:\n \nERROR 1347 (HY000): \'test.v\' is not BASE TABLE\n \nBy default, FLUSH statements are written to the binary log\nand will be replicated. The NO_WRITE_TO_BINLOG keyword\n(LOCAL is an alias) will ensure the statement is not written\nto the binary log. \n \nThe different flush options are:\n \nOption | Description | \n \nCHANGED_PAGE_BITMAPS | Internal command used for backup\npurposes. See the Information Schema CHANGED_PAGE_BITMAPS\nTable. | \n \nCLIENT_STATISTICS | Reset client statistics (see SHOW\nCLIENT_STATISTICS). | \n \nDES_KEY_FILE | Reloads the DES key file (Specified with the\n--des-key-file startup option). | \n \nHOSTS | Flush the hostname cache (used for converting ip to\nhost names and for unblocking blocked hosts. See\nmax_connect_errors) | \n \nINDEX_STATISTICS | Reset index statistics (see SHOW\nINDEX_STATISTICS). | \n \n[ERROR | ENGINE | GENERAL | SLOW | BINARY | RELAY] LOGS |\nClose and reopen the specified log type, or all log types if\nnone are specified. FLUSH RELAY LOGS [connection-name] can\nbe used to flush the relay logs for a specific connection.\nOnly one connection can be specified per FLUSH command. See\nMulti-source replication. FLUSH ENGINE LOGS will delete all\nunneeded Aria redo logs. Since MariaDB 10.1.30 and MariaDB\n10.2.11, FLUSH BINARY LOGS\nDELETE_DOMAIN_ID=(list-of-domains) can be used to discard\nobsolete GTID domains from the server\'s binary log state.\nIn order for this to be successful, no event group from the\nlisted GTID domains can be present in existing binary log\nfiles. If some still exist, then they must be purged prior\nto executing this command. If the command completes\nsuccessfully, then it also rotates the binary log. | \n \nMASTER | Deprecated option, use RESET MASTER instead. | \n \nPRIVILEGES | Reload all privileges from the privilege tables\nin the mysql database. If the server is started with\n--skip-grant-table option, this will activate the privilege\ntables again. | \n \nQUERY CACHE | Defragment the query cache to better utilize\nits memory. If you want to reset the query cache, you can do\nit with RESET QUERY CACHE. | \n \nQUERY_RESPONSE_TIME | See the QUERY_RESPONSE_TIME plugin. | \n \nSLAVE | Deprecated option, use RESET SLAVE instead. | \n \nSSL | Used to dynamically reinitialize the server\'s TLS\ncontext by reloading the files defined by several TLS system\nvariables. See FLUSH SSL for more information. This command\nwas first added in MariaDB 10.4.1. | \n \nSTATUS | Resets all server status variables that can be\nreset to 0. Not all global status variables support this, so\nnot all global values are reset. See FLUSH STATUS for more\ninformation. | \n \nTABLE | Close tables given as options or all open tables if\nno table list was used. From MariaDB 10.4.1, using without\nany table list will only close tables not in use, and tables\nnot locked by the FLUSH TABLES connection. If there are no\nlocked tables, FLUSH TABLES will be instant and will not\ncause any waits, as it no longer waits for tables in use.\nWhen a table list is provided, from MariaDB 10.4.1, the\nserver will wait for the end of any transactions that are\nusing the tables. Previously, FLUSH TABLES only waited for\nthe statements to complete. | \n \nTABLES | Same as FLUSH TABLE. | \n \nTABLES ... FOR EXPORT | For InnoDB tables, flushes table\nchanges to disk to permit binary table copies while the\nserver is running. Introduced in MariaDB 10.0.8. See FLUSH\nTABLES ... FOR EXPORT for more. | \n \nTABLES WITH READ LOCK | Closes all open tables. New tables\nare only allowed to be opened with read locks until an\nUNLOCK TABLES is given. | \n \nTABLES WITH READ LOCK AND DISABLE CHECKPOINT | As TABLES\nWITH READ LOCK but also disable all checkpoint writes by\ntransactional table engines. This is useful when doing a\ndisk snapshot of all tables. | \n \nTABLE_STATISTICS | Reset table statistics (see SHOW\nTABLE_STATISTICS). | \n \nUSER_RESOURCES | Resets all per hour user resources. This\nenables clients that have exhausted their resources to\nconnect again. | \n \nUSER_STATISTICS | Reset user statistics (see SHOW\nUSER_STATISTICS). | \n \nYou can also use the mysqladmin client to flush things. Use\nmysqladmin --help to examine what flush commands it\nsupports.\n \nFLUSH STATUS\n \nServer status variables can be reset by executing the\nfollowing:\n \nFLUSH STATUS;\n \nGlobal Status Variables that Support FLUSH STATUS\n \nNot all global status variables support being reset by FLUSH\nSTATUS. Currently, the following status variables are reset\nby FLUSH STATUS:\nAborted_clients\nAborted_connects\nAria_pagecache_blocks_not_flushed\nAria_pagecache_blocks_unused\nAria_pagecache_blocks_used\nBinlog_cache_disk_use\nBinlog_cache_use\nBinlog_stmt_cache_disk_use\nBinlog_stmt_cache_use\nConnection_errors_accept\nConnection_errors_internal\nConnection_errors_max_connections\nConnection_errors_peer_address\nConnection_errors_select\nConnection_errors_tcpwrap\nCreated_tmp_files\nDelayed_errors\nDelayed_writes\nFeature_check_constraint\nFeature_delay_key_write\nMax_used_connections\nOpened_plugin_libraries\nPerformance_schema_accounts_lost\nPerformance_schema_cond_instances_lost\nPerformance_schema_digest_lost\nPerformance_schema_file_handles_lost\nPerformance_schema_file_instances_lost\nPerformance_schema_hosts_lost\nPerformance_schema_locker_lost\nPerformance_schema_mutex_instances_lost\nPerformance_schema_rwlock_instances_lost\nPerformance_schema_session_connect_attrs_lost\nPerformance_schema_socket_instances_lost\nPerformance_schema_stage_classes_lost\nPerformance_schema_statement_classes_lost\nPerformance_schema_table_handles_lost\nPerformance_schema_table_instances_lost\nPerformance_schema_thread_instances_lost\nPerformance_schema_users_lost\nQcache_hits\nQcache_inserts\nQcache_lowmem_prunes\nQcache_not_cached\nRpl_semi_sync_master_no_times\nRpl_semi_sync_master_no_tx\nRpl_semi_sync_master_timefunc_failures\nRpl_semi_sync_master_wait_pos_backtraverse\nRpl_semi_sync_master_yes_tx\nRpl_transactions_multi_engine\nServer_audit_writes_failed\nSlave_retried_transactions\nSlow_launch_threads\nSsl_accept_renegotiates\nSsl_accepts\nSsl_callback_cache_hits\nSsl_client_connects\nSsl_connect_renegotiates\nSsl_ctx_verify_depth\nSsl_ctx_verify_mode\nSsl_finished_accepts\nSsl_finished_connects\nSsl_session_cache_hits\nSsl_session_cache_misses\nSsl_session_cache_overflows\nSsl_session_cache_size\nSsl_session_cache_timeouts\nSsl_sessions_reused\nSsl_used_session_cache_entries\nSubquery_cache_hit\nSubquery_cache_miss\nTable_locks_immediate\nTable_locks_waited\nTc_log_max_pages_used\nTc_log_page_waits\nTransactions_gtid_foreign_engine\nTransactions_multi_engine\n \nFLUSH SSL\n \nThe FLUSH SSL command was first added in MariaDB 10.4.\n \nIn MariaDB 10.4 and later, the FLUSH SSL command can be used\nto dynamically reinitialize the server\'s TLS context. This\nis most useful if you need to replace a certificate that is\nabout to expire without restarting the server.\n \nThis operation is performed by reloading the files defined\nby the following TLS system variables:\nssl_cert\nssl_key\nssl_ca\nssl_capath\nssl_crl\nssl_crlpath\n \nThese TLS system variables are not dynamic, so their values\ncan not be changed without restarting the server.\n \nIf you want to dynamically reinitialize the server\'s TLS\ncontext, then you need to change the certificate and key\nfiles at the relevant paths defined by these TLS system\nvariables, without actually changing the values of the\nvariables. See MDEV-19341 for more information.\n \nReducing Memory Usage\n \nTo flush some of the global caches that take up memory, you\ncould execute the following command:\n \nFLUSH LOCAL HOSTS,\n QUERY CACHE, \n TABLE_STATISTICS, \n INDEX_STATISTICS, \n USER_STATISTICS;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/flush/','','https://mariadb.com/kb/en/flush/'),(343,'FLUSH QUERY CACHE',26,'Description\n----------- \nYou can defragment the query cache to better utilize its\nmemory with\nthe FLUSH QUERY CACHE statement. The statement does not\nremove any queries from the cache.\n \nThe RESET QUERY CACHE statement removes all query results\nfrom the query cache.\nThe FLUSH TABLES statement also does this.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/flush-query-cache/','','https://mariadb.com/kb/en/flush-query-cache/'),(347,'LOAD INDEX',26,'Syntax\n------ \nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n \ntbl_index_list:\n tbl_name\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n \nDescription\n----------- \nThe LOAD INDEX INTO CACHE statement preloads a table index\ninto the key\ncache to which it has been assigned by an explicit CACHE\nINDEX\nstatement, or into the default key cache otherwise. \nLOAD INDEX INTO CACHE is used only for MyISAM or Aria\ntables. Until MariaDB 5.3, it was not supported for tables\nhaving user-defined partitioning, but this limitation was\nremoved in MariaDB 5.5.\n \nThe IGNORE LEAVES modifier causes only blocks for the\nnonleaf nodes of\nthe index to be preloaded.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/load-index/','','https://mariadb.com/kb/en/load-index/'),(377,'SHOW FUNCTION CODE',26,'Syntax\n------ \nSHOW FUNCTION CODE func_name\n \nDescription\n----------- \nSHOW FUNCTION CODE shows a representation of the internal\nimplementation of the stored function.\n \nIt is similar to SHOW PROCEDURE CODE but for stored\nfunctions.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-function-code/','','https://mariadb.com/kb/en/show-function-code/'),(209,'DECODE_HISTOGRAM',17,'DECODE_HISTOGRAM() was introduced in MariaDB 10.0.2\n \nSyntax\n------ \nDECODE_HISTOGRAM(hist_type,histogram)\n \nNote: Before MariaDB 10.0.10 the arguments were reversed.\n \nDescription\n----------- \nReturns a string of comma separated numeric values\ncorresponding to a probability distribution represented by\nthe histogram of type hist_type (SINGLE_PREC_HB or\nDOUBLE_PREC_HB). The hist_type and histogram would be\ncommonly used from the mysql.column_stats table.\n \nSee Histogram Based Statistics for details.\n \nExamples\n-------- \nCREATE TABLE origin (\n i INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,\n v INT UNSIGNED NOT NULL\n);\n \nINSERT INTO origin(v) VALUES \n (1),(2),(3),(4),(5),(10),(20),\n (30),(40),(50),(60),(70),(80),\n (90),(100),(200),(400),(800);\n \nSET histogram_size=10,histogram_type=SINGLE_PREC_HB;\n \nANALYZE TABLE origin PERSISTENT FOR ALL;\n \n+-------------+---------+----------+-----------------------------------------+\n| Table | Op | Msg_type | Msg_text |\n+-------------+---------+----------+-----------------------------------------+\n| test.origin | analyze | status | Engine-independent\nstatistics collected |\n| test.origin | analyze | status | OK |\n+-------------+---------+----------+-----------------------------------------+\n \nSELECT db_name,table_name,column_name,hist_type,\n hex(histogram),decode_histogram(hist_type,histogram) \n FROM mysql.column_stats WHERE db_name=\'test\' and\ntable_name=\'origin\';\n \n+---------+------------+-------------+----------------+----------------------+-------------------------------------------------------------------+\n| db_name | table_name | column_name | hist_type |\nhex(histogram) | decode_histogram(hist_type,histogram) |\n+---------+------------+-------------+----------------+----------------------+-------------------------------------------------------------------+\n| test | origin | i | SINGLE_PREC_HB | 0F2D3C5A7887A5C3D2F0\n|\n0.059,0.118,0.059,0.118,0.118,0.059,0.118,0.118,0.059,0.118,0.059\n|\n| test | origin | v | SINGLE_PREC_HB | 000001060C0F161C1F7F\n|\n0.000,0.000,0.004,0.020,0.024,0.012,0.027,0.024,0.012,0.376,0.502\n|\n+---------+------------+-------------+----------------+----------------------+-------------------------------------------------------------------+\n \nSET histogram_size=20,histogram_type=DOUBLE_PREC_HB;\n \nANALYZE TABLE origin PERSISTENT FOR ALL;\n \n+-------------+---------+----------+-----------------------------------------+\n| Table | Op | Msg_type | Msg_text |\n+-------------+---------+----------+-----------------------------------------+\n| test.origin | analyze | status | Engine-independent\nstatistics collected |\n| test.origin | analyze | status | OK |\n+-------------+---------+----------+-----------------------------------------+\n \nSELECT db_name,table_name,column_name,\n hist_type,hex(histogram),decode_histogram(hist_type,histogram)\n\n FROM mysql.column_stats WHERE db_name=\'test\' and\ntable_name=\'origin\';\n \n+---------+------------+-------------+----------------+------------------------------------------+-----------------------------------------------------------------------------------------+\n| db_name | table_name | column_name | hist_type |\nhex(histogram) | decode_histogram(hist_type,histogram) |\n+---------+------------+-------------+----------------+------------------------------------------+-----------------------------------------------------------------------------------------+\n| test | origin | i | DOUBLE_PREC_HB |\n0F0F2D2D3C3C5A5A78788787A5A5C3C3D2D2F0F0 |\n0.05882,0.11765,0.05882,0.11765,0.11765,0.05882,0.11765,0.11765,0.05882,0.11765,0.05882\n|\n| test | origin | v | DOUBLE_PREC_HB |\n5200F600480116067E0CB30F1B16831CB81FD67F |\n0.00125,0.00250,0.00125,0.01877,0.02502,0.01253,0.02502,0.02502,0.01253,0.37546,0.50063\n|\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/decode_histogram/','','https://mariadb.com/kb/en/decode_histogram/'),(211,'FOUND_ROWS',17,'Syntax\n------ \nFOUND_ROWS()\n \nDescription\n----------- \nA SELECT statement may include a LIMIT clause to restrict\nthe number\nof rows the server returns to the client. In some cases, it\nis\ndesirable to know how many rows the statement would have\nreturned\nwithout the LIMIT, but without running the statement again.\nTo obtain\nthis row count, include a SQL_CALC_FOUND_ROWS option in the\nSELECT\nstatement, and then invoke FOUND_ROWS() afterwards.\n \nYou can also use FOUND_ROWS() to obtain the number of rows\nreturned by a SELECT which does not contain a LIMIT clause.\nIn this case you don\'t need to use the SQL_CALC_FOUND_ROWS\noption. This can be useful for example in a stored\nprocedure.\n \nAlso, this function works with some other statements which\nreturn a resultset, including SHOW, DESC and HELP. For\nDELETE ... RETURNING you should use ROW_COUNT(). It also\nworks as a prepared statement, or after executing a prepared\nstatement.\n \nStatements which don\'t return any results don\'t affect\nFOUND_ROWS() - the previous value will still be returned.\n \nWarning: When used after a CALL statement, this function\nreturns the number of rows selected by the last query in the\nprocedure, not by the whole procedure.\n \nStatements using the FOUND_ROWS() function are not safe for\nreplication.\n \nExamples\n-------- \nSHOW ENGINES;\n \n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n| Engine | Support | Comment | Transactions | XA |\nSavepoints |\n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n| InnoDB | DEFAULT | Supports transactions, row-level\nlocking, and foreign keys | YES | YES | YES |\n...\n| SPHINX | YES | Sphinx storage engine | NO | NO | NO |\n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n11 rows in set (0.01 sec)\n \nSELECT FOUND_ROWS();\n+--------------+\n| FOUND_ROWS() |\n+--------------+\n| 11 |\n+--------------+\n \nSELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100\nLIMIT 10;\n \nSELECT FOUND_ROWS();\n+--------------+\n| FOUND_ROWS() |\n+--------------+\n| 23 |\n+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/found_rows/','','https://mariadb.com/kb/en/found_rows/'),(393,'SHOW PROFILES',26,'Syntax\n------ \nSHOW PROFILES\n \nDescription\n----------- \nThe SHOW PROFILES statement displays profiling information\nthat indicates resource usage for statements executed during\nthe course of the\ncurrent session. It is used together with \nSHOW PROFILE.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-profiles/','','https://mariadb.com/kb/en/show-profiles/'),(394,'SHOW QUERY_RESPONSE_TIME',26,'SHOW QUERY_RESPONSE_TIME was introduced in MariaDB 10.1.1.\n \nStarting with MariaDB 10.1.1, which introduced the\nInformation Schema plugin extension, it is possible to use\nSHOW QUERY_RESPONSE_TIME as an alternative for retrieving\ninformation from the QUERY_RESPONSE_TIME plugin.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-query_response_time/','','https://mariadb.com/kb/en/show-query_response_time/'),(397,'SHOW SLAVE STATUS',26,'Syntax\n------ \nSHOW SLAVE [\"connection_name\"] STATUS\n \nor\n \nSHOW ALL SLAVES STATUS\n \nDescription\n----------- \nThis statement is to be run on a slave and provides status\ninformation on essential parameters of the replication slave\nthreads.\n \nThis statement requires the SUPER or the REPLICATION_CLIENT\nprivilege.\n \nMulti-source\n \nMariaDB 10.0 introduced the FULL and \"connection_name\"\noptions to\nallow you to connect to many masters at the same time.\n \nALL SLAVES gives you a list of all connections to the\nmaster.\n \nThe rows will be sorted according to Connection_name.\n \nIf you specify a connection_name, you only get the\ninformation about that\nconnection. If connection_name is not used, then the name\nset by default_master_connection is used. If the connection\nname doesn\'t exist you will get an error:\nThere is no master connection for \'xxx\'.\n \nColumn descriptions\n \nName | Description | Added | \n \nConnection_name | Name of the master connection. Returned\nwith SHOW ALL SLAVES STATUS only. | MariaDB 10.0 | \n \nSlave_SQL_State | State of SQL thread. Returned with SHOW\nALL SLAVES STATUS only. See Slave SQL Thread States. |\nMariaDB 10.0 | \n \nSlave_IO_State | State of I/O thread. See Slave I/O Thread\nStates. | MariaDB 10.0 | \n \nMaster_host | Master host that the slave is connected to. | \n| \n \nMaster_user | Account user name being used to connect to the\nmaster. | | \n \nMaster_port | The port being used to connect to the master.\n| | \n \nConnect_Retry | Time in seconds between retries to connect.\nThe default is 60. The CHANGE MASTER TO statement can set\nthis. The master-retry-count option determines the maximum\nnumber of reconnection attempts. | | \n \nMaster_Log_File | Name of the master binary log file that\nthe I/O thread is currently reading from. | | \n \nRead_Master_Log_Pos | Position up to which the I/O thread\nhas read in the current master binary log file. | | \n \nRelay_Log_File | Name of the relay log file that the SQL\nthread is currently processing. | | \n \nRelay_Log_Pos | Position up to which the SQL thread has\nfinished processing in the current relay log file. | | \n \nRelay_Master_Log_File | Name of the master binary log file\nthat contains the most recent event executed by the SQL\nthread. | | \n \nSlave_IO_Running | Whether the slave I/O thread is running\nand connected (Yes), running but not connected to a master\n(Connecting) or not running (No). | | \n \nSlave_SQL_Running | Whether or not the SQL thread is\nrunning. | | \n \nReplicate_Do_DB | Databases specified for replicating with\nthe replicate_do_db option. | | \n \nReplicate_Ignore_DB | Databases specified for ignoring with\nthe replicate_ignore_db option. | | \n \nReplicate_Do_Table | Tables specified for replicating with\nthe replicate_do_table option. | | \n \nReplicate_Ignore_Table | Tables specified for ignoring with\nthe replicate_ignore_table option. | | \n \nReplicate_Wild_Do_Table | Tables specified for replicating\nwith the replicate_wild_do_table option. | | \n \nReplicate_Wild_Ignore_Table | Tables specified for ignoring\nwith the replicate_wild_ignore_table option. | | \n \nLast_Errno | Alias for Last_SQL_Errno (see below) | | \n \nLast Error | Alias for Last_SQL_Error (see below) | | \n \nSkip_Counter | Number of events that a slave skips from the\nmaster, as recorded in the sql_slave_skip_counter system\nvariable. | | \n \nExec_Master_Log_Pos | Position up to which the SQL thread\nhas processed in the current master binary log file. Can be\nused to start a new slave from a current slave with the\nCHANGE MASTER TO ... MASTER_LOG_POS option. | | \n \nRelay_Log_Space | Total size of all relay log files\ncombined. | | \n \nUntil_Condition | | | \n \nUntil_Log_File | The MASTER_LOG_FILE value of the START\nSLAVE UNTIL condition. | | \n \nUntil_Log_Pos | The MASTER_LOG_POS value of the START SLAVE\nUNTIL condition. | | \n \nMaster_SSL_Allowed | Whether an SSL connection is permitted\n(Yes), not permitted (No) or permitted but without the slave\nhaving SSL support enabled (Ignored) | | \n \nMaster_SSL_CA_File | The MASTER_SSL_CA option of the CHANGE\nMASTER TO statement. | | \n \nMaster_SSL_CA_Path | The MASTER_SSL_CAPATH option of the\nCHANGE MASTER TO statement. | | \n \nMaster_SSL_Cert | The MASTER_SSL_CERT option of the CHANGE\nMASTER TO statement. | | \n \nMaster_SSL_Cipher | The MASTER_SSL_CIPHER option of the\nCHANGE MASTER TO statement. | | \n \nMaster_SSL_Key | The MASTER_SSL_KEY option of the CHANGE\nMASTER TO statement. | | \n \nSeconds_Behind_Master | Difference between the timestamp\nlogged on the master for the event that the slave is\ncurrently processing, and the current timestamp on the\nslave. Zero if the slave is not currently processing an\nevent. From MariaDB 10.0.23 and MariaDB 10.1.9, with\nparallel replication, seconds_behind_master is updated only\nafter transactions commit. | | \n \nMaster_SSL_Verify_Server_Cert | The\nMASTER_SSL_VERIFY_SERVER_CERT option of the CHANGE MASTER TO\nstatement. | | \n \nLast_IO_Errno | Error code of the most recent error that\ncaused the I/O thread to stop (also recorded in the slave\'s\nerror log). 0 means no error. RESET SLAVE or RESET MASTER\nwill reset this value. | | \n \nLast_IO_Error | Error message of the most recent error that\ncaused the I/O thread to stop (also recorded in the slave\'s\nerror log). An empty string means no error. RESET SLAVE or\nRESET MASTER will reset this value. | | \n \nLast_SQL_Errno | Error code of the most recent error that\ncaused the SQL thread to stop (also recorded in the slave\'s\nerror log). 0 means no error. RESET SLAVE or RESET MASTER\nwill reset this value. | | \n \nLast_SQL_Error | Error message of the most recent error that\ncaused the SQL thread to stop (also recorded in the slave\'s\nerror log). An empty string means no error. RESET SLAVE or\nRESET MASTER will reset this value. | | \n \nReplicate_Ignore_Server_Ids | List of server_ids that are\ncurrently being ignored for replication purposes, or an\nempty string for none, as specified in the IGNORE_SERVER_IDS\noption of the CHANGE MASTER TO statement. | | \n \nMaster_Server_Id | The master\'s server_id value. | | \n \nMaster_SSL_Crl | The MASTER_SSL_CRL option of the CHANGE\nMASTER TO statement. | MariaDB 10.0 | \n \nMaster_SSL_Crlpath | The MASTER_SSL_CRLPATH option of the\nCHANGE MASTER TO statement. | MariaDB 10.0 | \n \nUsing_Gtid | Whether or not global transaction ID\'s are\nbeing used for replication (can be No, Slave_Pos, or\nCurrent_Pos). | MariaDB 10.0.2 | \n \nGtid_IO_Pos | Current global transaction ID value. | MariaDB\n10.0.2 | \n \nRetried_transactions | Number of retried transactions for\nthis connection. Returned with SHOW ALL SLAVES STATUS only.\n| MariaDB 10.0 | \n \nMax_relay_log_size | Max relay log size for this connection.\nReturned with SHOW ALL SLAVES STATUS only. | MariaDB 10.0 | \n \nExecuted_log_entries | How many log entries the slave has\nexecuted. Returned with SHOW ALL SLAVES STATUS only. |\nMariaDB 10.0 | \n \nSlave_received_heartbeats | How many heartbeats we have got\nfrom the master. Returned with SHOW ALL SLAVES STATUS only.\n| MariaDB 10.0 | \n \nSlave_heartbeat_period | How often to request a heartbeat\npacket from the master (in seconds). Returned with SHOW ALL\nSLAVES STATUS only. | MariaDB 10.0 | \n \nGtid_Slave_Pos | GTID of the last event group replicated on\na slave server, for each replication domain, as stored in\nthe gtid_slave_pos system variable. Returned with SHOW ALL\nSLAVES STATUS only. | MariaDB 10.0 | \n \nSQL_Delay | Value specified by MASTER_DELAY in CHANGE MASTER\n(or 0 if none). | MariaDB 10.2.3 | \n \nSQL_Remaining_Delay | When the slave is delaying the\nexecution of an event due to MASTER_DELAY, this is the\nnumber of seconds of delay remaining before the event will\nbe applied. Otherwise, the value is NULL. | MariaDB 10.2.3 |\n\n \nSlave_SQL_Running_State | The state of the SQL driver\nthreads, same as in SHOW PROCESSLIST. When the slave is\ndelaying the execution of an event due to MASTER_DELAY, this\nfield displays: \"Waiting until MASTER_DELAY seconds after\nmaster executed event\". | MariaDB 10.2.3 | \n \nSlave_DDL_Groups | This status variable counts the\noccurrence of DDL statements. This is a slave-side counter\nfor optimistic parallel replication. | MariaDB 10.3.7 | \n \nSlave_Non_Transactional_Groups | This status variable counts\nthe occurrence of non-transactional event groups. This is a\nslave-side counter for optimistic parallel replication. |\nMariaDB 10.3.7 | \n \nSlave_Transactional_Groups | This status variable counts the\noccurrence of transactional event groups. This is a\nslave-side counter for optimistic parallel replication. |\nMariaDB 10.3.7 | \n \nExamples\n-------- \nIf you issue this statement using the mysql client,\nyou can use a \\G statement terminator rather than a\nsemicolon to\nobtain a more readable vertical layout.\n \nSHOW SLAVE STATUS\\G\n*************************** 1. row\n***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: db01.example.com\n Master_User: replicant\n Master_Port: 3306\n Connect_Retry: 60\n Master_Log_File: mariadb-bin.000010\n Read_Master_Log_Pos: 548\n Relay_Log_File: relay-bin.000004\n Relay_Log_Pos: 837\n Relay_Master_Log_File: mariadb-bin.000010\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB: \n Replicate_Ignore_DB: \n Replicate_Do_Table: \n Replicate_Ignore_Table: \n Replicate_Wild_Do_Table: \n Replicate_Wild_Ignore_Table: \n Last_Errno: 0\n Last_Error: \n Skip_Counter: 0\n Exec_Master_Log_Pos: 548\n Relay_Log_Space: 1497\n Until_Condition: None\n Until_Log_File: \n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File: \n Master_SSL_CA_Path: \n Master_SSL_Cert: \n Master_SSL_Cipher: \n Master_SSL_Key: \n Seconds_Behind_Master: 0\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error: \n Last_SQL_Errno: 0\n Last_SQL_Error: \n Replicate_Ignore_Server_Ids: \n Master_Server_Id: 101\n Master_SSL_Crl: \n Master_SSL_Crlpath: \n Using_Gtid: No\n Gtid_IO_Pos: \n \nMariaDB [(none)]> SHOW ALL SLAVES STATUS\\G\n*************************** 1. row\n***************************\n Connection_name: \n Slave_SQL_State: Slave has read all relay log; waiting for\nthe slave I/O thread to update it\n Slave_IO_State: Waiting for master to send event\n Master_Host: db01.example.com\n Master_User: replicant\n Master_Port: 3306\n Connect_Retry: 60\n Master_Log_File: mariadb-bin.000010\n Read_Master_Log_Pos: 3608\n Relay_Log_File: relay-bin.000004\n Relay_Log_Pos: 3897\n Relay_Master_Log_File: mariadb-bin.000010\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB: \n Replicate_Ignore_DB: \n Replicate_Do_Table: \n Replicate_Ignore_Table: \n Replicate_Wild_Do_Table: \n Replicate_Wild_Ignore_Table: \n Last_Errno: 0\n Last_Error: \n Skip_Counter: 0\n Exec_Master_Log_Pos: 3608\n Relay_Log_Space: 4557\n Until_Condition: None\n Until_Log_File: \n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File: \n Master_SSL_CA_Path: \n Master_SSL_Cert: \n Master_SSL_Cipher: \n Master_SSL_Key: \n Seconds_Behind_Master: 0\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error: \n Last_SQL_Errno: 0\n Last_SQL_Error: \n Replicate_Ignore_Server_Ids: \n Master_Server_Id: 101\n Master_SSL_Crl: \n Master_SSL_Crlpath: \n Using_Gtid: No\n Gtid_IO_Pos:\n Retried_transactions: 0\n Max_relay_log_size: 104857600\n Executed_log_entries: 40\n Slave_received_heartbeats: 11\n Slave_heartbeat_period: 1800.000\n Gtid_Slave_Pos: 0-101-2320\n \nYou can also access some of the variables directly from\nstatus variables:\n \nSET @@default_master_connection=\"test\" ;\nshow status like \"%slave%\"\n \nVariable_name Value\nCom_show_slave_hosts 0\nCom_show_slave_status 0\nCom_start_all_slaves 0\nCom_start_slave 0\nCom_stop_all_slaves 0\nCom_stop_slave 0\nRpl_semi_sync_slave_status OFF\nSlave_connections 0\nSlave_heartbeat_period 1800.000\nSlave_open_temp_tables 0\nSlave_received_heartbeats 0\nSlave_retried_transactions 0\nSlave_running OFF\nSlaves_connected 0\nSlaves_running 1\n \n\n\nURL: https://mariadb.com/kb/en/show-slave-status/','','https://mariadb.com/kb/en/show-slave-status/'),(398,'SHOW STATUS',26,'Syntax\n------ \nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nSHOW STATUS provides server status information. This\ninformation also can be obtained using the mysqladmin\nextended-status command, or by querying the Information\nSchema GLOBAL_STATUS and SESSION_STATUS tables.\nThe LIKE clause, if present, indicates which variable names\nto match. The WHERE clause can be given to select rows using\nmore general conditions.\n \nWith the GLOBAL modifier, SHOW STATUS\ndisplays the status values for all connections to MariaDB.\nWith\nSESSION, it displays the status values\nfor the current connection. If no modifier is present, the\ndefault is\n SESSION. LOCAL is a synonym for\n SESSION. If you see a lot of 0 values, the reason is\nprobably that you have used SHOW STATUS with a new\nconnection instead of SHOW GLOBAL STATUS.\n \nSome status variables have only a global value. For these,\nyou get the\nsame value for both GLOBAL and SESSION.\n \nSee Server Status Variables for a full list, scope and\ndescription of the variables that can be viewed with SHOW\nSTATUS.\n \nThe LIKE clause, if present on its own, indicates which\nvariable name to match.\n \nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nExamples\n-------- \nFull output from MariaDB 10.1.17:\n \nSHOW GLOBAL STATUS;\n \n+--------------------------------------------------------------+----------------------------------------+\n| Variable_name | Value |\n+--------------------------------------------------------------+----------------------------------------+\n| Aborted_clients | 0 |\n| Aborted_connects | 0 |\n| Access_denied_errors | 0 |\n| Acl_column_grants | 0 |\n| Acl_database_grants | 2 |\n| Acl_function_grants | 0 |\n| Acl_procedure_grants | 0 |\n| Acl_proxy_users | 2 |\n| Acl_role_grants | 0 |\n| Acl_roles | 0 |\n| Acl_table_grants | 0 |\n| Acl_users | 6 |\n| Aria_pagecache_blocks_not_flushed | 0 |\n| Aria_pagecache_blocks_unused | 15706 |\n| Aria_pagecache_blocks_used | 0 |\n| Aria_pagecache_read_requests | 0 |\n| Aria_pagecache_reads | 0 |\n| Aria_pagecache_write_requests | 0 |\n| Aria_pagecache_writes | 0 |\n| Aria_transaction_log_syncs | 0 |\n| Binlog_commits | 0 |\n| Binlog_group_commits | 0 |\n| Binlog_group_commit_trigger_count | 0 |\n| Binlog_group_commit_trigger_lock_wait | 0 |\n| Binlog_group_commit_trigger_timeout | 0 |\n| Binlog_snapshot_file | |\n| Binlog_snapshot_position | 0 |\n| Binlog_bytes_written | 0 |\n| Binlog_cache_disk_use | 0 |\n| Binlog_cache_use | 0 |\n| Binlog_stmt_cache_disk_use | 0 |\n| Binlog_stmt_cache_use | 0 |\n| Busy_time | 0.000000 |\n| Bytes_received | 432 |\n| Bytes_sent | 15183 |\n| Com_admin_commands | 1 |\n| Com_alter_db | 0 |\n| Com_alter_db_upgrade | 0 |\n| Com_alter_event | 0 |\n| Com_alter_function | 0 |\n| Com_alter_procedure | 0 |\n| Com_alter_server | 0 |\n| Com_alter_table | 0 |\n| Com_alter_tablespace | 0 |\n| Com_analyze | 0 |\n| Com_assign_to_keycache | 0 |\n| Com_begin | 0 |\n| Com_binlog | 0 |\n| Com_call_procedure | 0 |\n| Com_change_db | 0 |\n| Com_change_master | 0 |\n| Com_check | 0 |\n| Com_checksum | 0 |\n| Com_commit | 0 |\n| Com_compound_sql | 0 |\n| Com_create_db | 0 |\n| Com_create_event | 0 |\n| Com_create_function | 0 |\n| Com_create_index | 0 |\n| Com_create_procedure | 0 |\n| Com_create_role | 0 |\n| Com_create_server | 0 |\n| Com_create_table | 0 |\n| Com_create_temporary_table | 0 |\n| Com_create_trigger | 0 |\n| Com_create_udf | 0 |\n| Com_create_user | 0 |\n| Com_create_view | 0 |\n| Com_dealloc_sql | 0 |\n| Com_delete | 0 |\n| Com_delete_multi | 0 |\n| Com_do | 0 |\n| Com_drop_db | 0 |\n| Com_drop_event | 0 |\n| Com_drop_function | 0 |\n| Com_drop_index | 0 |\n| Com_drop_procedure | 0 |\n| Com_drop_role | 0 |\n| Com_drop_server | 0 |\n| Com_drop_table | 0 |\n| Com_drop_temporary_table | 0 |\n| Com_drop_trigger | 0 |\n| Com_drop_user | 0 |\n| Com_drop_view | 0 |\n| Com_empty_query | 0 |\n| Com_execute_sql | 0 |\n| Com_flush | 0 |\n| Com_get_diagnostics | 0 |\n| Com_grant | 0 |\n| Com_grant_role | 0 |\n| Com_ha_close | 0 |\n| Com_ha_open | 0 |\n| Com_ha_read | 0 |\n| Com_help | 0 |\n| Com_insert | 0 |\n| Com_insert_select | 0 |\n| Com_install_plugin | 0 |\n| Com_kill | 0 |\n| Com_load | 0 |\n| Com_lock_tables | 0 |\n| Com_optimize | 0 |\n| Com_preload_keys | 0 |\n| Com_prepare_sql | 0 |\n| Com_purge | 0 |\n| Com_purge_before_date | 0 |\n| Com_release_savepoint | 0 |\n| Com_rename_table | 0 |\n| Com_rename_user | 0 |\n| Com_repair | 0 |\n| Com_replace | 0 |\n| Com_replace_select | 0 |\n| Com_reset | 0 |\n| Com_resignal | 0 |\n| Com_revoke | 0 |\n| Com_revoke_all | 0 |\n| Com_revoke_role | 0 |\n| Com_rollback | 0 |\n| Com_rollback_to_savepoint | 0 |\n| Com_savepoint | 0 |\n| Com_select | 1 |\n| Com_set_option | 0 |\n| Com_show_authors | 0 |\n| Com_show_binlog_events | 0 |\n| Com_show_binlogs | 0 |\n| Com_show_charsets | 0 |\n| Com_show_collations | 0 |\n| Com_show_contributors | 0 |\n| Com_show_create_db | 0 |\n| Com_show_create_event | 0 |\n| Com_show_create_func | 0 |\n| Com_show_create_proc | 0 |\n| Com_show_create_table | 0 |\n| Com_show_create_trigger | 0 |\n| Com_show_databases | 0 |\n| Com_show_engine_logs | 0 |\n| Com_show_engine_mutex | 0 |\n| Com_show_engine_status | 0 |\n| Com_show_errors | 0 |\n| Com_show_events | 0 |\n| Com_show_explain | 0 |\n| Com_show_fields | 0 |\n| Com_show_function_status | 0 |\n| Com_show_generic | 0 |\n| Com_show_grants | 0 |\n| Com_show_keys | 0 |\n| Com_show_master_status | 0 |\n| Com_show_open_tables | 0 |\n| Com_show_plugins | 0 |\n| Com_show_privileges | 0 |\n| Com_show_procedure_status | 0 |\n| Com_show_processlist | 0 |\n| Com_show_profile | 0 |\n| Com_show_profiles | 0 |\n| Com_show_relaylog_events | 0 |\n| Com_show_slave_hosts | 0 |\n| Com_show_slave_status | 0 |\n| Com_show_status | 2 |\n| Com_show_storage_engines | 0 |\n| Com_show_table_status | 0 |\n| Com_show_tables | 0 |\n| Com_show_triggers | 0 |\n| Com_show_variables | 0 |\n| Com_show_warnings | 0 |\n| Com_shutdown | 0 |\n| Com_signal | 0 |\n| Com_start_all_slaves | 0 |\n| Com_start_slave | 0 |\n| Com_stmt_close | 0 |\n| Com_stmt_execute | 0 |\n| Com_stmt_fetch | 0 |\n| Com_stmt_prepare | 0 |\n| Com_stmt_reprepare | 0 |\n| Com_stmt_reset | 0 |\n| Com_stmt_send_long_data | 0 |\n| Com_stop_all_slaves | 0 |\n| Com_stop_slave | 0 |\n| Com_truncate | 0 |\n| Com_uninstall_plugin | 0 |\n| Com_unlock_tables | 0 |\n| Com_update | 0 |\n| Com_update_multi | 0 |\n| Com_xa_commit | 0 |\n| Com_xa_end | 0 |\n| Com_xa_prepare | 0 |\n| Com_xa_recover | 0 |\n| Com_xa_rollback | 0 |\n| Com_xa_start | 0 |\n| Compression | OFF |\n| Connection_errors_accept | 0 |\n| Connection_errors_internal | 0 |\n| Connection_errors_max_connections | 0 |\n| Connection_errors_peer_address | 0 |\n| Connection_errors_select | 0 |\n| Connection_errors_tcpwrap | 0 |\n| Connections | 4 |\n| Cpu_time | 0.000000 |\n| Created_tmp_disk_tables | 0 |\n| Created_tmp_files | 6 |\n| Created_tmp_tables | 2 |\n| Delayed_errors | 0 |\n| Delayed_insert_threads | 0 |\n| Delayed_writes | 0 |\n| Delete_scan | 0 |\n| Empty_queries | 0 |\n| Executed_events | 0 |\n| Executed_triggers | 0 |\n| Feature_delay_key_write | 0 |\n| Feature_dynamic_columns | 0 |\n| Feature_fulltext | 0 |\n| Feature_gis | 0 |\n| Feature_locale | 0 |\n| Feature_subquery | 0 |\n| Feature_timezone | 0 |\n| Feature_trigger | 0 |\n| Feature_xml | 0 |\n| Flush_commands | 1 |\n| Handler_commit | 1 |\n| Handler_delete | 0 |\n| Handler_discover | 0 |\n| Handler_external_lock | 0 |\n| Handler_icp_attempts | 0 |\n| Handler_icp_match | 0 |\n| Handler_mrr_init | 0 |\n| Handler_mrr_key_refills | 0 |\n| Handler_mrr_rowid_refills | 0 |\n| Handler_prepare | 0 |\n| Handler_read_first | 3 |\n| Handler_read_key | 0 |\n| Handler_read_last | 0 |\n| Handler_read_next | 0 |\n| Handler_read_prev | 0 |\n| Handler_read_retry | 0 |\n| Handler_read_rnd | 0 |\n| Handler_read_rnd_deleted | 0 |\n| Handler_read_rnd_next | 537 |\n| Handler_rollback | 0 |\n| Handler_savepoint | 0 |\n| Handler_savepoint_rollback | 0 |\n| Handler_tmp_update | 0 |\n| Handler_tmp_write | 516 |\n| Handler_update | 0 |\n| Handler_write | 0 |\n| Innodb_available_undo_logs | 128 |\n| Innodb_background_log_sync | 222 |\n| Innodb_buffer_pool_bytes_data | 2523136 |\n| Innodb_buffer_pool_bytes_dirty | 0 |\n| Innodb_buffer_pool_dump_status | Dumping buffer pool(s)\nnot yet started |\n| Innodb_buffer_pool_load_status | Loading buffer pool(s)\nnot yet started |\n| Innodb_buffer_pool_pages_data | 154 |\n| Innodb_buffer_pool_pages_dirty | 0 |\n| Innodb_buffer_pool_pages_flushed | 1 |\n| Innodb_buffer_pool_pages_free | 8037 |\n| Innodb_buffer_pool_pages_lru_flushed | 0 |\n| Innodb_buffer_pool_pages_made_not_young | 0 |\n| Innodb_buffer_pool_pages_made_young | 0 |\n| Innodb_buffer_pool_pages_misc | 0 |\n| Innodb_buffer_pool_pages_old | 0 |\n| Innodb_buffer_pool_pages_total | 8191 |\n| Innodb_buffer_pool_read_ahead | 0 |\n| Innodb_buffer_pool_read_ahead_evicted | 0 |\n| Innodb_buffer_pool_read_ahead_rnd | 0 |\n| Innodb_buffer_pool_read_requests | 558 |\n| Innodb_buffer_pool_reads | 155 |\n| Innodb_buffer_pool_wait_free | 0 |\n| Innodb_buffer_pool_write_requests | 1 |\n| Innodb_checkpoint_age | 0 |\n| Innodb_checkpoint_max_age | 80826164 |\n| Innodb_data_fsyncs | 5 |\n| Innodb_data_pending_fsyncs | 0 |\n| Innodb_data_pending_reads | 0 |\n| Innodb_data_pending_writes | 0 |\n| Innodb_data_read | 2609664 |\n| Innodb_data_reads | 172 |\n| Innodb_data_writes | 5 |\n| Innodb_data_written | 34304 |\n| Innodb_dblwr_pages_written | 1 |\n| Innodb_dblwr_writes | 1 |\n| Innodb_deadlocks | 0 |\n| Innodb_have_atomic_builtins | ON |\n| Innodb_history_list_length | 0 |\n| Innodb_ibuf_discarded_delete_marks | 0 |\n| Innodb_ibuf_discarded_deletes | 0 |\n| Innodb_ibuf_discarded_inserts | 0 |\n| Innodb_ibuf_free_list | 0 |\n| Innodb_ibuf_merged_delete_marks | 0 |\n| Innodb_ibuf_merged_deletes | 0 |\n| Innodb_ibuf_merged_inserts | 0 |\n| Innodb_ibuf_merges | 0 |\n| Innodb_ibuf_segment_size | 2 |\n| Innodb_ibuf_size | 1 |\n| Innodb_log_waits | 0 |\n| Innodb_log_write_requests | 0 |\n| Innodb_log_writes | 1 |\n| Innodb_lsn_current | 1616829 |\n| Innodb_lsn_flushed | 1616829 |\n| Innodb_lsn_last_checkpoint | 1616829 |\n| Innodb_master_thread_active_loops | 0 |\n| Innodb_master_thread_idle_loops | 222 |\n| Innodb_max_trx_id | 2308 |\n| Innodb_mem_adaptive_hash | 2217568 |\n| Innodb_mem_dictionary | 630703 |\n| Innodb_mem_total | 140771328 |\n| Innodb_mutex_os_waits | 1 |\n| Innodb_mutex_spin_rounds | 30 |\n| Innodb_mutex_spin_waits | 1 |\n| Innodb_oldest_view_low_limit_trx_id | 0 |\n| Innodb_os_log_fsyncs | 3 |\n| Innodb_os_log_pending_fsyncs | 0 |\n| Innodb_os_log_pending_writes | 0 |\n| Innodb_os_log_written | 512 |\n| Innodb_page_size | 16384 |\n| Innodb_pages_created | 0 |\n| Innodb_pages_read | 154 |\n| Innodb_pages_written | 1 |\n| Innodb_purge_trx_id | 0 |\n| Innodb_purge_undo_no | 0 |\n| Innodb_read_views_memory | 88 |\n| Innodb_row_lock_current_waits | 0 |\n| Innodb_row_lock_time | 0 |\n| Innodb_row_lock_time_avg | 0 |\n| Innodb_row_lock_time_max | 0 |\n| Innodb_row_lock_waits | 0 |\n| Innodb_rows_deleted | 0 |\n| Innodb_rows_inserted | 0 |\n| Innodb_rows_read | 0 |\n| Innodb_rows_updated | 0 |\n| Innodb_system_rows_deleted | 0 |\n| Innodb_system_rows_inserted | 0 |\n| Innodb_system_rows_read | 0 |\n| Innodb_system_rows_updated | 0 |\n| Innodb_s_lock_os_waits | 2 |\n| Innodb_s_lock_spin_rounds | 60 |\n| Innodb_s_lock_spin_waits | 2 |\n| Innodb_truncated_status_writes | 0 |\n| Innodb_x_lock_os_waits | 0 |\n| Innodb_x_lock_spin_rounds | 0 |\n| Innodb_x_lock_spin_waits | 0 |\n| Innodb_page_compression_saved | 0 |\n| Innodb_page_compression_trim_sect512 | 0 |\n| Innodb_page_compression_trim_sect1024 | 0 |\n| Innodb_page_compression_trim_sect2048 | 0 |\n| Innodb_page_compression_trim_sect4096 | 0 |\n| Innodb_page_compression_trim_sect8192 | 0 |\n| Innodb_page_compression_trim_sect16384 | 0 |\n| Innodb_page_compression_trim_sect32768 | 0 |\n| Innodb_num_index_pages_written | 0 |\n| Innodb_num_non_index_pages_written | 5 |\n| Innodb_num_pages_page_compressed | 0 |\n| Innodb_num_page_compressed_trim_op | 0 |\n| Innodb_num_page_compressed_trim_op_saved | 0 |\n| Innodb_num_pages_page_decompressed | 0 |\n| Innodb_num_pages_page_compression_error | 0 |\n| Innodb_num_pages_encrypted | 0 |\n| Innodb_num_pages_decrypted | 0 |\n| Innodb_have_lz4 | OFF |\n| Innodb_have_lzo | OFF |\n| Innodb_have_lzma | OFF |\n| Innodb_have_bzip2 | OFF |\n| Innodb_have_snappy | OFF |\n| Innodb_defragment_compression_failures | 0 |\n| Innodb_defragment_failures | 0 |\n| Innodb_defragment_count | 0 |\n| Innodb_onlineddl_rowlog_rows | 0 |\n| Innodb_onlineddl_rowlog_pct_used | 0 |\n| Innodb_onlineddl_pct_progress | 0 |\n| Innodb_secondary_index_triggered_cluster_reads | 0 |\n| Innodb_secondary_index_triggered_cluster_reads_avoided | 0\n|\n| Innodb_encryption_rotation_pages_read_from_cache | 0 |\n| Innodb_encryption_rotation_pages_read_from_disk | 0 |\n| Innodb_encryption_rotation_pages_modified | 0 |\n| Innodb_encryption_rotation_pages_flushed | 0 |\n| Innodb_encryption_rotation_estimated_iops | 0 |\n| Innodb_scrub_background_page_reorganizations | 0 |\n| Innodb_scrub_background_page_splits | 0 |\n| Innodb_scrub_background_page_split_failures_underflow | 0\n|\n|\nInnodb_scrub_background_page_split_failures_out_of_filespace\n| 0 |\n| Innodb_scrub_background_page_split_failures_missing_index\n| 0 |\n| Innodb_scrub_background_page_split_failures_unknown | 0 |\n| Key_blocks_not_flushed | 0 |\n| Key_blocks_unused | 107163 |\n| Key_blocks_used | 0 |\n| Key_blocks_warm | 0 |\n| Key_read_requests | 0 |\n| Key_reads | 0 |\n| Key_write_requests | 0 |\n| Key_writes | 0 |\n| Last_query_cost | 0.000000 |\n| Master_gtid_wait_count | 0 |\n| Master_gtid_wait_time | 0 |\n| Master_gtid_wait_timeouts | 0 |\n| Max_statement_time_exceeded | 0 |\n| Max_used_connections | 1 |\n| Memory_used | 273614696 |\n| Not_flushed_delayed_rows | 0 |\n| Open_files | 25 |\n| Open_streams | 0 |\n| Open_table_definitions | 18 |\n| Open_tables | 11 |\n| Opened_files | 77 |\n| Opened_plugin_libraries | 0 |\n| Opened_table_definitions | 18 |\n| Opened_tables | 18 |\n| Opened_views | 0 |\n| Performance_schema_accounts_lost | 0 |\n| Performance_schema_cond_classes_lost | 0 |\n| Performance_schema_cond_instances_lost | 0 |\n| Performance_schema_digest_lost | 0 |\n| Performance_schema_file_classes_lost | 0 |\n| Performance_schema_file_handles_lost | 0 |\n| Performance_schema_file_instances_lost | 0 |\n| Performance_schema_hosts_lost | 0 |\n| Performance_schema_locker_lost | 0 |\n| Performance_schema_mutex_classes_lost | 0 |\n| Performance_schema_mutex_instances_lost | 0 |\n| Performance_schema_rwlock_classes_lost | 0 |\n| Performance_schema_rwlock_instances_lost | 0 |\n| Performance_schema_session_connect_attrs_lost | 0 |\n| Performance_schema_socket_classes_lost | 0 |\n| Performance_schema_socket_instances_lost | 0 |\n| Performance_schema_stage_classes_lost | 0 |\n| Performance_schema_statement_classes_lost | 0 |\n| Performance_schema_table_handles_lost | 0 |\n| Performance_schema_table_instances_lost | 0 |\n| Performance_schema_thread_classes_lost | 0 |\n| Performance_schema_thread_instances_lost | 0 |\n| Performance_schema_users_lost | 0 |\n| Prepared_stmt_count | 0 |\n| Qcache_free_blocks | 1 |\n| Qcache_free_memory | 1031336 |\n| Qcache_hits | 0 |\n| Qcache_inserts | 0 |\n| Qcache_lowmem_prunes | 0 |\n| Qcache_not_cached | 0 |\n| Qcache_queries_in_cache | 0 |\n| Qcache_total_blocks | 1 |\n| Queries | 4 |\n| Questions | 4 |\n| Rows_read | 10 |\n| Rows_sent | 517 |\n| Rows_tmp_read | 516 |\n| Rpl_status | AUTH_MASTER |\n| Select_full_join | 0 |\n| Select_full_range_join | 0 |\n| Select_range | 0 |\n| Select_range_check | 0 |\n| Select_scan | 2 |\n| Slave_connections | 0 |\n| Slave_heartbeat_period | 0.000 |\n| Slave_open_temp_tables | 0 |\n| Slave_received_heartbeats | 0 |\n| Slave_retried_transactions | 0 |\n| Slave_running | OFF |\n| Slave_skipped_errors | 0 |\n| Slaves_connected | 0 |\n| Slaves_running | 0 |\n| Slow_launch_threads | 0 |\n| Slow_queries | 0 |\n| Sort_merge_passes | 0 |\n| Sort_priority_queue_sorts | 0 |\n| Sort_range | 0 |\n| Sort_rows | 0 |\n| Sort_scan | 0 |\n| Ssl_accept_renegotiates | 0 |\n| Ssl_accepts | 0 |\n| Ssl_callback_cache_hits | 0 |\n| Ssl_cipher | |\n| Ssl_cipher_list | |\n| Ssl_client_connects | 0 |\n| Ssl_connect_renegotiates | 0 |\n| Ssl_ctx_verify_depth | 0 |\n| Ssl_ctx_verify_mode | 0 |\n| Ssl_default_timeout | 0 |\n| Ssl_finished_accepts | 0 |\n| Ssl_finished_connects | 0 |\n| Ssl_server_not_after | |\n| Ssl_server_not_before | |\n| Ssl_session_cache_hits | 0 |\n| Ssl_session_cache_misses | 0 |\n| Ssl_session_cache_mode | NONE |\n| Ssl_session_cache_overflows | 0 |\n| Ssl_session_cache_size | 0 |\n| Ssl_session_cache_timeouts | 0 |\n| Ssl_sessions_reused | 0 |\n| Ssl_used_session_cache_entries | 0 |\n| Ssl_verify_depth | 0 |\n| Ssl_verify_mode | 0 |\n| Ssl_version | |\n| Subquery_cache_hit | 0 |\n| Subquery_cache_miss | 0 |\n| Syncs | 2 |\n| Table_locks_immediate | 21 |\n| Table_locks_waited | 0 |\n| Tc_log_max_pages_used | 0 |\n| Tc_log_page_size | 4096 |\n| Tc_log_page_waits | 0 |\n| Threadpool_idle_threads | 0 |\n| Threadpool_threads | 0 |\n| Threads_cached | 0 |\n| Threads_connected | 1 |\n| Threads_created | 2 |\n| Threads_running | 1 |\n| Update_scan | 0 |\n| Uptime | 223 |\n| Uptime_since_flush_status | 223 |\n| wsrep_cluster_conf_id | 18446744073709551615 |\n| wsrep_cluster_size | 0 |\n| wsrep_cluster_state_uuid | |\n| wsrep_cluster_status | Disconnected |\n| wsrep_connected | OFF |\n| wsrep_local_bf_aborts | 0 |\n| wsrep_local_index | 18446744073709551615 |\n| wsrep_provider_name | |\n| wsrep_provider_vendor | |\n| wsrep_provider_version | |\n| wsrep_ready | OFF |\n| wsrep_thread_count | 0 |\n+--------------------------------------------------------------+----------------------------------------+\n516 rows in set (0.00 sec)\n \nExample of filtered output:\n \nSHOW STATUS LIKE \'Key%\';\n \n+------------------------+--------+\n| Variable_name | Value |\n+------------------------+--------+\n| Key_blocks_not_flushed | 0 |\n| Key_blocks_unused | 107163 |\n| Key_blocks_used | 0 |\n| Key_blocks_warm | 0 |\n| Key_read_requests | 0 |\n| Key_reads | 0 |\n| Key_write_requests | 0 |\n| Key_writes | 0 |\n+------------------------+--------+\n8 rows in set (0.00 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-status/','','https://mariadb.com/kb/en/show-status/'),(411,'DO',27,'Syntax\n------ \nDO expr [, expr] ...\n \nDescription\n----------- \n DO executes the expressions but does not return any\nresults. In most respects, DO is shorthand for\n SELECT expr, ..., but has the advantage that it is slightly\nfaster when you do not care about the result.\n \n DO is useful primarily with functions that have side\n effects, such as RELEASE_LOCK().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/do/','','https://mariadb.com/kb/en/do/'),(212,'LAST_INSERT_ID',17,'Syntax\n------ \nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n \nDescription\n----------- \nLAST_INSERT_ID() (no arguments) returns\nthe first automatically generated value successfully\ninserted for an\nAUTO_INCREMENT column as a result of the most recently\nexecuted INSERT\nstatement. The value of LAST_INSERT_ID() remains unchanged\nif no rows\nare successfully inserted.\n \nIf one gives an argument to LAST_INSERT_ID(), then it will\nreturn the value of the expression and\nthe next call to LAST_INSERT_ID() will return the same\nvalue. The value will also be sent to the client\nand can be accessed by the mysql_insert_id function.\n \nFor example, after inserting a row that generates an\nAUTO_INCREMENT\nvalue, you can get the value like this:\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 9 |\n+------------------+\n \nYou can also use LAST_INSERT_ID() to delete the last\ninserted row:\n \nDELETE FROM product WHERE id = LAST_INSERT_ID();\n \nIf no rows were successfully inserted, LAST_INSERT_ID()\nreturns 0.\n \nThe value of LAST_INSERT_ID() will be consistent across all\nversions\nif all rows in the INSERT or UPDATE statement were\nsuccessful.\n \nThe currently executing statement does not affect the value\nof\nLAST_INSERT_ID(). Suppose that you generate an\nAUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table\nwith its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID()\nwill remain\nstable in the second statement; its value for the second and\nlater\nrows is not affected by the earlier row insertions.\n(However, if you\nmix references to LAST_INSERT_ID() and LAST_INSERT_ID(expr),\nthe\neffect is undefined.)\n \nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if\nthe\nstatement is rolled back due to an error, the value of\nLAST_INSERT_ID() is left undefined. For manual ROLLBACK, the\nvalue of\nLAST_INSERT_ID() is not restored to that before the\ntransaction; it\nremains as it was at the point of the ROLLBACK.\n \nWithin the body of a stored routine (procedure or function)\nor a\ntrigger, the value of LAST_INSERT_ID() changes the same way\nas for\nstatements executed outside the body of these kinds of\nobjects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements\ndepends on the\nkind of routine:\nIf a stored procedure executes statements that change the\nvalue of LAST_INSERT_ID(), the new value will be seen by\nstatements that follow the procedure call.\n \nFor stored functions and triggers that change the value, the\nvalue is restored when the function or trigger ends, so\nfollowing statements will not see a changed value.\n \nExamples\n-------- \nCREATE TABLE t (\n id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY, \n f VARCHAR(1)) \nENGINE = InnoDB;\n \nINSERT INTO t(f) VALUES(\'a\');\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 1 |\n+------------------+\n \nINSERT INTO t(f) VALUES(\'b\');\n \nINSERT INTO t(f) VALUES(\'c\');\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 3 |\n+------------------+\n \nINSERT INTO t(f) VALUES(\'d\'),(\'e\');\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 4 |\n+------------------+\n \nSELECT * FROM t;\n \n+----+------+\n| id | f |\n+----+------+\n| 1 | a |\n| 2 | b |\n| 3 | c |\n| 4 | d |\n| 5 | e |\n+----+------+\n \nSELECT LAST_INSERT_ID(12);\n+--------------------+\n| LAST_INSERT_ID(12) |\n+--------------------+\n| 12 |\n+--------------------+\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 12 |\n+------------------+\n \nINSERT INTO t(f) VALUES(\'f\');\n \nSELECT LAST_INSERT_ID();\n+------------------+\n| LAST_INSERT_ID() |\n+------------------+\n| 6 |\n+------------------+\n \nSELECT * FROM t;\n \n+----+------+\n| id | f |\n+----+------+\n| 1 | a |\n| 2 | b |\n| 3 | c |\n| 4 | d |\n| 5 | e |\n| 6 | f |\n+----+------+\n \nSELECT LAST_INSERT_ID(12);\n+--------------------+\n| LAST_INSERT_ID(12) |\n+--------------------+\n| 12 |\n+--------------------+\n \nINSERT INTO t(f) VALUES(\'g\');\n \nSELECT * FROM t;\n \n+----+------+\n| id | f |\n+----+------+\n| 1 | a |\n| 2 | b |\n| 3 | c |\n| 4 | d |\n| 5 | e |\n| 6 | f |\n| 7 | g |\n+----+------+\n \n\n\nURL: https://mariadb.com/kb/en/last_insert_id/','','https://mariadb.com/kb/en/last_insert_id/'),(214,'PROCEDURE ANALYSE',17,'Syntax\n------ \nanalyse([max_elements[,max_memory]])\n \nDescription\n----------- \nThis procedure is defined in the sql/sql_analyse.cc file. It\nexamines\nthe result from a query and returns an analysis of the\nresults that\nsuggests optimal data types for each column. To obtain this\nanalysis,\nappend PROCEDURE ANALYSE to the end of a SELECT statement:\n \nSELECT ... FROM ... WHERE ... PROCEDURE\nANALYSE([max_elements,[max_memory]])\n \nFor example:\n \nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n \nThe results show some statistics for the values returned by\nthe query,\nand propose an optimal data type for the columns. This can\nbe helpful\nfor checking your existing tables, or after importing new\ndata. You\nmay need to try different settings for the arguments so that\nPROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n \nThe arguments are optional and are used as follows:\nmax_elements (default 256) is the maximum number of distinct\nvalues that analyse notices per column. This is used by\nanalyse to check whether the optimal data type should be of\ntype ENUM; if there are more than max_elements distinct\nvalues, then ENUM is not a suggested type.\nmax_memory (default 8192) is the maximum amount of memory\nthat analyse should allocate per column while trying to find\nall distinct values.\n \n\n\nURL: https://mariadb.com/kb/en/procedure-analyse/','','https://mariadb.com/kb/en/procedure-analyse/'),(412,'DUAL',27,'Description\n----------- \nYou are allowed to specify DUAL as a dummy table name in\nsituations where no tables are referenced, such as the\nfollowing SELECT statement:\n \nSELECT 1 + 1 FROM DUAL;\n \n+-------+\n| 1 + 1 |\n+-------+\n| 2 |\n+-------+\n \n DUAL is purely for the convenience of people who require\n that all SELECT statements should have\n FROM and possibly other clauses. MariaDB ignores the\n clauses. MariaDB does not require FROM DUAL if no tables\n are referenced.\n \nFROM DUAL could be used when you only SELECT computed\nvalues, but require a WHERE clause, perhaps to test that a\nscript correctly handles empty resultsets:\n \nSELECT 1 FROM DUAL WHERE FALSE;\n \nEmpty set (0.00 sec)\n \n\n\nURL: https://mariadb.com/kb/en/dual/','','https://mariadb.com/kb/en/dual/'),(414,'FOR UPDATE',27,'The FOR UPDATE clause of SELECT applies only when autocommit\nis set to 0 or the SELECT is enclosed in a transaction. A\nlock is acquired on the rows, and other transactions are\nprevented from writing the rows, acquire locks, and from\nreading them (unless their isolation level is READ\nUNCOMMITTED).\n \nIf autocommit is set to 1, the LOCK IN SHARE MODE and FOR\nUPDATE clauses have no effect.\n \nIf the isolation level is set to SERIALIZABLE, all plain\nSELECT statements are converted to SELECT ... LOCK IN SHARE\nMODE.\n \nExample\n \nSELECT * FROM trans WHERE period=2001 FOR UPDATE;\n \n\n\nURL: https://mariadb.com/kb/en/for-update/','','https://mariadb.com/kb/en/for-update/'),(213,'LAST_VALUE',17,'Syntax\n------ \nLAST_VALUE(expr,[expr,...])\n \nLAST_VALUE(expr) OVER (\n [ PARTITION BY partition_expression ]\n [ ORDER BY order_list ]\n) \n \nDescription\n----------- \nLAST_VALUE() evaluates all expressions and returns the last.\n \nThis is useful together with setting user variables to a\nvalue with @var:=expr, for example when you want to get data\nof rows updated/deleted without having to do two queries\nagainst the table.\n \nSince MariaDB 10.2.2, LAST_VALUE can be used as a window\nfunction.\n \nReturns NULL if no last value exists.\n \nExamples\n-------- \nCREATE TABLE t1 (a int, b int);\nINSERT INTO t1 VALUES(1,10),(2,20);\nDELETE FROM t1 WHERE a=1 AND last_value(@a:=a,@b:=b,1);\nSELECT @a,@b;\n \n+------+------+\n| @a | @b |\n+------+------+\n| 1 | 10 |\n+------+------+\n \nAs a window function:\n \nCREATE TABLE t1 (\n pk int primary key,\n a int,\n b int,\n c char(10),\n d decimal(10, 3),\n e real\n);\n \nINSERT INTO t1 VALUES\n( 1, 0, 1, \'one\', 0.1, 0.001),\n( 2, 0, 2, \'two\', 0.2, 0.002),\n( 3, 0, 3, \'three\', 0.3, 0.003),\n( 4, 1, 2, \'three\', 0.4, 0.004),\n( 5, 1, 1, \'two\', 0.5, 0.005),\n( 6, 1, 1, \'one\', 0.6, 0.006),\n( 7, 2, NULL, \'n_one\', 0.5, 0.007),\n( 8, 2, 1, \'n_two\', NULL, 0.008),\n( 9, 2, 2, NULL, 0.7, 0.009),\n(10, 2, 0, \'n_four\', 0.8, 0.010),\n(11, 2, 10, NULL, 0.9, NULL);\n \nSELECT pk, FIRST_VALUE(pk) OVER (ORDER BY pk) AS first_asc,\n LAST_VALUE(pk) OVER (ORDER BY pk) AS last_asc,\n FIRST_VALUE(pk) OVER (ORDER BY pk DESC) AS first_desc,\n LAST_VALUE(pk) OVER (ORDER BY pk DESC) AS last_desc\nFROM t1\nORDER BY pk DESC;\n \n+----+-----------+----------+------------+-----------+\n| pk | first_asc | last_asc | first_desc | last_desc |\n+----+-----------+----------+------------+-----------+\n| 11 | 1 | 11 | 11 | 11 |\n| 10 | 1 | 10 | 11 | 10 |\n| 9 | 1 | 9 | 11 | 9 |\n| 8 | 1 | 8 | 11 | 8 |\n| 7 | 1 | 7 | 11 | 7 |\n| 6 | 1 | 6 | 11 | 6 |\n| 5 | 1 | 5 | 11 | 5 |\n| 4 | 1 | 4 | 11 | 4 |\n| 3 | 1 | 3 | 11 | 3 |\n| 2 | 1 | 2 | 11 | 2 |\n| 1 | 1 | 1 | 11 | 1 |\n+----+-----------+----------+------------+-----------+\n \nCREATE OR REPLACE TABLE t1 (i int);\nINSERT INTO t1 VALUES\n(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);\n \nSELECT i,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW\nand 1 FOLLOWING) AS f_1f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW and\n1 FOLLOWING) AS l_1f,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 PRECEDING\nAND 1 FOLLOWING) AS f_1p1f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 PRECEDING AND\n1 FOLLOWING) AS f_1p1f,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 2 PRECEDING\nAND 1 PRECEDING) AS f_2p1p,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 2 PRECEDING AND\n1 PRECEDING) AS f_2p1p,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 FOLLOWING\nAND 2 FOLLOWING) AS f_1f2f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 FOLLOWING AND\n2 FOLLOWING) AS f_1f2f\nFROM t1;\n \n+------+------+------+--------+--------+--------+--------+--------+--------+\n| i | f_1f | l_1f | f_1p1f | f_1p1f | f_2p1p | f_2p1p |\nf_1f2f | f_1f2f |\n+------+------+------+--------+--------+--------+--------+--------+--------+\n| 1 | 1 | 2 | 1 | 2 | NULL | NULL | 2 | 3 |\n| 2 | 2 | 3 | 1 | 3 | 1 | 1 | 3 | 4 |\n| 3 | 3 | 4 | 2 | 4 | 1 | 2 | 4 | 5 |\n| 4 | 4 | 5 | 3 | 5 | 2 | 3 | 5 | 6 |\n| 5 | 5 | 6 | 4 | 6 | 3 | 4 | 6 | 7 |\n| 6 | 6 | 7 | 5 | 7 | 4 | 5 | 7 | 8 |\n| 7 | 7 | 8 | 6 | 8 | 5 | 6 | 8 | 9 |\n| 8 | 8 | 9 | 7 | 9 | 6 | 7 | 9 | 10 |\n| 9 | 9 | 10 | 8 | 10 | 7 | 8 | 10 | 10 |\n| 10 | 10 | 10 | 9 | 10 | 8 | 9 | NULL | NULL |\n+------+------+------+--------+--------+--------+--------+--------+--------+\n \n\n\nURL: https://mariadb.com/kb/en/last_value/','','https://mariadb.com/kb/en/last_value/'),(215,'ROW_COUNT',17,'Syntax\n------ \nROW_COUNT()\n \nDescription\n----------- \nROW_COUNT() returns the number of rows updated, inserted or\ndeleted\nby the preceding statement. This is the same as the row\ncount that the\nmysql client displays and the value from the\nmysql_affected_rows() C\nAPI function.\n \nGenerally:\nFor statements which return a result set (such as SELECT,\nSHOW, DESC or HELP), returns -1, even when the result set is\nempty. This is also true for administrative statements, such\nas OPTIMIZE.\nFor DML statements other than SELECT and for ALTER TABLE,\nreturns the number of affected rows.\nFor DDL statements (including TRUNCATE) and for other\nstatements which don\'t return any result set (such as USE,\nDO, SIGNAL or DEALLOCATE PREPARE), returns 0.\n \nFor UPDATE, affected rows is by default the number of rows\nthat were actually changed. If the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() is specified when connecting to mysqld,\naffected rows is instead the number of rows matched by the\nWHERE clause. \n \nFor REPLACE, deleted rows are also counted. So, if REPLACE\ndeletes a row and adds a new row, ROW_COUNT() returns 2.\n \nFor INSERT ... ON DUPLICATE KEY, updated rows are counted\ntwice. So, if INSERT adds a new rows and modifies another\nrow, ROW_COUNT() returns 3.\n \nROW_COUNT() does not take into account rows that are not\ndirectly deleted/updated by the last statement. This means\nthat rows deleted by foreign keys or triggers are not\ncounted.\n \nWarning: You can use ROW_COUNT() with prepared statements,\nbut you need to call it after EXECUTE, not after DEALLOCATE\nPREPARE, because the row count for allocate prepare is\nalways 0.\n \nWarning: When used after a CALL statement, this function\nreturns the number of rows affected by the last statement in\nthe procedure, not by the whole procedure.\n \nWarning: After INSERT DELAYED, ROW_COUNT() returns the\nnumber of the rows you tried to insert, not the number of\nthe successful writes.\n \nThis information can also be found in the diagnostics area.\n \nStatements using the ROW_COUNT() function are not safe for\nreplication.\n \nExamples\n-------- \nCREATE TABLE t (A INT);\n \nINSERT INTO t VALUES(1),(2),(3);\n \nSELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n \nDELETE FROM t WHERE A IN(1,2);\n \nSELECT ROW_COUNT(); \n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n \nExample with prepared statements:\n \nSET @q = \'INSERT INTO t VALUES(1),(2),(3);\';\n \nPREPARE stmt FROM @q;\n \nEXECUTE stmt;\n \nQuery OK, 3 rows affected (0.39 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n \nSELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/row_count/','','https://mariadb.com/kb/en/row_count/'),(416,'HANDLER Commands',27,'Syntax\n------ \nHANDLER tbl_name OPEN [ [AS] alias]\nHANDLER tbl_name READ index_name { = | >= | = | \n\nURL: https://mariadb.com/kb/en/handler-commands/','','https://mariadb.com/kb/en/handler-commands/'),(430,'LOCK IN SHARE MODE',27,'When LOCK IN SHARE MODE is specified in a SELECT statement,\nMariaDB will wait until all transactions that have modified\nthe rows are committed. Then, a write lock is acquired. All\ntransactions can read the rows, but if they want to modify\nthem, they have to wait until your transaction is committed.\n \nInnoDB/XtraDB supports row-level locking. selected rows can\nbe locked using LOCK IN SHARE MODE or FOR UPDATE. In both\ncases, a lock is acquired on the rows read by the query, and\nit will be released when the current transaction is\ncommitted.\n \nIf autocommit is set to 1, the LOCK IN SHARE MODE and FOR\nUPDATE clauses have no effect.\n \n\n\nURL: https://mariadb.com/kb/en/lock-in-share-mode/','','https://mariadb.com/kb/en/lock-in-share-mode/'),(219,'USER',17,'Syntax\n------ \nUSER()\n \nDescription\n----------- \nReturns the current MariaDB user name and host name, given\nwhen authenticating to MariaDB, as a string in the utf8\ncharacter set.\n \nNote that the value of USER() may differ from the value of\nCURRENT_USER(), which is the user used to authenticate the\ncurrent client. \nCURRENT_ROLE() returns the current active role.\n \nSYSTEM_USER() and SESSION_USER are synonyms for USER().\n \nStatements using the USER() function or one of its synonyms\nare not safe for statement level replication.\n \nExamples\n-------- \nshell> mysql --user=\"anonymous\"\n \nMariaDB [(none)]> select user(),current_user();\n+---------------------+----------------+\n| user() | current_user() |\n+---------------------+----------------+\n| anonymous@localhost | @localhost |\n+---------------------+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/user/','','https://mariadb.com/kb/en/user/'),(220,'VERSION',17,'Syntax\n------ \nVERSION()\n \nDescription\n----------- \nReturns a string that indicates the MariaDB server version.\nThe string\nuses the utf8 character set.\n \nExamples\n-------- \nSELECT VERSION();\n+----------------+\n| VERSION() |\n+----------------+\n| 10.4.7-MariaDB |\n+----------------+\n \nThe VERSION() string may have one or more of the following\nsuffixes:\n \nSuffix | Description | \n \n-embedded | The server is an embedded server (libmysqld). | \n \n-log | General logging, slow logging or binary (replication)\nlogging is enabled. | \n \n-debug | The server is compiled for debugging. | \n \n-valgrind |  The server is compiled to be instrumented with\nvalgrind. | \n \nChanging the Version String\n \nSome old legacy code may break because they are parsing the\nVERSION string and expecting a MySQL string or a simple\nversion\nstring like Joomla til API17, see MDEV-7780.\n \nFrom MariaDB 10.2, one can fool these applications by\nsetting the version string from the command line or the\nmy.cnf files with --version=....\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/version/','','https://mariadb.com/kb/en/version/'),(221,'Not Equal Operator',18,'Syntax\n------ \n, !=\n \nDescription\n----------- \nNot equal operator. Evaluates both SQL expressions and\nreturns 1 if they are not equal and 0 if they are equal, or\nNULL if either expression is NULL. If the expressions return\ndifferent data types, (for instance, a number and a string),\nperforms type conversion.\n \nWhen used in row comparisons these two queries return the\nsame results:\n \nSELECT (t1.a, t1.b) != (t2.x, t2.y) \nFROM t1 INNER JOIN t2;\n \nSELECT (t1.a != t2.x) OR (t1.b != t2.y)\nFROM t1 INNER JOIN t2;\n \nExamples\n-------- \nSELECT \'.01\' \'0.01\';\n \n+-----------------+\n| \'.01\' \'0.01\' |\n+-----------------+\n| 1 |\n+-----------------+\n \nSELECT .01 \'0.01\';\n \n+---------------+\n| .01 \'0.01\' |\n+---------------+\n| 0 |\n+---------------+\n \nSELECT \'zapp\' \'zappp\';\n \n+-------------------+\n| \'zapp\' \'zappp\' |\n+-------------------+\n| 1 |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not-equal/','','https://mariadb.com/kb/en/not-equal/'),(224,'<=>',18,'Syntax\n------ \n\n \nDescription\n----------- \nNULL-safe equal operator. It performs an equality comparison\nlike\nthe = operator, but returns 1 rather than NULL if both\noperands are\nNULL, and 0 rather than NULL if one operand is NULL.\n \na b is equivalent to a = b OR (a IS NULL AND b IS NULL).\n \nWhen used in row comparisons these two queries return the\nsame results:\n \nSELECT (t1.a, t1.b) (t2.x, t2.y) \nFROM t1 INNER JOIN t2;\n \nSELECT (t1.a t2.x) AND (t1.b t2.y)\nFROM t1 INNER JOIN t2;\n \nSee also NULL Values in MariaDB.\n \nExamples\n-------- \nSELECT 1 1, NULL NULL, 1 NULL;\n \n+---------+---------------+------------+\n| 1 1 | NULL NULL | 1 NULL |\n+---------+---------------+------------+\n| 1 | 1 | 0 |\n+---------+---------------+------------+\n \nSELECT 1 = 1, NULL = NULL, 1 = NULL;\n \n+-------+-------------+----------+\n| 1 = 1 | NULL = NULL | 1 = NULL |\n+-------+-------------+----------+\n| 1 | NULL | NULL |\n+-------+-------------+----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/null-safe-equal/','','https://mariadb.com/kb/en/null-safe-equal/'),(225,'=',18,'Syntax\n------ \nleft_expr = right_expr\n \nDescription\n----------- \nEqual operator. Evaluates both SQL expressions and returns 1\nif they are equal, 0 if they are not equal, or NULL if\neither expression is NULL. If the expressions return\ndifferent data types (for example, a number and a string), a\ntype conversion is performed.\n \nWhen used in row comparisons these two queries are\nsynonymous and return the same results:\n \nSELECT (t1.a, t1.b) = (t2.x, t2.y) FROM t1 INNER JOIN t2;\n \nSELECT (t1.a = t2.x) AND (t1.b = t2.y) FROM t1 INNER JOIN\nt2;\n \nTo perform a NULL-safe comparison, use the operator.\n \n= can also be used as an assignment operator.\n \nExamples\n-------- \nSELECT 1 = 0;\n \n+-------+\n| 1 = 0 |\n+-------+\n| 0 |\n+-------+\n \nSELECT \'0\' = 0;\n \n+---------+\n| \'0\' = 0 |\n+---------+\n| 1 |\n+---------+\n \nSELECT \'0.0\' = 0;\n \n+-----------+\n| \'0.0\' = 0 |\n+-----------+\n| 1 |\n+-----------+\n \nSELECT \'0.01\' = 0;\n \n+------------+\n| \'0.01\' = 0 |\n+------------+\n| 0 |\n+------------+\n \nSELECT \'.01\' = 0.01;\n \n+--------------+\n| \'.01\' = 0.01 |\n+--------------+\n| 1 |\n+--------------+\n \nSELECT (5 * 2) = CONCAT(\'1\', \'0\');\n+----------------------------+\n| (5 * 2) = CONCAT(\'1\', \'0\') |\n+----------------------------+\n| 1 |\n+----------------------------+\n \nSELECT 1 = NULL;\n \n+----------+\n| 1 = NULL |\n+----------+\n| NULL |\n+----------+\n \nSELECT NULL = NULL;\n \n+-------------+\n| NULL = NULL |\n+-------------+\n| NULL |\n+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/equal/','','https://mariadb.com/kb/en/equal/'),(433,'PROCEDURE',27,'The PROCEDURE clause of SELECT passes the whole result set\nto a Procedure which will process it. These Procedures are\nnot Stored Procedures, and can only be written in the C\nlanguage, so it is necessary to recompile the server.\n \nCurrently, the only available procedure is ANALYSE, which\nexamines the resultset and suggests the optimal datatypes\nfor each column. It is defined in the sql/sql_analyse.cc\nfile, and can be used as an example to create more\nProcedures.\n \nThis clause cannot be used in a view\'s definition.\n \n\n\nURL: https://mariadb.com/kb/en/procedure/','','https://mariadb.com/kb/en/procedure/'),(445,'EXPLAIN',28,'Syntax\n------ \nEXPLAIN tbl_name\n \nOr\n \nEXPLAIN [EXTENDED | PARTITIONS] \n {SELECT select_options | UPDATE update_options | DELETE\ndelete_options}\n \nDescription\n----------- \nThe EXPLAIN statement can be used either as a synonym for\nDESCRIBE or as a way to obtain information about how MariaDB\nexecutes a SELECT (as well as UPDATE and DELETE since\nMariaDB 10.0.5) statement:\n\'EXPLAIN tbl_name\' is synonymous with \n \'DESCRIBE tbl_name\' or \n \'SHOW COLUMNS FROM tbl_name\'.\nWhen you precede a SELECT statement (or, since MariaDB\n10.0.5, an UPDATE or a DELETE as well) with the keyword \n EXPLAIN, MariaDB displays information from the optimizer\n about the query execution plan. That is, MariaDB explains\nhow it would\n process the SELECT, UPDATE or DELETE, including information\nabout how tables\n are joined and in which order. EXPLAIN EXTENDED can be\n used to provide additional information.\nEXPLAIN PARTITIONS has been available since MySQL 5.1.5. It\nis useful only when examining queries involving partitioned\ntables. For details, see Partition pruning and selection.\nANALYZE statement, which performs the query as well as\nproducing EXPLAIN output, and provides actual as well as\nestimated statistics, has been available from MariaDB\n10.1.0.\nSince MariaDB 10.0.5, it has been possible to have EXPLAIN\noutput printed in the slow query log. See EXPLAIN in the\nSlow Query Log for details.\n \nSince MariaDB 10.0, SHOW EXPLAIN shows the output of a\nrunning statement. In some cases, its output can be closer\nto reality than EXPLAIN.\n \nSince MariaDB 10.1, the ANALYZE statement runs a statement\nand returns information about its execution plan. It also\nshows additional columns, to check how much the optimizer\'s\nestimation about filtering and found rows are close to\nreality.\n \nThere is an online EXPLAIN Analyzer that you can use to\nshare EXPLAIN and EXPLAIN EXTENDED output with others.\n \nEXPLAIN can acquire metadata locks in the same way that\nSELECT does, as it needs to know table metadata and,\nsometimes, data as well.\n \nThe columns in EXPLAIN ... SELECT\n \nColumn name | Description | \n \nid | Sequence number that shows in which order tables are\njoined. | \n \nselect_type | What kind of SELECT the table comes from. | \n \ntable | Alias name of table. Materialized temporary tables\nfor sub queries are named | \n \ntype | How rows are found from the table (join type). | \n \npossible_keys | keys in table that could be used to find\nrows in the table | \n \nkey | The name of the key that is used to retrieve rows.\nNULL is no key was used. | \n \nkey_len | How many bytes of the key that was used (shows if\nwe are using only parts of the multi-column key). | \n \nref | The reference that is used to as the key value. | \n \nrows | An estimate of how many rows we will find in the\ntable for each key lookup. | \n \nExtra | Extra information about this join. | \n \nHere are descriptions of the values for some of the more\ncomplex columns in EXPLAIN ... SELECT:\n \n\"select_type\" column\n \nThe select_type column can have the following values:\n \nValue | Description | \n \nDEPENDENT SUBQUERY | The SUBQUERY is DEPENDENT. | \n \nDEPENDENT UNION | The UNION is DEPENDENT. | \n \nDERIVED | The SELECT is DERIVED from the PRIMARY. | \n \nMATERIALIZED | The SUBQUERY is MATERIALIZED. | \n \nPRIMARY | The SELECT is a PRIMARY one. | \n \nSIMPLE | The SELECT is a SIMPLE one. | \n \nSUBQUERY | The SELECT is a SUBQUERY of the PRIMARY. | \n \nUNCACHEABLE SUBQUERY | The SUBQUERY is UNCACHEABLE. | \n \nUNCACHEABLE UNION | The UNION is UNCACHEABLE. | \n \nUNION | The SELECT is a UNION of the PRIMARY. | \n \nUNION RESULT | The result of the UNION. | \n \n\"Type\" column\n \nThis column contains information on how the table is\naccessed.\n \nValue | Description | \n \nALL | A full table scan is done for the table (all rows are\nread). This is bad if the table is large and the table is\njoined against a previous table! This happens when the\noptimizer could not find any usable index to access rows. | \n \nconst | There is only one possibly matching row in the\ntable. The row is read before the optimization phase and all\ncolumns in the table are treated as constants. | \n \neq_ref | A unique index is used to find the rows. This is\nthe best possible plan to find the row. | \n \nfulltext | A fulltext index is used to access the rows. | \n \nindex_merge | A \'range\' access is done for for several\nindex and the found rows are merged. The key column shows\nwhich keys are used. | \n \nindex_subquery | This is similar as ref, but used for sub\nqueries that are transformed to key lookups. | \n \nindex | A full scan over the used index. Better than ALL but\nstill bad if index is large and the table is joined against\na previous table. | \n \nrange | The table will be accessed with a key over one or\nmore value ranges. | \n \nref_or_null | Like \'ref\' but in addition another search\nfor the \'null\' value is done if the first value was not\nfound. This happens usually with sub queries. | \n \nref | A non unique index or prefix of an unique index is\nused to find the rows. Good if the prefix doesn\'t match\nmany rows. | \n \nsystem | The table has 0 or 1 rows. | \n \nunique_subquery | This is similar as eq_ref, but used for\nsub queries that are transformed to key lookups | \n \n\"Extra\" column\n \nThis column consists of one or more of the following values,\nseparated by \';\'\n \n Note that some of these values are detected after the\noptimization phase.\n \nThe optimization phase can do the following changes to the\nWHERE clause:\nAdd the expressions from the ON and USING clauses to the\nWHERE\n clause.\nConstant propagation: If there is column=constant, replace\nall column\n instances with this constant.\nReplace all columns from \'const\' tables with their values.\nRemove the used key columns from the WHERE (as this will be\ntested as\n part of the key lookup).\nRemove impossible constant sub expressions.\n For example WHERE \'(a=1 and a=2) OR b=1\' becomes \'b=1\'.\nReplace columns with other columns that has identical\nvalues:\n Example: WHERE a=b and a=c may be treated\n as \'WHERE a=b and a=c and b=c\'.\nAdd extra conditions to detect impossible row conditions\nearlier. This\n happens mainly with OUTER JOIN where we in some cases add\ndetection\n of NULL values in the WHERE (Part of \'Not exists\'\noptimization).\n This can cause an unexpected \'Using where\' in the Extra\ncolumn.\nFor each table level we remove expressions that have already\nbeen tested when\n we read the previous row. Example: When joining tables t1\nwith t2\n using the following WHERE \'t1.a=1 and t1.a=t2.b\', we\ndon\'t have to\n test \'t1.a=1\' when checking rows in t2 as we already know\nthat this\n expression is true. \n \nValue | Description | \n \nconst row not found | The table was a system table (a table\nwith should exactly one row), but no row was found. | \n \nDistinct | If distinct optimization (remove duplicates) was\nused. This is marked only for the last table in the SELECT.\n| \n \nFull scan on NULL key | The table is a part of the sub query\nand if the value that is used to match the sub query will be\nNULL, we will do a full table scan. | \n \nImpossible HAVING | The used HAVING clause is always false\nso the SELECT will return no rows. | \n \nImpossible WHERE noticed after reading const tables. | The\nused WHERE clause is always false so the SELECT will return\nno rows. This case was detected after we had read all\n\'const\' tables and used the column values as constant in\nthe WHERE clause. For example: WHERE const_column=5 and\nconst_column had a value of 4. | \n \nImpossible WHERE | The used WHERE clause is always false so\nthe SELECT will return no rows. For example: WHERE 1=2 | \n \nNo matching min/max row | During early optimization of\nMIN()/MAX() values it was detected that no row could match\nthe WHERE clause. The MIN()/MAX() function will return NULL.\n| \n \nno matching row in const table | The table was a const table\n(a table with only one possible matching row), but no row\nwas found. | \n \nNo tables used | The SELECT was a sub query that did not use\nany tables. For example a there was no FROM clause or a FROM\nDUAL clause. | \n \nNot exists | Stop searching after more row if we find one\nsingle matching row. This optimization is used with LEFT\nJOIN where one is explicitly searching for rows that\ndoesn\'t exists in the LEFT JOIN TABLE. Example: SELECT *\nFROM t1 LEFT JOIN t2 on (...) WHERE t2.not_null_column IS\nNULL. As t2.not_null_column can only be NULL if there was no\nmatching row for on condition, we can stop searching if we\nfind a single matching row. | \n \nOpen_frm_only | For information_schema tables. Only the frm\n(table definition file was opened) was opened for each\nmatching row. | \n \nOpen_full_table | For information_schema tables. A full\ntable open for each matching row is done to retrieve the\nrequested information. (Slow) | \n \nOpen_trigger_only | For information_schema tables. Only the\ntrigger file definition was opened for each matching row. | \n \nRange checked for each record (index map: ...) | This only\nhappens when there was no good default index to use but\nthere may some index that could be used when we can treat\nall columns from previous table as constants. For each row\ncombination the optimizer will decide which index to use (if\nany) to fetch a row from this table. This is not fast, but\nfaster than a full table scan that is the only other choice.\nThe index map is a bitmask that shows which index are\nconsidered for each row condition. | \n \nScanned 0/1/all databases | For information_schema tables.\nShows how many times we had to do a directory scan. | \n \nSelect tables optimized away | All tables in the join was\noptimized away. This happens when we are only using\nCOUNT(*), MIN() and MAX() functions in the SELECT and we\nwhere able to replace all of these with constants. | \n \nSkip_open_table | For information_schema tables. The queried\ntable didn\'t need to be opened. | \n \nunique row not found | The table was detected to be a const\ntable (a table with only one possible matching row) during\nthe early optimization phase, but no row was found. | \n \nUsing filesort | Filesort is needed to resolve the query.\nThis means an extra phase where we first collect all columns\nto sort, sort them with a disk based merge sort and then use\nthe sorted set to retrieve the rows in sorted order. If the\ncolumn set is small, we store all the columns in the sort\nfile to not have to go to the database to retrieve them\nagain. | \n \nUsing index | Only the index is used to retrieve the needed\ninformation from the table. There is no need to perform an\nextra seek to retrieve the actual record. | \n \nUsing index condition | Like \'Using where\' but the where\ncondition is pushed down to the table engine for internal\noptimization at the index level. | \n \nUsing index condition(BKA) | Like \'Using index condition\'\nbut in addition we use batch key access to retrieve rows. | \n \nUsing index for group-by | The index is being used to\nresolve a GROUP BY or DISTINCT query. The rows are not read.\nThis is very efficient if the table has a lot of identical\nindex entries as duplicates are quickly jumped over. | \n \nUsing intersect(...) | For index_merge joins. Shows which\nindex are part of the intersect. | \n \nUsing join buffer | We store previous row combinations in a\nrow buffer to be able to match each row against all of the\nrows combinations in the join buffer at one go. | \n \nUsing sort_union(...) | For index_merge joins. Shows which\nindex are part of the union. | \n \nUsing temporary | A temporary table is created to hold the\nresult. This typically happens if you are using GROUP BY,\nDISTINCT or ORDER BY. | \n \nUsing where | A WHERE expression (in additional to the\npossible key lookup) is used to check if the row should be\naccepted. If you don\'t have \'Using where\' together with a\njoin type of ALL, you are probably doing something wrong! | \n \nUsing where with pushed condition | Like \'Using where\' but\nthe where condition is pushed down to the table engine for\ninternal optimization at the row level. | \n \nUsing buffer | The UPDATE statement will first buffer the\nrows, and then run the updates, rather than do updates on\nthe fly. See Using Buffer UPDATE Algorithm for a detailed\nexplanation. | \n \nEXPLAIN EXTENDED\n \nThe EXTENDED keyword adds another column, filtered, to the\noutput. This is a percentage estimate of the table rows that\nwill be filtered by the condition.\n \nAn EXPLAIN EXTENDED will always throw a warning, as it adds\nextra Message information to a subsequent SHOW WARNINGS\nstatement. This includes what the SELECT query would look\nlike after optimizing and rewriting rules are applied and\nhow the optimizer qualifies columns and tables.\n \nExamples\n-------- \nAs synonym for DESCRIBE or SHOW COLUMNS FROM:\n \nDESCRIBE city;\n \n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | YES | | NULL | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | YES | | NULL | |\n+------------+----------+------+-----+---------+----------------+\n \nA simple set of examples to see how EXPLAIN can identify\npoor index usage:\n \nCREATE TABLE IF NOT EXISTS `employees_example` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `first_name` varchar(30) NOT NULL,\n `last_name` varchar(40) NOT NULL,\n `position` varchar(25) NOT NULL,\n `home_address` varchar(50) NOT NULL,\n `home_phone` varchar(12) NOT NULL,\n `employee_code` varchar(25) NOT NULL,\n PRIMARY KEY (`id`),\n UNIQUE KEY `employee_code` (`employee_code`),\n KEY `first_name` (`first_name`,`last_name`)\n) ENGINE=Aria;\n \nINSERT INTO `employees_example` (`first_name`, `last_name`,\n`position`, `home_address`, `home_phone`, `employee_code`)\n VALUES\n (\'Mustapha\', \'Mond\', \'Chief Executive Officer\', \'692\nPromiscuous Plaza\', \'326-555-3492\', \'MM1\'),\n (\'Henry\', \'Foster\', \'Store Manager\', \'314 Savage\nCircle\', \'326-555-3847\', \'HF1\'),\n (\'Bernard\', \'Marx\', \'Cashier\', \'1240 Ambient\nAvenue\', \'326-555-8456\', \'BM1\'),\n (\'Lenina\', \'Crowne\', \'Cashier\', \'281 Bumblepuppy\nBoulevard\', \'328-555-2349\', \'LC1\'),\n (\'Fanny\', \'Crowne\', \'Restocker\', \'1023 Bokanovsky\nLane\', \'326-555-6329\', \'FC1\'),\n (\'Helmholtz\', \'Watson\', \'Janitor\', \'944 Soma\nCourt\', \'329-555-2478\', \'HW1\');\n \nSHOW INDEXES FROM employees_example;\n \n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n| Table | Non_unique | Key_name | Seq_in_index | Column_name\n| Collation | Cardinality | Sub_part | Packed | Null |\nIndex_type | Comment | Index_comment |\n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n| employees_example | 0 | PRIMARY | 1 | id | A | 7 | NULL |\nNULL | | BTREE | | |\n| employees_example | 0 | employee_code | 1 | employee_code\n| A | 7 | NULL | NULL | | BTREE | | |\n| employees_example | 1 | first_name | 1 | first_name | A |\nNULL | NULL | NULL | | BTREE | | |\n| employees_example | 1 | first_name | 2 | last_name | A |\nNULL | NULL | NULL | | BTREE | | |\n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n \nSELECT on a primary key:\n \nEXPLAIN SELECT * FROM employees_example WHERE id=1;\n \n+------+-------------+-------------------+-------+---------------+---------+---------+-------+------+-------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | Extra |\n+------+-------------+-------------------+-------+---------------+---------+---------+-------+------+-------+\n| 1 | SIMPLE | employees_example | const | PRIMARY | PRIMARY\n| 4 | const | 1 | |\n+------+-------------+-------------------+-------+---------------+---------+---------+-------+------+-------+\n \nThe type is const, which means that only one possible result\ncould be returned. \nNow, returning the same record but searching by their phone\nnumber:\n \nEXPLAIN SELECT * FROM employees_example WHERE\nhome_phone=\'326-555-3492\';\n \n+------+-------------+-------------------+------+---------------+------+---------+------+------+-------------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | Extra |\n+------+-------------+-------------------+------+---------------+------+---------+------+------+-------------+\n| 1 | SIMPLE | employees_example | ALL | NULL | NULL | NULL\n| NULL | 6 | Using where |\n+------+-------------+-------------------+------+---------------+------+---------+------+------+-------------+\n \nHere, the type is All, which means no index could be used.\nLooking at the rows count, a full table scan (all six rows)\nhad to be performed in order to retrieve the record. If\nit\'s a requirement to search by phone number, an index will\nhave to be created.\n \nSHOW EXPLAIN example:\n \nSHOW EXPLAIN FOR 1;\n \n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | Extra |\n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n| 1 | SIMPLE | tbl | index | NULL | a | 5 | NULL | 1000107 |\nUsing index |\n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n1 row in set, 1 warning (0.00 sec)\n \nExample of ref_or_null optimization\n \nSELECT * FROM table_name\n WHERE key_column=expr OR key_column IS NULL;\n \nref_or_null is something that often happens when you use\nsubqueries with NOT IN as then one has to do an extra check\nfor NULL values if the first value didn\'t have a matching\nrow. \n \n\n\nURL: https://mariadb.com/kb/en/explain/','','https://mariadb.com/kb/en/explain/'),(446,'EXPLAIN ANALYZE',28,'The syntax for the EXPLAIN ANALYZE feature was changed to\nANALYZE statement, available since MariaDB 10.1.0. See\nANALYZE statement. \n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/explain-analyze/','','https://mariadb.com/kb/en/explain-analyze/'),(450,'CONTAINS',30,'Syntax\n------ \nContains(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether a geometry g1 completely\ncontains geometry g2. CONTAINS() is based on the original\nMySQL implementation and uses object bounding rectangles,\nwhile ST_CONTAINS() uses object shapes. \n \nThis tests the opposite relationship to Within().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/contains/','','https://mariadb.com/kb/en/contains/'),(451,'CROSSES',30,'Syntax\n------ \nCrosses(g1,g2)\n \nDescription\n----------- \nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is\na Polygon or a MultiPolygon, or if g2 is a\nPoint or a MultiPoint. Otherwise, returns 0.\n \nThe term spatially crosses denotes a spatial relation\nbetween two\ngiven geometries that has the following properties:\nThe two geometries intersect\nTheir intersection results in a geometry that has a\ndimension that is one\n less than the maximum dimension of the two given geometries\nTheir intersection is not equal to either of the two given\ngeometries\n \nCROSSES() is based on the original MySQL implementation, and\nuses object bounding rectangles, while ST_CROSSES() uses\nobject shapes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/crosses/','','https://mariadb.com/kb/en/crosses/'),(226,'>',18,'Syntax\n------ \n>\n \nDescription\n----------- \nGreater than operator. Evaluates both SQL expressions and\nreturns 1 if the left value is greater than the right value\nand 0 if it is not, or NULL if either expression is NULL. If\nthe expressions return different data types, (for instance,\na number and a string), performs type conversion.\n \nWhen used in row comparisons these two queries return the\nsame results:\n \nSELECT (t1.a, t1.b) > (t2.x, t2.y) \nFROM t1 INNER JOIN t2;\n \nSELECT (t1.a > t2.x) OR ((t1.a = t2.x) AND (t1.b > t2.y))\nFROM t1 INNER JOIN t2;\n \nExamples\n-------- \nSELECT 2 > 2;\n \n+-------+\n| 2 > 2 |\n+-------+\n| 0 |\n+-------+\n \nSELECT \'b\' > \'a\';\n \n+-----------+\n| \'b\' > \'a\' |\n+-----------+\n| 1 |\n+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/greater-than/','','https://mariadb.com/kb/en/greater-than/'),(227,'>=',18,'Syntax\n------ \n>=\n \nDescription\n----------- \nGreater than or equal operator. Evaluates both SQL\nexpressions and returns 1 if the left value is greater than\nor equal to the right value and 0 if it is not, or NULL if\neither expression is NULL. If the expressions return\ndifferent data types, (for instance, a number and a string),\nperforms type conversion.\n \nWhen used in row comparisons these two queries return the\nsame results:\n \nSELECT (t1.a, t1.b) >= (t2.x, t2.y) \nFROM t1 INNER JOIN t2;\n \nSELECT (t1.a > t2.x) OR ((t1.a = t2.x) AND (t1.b >= t2.y))\nFROM t1 INNER JOIN t2;\n \nExamples\n-------- \nSELECT 2 >= 2;\n \n+--------+\n| 2 >= 2 |\n+--------+\n| 1 |\n+--------+\n \nSELECT \'A\' >= \'a\';\n \n+------------+\n| \'A\' >= \'a\' |\n+------------+\n| 1 |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/greater-than-or-equal/','','https://mariadb.com/kb/en/greater-than-or-equal/'),(229,'COALESCE',18,'Syntax\n------ \nCOALESCE(value,...)\n \nDescription\n----------- \nReturns the first non-NULL value in the list, or NULL if\nthere are no\nnon-NULL values. At least one parameter must be passed.\n \nSee also NULL Values in MariaDB.\n \nExamples\n-------- \nSELECT COALESCE(NULL,1);\n+------------------+\n| COALESCE(NULL,1) |\n+------------------+\n| 1 |\n+------------------+\n \nSELECT COALESCE(NULL,NULL,NULL);\n+--------------------------+\n| COALESCE(NULL,NULL,NULL) |\n+--------------------------+\n| NULL |\n+--------------------------+\n \nWhen two arguments are given, COALESCE() is the same as\nIFNULL():\n \nSET @a=NULL, @b=1;\n \nSELECT COALESCE(@a, @b), IFNULL(@a, @b);\n+------------------+----------------+\n| COALESCE(@a, @b) | IFNULL(@a, @b) |\n+------------------+----------------+\n| 1 | 1 |\n+------------------+----------------+\n \nHex type confusion:\n \nCREATE TABLE t1 (a INT, b VARCHAR(10));\nINSERT INTO t1 VALUES (0x31, 0x61),(COALESCE(0x31),\nCOALESCE(0x61));\n \nSELECT * FROM t1;\n \n+------+------+\n| a | b |\n+------+------+\n| 49 | a |\n| 1 | a |\n+------+------+\n \nThe reason for the differing results above is that when 0x31\nis inserted directly to the column, it\'s treated as a\nnumber (see Hexadecimal Literals), while when 0x31 is passed\nto COALESCE(), it\'s treated as a string, because:\nHEX values have a string data type by default.\nCOALESCE() has the same data type as the argument. \n \n\n\nURL: https://mariadb.com/kb/en/coalesce/','','https://mariadb.com/kb/en/coalesce/'),(231,'IN',18,'Syntax\n------ \nexpr IN (value,...)\n \nDescription\n----------- \nReturns 1 if expr is equal to any of the values in the IN\nlist, else\nreturns 0. If all values are constants, they are evaluated\naccording\nto the type of expr and sorted. The search for the item then\nis done\nusing a binary search. This means IN is very quick if the IN\nvalue\nlist consists entirely of constants. Otherwise, type\nconversion takes\nplace according to the rules described at Type Conversion,\nbut\napplied to all the arguments.\n \nIf expr is NULL, IN always returns NULL. If at least one of\nthe values in the list is NULL, and one of the comparisons\nis true, the result is 1. If at least one of the values in\nthe list is NULL and none of the comparisons is true, the\nresult is NULL.\n \nExamples\n-------- \nSELECT 2 IN (0,3,5,7);\n+----------------+\n| 2 IN (0,3,5,7) |\n+----------------+\n| 0 |\n+----------------+\n \nSELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n+----------------------------------+\n| \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\') |\n+----------------------------------+\n| 1 |\n+----------------------------------+ \n \nType conversion:\n \nSELECT 1 IN (\'1\', \'2\', \'3\');\n+----------------------+\n| 1 IN (\'1\', \'2\', \'3\') |\n+----------------------+\n| 1 |\n+----------------------+\n \nSELECT NULL IN (1, 2, 3);\n+-------------------+\n| NULL IN (1, 2, 3) |\n+-------------------+\n| NULL |\n+-------------------+\n \nMariaDB [(none)]> SELECT 1 IN (1, 2, NULL);\n+-------------------+\n| 1 IN (1, 2, NULL) |\n+-------------------+\n| 1 |\n+-------------------+\n \nMariaDB [(none)]> SELECT 5 IN (1, 2, NULL);\n+-------------------+\n| 5 IN (1, 2, NULL) |\n+-------------------+\n| NULL |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/in/','','https://mariadb.com/kb/en/in/'),(452,'DISJOINT',30,'Syntax\n------ \nDisjoint(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether g1 is spatially disjoint\nfrom\n(does not intersect) g2.\n \nDISJOINT() tests the opposite relationship to INTERSECTS().\n \nDISJOINT() is based on the original MySQL implementation and\nuses object bounding rectangles, while ST_DISJOINT() uses\nobject shapes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/disjoint/','','https://mariadb.com/kb/en/disjoint/'),(453,'EQUALS',30,'Syntax\n------ \nEquals(g1,g2)\n \nFrom MariaDB 10.2.3:\n \nMBREQUALS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether g1 is spatially equal to\ng2.\n \nEQUALS() is based on the original MySQL implementation and\nuses object bounding rectangles, while ST_EQUALS() uses\nobject shapes.\n \nFrom MariaDB 10.2.3, MBREQUALS is a synonym for Equals.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/equals/','','https://mariadb.com/kb/en/equals/'),(454,'INTERSECTS',30,'Syntax\n------ \nINTERSECTS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 spatially\nintersects geometry g2.\n \nINTERSECTS() is based on the original MySQL implementation\nand uses object bounding rectangles, while ST_INTERSECTS()\nuses object shapes.\n \nINTERSECTS() tests the opposite relationship to DISJOINT().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/intersects/','','https://mariadb.com/kb/en/intersects/'),(455,'OVERLAPS',30,'Syntax\n------ \nOVERLAPS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether g1 spatially overlaps g2.\nThe term spatially overlaps is used if two geometries\nintersect and their\nintersection results in a geometry of the same dimension but\nnot equal to\neither of the given geometries.\n \nOVERLAPS() is based on the original MySQL implementation and\nuses object bounding rectangles, while ST_OVERLAPS() uses\nobject shapes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/overlaps/','','https://mariadb.com/kb/en/overlaps/'),(458,'ST_DIFFERENCE',30,'Syntax\n------ \nST_DIFFERENCE(g1,g2)\n \nDescription\n----------- \nReturns a geometry representing the point set difference of\nthe given geometry values.\n \nExample\n \nSET @g1 = POINT(10,10), @g2 = POINT(20,20);\n \nSELECT ST_AsText(ST_Difference(@g1, @g2));\n+------------------------------------+\n| ST_AsText(ST_Difference(@g1, @g2)) |\n+------------------------------------+\n| POINT(10 10) |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_difference/','','https://mariadb.com/kb/en/st_difference/'),(233,'IS',18,'Syntax\n------ \nIS boolean_value\n \nDescription\n----------- \nTests a value against a boolean value, where boolean_value\ncan be\nTRUE, FALSE, or UNKNOWN.\n \nThere is an important difference between using IS TRUE or\ncomparing a value with TRUE using =. When using =, only 1\nequals to TRUE. But when using IS TRUE, all values which are\nlogically true (like a number > 1) return TRUE.\n \nExamples\n-------- \nSELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n+-----------+------------+-----------------+\n| 1 IS TRUE | 0 IS FALSE | NULL IS UNKNOWN |\n+-----------+------------+-----------------+\n| 1 | 1 | 1 |\n+-----------+------------+-----------------+\n \nDifference between = and IS TRUE:\n \nSELECT 2 = TRUE, 2 IS TRUE;\n+----------+-----------+\n| 2 = TRUE | 2 IS TRUE |\n+----------+-----------+\n| 0 | 1 |\n+----------+-----------+\n \n\n\nURL: https://mariadb.com/kb/en/is/','','https://mariadb.com/kb/en/is/'),(234,'IS NOT',18,'Syntax\n------ \nIS NOT boolean_value\n \nDescription\n----------- \nTests a value against a boolean value, where boolean_value\ncan be\nTRUE, FALSE, or UNKNOWN. \n \nExamples\n-------- \nSELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT\nUNKNOWN;\n+------------------+------------------+---------------------+\n| 1 IS NOT UNKNOWN | 0 IS NOT UNKNOWN | NULL IS NOT UNKNOWN\n|\n+------------------+------------------+---------------------+\n| 1 | 1 | 0 |\n+------------------+------------------+---------------------+\n \nSELECT NULL IS NOT TRUE, NULL IS NOT FALSE;\n+------------------+-------------------+\n| NULL IS NOT TRUE | NULL IS NOT FALSE |\n+------------------+-------------------+\n| 1 | 1 |\n+------------------+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/is-not/','','https://mariadb.com/kb/en/is-not/'),(236,'IS NULL',18,'Syntax\n------ \nIS NULL\n \nDescription\n----------- \nTests whether a value is NULL. See also NULL Values in\nMariaDB.\n \nExamples\n-------- \nSELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n+-----------+-----------+--------------+\n| 1 IS NULL | 0 IS NULL | NULL IS NULL |\n+-----------+-----------+--------------+\n| 0 | 0 | 1 |\n+-----------+-----------+--------------+\n \nCompatibility\n \nSome ODBC applications use the syntax auto_increment_field\nIS NOT NULL to find the latest row that was inserted with an\nautogenerated key value. If your applications need this, you\ncan set the sql_auto_is_null variable to 1.\n \nSET @@sql_auto_is_null=1;\nCREATE TABLE t1 (auto_increment_column INT NOT NULL\nAUTO_INCREMENT PRIMARY KEY);\nINSERT INTO t1 VALUES (NULL);\nSELECT * FROM t1 WHERE auto_increment_column IS NULL;\n \n+-----------------------+\n| auto_increment_column |\n+-----------------------+\n| 1 |\n+-----------------------+\n \n\n\nURL: https://mariadb.com/kb/en/is-null/','','https://mariadb.com/kb/en/is-null/'),(238,'LEAST',18,'Syntax\n------ \nLEAST(value1,value2,...)\n \nDescription\n----------- \nWith two or more arguments, returns the smallest\n(minimum-valued)\nargument. The arguments are compared using the following\nrules:\nIf the return value is used in an INTEGER context or all\narguments are integer-valued, they are compared as integers.\nIf the return value is used in a REAL context or all\narguments are real-valued, they are compared as reals.\nIf any argument is a case-sensitive string, the arguments\nare compared as case-sensitive strings.\nIn all other cases, the arguments are compared as\ncase-insensitive strings.\n \nLEAST() returns NULL if any argument is NULL.\n \nExamples\n-------- \nSELECT LEAST(2,0);\n+------------+\n| LEAST(2,0) |\n+------------+\n| 0 |\n+------------+\n \nSELECT LEAST(34.0,3.0,5.0,767.0);\n+---------------------------+\n| LEAST(34.0,3.0,5.0,767.0) |\n+---------------------------+\n| 3.0 |\n+---------------------------+\n \nSELECT LEAST(\'B\',\'A\',\'C\');\n+--------------------+\n| LEAST(\'B\',\'A\',\'C\') |\n+--------------------+\n| A |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/least/','','https://mariadb.com/kb/en/least/'),(239,'NOT BETWEEN',18,'Syntax\n------ \nexpr NOT BETWEEN min AND max\n \nDescription\n----------- \nThis is the same as NOT (expr BETWEEN min AND max).\n \nNote that the meaning of the alternative form NOT expr\nBETWEEN min AND max is affected by the HIGH_NOT_PRECEDENCE\nSQL_MODE flag.\n \nExamples\n-------- \nSELECT 1 NOT BETWEEN 2 AND 3;\n+-----------------------+\n| 1 NOT BETWEEN 2 AND 3 |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT \'b\' NOT BETWEEN \'a\' AND \'c\';\n+-----------------------------+\n| \'b\' NOT BETWEEN \'a\' AND \'c\' |\n+-----------------------------+\n| 0 |\n+-----------------------------+\n \nNULL:\n \nSELECT 1 NOT BETWEEN 1 AND NULL;\n+--------------------------+\n| 1 NOT BETWEEN 1 AND NULL |\n+--------------------------+\n| NULL |\n+--------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not-between/','','https://mariadb.com/kb/en/not-between/'),(240,'NOT IN',18,'Syntax\n------ \nexpr NOT IN (value,...)\n \nDescription\n----------- \nThis is the same as NOT (expr IN (value,...)).\n \nExamples\n-------- \nSELECT 2 NOT IN (0,3,5,7);\n+--------------------+\n| 2 NOT IN (0,3,5,7) |\n+--------------------+\n| 1 |\n+--------------------+\n \nSELECT \'wefwf\' NOT IN (\'wee\',\'wefwf\',\'weg\');\n+--------------------------------------+\n| \'wefwf\' NOT IN (\'wee\',\'wefwf\',\'weg\') |\n+--------------------------------------+\n| 0 |\n+--------------------------------------+\n \nSELECT 1 NOT IN (\'1\', \'2\', \'3\');\n+--------------------------+\n| 1 NOT IN (\'1\', \'2\', \'3\') |\n+--------------------------+\n| 0 |\n+--------------------------+\n \nNULL:\n \nSELECT NULL NOT IN (1, 2, 3);\n+-----------------------+\n| NULL NOT IN (1, 2, 3) |\n+-----------------------+\n| NULL |\n+-----------------------+\n \nSELECT 1 NOT IN (1, 2, NULL);\n+-----------------------+\n| 1 NOT IN (1, 2, NULL) |\n+-----------------------+\n| 0 |\n+-----------------------+\n \nSELECT 5 NOT IN (1, 2, NULL);\n+-----------------------+\n| 5 NOT IN (1, 2, NULL) |\n+-----------------------+\n| NULL |\n+-----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not-in/','','https://mariadb.com/kb/en/not-in/'),(460,'ST_DISTANCE',30,'ST_DISTANCE() was introduced in MariaDB 5.3.3.\n \nSyntax\n------ \nST_DISTANCE(g1,g2)\n \nDescription\n----------- \nReturns the distance between two geometries, or null if not\ngiven valid inputs.\n \nExample\n \nSELECT ST_Distance(POINT(1,2),POINT(2,2));\n+------------------------------------+\n| ST_Distance(POINT(1,2),POINT(2,2)) |\n+------------------------------------+\n| 1 |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_distance/','','https://mariadb.com/kb/en/st_distance/'),(463,'ST_LENGTH',30,'Syntax\n------ \nST_LENGTH(ls)\n \nDescription\n----------- \nReturns as a double-precision number the length of the\nLineString value ls in its associated spatial reference.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT ST_LENGTH(ST_GeomFromText(@ls));\n+---------------------------------+\n| ST_LENGTH(ST_GeomFromText(@ls)) |\n+---------------------------------+\n| 2.82842712474619 |\n+---------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_length/','','https://mariadb.com/kb/en/st_length/'),(464,'ST_OVERLAPS',30,'Syntax\n------ \nST_OVERLAPS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 spatially\noverlaps geometry g2.\n \nThe term spatially overlaps is used if two geometries\nintersect and their\nintersection results in a geometry of the same dimension but\nnot equal to\neither of the given geometries.\n \nST_OVERLAPS() uses object shapes, while OVERLAPS(), based on\nthe original MySQL implementation, uses object bounding\nrectangles.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-overlaps/','','https://mariadb.com/kb/en/st-overlaps/'),(249,'Parentheses',19,'Parentheses are sometimes called precedence operators - this\nmeans that they can be used to change the other operator\'s\nprecedence in an expression. The expressions that are\nwritten between parentheses are computed before the\nexpressions that are written outside. Parentheses must\nalways contain an expression (that is, they cannot be\nempty), and can be nested.\n \nFor example, the following expressions could return\ndifferent results:\nNOT a OR b\nNOT (a OR b)\n \nIn the first case, NOT applies to a, so if a is FALSE or b\nis TRUE, the expression returns TRUE. In the second case,\nNOT applies to the result of a OR b, so if at least one of a\nor b is TRUE, the expression is TRUE.\n \nWhen the precedence of operators is not intuitive, you can\nuse parentheses to make it immediately clear for whoever\nreads the statement.\n \nThe precedence of the NOT operator can also be affected by\nthe HIGH_NOT_PRECEDENCE SQL_MODE flag.\n \nOther uses\n \nParentheses must always be used to enclose subqueries.\n \nParentheses can also be used in a JOIN statement between\nmultiple tables to determine which tables must be joined\nfirst.\n \nAlso, parentheses are used to enclose the list of parameters\nto be passed to built-in functions, user-defined functions\nand stored routines. However, when no parameter is passed to\na stored procedure, parentheses are optional. For builtin\nfunctions and user-defined functions, spaces are not allowed\nbetween the function name and the open parenthesis, unless\nthe IGNORE_SPACE SQL_MODE is set. For stored routines (and\nfor functions if IGNORE_SPACE is set) spaces are allowed\nbefore the open parenthesis, including tab characters and\nnew line characters.\n \nSyntax errors\n \nIf there are more open parentheses than closed parentheses,\nthe error usually looks like this:\n \nERROR 1064 (42000): You have an error in your SQL syntax;\ncheck the manual that\ncorresponds to your MariaDB server version for the right\nsyntax to use near \'\' a\nt line 1\n \nNote the empty string.\n \nIf there are more closed parentheses than open parentheses,\nthe error usually looks like this:\n \nERROR 1064 (42000): You have an error in your SQL syntax;\ncheck the manual that\ncorresponds to your MariaDB server version for the right\nsyntax to use near \')\'\nat line 1\n \nNote the quoted closed parenthesis.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/parentheses/','','https://mariadb.com/kb/en/parentheses/'),(251,'ANALYZE TABLE',20,'Syntax\n------ \nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE tbl_name\n[,tbl_name ...] \n [PERSISTENT FOR [ALL|COLUMNS ([col_name [,col_name ...]])] \n [INDEXES ([index_name [,index_name ...]])]] \n \nDescription\n----------- \nANALYZE TABLE analyzes and stores the key distribution for a\ntable (index statistics). During the analysis, the table is\nlocked with a read lock. This statement works with MyISAM,\nAria and InnoDB tables. For MyISAM tables, this statement is\nequivalent\nto using myisamchk --analyze.\n \nFor more information on how the analysis works within\nInnoDB, see\nInnoDB Limitations.\n \nMariaDB uses the stored key distribution to decide the order\nin which\ntables should be joined when you perform a join on something\nother than\na constant. In addition, key distributions can be used when\ndeciding\nwhich indexes to use for a specific table within a query.\n \nThis statement requires SELECT and INSERT privileges for the\ntable.\n \nBy default, ANALYZE TABLE statements are written to the\nbinary log and will be replicated. The NO_WRITE_TO_BINLOG\nkeyword (LOCAL is an alias) will ensure the statement is not\nwritten to the binary log. \n \nANALYZE TABLE is also supported for partitioned tables. You\ncan use ALTER TABLE ... ANALYZE PARTITION to analyze one or\nmore partitions.\n \nThe Aria storage engine supports progress reporting for the\nANALYZE TABLE statement.\n \nEngine-Independent Statistics\n \nIn MariaDB 10.0 and later, ANALYZE TABLE supports\nengine-independent statistics. See Engine-Independent Table\nStatistics: Collecting Statistics with the ANALYZE TABLE\nStatement for more information.\n \n\n\nURL: https://mariadb.com/kb/en/analyze-table/','','https://mariadb.com/kb/en/analyze-table/'),(252,'CHECK TABLE',20,'Syntax\n------ \nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n \noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED |\nCHANGED}\n \nDescription\n----------- \nCHECK TABLE checks a table or tables for errors. CHECK TABLE\nworks for\nArchive, Aria, CSV, InnoDB, and MyISAM tables. For Aria and\nMyISAM tables, the\nkey statistics are updated as well. For CSV, see also\nChecking and Repairing CSV Tables.\n \nAs an alternative, myisamchk is a commandline tool for\nchecking MyISAM tables when the tables are not being\naccessed.\n \nFor checking dynamic columns integrity, COLUMN_CHECK() can\nbe used.\n \nCHECK TABLE can also check views for problems, such as\ntables\nthat are referenced in the view definition that no longer\nexist.\n \nCHECK TABLE is also supported for partitioned tables. You\ncan\nuse ALTER TABLE ... CHECK PARTITION \nto check one or more partitions.\n \nThe meaning of the different options are as follows - note\nthat this can vary a bit between\nstorage engines:\n \nFOR UPGRADE | Do a very quick check if the storage format\nfor the table has changed so that one needs to do a REPAIR.\nThis is only needed when one upgrades between major versions\nof MariaDB or MySQL. This is usually done by running\nmysql_upgrade. | \n \nFAST | Only check tables that has not been closed properly\nor are marked as corrupt. Only supported by the MyISAM and\nAria engines. For other engines the table is checked\nnormally | \n \nCHANGED | Check only tables that has changed since last\nREPAIR / CHECK. Only supported by the MyISAM and Aria\nengines. For other engines the table is checked normally. | \n \nQUICK | Do a fast check. For MyISAM and Aria engine this\nmeans we skip checking the delete link chain which may take\nsome time. | \n \nMEDIUM | Scan also the data files. Checks integrity between\ndata and index files with checksums. In most cases this\nshould find all possible errors. | \n \nEXTENDED | Does a full check to verify every possible error.\nFor MyISAM and Aria we verify for each row that all it keys\nexists and points to the row. This may take a long time on\nbig tables! | \n \nFor most cases running CHECK TABLE without options or MEDIUM\nshould be\ngood enough.\n \nSince MariaDB 5.3, the Aria storage engine supports progress\nreporting for this statement.\n \nIf you want to know if two tables are identical, take a look\nat CHECKSUM TABLE.\n \nXtraDB/InnoDB\n \nIf CHECK TABLE finds an error in an InnoDB table, MariaDB\nmight shutdown to prevent the error propagation. In this\ncase, the problem will be reported in the error log.\nOtherwise, since MariaDB 5.5, the table or an index might be\nmarked as corrupted, to prevent use. This does not happen\nwith some minor problems, like a wrong number of entries in\na secondary index. Those problems are reported in the output\nof CHECK TABLE.\n \nEach tablespace contains a header with metadata. This header\nis not checked by this statement.\n \nDuring the execution of CHECK TABLE, other threads may be\nblocked.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sql-commands-check-table/','','https://mariadb.com/kb/en/sql-commands-check-table/'),(467,'TOUCHES',30,'Syntax\n------ \nTouches(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether g1 spatially touches g2.\nTwo\ngeometries spatially touch if the interiors of the\ngeometries do not intersect,\nbut the boundary of one of the geometries intersects either\nthe boundary or the\ninterior of the other.\n \nTOUCHES() is based on the original MySQL implementation and\nuses object bounding rectangles, while ST_TOUCHES() uses\nobject shapes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/touches/','','https://mariadb.com/kb/en/touches/'),(255,'OPTIMIZE TABLE',20,'Syntax\n------ \nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [WAIT n | NOWAIT]\n \nDescription\n----------- \nOPTIMIZE TABLE has two main functions. It can either be used\nto defragment tables, or to update the InnoDB fulltext\nindex.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nDefragmenting\n \nOPTIMIZE TABLE works for InnoDB (before MariaDB 10.1.1, only\nif the innodb_file_per_table server system variable is set),\nAria, MyISAM and ARCHIVE tables, and should be used if you\nhave deleted a large part of a table or if you have made\nmany changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT\ncolumns). Deleted rows are maintained in a\nlinked list and subsequent INSERT operations reuse old row\npositions.\n \nThis statement requires SELECT and INSERT privileges for the\ntable.\n \nBy default, OPTIMIZE TABLE statements are written to the\nbinary log and will be replicated. The NO_WRITE_TO_BINLOG\nkeyword (LOCAL is an alias) will ensure the statement is not\nwritten to the binary log. \n \nOPTIMIZE TABLE is also supported for partitioned tables. You\ncan use \nALTER TABLE ... OPTIMIZE PARTITION \nto optimize one or more partitions.\n \nYou can use OPTIMIZE TABLE to reclaim the unused\nspace and to defragment the data file. With other storage\nengines, OPTIMIZE TABLE does nothing by default, and returns\nthis message: \" The storage engine for the table doesn\'t\nsupport optimize\". However, if the server has been started\nwith the --skip-new option, OPTIMIZE TABLE is linked to\nALTER TABLE, and recreates the table. This operation frees\nthe unused space and updates index statistics.\n \nSince MariaDB 5.3, the Aria storage engine supports progress\nreporting for this statement.\n \nIf a MyISAM table is fragmented, concurrent inserts will not\nbe performed until an OPTIMIZE TABLE statement is executed\non that table, unless the concurrent_insert server system\nvariable is set to ALWAYS.\n \nUpdating an InnoDB fulltext index\n \nWhen rows are added or deleted to an InnoDB fulltext index,\nthe index is not immediately re-organized, as this can be an\nexpensive operation. Change statistics are stored in a\nseparate location . The fulltext index is only fully\nre-organized when an OPTIMIZE TABLE statement is run.\n \nBy default, an OPTIMIZE TABLE will defragment a table. In\norder to use it to update fulltext index statistics, the\ninnodb_optimize_fulltext_only system variable must be set to\n1. This is intended to be a temporary setting, and should be\nreset to 0 once the fulltext index has been re-organized.\n \nSince fulltext re-organization can take a long time, the\ninnodb_ft_num_word_optimize variable limits the\nre-organization to a number of words (2000 by default). You\ncan run multiple OPTIMIZE statements to fully re-organize\nthe index.\n \nDefragmenting InnoDB tablespaces\n \nMariaDB 10.1.1 merged the Facebook/Kakao defragmentation\npatch \n \nMariaDB 10.1.1 merged the Facebook/Kakao defragmentation\npatch, allowing one to use OPTIMIZE TABLE to defragment\nInnoDB tablespaces. For this functionality to be enabled,\nthe innodb_defragment system variable must be enabled. No\nnew tables are created and there is no need to copy data\nfrom old tables to new tables. Instead, this feature loads n\npages (determined by innodb-defragment-n-pages) and tries to\nmove records so that pages would be full of records and then\nfrees pages that are fully empty after the operation. Note\nthat tablespace files (including ibdata1) will not shrink as\nthe result of defragmentation, but one will get better\nmemory utilization in the InnoDB buffer pool as there are\nfewer data pages in use.\n \nSee Defragmenting InnoDB Tablespaces for more details.\n \n\n\nURL: https://mariadb.com/kb/en/optimize-table/','','https://mariadb.com/kb/en/optimize-table/'),(256,'REPAIR TABLE',20,'Syntax\n------ \nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n \nDescription\n----------- \nREPAIR TABLE repairs a possibly corrupted table. By default,\nit has the same effect as\n \nmyisamchk --recover tbl_name\n \nor\n \naria_chk --recover tbl_name\n \nSee aria_chk and myisamchk for more.\n \nREPAIR TABLE works for Archive, Aria, CSV and MyISAM tables.\nFor XtraDB/InnoDB, see recovery modes. For CSV, see also\nChecking and Repairing CSV Tables. For Archive, this\nstatement also improves compression. If the storage engine\ndoes not support this statement, a warning is issued.\n \nThis statement requires SELECT and INSERT privileges for the\ntable.\n \nBy default, REPAIR TABLE statements are written to the\nbinary log and will be replicated. The NO_WRITE_TO_BINLOG\nkeyword (LOCAL is an alias) will ensure the statement is not\nwritten to the binary log.\n \nWhen an index is recreated, the storage engine may use a\nconfigurable buffer in the process. Incrementing the buffer\nspeeds up the index creation. Aria and MyISAM allocate a\nbuffer whose size is defined by aria_sort_buffer_size or\nmyisam_sort_buffer_size, also used for ALTER TABLE.\n \nREPAIR TABLE is also supported for partitioned tables.\nHowever, the USE_FRM option cannot be used with this\nstatement\non a partitioned table.\n \n ALTER TABLE ... REPAIR PARTITION can be used\nto repair one or more partitions.\n \nThe Aria storage engine supports progress reporting for this\nstatement.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/repair-table/','','https://mariadb.com/kb/en/repair-table/'),(472,'CURDATE',31,'Syntax\n------ \nCURDATE()\n \nDescription\n----------- \nReturns the current date as a value in \'YYYY-MM-DD\' or\nYYYYMMDD\nformat, depending on whether the function is used in a\nstring or\nnumeric context.\n \nExamples\n-------- \nSELECT CURDATE();\n+------------+\n| CURDATE() |\n+------------+\n| 2019-03-05 |\n+------------+\n \nIn a numeric context (note this is not performing date\ncalculations):\n \nSELECT CURDATE() +0;\n \n+--------------+\n| CURDATE() +0 |\n+--------------+\n| 20190305 |\n+--------------+\n \nData calculation:\n \nSELECT CURDATE() - INTERVAL 5 DAY;\n \n+----------------------------+\n| CURDATE() - INTERVAL 5 DAY |\n+----------------------------+\n| 2019-02-28 |\n+----------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/curdate/','','https://mariadb.com/kb/en/curdate/'),(473,'CURRENT_DATE',31,'Syntax\n------ \nCURRENT_DATE, CURRENT_DATE()\n \nDescription\n----------- \nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/current_date/','','https://mariadb.com/kb/en/current_date/'),(474,'CURRENT_TIME',31,'Syntax\n------ \nCURRENT_TIME\nCURRENT_TIME([precision])\n \nDescription\n----------- \nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n \n\n\nURL: https://mariadb.com/kb/en/current_time/','','https://mariadb.com/kb/en/current_time/'),(475,'CURRENT_TIMESTAMP',31,'Syntax\n------ \nCURRENT_TIMESTAMP\nCURRENT_TIMESTAMP([precision])\n \nDescription\n----------- \nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for\nNOW().\n \n\n\nURL: https://mariadb.com/kb/en/current_timestamp/','','https://mariadb.com/kb/en/current_timestamp/'),(476,'CURTIME',31,'Syntax\n------ \nCURTIME([precision])\n \nDescription\n----------- \nReturns the current time as a value in \'HH:MM:SS\' or\nHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed\nin the current time zone.\n \nThe optional precision determines the microsecond precision.\nSee Microseconds in MariaDB.\n \nExamples\n-------- \nSELECT CURTIME();\n+-----------+\n| CURTIME() |\n+-----------+\n| 12:45:39 |\n+-----------+\n \nSELECT CURTIME() + 0;\n \n+---------------+\n| CURTIME() + 0 |\n+---------------+\n| 124545.000000 |\n+---------------+\n \nWith precision:\n \nSELECT CURTIME(2);\n+-------------+\n| CURTIME(2) |\n+-------------+\n| 09:49:08.09 |\n+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/curtime/','','https://mariadb.com/kb/en/curtime/'),(257,'REPAIR VIEW',20,'REPAIR VIEW was introduced in MariaDB 10.0.18 and MariaDB\n5.5.43.\n \nSyntax\n------ \nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] VIEW view_name[,\nview_name] ... [FROM MYSQL]\n \nDescription\n----------- \nThe REPAIR VIEW statement was introduced to assist with\nfixing MDEV-6916, an issue introduced in MariaDB 5.2 where\nthe view algorithms were swapped compared to their MySQL on\ndisk representation. It checks whether the view algorithm is\ncorrect. It is run as part of mysql_upgrade, and should not\nnormally be required in regular use.\n \nBy default it corrects the checksum and if necessary adds\nthe mariadb-version field. If the optional FROM MYSQL clause\nis used, and no mariadb-version field is present, the MERGE\nand TEMPTABLE algorithms are toggled.\n \nBy default, REPAIR VIEW statements are written to the binary\nlog and will be replicated. The NO_WRITE_TO_BINLOG keyword\n(LOCAL is an alias) will ensure the statement is not written\nto the binary log.\n \nNote that REPAIR VIEW in MariaDB 10.0.18 and MariaDB 5.5.43\ncould crash the server (see MDEV-8115). Upgrade to a later\nversion.\n \n\n\nURL: https://mariadb.com/kb/en/repair-view/','','https://mariadb.com/kb/en/repair-view/'),(258,'CREATE FUNCTION UDF',21,'Syntax\n------ \nCREATE [OR REPLACE] [AGGREGATE] FUNCTION [IF NOT EXISTS]\nfunction_name\n RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n \nDescription\n----------- \nA user-defined function (UDF) is a way to extend MariaDB\nwith a new function\nthat works like a native (built-in) MariaDB function such as\nABS() or\nCONCAT().\n \nfunction_name is the name that should be used in SQL\nstatements to invoke\nthe function. \n \nTo create a function, you must have the INSERT privilege for\nthe\nmysql database. This is necessary because CREATE FUNCTION\nadds a row to the\nmysql.func system table that records the function\'s name,\ntype, and shared library name. If you do not have this\ntable, you should run\nthe mysql_upgrade command to create it.\n \nUDFs need to be written in C, C++ or another language that\nuses C calling\nconventions, MariaDB needs to have been dynamically\ncompiled, and your\noperating system must support dynamic loading.\n \nFor an example, see sql/udf_example.cc in the source tree.\nFor a collection of existing UDFs see\nhttp://www.mysqludf.org/.\n \nStatements making use of user-defined functions are not\nsafe for replication.\n \nFor creating a stored function as opposed to a user-defined\nfunction, see\nCREATE FUNCTION.\n \nFor valid identifiers to use as function names, see\nIdentifier Names.\n \nRETURNS\n \nThe RETURNS clause indicates the type of the function\'s\nreturn value, and can be one of STRING, INTEGER, REAL or\nDECIMAL. DECIMAL functions currently return string values\nand should be written like STRING functions.\n \nshared_library_name\n \nshared_library_name is the basename of the shared object\nfile that contains\nthe code that implements the function. The file must be\nlocated in the plugin\ndirectory. This directory is given by the value of the\nplugin_dir system variable. Note that\nbefore MariaDB/MySQL 5.1, the shared object could be located\nin any directory\nthat was searched by your system\'s dynamic linker.\n \nAGGREGATE\n \nAggregate functions are summary functions such as SUM() and\nAVG().\n \nAggregate UDF functions can be used as window functions.\n \nOR REPLACE\n \nThe OR REPLACE clause was added in MariaDB 10.1.3\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP FUNCTION IF EXISTS function_name;\n \nCREATE FUNCTION name ...;\n \nIF NOT EXISTS\n \nThe IF NOT EXISTS clause was added in MariaDB 10.1.3\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the specified function\nalready exists. Cannot be used together with OR REPLACE.\n \nUpgrading a UDF\n \nTo upgrade the UDF\'s shared library, first run a\nDROP FUNCTION statement, then upgrade the shared library and\nfinally run the CREATE FUNCTION statement. If you upgrade\nwithout following\nthis process, you may crash the server.\n \nExamples\n-------- \nCREATE FUNCTION jsoncontains_path RETURNS integer SONAME\n\'ha_connect.so\';\n \nQuery OK, 0 rows affected (0.00 sec)\n \nOR REPLACE and IF NOT EXISTS:\n \nCREATE FUNCTION jsoncontains_path RETURNS integer SONAME\n\'ha_connect.so\';\n \nERROR 1125 (HY000): Function \'jsoncontains_path\' already\nexists\n \nCREATE OR REPLACE FUNCTION jsoncontains_path RETURNS integer\nSONAME \'ha_connect.so\';\n \nQuery OK, 0 rows affected (0.00 sec)\n \nCREATE FUNCTION IF NOT EXISTS jsoncontains_path RETURNS\ninteger SONAME \'ha_connect.so\';\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+---------------------------------------------+\n| Level | Code | Message |\n+-------+------+---------------------------------------------+\n| Note | 1125 | Function \'jsoncontains_path\' already\nexists |\n+-------+------+---------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-function-udf/','','https://mariadb.com/kb/en/create-function-udf/'),(477,'DATE FUNCTION',31,'Syntax\n------ \nDATE(expr)\n \nDescription\n----------- \nExtracts the date part of the date or datetime expression\nexpr.\n \nExamples\n-------- \nSELECT DATE(\'2013-07-18 12:21:32\');\n+-----------------------------+\n| DATE(\'2013-07-18 12:21:32\') |\n+-----------------------------+\n| 2013-07-18 |\n+-----------------------------+\n \nError Handling\n \nUntil MariaDB 5.5.32, some versions of MariaDB returned\n0000-00-00 when passed an invalid date. From 5.5.32, NULL is\nreturned.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/date-function/','','https://mariadb.com/kb/en/date-function/'),(482,'DAY',31,'Syntax\n------ \nDAY(date)\n \nDescription\n----------- \nDAY() is a synonym for DAYOFMONTH().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/day/','','https://mariadb.com/kb/en/day/'),(486,'DAYOFYEAR',31,'Syntax\n------ \nDAYOFYEAR(date)\n \nDescription\n----------- \nReturns the day of the year for date, in the range 1 to 366.\n \nExamples\n-------- \nSELECT DAYOFYEAR(\'2018-02-16\');\n+-------------------------+\n| DAYOFYEAR(\'2018-02-16\') |\n+-------------------------+\n| 47 |\n+-------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/dayofyear/','','https://mariadb.com/kb/en/dayofyear/'),(488,'FROM_DAYS',31,'Syntax\n------ \nFROM_DAYS(N)\n \nDescription\n----------- \nGiven a day number N, returns a DATE value. The day count is\nbased on the number of days from the start of the standard\ncalendar (0000-00-00). \n \nThe function is not designed for use with dates before the\nadvent of the Gregorian calendar in October 1582. Results\nwill not be reliable since it doesn\'t account for the lost\ndays when the calendar changed from the Julian calendar.\n \nThis is the converse of the TO_DAYS() function.\n \nExamples\n-------- \nSELECT FROM_DAYS(730669);\n+-------------------+\n| FROM_DAYS(730669) |\n+-------------------+\n| 2000-07-03 |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/from_days/','','https://mariadb.com/kb/en/from_days/'),(493,'LOCALTIME',31,'Syntax\n------ \nLOCALTIME\nLOCALTIME([precision])\n \nDescription\n----------- \nLOCALTIME and LOCALTIME() are synonyms for NOW().\n \n\n\nURL: https://mariadb.com/kb/en/localtime/','','https://mariadb.com/kb/en/localtime/'),(494,'LOCALTIMESTAMP',31,'Syntax\n------ \nLOCALTIMESTAMP\nLOCALTIMESTAMP([precision])\n \nDescription\n----------- \nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n \n\n\nURL: https://mariadb.com/kb/en/localtimestamp/','','https://mariadb.com/kb/en/localtimestamp/'),(259,'DROP FUNCTION UDF',21,'Syntax\n------ \nDROP FUNCTION [IF EXISTS] function_name\n \nDescription\n----------- \nThis statement drops the user-defined function (UDF) named\nfunction_name.\n \nTo drop a function, you must have the DELETE privilege for\nthe mysql database. This is because DROP FUNCTION removes\nthe row from the mysql.func system table that records the\nfunction\'s name, type and shared library name.\n \nFor dropping a stored function, see DROP FUNCTION.\n \nUpgrading a UDF\n \nTo upgrade the UDF\'s shared library, first run a DROP\nFUNCTION statement, then upgrade the shared library and\nfinally run the CREATE FUNCTION statement. If you upgrade\nwithout following this process, you may crash the server.\n \nExamples\n-------- \nDROP FUNCTION jsoncontains_path;\n \nIF EXISTS:\n \nDROP FUNCTION jsoncontains_path;\n \nERROR 1305 (42000): FUNCTION test.jsoncontains_path does not\nexist\n \nDROP FUNCTION IF EXISTS jsoncontains_path;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------------------------------+\n| Level | Code | Message |\n+-------+------+------------------------------------------------+\n| Note | 1305 | FUNCTION test.jsoncontains_path does not\nexist |\n+-------+------+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/drop-function-udf/','','https://mariadb.com/kb/en/drop-function-udf/'),(260,'Creating User-Defined Functions',21,'User-defined functions allow MariaDB to be extended with a\nnew function that works like a native (built-in) MariaDB\nfunction such as ABS() or CONCAT(). There are alternative\nways to add a new function: writing a native function (which\nrequires modifying and compiling the server source code), or\nwriting a stored function.\n \nStatements making use of user-defined functions are not safe\nfor replication.\n \nFunctions are written in C or C++, and to make use of them,\nthe operating system must support dynamic loading. \n \nEach new SQL function requires corresponding functions\nwritten in C/C++. In the list below, at least the main\nfunction - x() - and one other, are required. x should be\nreplaced by the name of the function you are creating.\n \nAll functions need to be thread-safe, so not global or\nstatic variables that change can be allocated. Memory is\nallocated in x_init()/ and freed in x_deinit(). \n \nSimple Functions\n \nx()\n \nRequired for all UDF\'s, this is where the results are\ncalculated.\n \nC/C++ type | SQL type | \n \nchar * | STRING | \n \nlong long | INTEGER | \n \ndouble | REAL | \n \nDECIMAL functions return string values, and so should be\nwritten accordingly. It is not possible to create ROW\nfunctions.\n \nx_init()\n \nInitialization function for x(). Can be used for the\nfollowing:\nCheck the number of arguments to X() (the SQL equivalent).\nVerify the argument types, or to force arguments to be of a\nparticular type after the function is called.\nSpecify whether the result can be NULL.\nSpecify the maximum result length.\nFor REAL functions, specify the maximum number of decimals\nfor the result.\nAllocate any required memory.\n To verify that the arguments are of a required type or,\nalternatively, to tell MySQL to coerce arguments to the\nrequired types when the main function is called.\n \nx_deinit()\n \nDe-initialization function for x(). Used to de-allocate\nmemory that was allocated in x_init().\n \nDescription\n----------- \nEach time the SQL function X() is called:\nMariaDB will first call the C/C++ initialization function,\nx_init(), assuming it exists. All setup will be performed,\nand if it returns an error, the SQL statement is aborted and\nno further functions are called.\nIf there is no x_init() function, or it has been called and\ndid not return an error, x() is then called once per row.\nAfter all rows have finished processing, x_deinit() is\ncalled, if present, to clean up by de-allocating any memory\nthat was allocated in x_init().\nSee User-defined Functions Calling Sequences for more\ndetails on the functions.\n \nAggregate Functions\n \nThe following functions are required for aggregate\nfunctions, such as AVG() and SUM(). \n \nx_clear()\n \nUsed to reset the current aggregate, but without inserting\nthe argument as the initial aggregate value for the new\ngroup.\n \nx_add()\n \nUsed to add the argument to the current aggregate. \n \nx_remove()\n \nStaring from MariaDB 10.4 it improves the support of window\nfunctions (so it is not obligatory to add it) and should\nremove the argument from the current aggregate.\n \nDescription\n----------- \nEach time the aggregate SQL function X() is called:\nMariaDB will first call the C/C++ initialization function,\nx_init(), assuming it exists. All setup will be performed,\nand if it returns an error, the SQL statement is aborted and\nno further functions are called.\nIf there is no x_init() function, or it has been called and\ndid not return an error, x() is then called once per row.\nAfter all rows have finished processing, x_deinit() is\ncalled, if present, to clean up by de-allocating any memory\nthat was allocated in x_init().\n \nMariaDB will first call the C/C++ initialization function,\nx_init(), assuming it exists. All setup will be performed,\nand if it returns an error, the SQL statement is aborted and\nno further functions are called.\nThe table is sorted according to the GROUP BY expression.\nx_clear() is called for the first row of each new group.\nx_add() is called once per row for each row in the same\ngroup.\nx() is called when the group changes, or after the last row,\nto get the aggregate result. \nThe latter three steps are repeated until all rows have been\nprocessed.\nAfter all rows have finished processing, x_deinit() is\ncalled, if present, to clean up by de-allocating any memory\nthat was allocated in x_init().\n \nExamples\n-------- \nFor an example, see sql/udf_example.cc in the source tree.\nFor a collection of existing UDFs see\nhttps://github.com/mysqludf.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/creating-user-defined-functions/','','https://mariadb.com/kb/en/creating-user-defined-functions/'),(498,'MINUTE',31,'Syntax\n------ \nMINUTE(time)\n \nDescription\n----------- \nReturns the minute for time, in the range 0 to 59. \n \nExamples\n-------- \nSELECT MINUTE(\'2013-08-03 11:04:03\');\n+-------------------------------+\n| MINUTE(\'2013-08-03 11:04:03\') |\n+-------------------------------+\n| 4 |\n+-------------------------------+\n \n SELECT MINUTE (\'23:12:50\');\n+---------------------+\n| MINUTE (\'23:12:50\') |\n+---------------------+\n| 12 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/minute/','','https://mariadb.com/kb/en/minute/'),(499,'MONTH',31,'Syntax\n------ \nMONTH(date)\n \nDescription\n----------- \nReturns the month for date in the range 1 to 12 for January\nto\nDecember, or 0 for dates such as \'0000-00-00\' or\n\'2008-00-00\' that\nhave a zero month part.\n \nExamples\n-------- \nSELECT MONTH(\'2019-01-03\');\n+---------------------+\n| MONTH(\'2019-01-03\') |\n+---------------------+\n| 1 |\n+---------------------+\n \nSELECT MONTH(\'2019-00-03\');\n+---------------------+\n| MONTH(\'2019-00-03\') |\n+---------------------+\n| 0 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/month/','','https://mariadb.com/kb/en/month/'),(500,'MONTHNAME',31,'Syntax\n------ \nMONTHNAME(date)\n \nDescription\n----------- \nReturns the full name of the month for date. The language\nused for the name is controlled by the value of the\nlc_time_names system variable. See server locale for more on\nthe supported locales.\n \nExamples\n-------- \nSELECT MONTHNAME(\'2019-02-03\');\n+-------------------------+\n| MONTHNAME(\'2019-02-03\') |\n+-------------------------+\n| February |\n+-------------------------+\n \nChanging the locale:\n \nSET lc_time_names = \'fr_CA\';\n \nSELECT MONTHNAME(\'2019-05-21\');\n+-------------------------+\n| MONTHNAME(\'2019-05-21\') |\n+-------------------------+\n| mai |\n+-------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/monthname/','','https://mariadb.com/kb/en/monthname/'),(261,'User-Defined Functions Calling Sequences',21,'The functions described in Creating User-defined Functions\nare expanded on this page. They are declared as follows:\n \nSimple Functions\n \nx()\n \nIf x() returns an integer, it is declared as follows:\n \nlong long x(UDF_INIT *initid, UDF_ARGS *args,\n char *is_null, char *error);\n \nIf x() returns a string (DECIMAL functions also return\nstring values), it is declared as follows:\n \nchar *x(UDF_INIT *initid, UDF_ARGS *args,\n char *result, unsigned long *length,\n char *is_null, char *error);\n \nIf x() returns a real, it is declared as follows:\n \ndouble x(UDF_INIT *initid, UDF_ARGS *args,\n char *is_null, char *error);\n \nx_init()\n \nmy_bool x_init(UDF_INIT *initid, UDF_ARGS *args, char\n*message);\n \nx_deinit()\n \nvoid x_deinit(UDF_INIT *initid);\n \nDescription\n----------- \ninitid is a parameter passed to all three functions that\npoints to a UDF_INIT structure, used for communicating\ninformation between the functions. Its structure members\nare:\nmy_bool maybe_null\nmaybe_null should be set to 1 if x_init can return a NULL\nvalue, Defaults to 1 if any arguments are declared\nmaybe_null.\n \nunsigned int decimals\nNumber of decimals after the decimal point. The default, if\nan explicit number of decimals is passed in the arguments to\nthe main function, is the maximum number of decimals, so if\n9.5, 9.55 and 9.555 are passed to the function, the default\nwould be three (based on 9.555, the maximum). If there are\nno explicit number of decimals, the default is set to 31, or\none more than the maximum for the DOUBLE, FLOAT and DECIMAL\ntypes. This default can be changed in the function to suit\nthe actual calculation.\n \nunsigned int max_length\nMaximum length of the result. For integers, the default is\n21. For strings, the length of the longest argument. For\nreals, the default is 13 plus the number of decimals\nindicated by initid->decimals. The length includes any signs\nor decimal points. Can also be set to 65KB or 16MB in order\nto return a BLOB. The memory remains unallocated, but this\nis used to decide on the data type to use if the data needs\nto be temporarily stored.\n \nchar *ptr\nA pointer for use as required by the function. Commonly,\ninitid->ptr is used to communicate allocated memory, with\nx_init() allocating the memory and assigning it to this\npointer, x() using it, and x_deinit() de-allocating it.\n \nmy_bool const_item\nShould be set to 1 in x_init() if x() always returns the\nsame value, otherwise 0.\n \n\nAggregate Functions\n \nx_clear()\n \nx_clear() is a required function for aggregate functions,\nand is declared as follows:\n \nvoid x_clear(UDF_INIT *initid, char *is_null, char *error);\n \nIt is called when the summary results need to be reset, that\nis at the beginning of each new group. but also to reset the\nvalues when there were no matching rows.\n \nis_null is set to point to CHAR(0) before calling x_clear().\n \nIn the case of an error, you can store the value to which\nthe error argument points (a single-byte variable, not a\nstring string buffer) in the variable.\n \nx_reset()\n \nx_reset() is declared as follows:\n \nvoid x_reset(UDF_INIT *initid, UDF_ARGS *args,\n char *is_null, char *error);\n \nIt is called on finding the first row in a new group. Should\nreset the summary variables, and then use UDF_ARGS as the\nfirst value in the group\'s internal summary value. The\nfunction is not required if the UDF interface uses\nx_clear().\n \nx_add()\n \nx_add() is declared as follows:\n \nvoid x_add(UDF_INIT *initid, UDF_ARGS *args,\n char *is_null, char *error);\n \nIt is called for all rows belonging to the same group, and\nshould be used to add the value in UDF_ARGS to the internal\nsummary variable.\n \nx_remove()\n \nx_remove() was added in MariaDB 10.4 and is declared as\nfollows (same as x_add()):\n \nvoid x_remove(UDF_INIT* initid, UDF_ARGS* args,\n char* is_null, char *error );\n \nIt adds more efficient support of aggregate UDFs as window\nfunctions. x_remove() should \"subtract\" the row (reverse\nx_add()). In MariaDB 10.4 aggregate UDFs will work as WINDOW\nfunctions without x_remove() but it will not be so\nefficient.\n \nIf x_remove() supported (defined) detected automatically.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/user-defined-functions-calling-sequences/','','https://mariadb.com/kb/en/user-defined-functions-calling-sequences/'),(262,'User-Defined Functions Security',21,'The MariaDB server imposes a number of limitations on\nuser-defined functions for security purposes.\nThe INSERT privilege for the mysql database is required to\nrun CREATE FUNCTION, as a record will be added to the\nmysql.func-table.\nThe DELETE privilege for the mysql database is required to\nrun DROP FUNCTION as the corresponding record will be\nremoved from the mysql.func-table.\nUDF object files can only be placed in the plugin directory,\nas specified by the value of the plugin_dir system variable.\nAt least one symbol, beyond the required x() - corresponding\nto an SQL function X()) - is required. These can be\nx_init(), x_deinit(), xxx_reset(), x_clear() and x_add()\nfunctions (see Creating User-defined Functions). The\nallow-suspicious-udfs mysqld option (by default unset)\nprovides a workaround, permitting only one symbol to be\nused. This is not recommended, as it opens the possibility\nof loading shared objects that are not legitimate\nuser-defined functions.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/user-defined-functions-security/','','https://mariadb.com/kb/en/user-defined-functions-security/'),(504,'QUARTER',31,'Syntax\n------ \nQUARTER(date)\n \nDescription\n----------- \nReturns the quarter of the year for date, in the range 1 to\n4. Returns 0 if month contains a zero value, or NULL if the\ngiven value is not otherwise a valid date (zero values are\naccepted).\n \nExamples\n-------- \nSELECT QUARTER(\'2008-04-01\');\n+-----------------------+\n| QUARTER(\'2008-04-01\') |\n+-----------------------+\n| 2 |\n+-----------------------+\n \nSELECT QUARTER(\'2019-00-01\');\n+-----------------------+\n| QUARTER(\'2019-00-01\') |\n+-----------------------+\n| 0 |\n+-----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/quarter/','','https://mariadb.com/kb/en/quarter/'),(505,'SECOND',31,'Syntax\n------ \nSECOND(time)\n \nDescription\n----------- \nReturns the second for a given time (which can include\nmicroseconds), in the range 0 to 59, or NULL if not given a\nvalid time value.\n \nExamples\n-------- \nSELECT SECOND(\'10:05:03\');\n+--------------------+\n| SECOND(\'10:05:03\') |\n+--------------------+\n| 3 |\n+--------------------+\n \nSELECT SECOND(\'10:05:01.999999\');\n+---------------------------+\n| SECOND(\'10:05:01.999999\') |\n+---------------------------+\n| 1 |\n+---------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/second/','','https://mariadb.com/kb/en/second/'),(511,'TIME Function',31,'Syntax\n------ \nTIME(expr)\n \nDescription\n----------- \nExtracts the time part of the time or datetime expression\nexpr and\nreturns it as a string.\n \nExamples\n-------- \nSELECT TIME(\'2003-12-31 01:02:03\');\n+-----------------------------+\n| TIME(\'2003-12-31 01:02:03\') |\n+-----------------------------+\n| 01:02:03 |\n+-----------------------------+\n \nSELECT TIME(\'2003-12-31 01:02:03.000123\');\n+------------------------------------+\n| TIME(\'2003-12-31 01:02:03.000123\') |\n+------------------------------------+\n| 01:02:03.000123 |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/time-function/','','https://mariadb.com/kb/en/time-function/'),(263,'mysql.func Table',21,'The mysql.func table stores information about user-defined\nfunctions (UDFs) created with the CREATE FUNCTION UDF\nstatement.\n \nIn MariaDB 10.4 and later, this table uses the Aria storage\nengine.\n \nMariaDB until 10.3\n \nIn MariaDB 10.3 and before, this table uses the MyISAM\nstorage engine.\n \nThe mysql.func table contains the following fields:\n \nField | Type | Null | Key | Default | Description | \n \nname | char(64) | NO | PRI | | UDF name | \n \nret | tinyint(1) | NO | | 0 | | \n \ndl | char(128) | NO | | | Shared library name | \n \ntype | enum(\'function\',\'aggregate\') | NO | | NULL |\nType, either function or aggregate. Aggregate functions are\nsummary functions such as SUM() and AVG(). | \n \nExample\n \nSELECT * FROM mysql.func;\n+------------------------------+-----+--------------+-----------+\n| name | ret | dl | type |\n+------------------------------+-----+--------------+-----------+\n| spider_direct_sql | 2 | ha_spider.so | function |\n| spider_bg_direct_sql | 2 | ha_spider.so | aggregate |\n| spider_ping_table | 2 | ha_spider.so | function |\n| spider_copy_tables | 2 | ha_spider.so | function |\n| spider_flush_table_mon_cache | 2 | ha_spider.so | function\n|\n+------------------------------+-----+--------------+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mysqlfunc-table/','','https://mariadb.com/kb/en/mysqlfunc-table/'),(264,'AUTO_INCREMENT',22,'Description\n----------- \nThe AUTO_INCREMENT attribute can be used to generate a\nunique identity for new rows. When you insert a new record\nto the table, and the auto_increment field is NULL or\nDEFAULT, the value will automatically be incremented. This\nalso applies to 0, unless the NO_AUTO_VALUE_ON_ZERO SQL_MODE\nis enabled.\n \nAUTO_INCREMENT columns start from 1 by default. The\nautomatically generated value can never be lower than 0.\n \nEach table can have only one AUTO_INCREMENT column. It must\ndefined as a key (not necessarily the PRIMARY KEY or UNIQUE\nkey). In some storage engines (including the default\nInnoDB), if the key consists of multiple columns, the\nAUTO_INCREMENT column must be the first column. Storage\nengines that permit the column to be placed elsewhere are\nAria, MyISAM, MERGE, Spider, TokuDB, BLACKHOLE, FederatedX\nand Federated.\n \nCREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n );\n \nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'fox\'),(\'whale\'),(\'ostrich\');\n \nSELECT * FROM animals;\n \n+----+---------+\n| id | name |\n+----+---------+\n| 1 | dog |\n| 2 | cat |\n| 3 | penguin |\n| 4 | fox |\n| 5 | whale |\n| 6 | ostrich |\n+----+---------+\n \nSERIAL is an alias for BIGINT UNSIGNED NOT NULL\nAUTO_INCREMENT UNIQUE.\n \nCREATE TABLE t (id SERIAL, c CHAR(1)) ENGINE=InnoDB;\n \nSHOW CREATE TABLE t \\G\n*************************** 1. row\n***************************\n Table: t\nCreate Table: CREATE TABLE `t` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n `c` char(1) DEFAULT NULL,\n UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1\n \nSetting or Changing the Auto_Increment Value\n \nYou can use an ALTER TABLE statement to assign a new value\nto the auto_increment table option, or set the insert_id\nserver system variable to change the next AUTO_INCREMENT\nvalue inserted by the current session.\n \nLAST_INSERT_ID() can be used to see the last AUTO_INCREMENT\nvalue inserted by the current session.\n \nALTER TABLE animals AUTO_INCREMENT=8;\n \nINSERT INTO animals (name) VALUES (\'aardvark\');\n \nSELECT * FROM animals;\n \n+----+-----------+\n| id | name |\n+----+-----------+\n| 1 | dog |\n| 2 | cat |\n| 3 | penguin |\n| 4 | fox |\n| 5 | whale |\n| 6 | ostrich |\n| 8 | aardvark |\n+----+-----------+\n \nSET insert_id=12;\n \nINSERT INTO animals (name) VALUES (\'gorilla\');\n \nSELECT * FROM animals;\n \n+----+-----------+\n| id | name |\n+----+-----------+\n| 1 | dog |\n| 2 | cat |\n| 3 | penguin |\n| 4 | fox |\n| 5 | whale |\n| 6 | ostrich |\n| 8 | aardvark |\n| 12 | gorilla |\n+----+-----------+\n \nInnoDB/XtraDB\n \nUntil MariaDB 10.2.3, InnoDB and XtraDB used an\nauto-increment counter that is stored in memory. When the\nserver restarts, the counter is re-initialized to the\nhighest value used in the table, which cancels the effects\nof any AUTO_INCREMENT = N option in the table statements.\n \nFrom MariaDB 10.2.4, this restriction has been lifted and\nAUTO_INCREMENT is persistent.\n \nSee also AUTO_INCREMENT Handling in XtraDB/InnoDB.\n \nSetting Explicit Values\n \nIt is possible to specify a value for an AUTO_INCREMENT\ncolumn. The value must not exist in the key.\n \nIf the new value is higher than the current maximum value,\nthe AUTO_INCREMENT value is updated, so the next value will\nbe higher. If the new value is lower than the current\nmaximum value, the AUTO_INCREMENT value remains unchanged.\n \nThe following example demonstrates these behaviours:\n \nCREATE TABLE t (id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY\nKEY) ENGINE = InnoDB;\n \nINSERT INTO t VALUES (NULL);\nSELECT id FROM t;\n \n+----+\n| id |\n+----+\n| 1 |\n+----+\n \nINSERT INTO t VALUES (10); -- higher value\nSELECT id FROM t;\n \n+----+\n| id |\n+----+\n| 1 |\n| 10 |\n+----+\n \nINSERT INTO t VALUES (2); -- lower value\nINSERT INTO t VALUES (NULL); -- auto value\nSELECT id FROM t;\n \n+----+\n| id |\n+----+\n| 1 |\n| 2 |\n| 10 |\n| 11 |\n+----+\n \nThe ARCHIVE storage engine does not allow to insert a value\nthat is lower than the current maximum.\n \nMissing Values\n \nAn AUTO_INCREMENT column normally has missing values. This\nhappens because if a row is deleted, or an AUTO_INCREMENT\nvalue is explicitly updated, old values are never re-used.\nThe REPLACE statement also deletes a row, and its value is\nwasted. With InnoDB, values can be reserved by a\ntransaction; but if the transaction fails (for example,\nbecause of a ROLLBACK) the reserved value will be lost.\n \nThus AUTO_INCREMENT values can be used to sort results in a\nchronological order, but not to create a numeric sequence.\n \nReplication\n \nTo make master-master or Galera safe to use AUTO_INCREMENT\none should use the system variables \n auto_increment_increment and auto_increment_offset to\ngenerate unique values for each server.\n \nCHECK Constraints, DEFAULT Values and Virtual Columns\n \nFrom MariaDB 10.2.6 auto_increment columns are no longer\npermitted in CHECK constraints, DEFAULT value expressions\nand virtual columns. They were permitted in earlier\nversions, but did not work correctly. See MDEV-11117.\n \n\n\nURL: https://mariadb.com/kb/en/auto_increment/','','https://mariadb.com/kb/en/auto_increment/'),(516,'TIME_FORMAT',31,'Syntax\n------ \nTIME_FORMAT(time,format)\n \nDescription\n----------- \nThis is used like the DATE_FORMAT() function, but the format\nstring\nmay contain format specifiers only for hours, minutes, and\nseconds.\nOther specifiers produce a NULL value or 0.\n \nExamples\n-------- \nSELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n+--------------------------------------------+\n| TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\') |\n+--------------------------------------------+\n| 100 100 04 04 4 |\n+--------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/time_format/','','https://mariadb.com/kb/en/time_format/'),(517,'TIME_TO_SEC',31,'Syntax\n------ \nTIME_TO_SEC(time)\n \nDescription\n----------- \nReturns the time argument, converted to seconds.\n \nThe value returned by TIME_TO_SEC is of type DOUBLE. Before\nMariaDB 5.3 (and MySQL 5.6), the type was INT. See\nMicroseconds in MariaDB.\n \nExamples\n-------- \nSELECT TIME_TO_SEC(\'22:23:00\');\n+-------------------------+\n| TIME_TO_SEC(\'22:23:00\') |\n+-------------------------+\n| 80580 |\n+-------------------------+\n \nSELECT TIME_TO_SEC(\'00:39:38\');\n+-------------------------+\n| TIME_TO_SEC(\'00:39:38\') |\n+-------------------------+\n| 2378 |\n+-------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/time_to_sec/','','https://mariadb.com/kb/en/time_to_sec/'),(265,'BIGINT',22,'Syntax\n------ \nBIGINT[(M)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to\n18446744073709551615.\n \nIf a column has been set to ZEROFILL, all values will be\nprepended by zeros so that the BIGINT value contains a\nnumber of M digits.\n \nNote: If the ZEROFILL attribute has been specified, the\ncolumn will automatically become UNSIGNED.\n \nFor more details on the attributes, see Numeric Data Type\nOverview.\n \nSERIAL is an alias for:\n \nBIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE\n \nExamples\n-------- \nCREATE TABLE bigints (a BIGINT,b BIGINT UNSIGNED,c BIGINT\nZEROFILL);\n \nINSERT INTO bigints VALUES (-10,-10,-10);\nQuery OK, 1 row affected, 2 warnings (0.08 sec)\nWarning (Code 1264): Out of range value for column \'b\' at\nrow 1\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO bigints VALUES (-10,10,-10);Query OK, 1 row\naffected, 1 warning (0.08 sec)\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO bigints VALUES (-10,10,10);\n \nINSERT INTO bigints VALUES\n(9223372036854775808,9223372036854775808,9223372036854775808);\nQuery OK, 1 row affected, 1 warning (0.07 sec)\nWarning (Code 1264): Out of range value for column \'a\' at\nrow 1\n \nINSERT INTO bigints VALUES\n(9223372036854775807,9223372036854775808,9223372036854775808);\n \nSELECT * FROM bigints;\n+---------------------+---------------------+----------------------+\n| a | b | c |\n+---------------------+---------------------+----------------------+\n| -10 | 0 | 00000000000000000000 |\n| -10 | 10 | 00000000000000000000 |\n| -10 | 10 | 00000000000000000010 |\n| 9223372036854775807 | 9223372036854775808 |\n09223372036854775808 |\n| 9223372036854775807 | 9223372036854775808 |\n09223372036854775808 |\n+---------------------+---------------------+----------------------+\n \n\n\nURL: https://mariadb.com/kb/en/bigint/','','https://mariadb.com/kb/en/bigint/'),(266,'BINARY',22,'Syntax\n------ \nBINARY(M)\n \nDescription\n----------- \nThe BINARY type is similar to the CHAR type, but stores\nbinary\nbyte strings rather than non-binary character strings. M\nrepresents the\ncolumn length in bytes.\n \nIt contains no character set, and comparison and sorting are\nbased on the numeric value of the bytes.\n \nIf the maximum length is exceeded, and SQL strict mode is\nnot enabled , the extra characters will be dropped with a\nwarning. If strict mode is enabled, an error will occur.\n \nBINARY values are right-padded with 0x00 (the zero byte) to\nthe specified length when inserted. The padding is not\nremoved on select, so this needs to be taken into account\nwhen sorting and comparing, where all bytes are significant.\nThe zero byte, 0x00 is less than a space for comparison\npurposes.\n \nExamples\n-------- \nInserting too many characters, first with strict mode off,\nthen with it on:\n \nCREATE TABLE bins (a BINARY(10));\n \nINSERT INTO bins VALUES(\'12345678901\');\nQuery OK, 1 row affected, 1 warning (0.04 sec)\n \nSELECT * FROM bins;\n \n+------------+\n| a |\n+------------+\n| 1234567890 |\n+------------+\n \nSET sql_mode=\'STRICT_ALL_TABLES\';\n \nINSERT INTO bins VALUES(\'12345678901\');\nERROR 1406 (22001): Data too long for column \'a\' at row 1\n \nSorting is performed with the byte value:\n \nTRUNCATE bins;\n \nINSERT INTO bins VALUES(\'A\'),(\'B\'),(\'a\'),(\'b\');\n \nSELECT * FROM bins ORDER BY a;\n \n+------+\n| a |\n+------+\n| A |\n| B |\n| a |\n| b |\n+------+\n \nUsing CAST to sort as a CHAR instead:\n \nSELECT * FROM bins ORDER BY CAST(a AS CHAR);\n+------+\n| a |\n+------+\n| a |\n| A |\n| b |\n| B |\n+------+\n \nThe field is a BINARY(10), so padding of two \'\\0\'s are\ninserted, causing comparisons that don\'t take this into\naccount to fail:\n \nTRUNCATE bins;\n \nINSERT INTO bins VALUES(\'12345678\');\n \nSELECT a = \'12345678\', a = \'12345678\\0\\0\' from bins;\n \n+----------------+--------------------+\n| a = \'12345678\' | a = \'12345678\\0\\0\' |\n+----------------+--------------------+\n| 0 | 1 |\n+----------------+--------------------+\n \n\n\nURL: https://mariadb.com/kb/en/binary/','','https://mariadb.com/kb/en/binary/'),(267,'BIT',22,'Syntax\n------ \nBIT[(M)]\n \nDescription\n----------- \nA bit-field type. M indicates the number of bits per value,\nfrom 1 to\n64. The default is 1 if M is omitted.\n \nBit values can be inserted with b\'value\' notation, where\nvalue is the bit value in 0\'s and 1\'s.\n \nBit fields are automatically zero-padded from the left to\nthe full length of the bit, so for example in a BIT(4)\nfield, \'10\' is equivalent to \'0010\'.\n \nBits are returned as binary, so to display them, either add\n0, or use a function such as HEX, OCT or BIN to convert\nthem.\n \nExamples\n-------- \nCREATE TEMPORARY TABLE b ( b1 BIT(8) );\nINSERT INTO b VALUES\n(b\'11111111\'),(b\'01010101\'),(b\'1111111111111\');\nQuery OK, 3 rows affected, 1 warning (0.10 sec)\nRecords: 3 Duplicates: 0 Warnings: 1\n \nSHOW WARNINGS;\n+---------+------+---------------------------------------------+\n| Level | Code | Message |\n+---------+------+---------------------------------------------+\n| Warning | 1264 | Out of range value for column \'b1\' at\nrow 3 |\n+---------+------+---------------------------------------------+\n \nSELECT b1+0, HEX(b1), OCT(b1), BIN(b1) FROM b;\n+------+---------+---------+----------+\n| b1+0 | HEX(b1) | OCT(b1) | BIN(b1) |\n+------+---------+---------+----------+\n| 255 | FF | 377 | 11111111 |\n| 85 | 55 | 125 | 1010101 |\n| 255 | FF | 377 | 11111111 |\n+------+---------+---------+----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bit/','','https://mariadb.com/kb/en/bit/'),(521,'UTC_DATE',31,'Syntax\n------ \nUTC_DATE, UTC_DATE()\n \nDescription\n----------- \nReturns the current UTC date as a value in \'YYYY-MM-DD\' or\nYYYYMMDD\nformat, depending on whether the function is used in a\nstring or numeric context. \n \nExamples\n-------- \nSELECT UTC_DATE(), UTC_DATE() + 0;\n \n+------------+----------------+\n| UTC_DATE() | UTC_DATE() + 0 |\n+------------+----------------+\n| 2010-03-27 | 20100327 |\n+------------+----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/utc_date/','','https://mariadb.com/kb/en/utc_date/'),(522,'UTC_TIME',31,'Syntax\n------ \nUTC_TIME\nUTC_TIME([precision])\n \nDescription\n----------- \nReturns the current UTC time as a value in \'HH:MM:SS\' or\nHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. \n \nThe optional precision determines the microsecond precision.\nSee Microseconds in MariaDB.\n \nExamples\n-------- \nSELECT UTC_TIME(), UTC_TIME() + 0;\n \n+------------+----------------+\n| UTC_TIME() | UTC_TIME() + 0 |\n+------------+----------------+\n| 17:32:34 | 173234.000000 |\n+------------+----------------+\n \nWith precision:\n \nSELECT UTC_TIME(5);\n+----------------+\n| UTC_TIME(5) |\n+----------------+\n| 07:52:50.78369 |\n+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/utc_time/','','https://mariadb.com/kb/en/utc_time/'),(530,'AsBinary',32,'A synonym for ST_AsBinary().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-asbinary/','','https://mariadb.com/kb/en/wkb-asbinary/'),(531,'AsWKB',32,'A synonym for ST_AsBinary().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/aswkb/','','https://mariadb.com/kb/en/aswkb/'),(532,'MLineFromWKB',32,'Syntax\n------ \nMLineFromWKB(wkb[,srid])\nMultiLineStringFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a MULTILINESTRING value using its WKB\nrepresentation and SRID.\n \nMLineFromWKB() and MultiLineStringFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(MLineFromText(\'MULTILINESTRING((10\n48,10 21,10 0),(16 0,16 23,16 48))\'));\n \nSELECT ST_AsText(MLineFromWKB(@g));\n+--------------------------------------------------------+\n| ST_AsText(MLineFromWKB(@g)) |\n+--------------------------------------------------------+\n| MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) |\n+--------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mlinefromwkb/','','https://mariadb.com/kb/en/mlinefromwkb/'),(268,'BLOB',22,'Syntax\n------ \nBLOB[(M)]\n \nDescription\n----------- \nA BLOB column with a maximum length of 65,535 (216 - 1)\nbytes. Each\nBLOB value is stored using a two-byte length prefix that\nindicates the\nnumber of bytes in the value.\n \nAn optional length M can be given for this type. If this is\ndone,\nMariaDB creates the column as the smallest BLOB type large\nenough to\nhold values M bytes long.\n \nBLOBS can also be used to store dynamic columns.\n \nBefore MariaDB 10.2.1, BLOB and TEXT columns could not be\nassigned a DEFAULT value. This restriction was lifted in\nMariaDB 10.2.1.\n \nIndexing\n \nIn MariaDB 10.4, it is possible to set a Unique index on a\ncolumn that uses the BLOB data type. In previous releases\nthis was not possible, as the index would only guarantee the\nuniqueness of a fixed number of characters.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, BLOB is a synonym for\nLONGBLOB.\n \n\n\nURL: https://mariadb.com/kb/en/blob/','','https://mariadb.com/kb/en/blob/'),(270,'BOOLEAN',22,'Syntax\n------ \nBOOL, BOOLEAN\n \nDescription\n----------- \nThese types are synonyms for TINYINT(1). \nA value of zero is considered false. Non-zero values are\nconsidered true:\n \nmysql> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n \nmysql> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n \nmysql> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n \nHowever, the values TRUE and FALSE are merely aliases for 1\nand 0,\nrespectively, as shown here:\n \nmysql> SELECT IF(0 = FALSE, \'true\', \'false\');\n \n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n \nmysql> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n \nmysql> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n \nmysql> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n \nUNKNOWN is an alias for NULL.\n \nThe last two statements display the results shown because 2\nis equal\nto neither 1 nor 0.\n \n\n\nURL: https://mariadb.com/kb/en/boolean/','','https://mariadb.com/kb/en/boolean/'),(271,'CHAR',22,'This article covers the CHAR data type. See CHAR Function\nfor the function.\n \nSyntax\n------ \n[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA fixed-length string that is always right-padded with\nspaces to the specified\nlength when stored. M represents the column length in\ncharacters. The range\nof M is 0 to 255. If M is omitted, the length is 1.\n \nCHAR(0) columns can contain 2 values: an empty string or\nNULL. Such columns cannot be part of an index. The CONNECT\nstorage engine does not support CHAR(0).\n \nNote: Trailing spaces are removed when CHAR values are\nretrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n \nBefore MariaDB 10.2, all collations were of type PADSPACE,\nmeaning that CHAR (as well as VARCHAR and TEXT) values are\ncompared without regard for trailing spaces. This does not\napply to the LIKE pattern-matching operator, which takes\ninto account trailing spaces.\n \nIf a unique index consists of a column where trailing pad\ncharacters are stripped or ignored, inserts into that column\nwhere values differ only by the number of trailing pad\ncharacters will result in a duplicate-key error.\n \nExamples\n-------- \nTrailing spaces:\n \nCREATE TABLE strtest (c CHAR(10));\nINSERT INTO strtest VALUES(\'Maria \');\n \nSELECT c=\'Maria\',c=\'Maria \' FROM strtest;\n \n+-----------+--------------+\n| c=\'Maria\' | c=\'Maria \' |\n+-----------+--------------+\n| 1 | 1 |\n+-----------+--------------+\n \nSELECT c LIKE \'Maria\',c LIKE \'Maria \' FROM strtest;\n \n+----------------+-------------------+\n| c LIKE \'Maria\' | c LIKE \'Maria \' |\n+----------------+-------------------+\n| 1 | 0 |\n+----------------+-------------------+\n \nNO PAD Collations\n \nNO PAD collations regard trailing spaces as normal\ncharacters. You can get a list of all NO PAD collations by\nquerying the Information Schema Collations table, for\nexample:\n \nSELECT collation_name FROM information_schema.collations \n WHERE collation_name LIKE \"%nopad%\";\n \n+------------------------------+\n| collation_name |\n+------------------------------+\n| big5_chinese_nopad_ci |\n| big5_nopad_bin |\n...\n \n\n\nURL: https://mariadb.com/kb/en/char/','','https://mariadb.com/kb/en/char/'),(533,'MPointFromWKB',32,'Syntax\n------ \nMPointFromWKB(wkb[,srid])\nMultiPointFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a MULTIPOINT value using its WKB representation\nand SRID.\n \nMPointFromWKB() and MultiPointFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(MPointFromText(\'MultiPoint( 1 1, 2 2,\n5 3, 7 2, 9 3, 8 4, 6 6, 6 9, 4 9, 1 5 )\'));\n \nSELECT ST_AsText(MPointFromWKB(@g));\n+-----------------------------------------------------+\n| ST_AsText(MPointFromWKB(@g)) |\n+-----------------------------------------------------+\n| MULTIPOINT(1 1,2 2,5 3,7 2,9 3,8 4,6 6,6 9,4 9,1 5) |\n+-----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mpointfromwkb/','','https://mariadb.com/kb/en/mpointfromwkb/'),(535,'GeomCollFromWKB',32,'A synonym for ST_GeomCollFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-geomcollfromwkb/','','https://mariadb.com/kb/en/wkb-geomcollfromwkb/'),(536,'GeometryCollectionFromWKB',32,'A synonym for ST_GeomCollFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometrycollectionfromwkb/','','https://mariadb.com/kb/en/geometrycollectionfromwkb/'),(537,'GeometryFromWKB',32,'A synonym for ST_GeomFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometryfromwkb/','','https://mariadb.com/kb/en/geometryfromwkb/'),(538,'GeomFromWKB',32,'A synonym for ST_GeomFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-geomfromwkb/','','https://mariadb.com/kb/en/wkb-geomfromwkb/'),(539,'LineFromWKB',32,'A synonym for ST_LineFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-linefromwkb/','','https://mariadb.com/kb/en/wkb-linefromwkb/'),(540,'LineStringFromWKB',32,'A synonym for ST_LineFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/linestringfromwkb/','','https://mariadb.com/kb/en/linestringfromwkb/'),(541,'MultiLineStringFromWKB',32,'A synonym for MLineFromWKB().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multilinestringfromwkb/','','https://mariadb.com/kb/en/multilinestringfromwkb/'),(542,'MultiPointFromWKB',32,'A synonym for MPointFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipointfromwkb/','','https://mariadb.com/kb/en/multipointfromwkb/'),(543,'MultiPolygonFromWKB',32,'Synonym for MPolyFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/multipolygonfromwkb/','','https://mariadb.com/kb/en/multipolygonfromwkb/'),(544,'PointFromWKB',32,'A synonym for ST_PointFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-pointfromwkb/','','https://mariadb.com/kb/en/wkb-pointfromwkb/'),(273,'DATE',22,'Syntax\n------ \nDATE\n \nDescription\n----------- \nA date. The supported range is \'1000-01-01\' to\n\'9999-12-31\'. MariaDB\ndisplays DATE values in \'YYYY-MM-DD\' format, but can be\nassigned dates in looser formats, including strings or\nnumbers, as long as they make sense. These include a short\nyear, YY-MM-DD, no delimiters, YYMMDD, or any other\nacceptable delimiter, for example YYYY/MM/DD. For details,\nsee date and time literals.\n \n\'0000-00-00\' is a permitted special value (zero-date),\nunless the NO_ZERO_DATE SQL_MODE is used. Also, individual\ncomponents of a date can be set to 0 (for example:\n\'2015-00-12\'), unless the NO_ZERO_IN_DATE SQL_MODE is\nused. In many cases, the result of en expression involving a\nzero-date, or a date with zero-parts, is NULL. If the\nALLOW_INVALID_DATES SQL_MODE is enabled, if the day part is\nin the range between 1 and 31, the date does not produce any\nerror, even for months that have less than 31 days.\n \nExamples\n-------- \nCREATE TABLE t1 (d DATE);\n \nINSERT INTO t1 VALUES (\"2010-01-12\"), (\"2011-2-28\"),\n(\'120314\'),(\'13*04*21\');\n \nSELECT * FROM t1;\n \n+------------+\n| d |\n+------------+\n| 2010-01-12 |\n| 2011-02-28 |\n| 2012-03-14 |\n| 2013-04-21 |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/date/','','https://mariadb.com/kb/en/date/'),(274,'DATETIME',22,'Syntax\n------ \nDATETIME [(microsecond precision)]\n \nDescription\n----------- \nA date and time combination. The supported range is\n\'1000-01-01 00:00:00.000000\' to \'9999-12-31\n23:59:59.999999\'.\nMariaDB displays DATETIME values in \'YYYY-MM-DD HH:MM:SS\'\nformat, but\nallows assignment of values to DATETIME columns using either\nstrings or\nnumbers. For details, see date and time literals.\n \nThe microsecond precision can be from 0-6. If not specified\n0 is used.\n \n\'0000-00-00\' is a permitted special value (zero-date),\nunless the NO_ZERO_DATE SQL_MODE is used. Also, individual\ncomponents of a date can be set to 0 (for example:\n\'2015-00-12\'), unless the NO_ZERO_IN_DATE SQL_MODE is\nused. In many cases, the result of en expression involving a\nzero-date, or a date with zero-parts, is NULL. If the\nALLOW_INVALID_DATES SQL_MODE is enabled, if the day part is\nin the range between 1 and 31, the date does not produce any\nerror, even for months that have less than 31 days.\n \nSince MariaDB 10.0.1, DATETIME columns also accept\nCURRENT_TIMESTAMP as the default value.\n \nMariaDB 10.1.2 introduced the --mysql56-temporal-format\noption, on by default, which allows MariaDB to store\nDATETMEs using the same low-level format MySQL 5.6 uses. For\nmore information, see Internal Format, below.\n \nFor storage requirements, see Data Type Storage\nRequirements.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, DATE with a time portion\nis a synonym for DATETIME.\n \nInternal Format\n \nIn MariaDB 10.1.2 a new temporal format was introduced from\nMySQL 5.6 that alters how the TIME, DATETIME and TIMESTAMP\ncolumns operate at lower levels. These changes allow these\ntemporal data types to have fractional parts and negative\nvalues. You can disable this feature using the\nmysql56_temporal_format system variable.\n \nTables that include TIMESTAMP values that were created on an\nolder version of MariaDB or that were created while the\nmysql56_temporal_format system variable was disabled\ncontinue to store data using the older data type format.\n \nIn order to update table columns from the older format to\nthe newer format, execute an ALTER TABLE... MODIFY COLUMN\nstatement that changes the column to the *same* data type.\nThis change may be needed if you want to export the table\'s\ntablespace and import it onto a server that has\nmysql56_temporal_format=ON set (see MDEV-15225).\n \nFor instance, if you have a DATETIME column in your table: \n \nSHOW VARIABLES LIKE \'mysql56_temporal_format\';\n \n+-------------------------+-------+\n| Variable_name | Value |\n+-------------------------+-------+\n| mysql56_temporal_format | ON |\n+-------------------------+-------+\n \nALTER TABLE example_table MODIFY ts_col DATETIME;\n \nWhen MariaDB executes the ALTER TABLE statement, it converts\nthe data from the older temporal format to the newer one. \n \nIn the event that you have several tables and columns using\ntemporal data types that you want to switch over to the new\nformat, make sure the system variable is enabled, then\nperform a dump and restore using mysqldump. The columns\nusing relevant temporal data types are restored using the\nnew temporal format.\n \nExamples\n-------- \nCREATE TABLE t1 (d DATETIME);\n \nINSERT INTO t1 VALUES (\"2011-03-11\"), (\"2012-04-19\n13:08:22\"),\n (\"2013-07-18 13:44:22.123456\");\n \nSELECT * FROM t1;\n \n+---------------------+\n| d |\n+---------------------+\n| 2011-03-11 00:00:00 |\n| 2012-04-19 13:08:22 |\n| 2013-07-18 13:44:22 |\n+---------------------+\n \nCREATE TABLE t2 (d DATETIME(6));\n \nINSERT INTO t2 VALUES (\"2011-03-11\"), (\"2012-04-19\n13:08:22\"),\n (\"2013-07-18 13:44:22.123456\");\n \nSELECT * FROM t2;\n \n+----------------------------+\n| d |\n+----------------------------+\n| 2011-03-11 00:00:00.000000 |\n| 2012-04-19 13:08:22.000000 |\n| 2013-07-18 13:44:22.123456 |\n+----------------------------++\n \nStrings used in datetime context are automatically converted\nto datetime(6). If you want to have a datetime without\nseconds, you should use CONVERT(..,datetime).\n \nSELECT CONVERT(\'2007-11-30 10:30:19\',datetime);\n+-----------------------------------------+\n| CONVERT(\'2007-11-30 10:30:19\',datetime) |\n+-----------------------------------------+\n| 2007-11-30 10:30:19 |\n+-----------------------------------------+\n \nSELECT CONVERT(\'2007-11-30 10:30:19\',datetime(6));\n+--------------------------------------------+\n| CONVERT(\'2007-11-30 10:30:19\',datetime(6)) |\n+--------------------------------------------+\n| 2007-11-30 10:30:19.000000 |\n+--------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/datetime/','','https://mariadb.com/kb/en/datetime/'),(545,'PolyFromWKB',32,'A synonym for ST_PolyFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/wkb-polyfromwkb/','','https://mariadb.com/kb/en/wkb-polyfromwkb/'),(546,'PolygonFromWKB',32,'A synonym for ST_PolyFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/polygonfromwkb/','','https://mariadb.com/kb/en/polygonfromwkb/'),(547,'ST_AsBinary',32,'Syntax\n------ \nST_AsBinary(g)\nAsBinary(g)\nST_AsWKB(g)\nAsWKB(g)\n \nDescription\n----------- \nConverts a value in internal geometry format to its WKB\nrepresentation and returns the binary result.\n \nST_AsBinary(), AsBinary(), ST_AsWKB() and AsWKB() are\nsynonyms,\n \nExamples\n-------- \nSET @poly = ST_GeomFromText(\'POLYGON((0 0,0 1,1 1,1 0,0\n0))\');\nSELECT ST_AsBinary(@poly);\n \nSELECT ST_AsText(ST_GeomFromWKB(ST_AsWKB(@poly)));\n+--------------------------------------------+\n| ST_AsText(ST_GeomFromWKB(ST_AsWKB(@poly))) |\n+--------------------------------------------+\n| POLYGON((0 0,0 1,1 1,1 0,0 0)) |\n+--------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_asbinary/','','https://mariadb.com/kb/en/st_asbinary/'),(548,'ST_AsWKB',32,'A synonym for ST_AsBinary().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_aswkb/','','https://mariadb.com/kb/en/st_aswkb/'),(550,'ST_GeometryCollectionFromWKB',32,'A synonym for ST_GeomCollFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geometrycollectionfromwkb/','','https://mariadb.com/kb/en/st_geometrycollectionfromwkb/'),(551,'ST_GeometryFromWKB',32,'A synonym for ST_GeomFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geometryfromwkb/','','https://mariadb.com/kb/en/st_geometryfromwkb/'),(275,'DECIMAL',22,'Syntax\n------ \nDECIMAL[(M[,D])] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA packed \"exact\" fixed-point number. M is the total number\nof digits (the\nprecision) and D is the number of digits after the decimal\npoint (the\nscale). The decimal point and (for negative numbers) the\n\"-\" sign are not\ncounted in M. If D is 0, values have no decimal point or\nfractional\npart and on INSERT the value will be rounded to the nearest\nDECIMAL. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30 before\nMariadB 10.2.1 and 38 afterwards. If D is omitted, the\ndefault is 0. If M is omitted, the default is 10.\n \nUNSIGNED, if specified, disallows negative values.\n \nZEROFILL, if specified, pads the number with zeros, up to\nthe total number\nof digits specified by M.\n \nAll basic calculations (+, -, *, /) with DECIMAL columns are\ndone with\na precision of 65 digits.\n \nFor more details on the attributes, see Numeric Data Type\nOverview.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, NUMBER is a synonym.\n \nExamples\n-------- \nCREATE TABLE t1 (d DECIMAL UNSIGNED ZEROFILL);\n \nINSERT INTO t1 VALUES (1),(2),(3),(4.0),(5.2),(5.7);\nQuery OK, 6 rows affected, 2 warnings (0.16 sec)\nRecords: 6 Duplicates: 0 Warnings: 2\n \nNote (Code 1265): Data truncated for column \'d\' at row 5\nNote (Code 1265): Data truncated for column \'d\' at row 6\n \nSELECT * FROM t1;\n \n+------------+\n| d |\n+------------+\n| 0000000001 |\n| 0000000002 |\n| 0000000003 |\n| 0000000004 |\n| 0000000005 |\n| 0000000006 |\n+------------+\n \nINSERT INTO t1 VALUES (-7);\nERROR 1264 (22003): Out of range value for column \'d\' at\nrow 1\n \n\n\nURL: https://mariadb.com/kb/en/decimal/','','https://mariadb.com/kb/en/decimal/'),(276,'ENUM',22,'Syntax\n------ \nENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name]\n[COLLATE collation_name]\n \nDescription\n----------- \nAn enumeration. A string object that can have only one\nvalue, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or\nthe special \n\'\' error value. In theory, an ENUM column can have a\nmaximum of 65,535 distinct\nvalues; in practice, the real maximum depends on many\nfactors. ENUM values are represented internally as integers.\n \nTrailing spaces are automatically stripped from ENUM values\non table creation.\n \nENUMs require relatively little storage space compared to\nstrings, either one or two bytes depending on the number of\nenumeration values.\n \nNULL and empty values\n \nAn ENUM can also contain NULL and empty values. If the ENUM\ncolumn is declared to permit NULL values, NULL becomes a\nvalid value, as well as the default value (see below). If\nstrict SQL Mode is not enabled, and an invalid value is\ninserted into an ENUM, a special empty string, with an index\nvalue of zero (see Numeric index, below), is inserted, with\na warning. This may be confusing, because the empty string\nis also a possible value, and the only difference if that in\nthis case its index is not 0. Inserting will fail with an\nerror if strict mode is active.\n \nIf a DEFAULT clause is missing, the default value will be:\nNULL is the column is nullable;\notherwise, the first value in the enumaration.\n \nNumeric index\n \nENUM values are indexed numerically in the order they are\ndefined, and sorting will be performed in this numeric\norder. We suggest not using ENUM to store numerals, as there\nis little to no storage space benefit, and it is easy to\nconfuse the enum integer with the enum numeral value by\nleaving out the quotes.\n \nAn ENUM defined as ENUM(\'apple\',\'orange\',\'pear\') would\nhave the following index values:\n \nIndex | Value | \n \nNULL | NULL | \n \n0 | \'\' | \n \n1 | \'apple\' | \n \n2 | \'orange\' | \n \n3 | \'pear\' | \n \nExamples\n-------- \nCREATE TABLE fruits (\n id INT NOT NULL auto_increment PRIMARY KEY,\n fruit ENUM(\'apple\',\'orange\',\'pear\'),\n bushels INT);\n \nDESCRIBE fruits;\n \n+---------+-------------------------------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+---------+-------------------------------+------+-----+---------+----------------+\n| id | int(11) | NO | PRI | NULL | auto_increment |\n| fruit | enum(\'apple\',\'orange\',\'pear\') | YES | | NULL\n| |\n| bushels | int(11) | YES | | NULL | |\n+---------+-------------------------------+------+-----+---------+----------------+\n \nINSERT INTO fruits\n (fruit,bushels) VALUES\n (\'pear\',20),\n (\'apple\',100),\n (\'orange\',25);\n \nINSERT INTO fruits\n (fruit,bushels) VALUES\n (\'avocado\',10);\nERROR 1265 (01000): Data truncated for column \'fruit\' at\nrow 1\n \nSELECT * FROM fruits;\n \n+----+--------+---------+\n| id | fruit | bushels |\n+----+--------+---------+\n| 1 | pear | 20 |\n| 2 | apple | 100 |\n| 3 | orange | 25 |\n+----+--------+---------+\n \nSelecting by numeric index:\n \nSELECT * FROM fruits WHERE fruit=2;\n \n+----+--------+---------+\n| id | fruit | bushels |\n+----+--------+---------+\n| 3 | orange | 25 |\n+----+--------+---------+\n \nSorting is according to the index value:\n \nCREATE TABLE enums (a ENUM(\'2\',\'1\'));\n \nINSERT INTO enums VALUES (\'1\'),(\'2\');\n \nSELECT * FROM enums ORDER BY a ASC;\n \n+------+\n| a |\n+------+\n| 2 |\n| 1 |\n+------+\n \nIt\'s easy to get confused between returning the enum\ninteger with the stored value, so we don\'t suggest using\nENUM to store numerals. The first example returns the 1st\nindexed field (\'2\' has an index value of 1, as it\'s\ndefined first), while the second example returns the string\nvalue \'1\'.\n \nSELECT * FROM enums WHERE a=1;\n \n+------+\n| a |\n+------+\n| 2 |\n+------+\n \nSELECT * FROM enums WHERE a=\'1\';\n \n+------+\n| a |\n+------+\n| 1 |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/enum/','','https://mariadb.com/kb/en/enum/'),(552,'ST_GeomFromWKB',32,'Syntax\n------ \nST_GeomFromWKB(wkb[,srid])\nST_GeometryFromWKB(wkb[,srid])\nGeomFromWKB(wkb[,srid])\nGeometryFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a geometry value of any type using its WKB\nrepresentation and SRID.\n \nST_GeomFromWKB(), ST_GeometryFromWKB(), GeomFromWKB() and\nGeometryFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(ST_LineFromText(\'LINESTRING(0 4, 4\n6)\'));\n \nSELECT ST_AsText(ST_GeomFromWKB(@g));\n+-------------------------------+\n| ST_AsText(ST_GeomFromWKB(@g)) |\n+-------------------------------+\n| LINESTRING(0 4,4 6) |\n+-------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geomfromwkb/','','https://mariadb.com/kb/en/st_geomfromwkb/'),(553,'ST_LineFromWKB',32,'Syntax\n------ \nST_LineFromWKB(wkb[,srid])\nLineFromWKB(wkb[,srid])\nST_LineStringFromWKB(wkb[,srid])\nLineStringFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a LINESTRING value using its WKB representation\nand SRID.\n \nST_LineFromWKB(), LineFromWKB(), ST_LineStringFromWKB(), and\nLineStringFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(ST_LineFromText(\'LineString(0 4,4\n6)\'));\n \nSELECT ST_AsText(ST_LineFromWKB(@g)) AS l;\n \n+---------------------+\n| l |\n+---------------------+\n| LINESTRING(0 4,4 6) |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_linefromwkb/','','https://mariadb.com/kb/en/st_linefromwkb/'),(554,'ST_LineStringFromWKB',32,'A synonym for ST_LineFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_linestringfromwkb/','','https://mariadb.com/kb/en/st_linestringfromwkb/'),(555,'ST_PointFromWKB',32,'Syntax\n------ \nST_PointFromWKB(wkb[,srid])\nPointFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a POINT value using its WKB representation and\nSRID.\n \nST_PointFromWKB() and PointFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(ST_PointFromText(\'POINT(0 4)\'));\n \nSELECT ST_AsText(ST_PointFromWKB(@g)) AS p;\n \n+------------+\n| p |\n+------------+\n| POINT(0 4) |\n+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_pointfromwkb/','','https://mariadb.com/kb/en/st_pointfromwkb/'),(277,'DOUBLE',22,'Syntax\n------ \nDOUBLE[(M,D)] [SIGNED | UNSIGNED | ZEROFILL]\nDOUBLE PRECISION[(M,D)] [SIGNED | UNSIGNED | ZEROFILL]\nREAL[(M,D)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA normal-size (double-precision) floating-point number (see\nFLOAT for a single-precision floating-point number).\n \nAllowable values are:\n-1.7976931348623157E+308 to -2.2250738585072014E-308\n0\n2.2250738585072014E-308 to 1.7976931348623157E+308\n \nThese are the theoretical limits, based on the IEEE\nstandard. The actual range\nmight be slightly smaller depending on your hardware or\noperating system.\n \nM is the total number of digits and D is the number of\ndigits\nfollowing the decimal point. If M and D are omitted, values\nare stored\nto the limits allowed by the hardware. A double-precision\nfloating-point number is accurate to approximately 15\ndecimal places.\n \nUNSIGNED, if specified, disallows negative values.\n \nZEROFILL, if specified, pads the number with zeros, up to\nthe total number\nof digits specified by M.\n \nREAL and DOUBLE PRECISION are synonyms, unless the\nREAL_AS_FLOAT SQL mode is enabled, in which case REAL is a\nsynonym for FLOAT rather than DOUBLE.\n \nSee Floating Point Accuracy for issues when using\nfloating-point numbers.\n \nFor more details on the attributes, see Numeric Data Type\nOverview.\n \nExamples\n-------- \nCREATE TABLE t1 (d DOUBLE(5,0) zerofill);\n \nINSERT INTO t1 VALUES (1),(2),(3),(4);\n \nSELECT * FROM t1;\n \n+-------+\n| d |\n+-------+\n| 00001 |\n| 00002 |\n| 00003 |\n| 00004 |\n+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/double/','','https://mariadb.com/kb/en/double/'),(278,'FLOAT',22,'Syntax\n------ \nFLOAT[(M,D)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA small (single-precision) floating-point number (see DOUBLE\nfor a regular-size floating point number). Allowable values\nare:\n-3.402823466E+38 to -1.175494351E-38\n0\n1.175494351E-38 to 3.402823466E+38. \n \nThese are the theoretical limits, based on the IEEE \nstandard. The actual range might be slightly smaller\ndepending on your\nhardware or operating system.\n \nM is the total number of digits and D is the number of\ndigits\nfollowing the decimal point. If M and D are omitted, values\nare stored\nto the limits allowed by the hardware. A single-precision\nfloating-point number is accurate to approximately 7 decimal\nplaces.\n \nUNSIGNED, if specified, disallows negative values.\n \nUsing FLOAT might give you some unexpected problems because\nall\ncalculations in MariaDB are done with double precision. See\nFloating Point Accuracy.\n \nFor more details on the attributes, see Numeric Data Type\nOverview.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/float/','','https://mariadb.com/kb/en/float/'),(280,'JSON Data Type',22,'The JSON alias was added in MariaDB 10.2.7. This was done to\nmake it possible to use JSON columns in statement based\nreplication from MySQL to MariaDB and to make it possible\nfor MariaDB to read mysqldumps from MySQL.\n \nJSON is an alias for LONGTEXT introduced for compatibility\nreasons with MySQL\'s JSON data type. MariaDB implements\nthis as a LONGTEXT rather, as the JSON data type contradicts\nthe SQL standard, and MariaDB\'s benchmarks indicate that\nperformance is at least equivalent.\n \nIn order to ensure that a a valid json document is inserted,\nthe JSON_VALID function can be used as a CHECK constraint.\nThis constraint is automatically included for types using\nthe JSON alias from MariaDB 10.4.3.\n \nExamples\n-------- \nCREATE TABLE t (j JSON);\n \nDESC t;\n+-------+----------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+----------+------+-----+---------+-------+\n| j | longtext | YES | | NULL | |\n+-------+----------+------+-----+---------+-------+\n \nWith validation:\n \nCREATE TABLE t2 (\n j JSON \n CHECK (JSON_VALID(j))\n);\n \nINSERT INTO t2 VALUES (\'invalid\');\nERROR 4025 (23000): CONSTRAINT `j` failed for `test`.`t2`\n \nINSERT INTO t2 VALUES (\'{\"id\": 1, \"name\":\n\"Monty\"}\');\nQuery OK, 1 row affected (0.13 sec)\n \nReplicating JSON Data Between MySQL and MariaDB\n \nThe JSON type in MySQL stores the JSON object in a compact\nform, not as LONGTEXT as in MariaDB.\nThis means that row based replication will not work for JSON\ntypes from MySQL to MariaDB.\n \nThere are a a few different ways to solve this:\nUse statement based replication.\nChange the JSON column to type TEXT in MySQL\n \nConverting a MySQL TABLE with JSON Fields to MariaDB\n \nMariaDB can\'t directly access MySQL\'s JSON format.\n \nThere are a a few different ways to move the table to\nMariaDB:\nChange the JSON column to type TEXT in MySQL. After this,\nMariaDB can directly use the table without any need for a\ndump and restore.\nUse mysqldump to copy the table.\n \nDifferences Between MySQL JSON Strings and MariaDB JSON\nStrings\n \nIn MySQL, JSON is an object and is compared according to\njson values. In MariaDB JSON strings are normal strings and\ncompared as strings. One exception is when using\nJSON_EXTRACT() in which case strings are unescaped before\ncomparison.\n \n\n\nURL: https://mariadb.com/kb/en/json-data-type/','','https://mariadb.com/kb/en/json-data-type/'),(556,'ST_PolyFromWKB',32,'Syntax\n------ \nST_PolyFromWKB(wkb[,srid])\nST_PolygonFromWKB(wkb[,srid])\nPolyFromWKB(wkb[,srid])\nPolygonFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a POLYGON value using its WKB representation and\nSRID.\n \nST_PolyFromWKB(), ST_PolygonFromWKB(), PolyFromWKB() and\nPolygonFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(ST_PolyFromText(\'POLYGON((1 1,1 5,4\n9,6 9,9 3,7 2,1 1))\'));\n \nSELECT ST_AsText(ST_PolyFromWKB(@g)) AS p;\n \n+----------------------------------------+\n| p |\n+----------------------------------------+\n| POLYGON((1 1,1 5,4 9,6 9,9 3,7 2,1 1)) |\n+----------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_polyfromwkb/','','https://mariadb.com/kb/en/st_polyfromwkb/'),(557,'ST_PolygonFromWKB',32,'A synonym for ST_PolyFromWKB.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_polygonfromwkb/','','https://mariadb.com/kb/en/st_polygonfromwkb/'),(558,'BOUNDARY',36,'A synonym for ST_BOUNDARY.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-properties-boundary/','','https://mariadb.com/kb/en/geometry-properties-boundary/'),(559,'DIMENSION',36,'A synonym for ST_DIMENSION.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/dimension/','','https://mariadb.com/kb/en/dimension/'),(560,'ENVELOPE',36,'A synonym for ST_ENVELOPE.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-properties-envelope/','','https://mariadb.com/kb/en/geometry-properties-envelope/'),(561,'GeometryN',36,'A synonym for ST_GeometryN.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/geometry-properties-geometryn/','','https://mariadb.com/kb/en/geometry-properties-geometryn/'),(562,'GeometryType',36,'A synonym for ST_GeometryType.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/geometry-properties-geometrytype/','','https://mariadb.com/kb/en/geometry-properties-geometrytype/'),(563,'IsClosed',36,'A synonym for ST_IsClosed.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/isclosed/','','https://mariadb.com/kb/en/isclosed/'),(564,'IsEmpty',36,'A synonym for ST_IsEmpty.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-properties-isempty/','','https://mariadb.com/kb/en/geometry-properties-isempty/'),(565,'IsRing',36,'A synonym for ST_IsRing.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/isring/','','https://mariadb.com/kb/en/isring/'),(279,'Geometry Types',22,'Description\n----------- \nMariaDB provides a standard way of creating spatial columns\nfor geometry types,\nfor example, with CREATE TABLE or ALTER TABLE.\nCurrently, spatial columns are supported for MyISAM, InnoDB,\nNDB, and ARCHIVE\ntables. See also SPATIAL INDEX.\n \nThe basic geometry type is GEOMETRY. But the type can be\nmore specific. The following types are supported:\n \nGeometry Types | \n \nPOINT | \n \nLINESTRING | \n \nPOLYGON | \n \nMULTIPOINT | \n \nMULTILINESTRING | \n \nMULTIPOLYGON | \n \nGEOMETRYCOLLECTION | \n \nGEOMETRY | \n \nExamples\n-------- \nNote: For clarity, only one type is listed per table in the\nexamples below, but a table\nrow can contain multiple types. For example:\n \nCREATE TABLE object (shapeA POLYGON, shapeB LINESTRING);\n \nPOINT\n \nCREATE TABLE gis_point (g POINT);\nSHOW FIELDS FROM gis_point;\n \nINSERT INTO gis_point VALUES\n (PointFromText(\'POINT(10 10)\')),\n (PointFromText(\'POINT(20 10)\')),\n (PointFromText(\'POINT(20 20)\')),\n (PointFromWKB(AsWKB(PointFromText(\'POINT(10 20)\'))));\n \nLINESTRING\n \nCREATE TABLE gis_line (g LINESTRING);\nSHOW FIELDS FROM gis_line;\n \nINSERT INTO gis_line VALUES\n (LineFromText(\'LINESTRING(0 0,0 10,10 0)\')),\n (LineStringFromText(\'LINESTRING(10 10,20 10,20 20,10 20,10\n10)\')),\n (LineStringFromWKB(AsWKB(LineString(Point(10, 10),\nPoint(40, 10)))));\n \nPOLYGON\n \nCREATE TABLE gis_polygon (g POLYGON);\nSHOW FIELDS FROM gis_polygon;\n \nINSERT INTO gis_polygon VALUES\n (PolygonFromText(\'POLYGON((10 10,20 10,20 20,10 20,10\n10))\')),\n (PolyFromText(\'POLYGON((0 0,50 0,50 50,0 50,0 0), (10\n10,20 10,20 20,10 20,10 10))\')),\n (PolyFromWKB(AsWKB(Polygon(LineString(Point(0, 0),\nPoint(30, 0), Point(30, 30), Point(0, 0))))));\n \nMULTIPOINT\n \nCREATE TABLE gis_multi_point (g MULTIPOINT);\nSHOW FIELDS FROM gis_multi_point;\n \nINSERT INTO gis_multi_point VALUES\n (MultiPointFromText(\'MULTIPOINT(0 0,10 10,10 20,20\n20)\')),\n (MPointFromText(\'MULTIPOINT(1 1,11 11,11 21,21 21)\')),\n (MPointFromWKB(AsWKB(MultiPoint(Point(3, 6), Point(4,\n10)))));\n \nMULTILINESTRING\n \nCREATE TABLE gis_multi_line (g MULTILINESTRING);\nSHOW FIELDS FROM gis_multi_line;\n \nINSERT INTO gis_multi_line VALUES\n (MultiLineStringFromText(\'MULTILINESTRING((10 48,10 21,10\n0),(16 0,16 23,16 48))\')),\n (MLineFromText(\'MULTILINESTRING((10 48,10 21,10 0))\')),\n (MLineFromWKB(AsWKB(MultiLineString(LineString(Point(1, 2),\nPoint(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21,\n7))))));\n \nMULTIPOLYGON\n \nCREATE TABLE gis_multi_polygon (g MULTIPOLYGON);\nSHOW FIELDS FROM gis_multi_polygon;\n \nINSERT INTO gis_multi_polygon VALUES\n (MultiPolygonFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84\n42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67\n13,59 13,59 18)))\')),\n (MPolyFromText(\'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28\n26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59\n13,59 18)))\')),\n (MPolyFromWKB(AsWKB(MultiPolygon(Polygon(LineString(Point(0,\n3), Point(3, 3), Point(3, 0), Point(0, 3)))))));\n \nGEOMETRYCOLLECTION\n \nCREATE TABLE gis_geometrycollection (g GEOMETRYCOLLECTION);\nSHOW FIELDS FROM gis_geometrycollection;\n \nINSERT INTO gis_geometrycollection VALUES\n (GeomCollFromText(\'GEOMETRYCOLLECTION(POINT(0 0),\nLINESTRING(0 0,10 10))\')),\n (GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6),\nLineString(Point(3, 6), Point(7, 9)))))),\n (GeomFromText(\'GeometryCollection()\')),\n (GeomFromText(\'GeometryCollection EMPTY\'));\n \nGEOMETRY\n \nCREATE TABLE gis_geometry (g GEOMETRY);\nSHOW FIELDS FROM gis_geometry;\n \nINSERT into gis_geometry SELECT * FROM gis_point;\n \nINSERT into gis_geometry SELECT * FROM gis_line;\n \nINSERT into gis_geometry SELECT * FROM gis_polygon;\n \nINSERT into gis_geometry SELECT * FROM gis_multi_point;\n \nINSERT into gis_geometry SELECT * FROM gis_multi_line;\n \nINSERT into gis_geometry SELECT * FROM gis_multi_polygon;\n \nINSERT into gis_geometry SELECT * FROM\ngis_geometrycollection;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-types/','','https://mariadb.com/kb/en/geometry-types/'),(284,'MEDIUMINT',22,'Syntax\n------ \nMEDIUMINT[(M)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA medium-sized integer. The signed range is -8388608 to\n8388607. The\nunsigned range is 0 to 16777215.\n \nZEROFILL pads the integer with zeroes and assumes UNSIGNED\n(even if UNSIGNED is not specified).\n \nFor details on the attributes, see Numeric Data Type\nOverview.\n \nExamples\n-------- \nCREATE TABLE mediumints (a MEDIUMINT,b MEDIUMINT UNSIGNED,c\nMEDIUMINT ZEROFILL);\n \nDESCRIBE mediumints;\n+-------+--------------------------------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+--------------------------------+------+-----+---------+-------+\n| a | mediumint(9) | YES | | NULL | |\n| b | mediumint(8) unsigned | YES | | NULL | |\n| c | mediumint(8) unsigned zerofill | YES | | NULL | |\n+-------+--------------------------------+------+-----+---------+-------+\n \nINSERT INTO mediumints VALUES (-10,-10,-10);\nQuery OK, 1 row affected, 2 warnings (0.05 sec)\nWarning (Code 1264): Out of range value for column \'b\' at\nrow 1\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO mediumints VALUES (-10,10,-10);\nQuery OK, 1 row affected, 1 warning (0.08 sec)\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO mediumints VALUES (-10,10,10);\n \nINSERT INTO mediumints VALUES (8388608,8388608,8388608);\nQuery OK, 1 row affected, 1 warning (0.05 sec)\nWarning (Code 1264): Out of range value for column \'a\' at\nrow 1\n \nINSERT INTO mediumints VALUES (8388607,8388608,8388608);\n \nSELECT * FROM mediumints;\n+---------+---------+----------+\n| a | b | c |\n+---------+---------+----------+\n| -10 | 0 | 00000000 |\n| -10 | 0 | 00000000 |\n| -10 | 10 | 00000000 |\n| -10 | 10 | 00000010 |\n| 8388607 | 8388608 | 08388608 |\n| 8388607 | 8388608 | 08388608 |\n+---------+---------+----------+\n \n\n\nURL: https://mariadb.com/kb/en/mediumint/','','https://mariadb.com/kb/en/mediumint/'),(566,'IsSimple',36,'A synonym for ST_IsSImple.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-properties-issimple/','','https://mariadb.com/kb/en/geometry-properties-issimple/'),(567,'NumGeometries',36,'A synonym for ST_NumGeometries.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/geometry-properties-numgeometries/','','https://mariadb.com/kb/en/geometry-properties-numgeometries/'),(568,'SRID',36,'A synonym for ST_SRID.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/geometry-properties-srid/','','https://mariadb.com/kb/en/geometry-properties-srid/'),(570,'ST_DIMENSION',36,'Syntax\n------ \nST_Dimension(g)\nDimension(g)\n \nDescription\n----------- \nReturns the inherent dimension of the geometry value g. The\nresult can\nbe\n \nDimension | Definition | \n \n -1 | empty geometry | \n \n 0 | geometry with no length or area | \n \n 1 | geometry with no area but nonzero length | \n \n 2 | geometry with nonzero area | \n \nST_Dimension() and Dimension() are synonyms.\n \nExamples\n-------- \nSELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_dimension/','','https://mariadb.com/kb/en/st_dimension/'),(572,'ST_GEOMETRYN',36,'Syntax\n------ \nST_GeometryN(gc,N)\nGeometryN(gc,N)\n \nDescription\n----------- \nReturns the N-th geometry in the GeometryCollection gc.\nGeometries are numbered beginning with 1.\n \nST_GeometryN() and GeometryN() are synonyms.\n \nExample\n \nSET @gc = \'GeometryCollection(Point(1 1),LineString(12 14,\n9 11))\';\n \nSELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geometryn/','','https://mariadb.com/kb/en/st_geometryn/'),(286,'Numeric Data Type Overview',22,'There are a number of numeric data types:\nTINYINT\nBOOLEAN - Synonym for TINYINT(1)\nSMALLINT\nMEDIUMINT\nINT, INTEGER\nBIGINT\nDECIMAL, DEC, NUMERIC, FIXED\nFLOAT\nDOUBLE, DOUBLE PRECISION, REAL\nBIT\n \nSee the specific articles for detailed information on each.\n \nSIGNED, UNSIGNED and ZEROFILL\n \nMost numeric types can be defined as SIGNED, UNSIGNED or\nZEROFILL, for example:\n \nTINYINT[(M)] [SIGNED | UNSIGNED | ZEROFILL]\n \nIf SIGNED, or no attribute, is specified, a portion of the\nnumeric type will be reserved for the sign (plus or minus).\nFor example, a TINYINT SIGNED can range from -128 to 127. \n \nIf UNSIGNED is specified, no portion of the numeric type is\nreserved for the sign, so for integer types range can be\nlarger. For example, a TINYINT UNSIGNED can range from 0 to\n255. Floating point and fixed-point types also can be\nUNSIGNED, but this only prevents negative values from being\nstored and doesn\'t alter the range. \n \nIf ZEROFILL is specified, the column will be set to UNSIGNED\nand the spaces used by default to pad the field are replaced\nwith zeros. ZEROFILL is ignored in expressions or as part of\na UNION. ZEROFILL is a non-standard MySQL and MariaDB\nenhancement.\n \nNote that although the preferred syntax indicates that the\nattributes are exclusive, more than one attribute can be\nspecified.\n \nUntil MariaDB 10.2.7 (MDEV-8659), any combination of the\nattributes could be used in any order, with duplicates. In\nthis case:\nthe presence of ZEROFILL makes the column UNSIGNED ZEROFILL.\nthe presence of UNSIGNED makes the column UNSIGNED.\n \nFrom MariaDB 10.2.8, only the following combinations are\nsupported:\nSIGNED\nUNSIGNED\nZEROFILL\nUNSIGNED ZEROFILL\nZEROFILL UNSIGNED\n \nThe latter two should be replaced with simply ZEROFILL, but\nare still accepted by the parser.\n \nExamples\n-------- \nCREATE TABLE zf (\n i1 TINYINT SIGNED,\n i2 TINYINT UNSIGNED,\n i3 TINYINT ZEROFILL\n);\n \nINSERT INTO zf VALUES (2,2,2);\n \nSELECT * FROM zf;\n \n+------+------+------+\n| i1 | i2 | i3 |\n+------+------+------+\n| 2 | 2 | 002 |\n+------+------+------+\n \nRange\n \nWhen attempting to add a value that is out of the valid\nrange for the numeric type, MariaDB will react depending on\nthe strict SQL_MODE setting.\n \nIf strict_mode has been set (the default from MariaDB\n10.2.4), MariaDB will return an error.\n \nIf strict_mode has not been set (the default until MariaDB\n10.2.3), MariaDB will adjust the number to fit in the field,\nreturning a warning.\n \nExamples\n-------- \nWith strict_mode set:\n \nSHOW VARIABLES LIKE \'sql_mode\';\n \n+---------------+-------------------------------------------------------------------------------------------+\n| Variable_name | Value |\n+---------------+-------------------------------------------------------------------------------------------+\n| sql_mode |\nSTRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION\n|\n+---------------+-------------------------------------------------------------------------------------------+\n \nCREATE TABLE ranges (i1 TINYINT, i2 SMALLINT, i3 TINYINT\nUNSIGNED);\n \nINSERT INTO ranges VALUES (257,257,257);\nERROR 1264 (22003): Out of range value for column \'i1\' at\nrow 1\n \nSELECT * FROM ranges;\n \nEmpty set (0.10 sec)\n \nWith strict_mode unset:\n \nSHOW VARIABLES LIKE \'sql_mode%\';\n \n+---------------+-------+\n| Variable_name | Value |\n+---------------+-------+\n| sql_mode | |\n+---------------+-------+\n \nCREATE TABLE ranges (i1 TINYINT, i2 SMALLINT, i3 TINYINT\nUNSIGNED);\n \nINSERT INTO ranges VALUES (257,257,257);\nQuery OK, 1 row affected, 2 warnings (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+---------------------------------------------+\n| Level | Code | Message |\n+---------+------+---------------------------------------------+\n| Warning | 1264 | Out of range value for column \'i1\' at\nrow 1 |\n| Warning | 1264 | Out of range value for column \'i3\' at\nrow 1 |\n+---------+------+---------------------------------------------+\n2 rows in set (0.00 sec)\n \nSELECT * FROM ranges;\n \n+------+------+------+\n| i1 | i2 | i3 |\n+------+------+------+\n| 127 | 257 | 255 |\n+------+------+------+\n \nAuto_increment\n \nThe AUTO_INCREMENT attribute can be used to generate a\nunique identity for new rows. For more details, see\nauto_increment.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/numeric-data-type-overview/','','https://mariadb.com/kb/en/numeric-data-type-overview/'),(289,'SMALLINT',22,'Syntax\n------ \nSMALLINT[(M)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA small integer. The signed range is -32768 to 32767. The\nunsigned range is 0 to 65535.\n \nIf a column has been set to ZEROFILL, all values will be\nprepended by zeros so that the SMALLINT value contains a\nnumber of M digits.\n \nNote: If the ZEROFILL attribute has been specified, the\ncolumn will automatically become UNSIGNED.\n \nFor more details on the attributes, see Numeric Data Type\nOverview.\n \nExamples\n-------- \nCREATE TABLE smallints (a SMALLINT,b SMALLINT UNSIGNED,c\nSMALLINT ZEROFILL);\n \nINSERT INTO smallints VALUES (-10,-10,-10);\nQuery OK, 1 row affected, 2 warnings (0.09 sec)\nWarning (Code 1264): Out of range value for column \'b\' at\nrow 1\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO smallints VALUES (-10,10,-10);\nQuery OK, 1 row affected, 1 warning (0.08 sec)\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO smallints VALUES (-10,10,10);\n \nINSERT INTO smallints VALUES (32768,32768,32768);\nQuery OK, 1 row affected, 1 warning (0.04 sec)\nWarning (Code 1264): Out of range value for column \'a\' at\nrow 1\n \nINSERT INTO smallints VALUES (32767,32768,32768);\n \nSELECT * FROM smallints;\n+-------+-------+-------+\n| a | b | c |\n+-------+-------+-------+\n| -10 | 0 | 00000 |\n| -10 | 10 | 00000 |\n| -10 | 10 | 00010 |\n| 32767 | 32768 | 32768 |\n| 32767 | 32768 | 32768 |\n+-------+-------+-------+\n \n\n\nURL: https://mariadb.com/kb/en/smallint/','','https://mariadb.com/kb/en/smallint/'),(573,'ST_GEOMETRYTYPE',36,'Syntax\n------ \nST_GeometryType(g)\nGeometryType(g)\n \nDescription\n----------- \nReturns as a string the name of the geometry type of which\nthe\ngeometry instance g is a member. The name corresponds to one\nof the\ninstantiable Geometry subclasses.\n \nST_GeometryType() and GeometryType() are synonyms.\n \nExamples\n-------- \nSELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geometrytype/','','https://mariadb.com/kb/en/st_geometrytype/'),(575,'ST_ISEMPTY',36,'Syntax\n------ \nST_IsEmpty(g)\nIsEmpty(g)\n \nDescription\n----------- \nIsEmpty is a function defined by the OpenGIS specification,\nbut is not fully implemented by MariaDB or MySQL. \n \nSince MariaDB and MySQL do not support GIS EMPTY values such\nas POINT EMPTY, as implemented it simply returns 1 if the\ngeometry value g is invalid, 0 if it is valid, and NULL if\nthe argument is NULL.\n \nST_IsEmpty() and IsEmpty() are synonyms.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_isempty/','','https://mariadb.com/kb/en/st_isempty/'),(576,'ST_IsRing',36,'The ST_IsRing function was introduced in MariaDB 10.1.2\n \nSyntax\n------ \nST_IsRing(g)\nIsRing(g)\n \nDescription\n----------- \nReturns true if a given LINESTRING is a ring, that is, both\nST_IsClosed and ST_IsSimple. A simple curve does not pass\nthrough the same point more than once. However, see\nMDEV-7510.\n \nSt_IsRing() and IsRing() are synonyms.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_isring/','','https://mariadb.com/kb/en/st_isring/'),(290,'String Literals',22,'Strings are sequences of characters and are enclosed with\nquotes.\n \nThe syntax is:\n \n[_charset_name]\'string\' [COLLATE collation_name]\n \nFor example:\n \n\'The MariaDB Foundation\'\n_utf8 \'Foundation\' COLLATE utf8_unicode_ci;\n \nStrings can either be enclosed in single quotes or in double\nquotes (the same character must be used to both open and\nclose the string).\n \nThe ANSI SQL-standard does not permit double quotes for\nenclosing strings, and although MariaDB does by default, if\nthe MariaDB server has enabled the ANSI_QUOTES_SQL SQL_MODE,\ndouble quotes will be treated as being used for identifiers\ninstead of strings.\n \nStrings that are next to each other are automatically\nconcatenated. For example:\n \n\'The \' \'MariaDB \' \'Foundation\'\n \nand\n \n\'The MariaDB Foundation\'\n \nare equivalent.\n \nThe \\ (backslash character) is used to escape characters.\nFor example:\n \n\'MariaDB\'s new features\'\n \nis not a valid string because of the single quote in the\nmiddle of the string, which is treated as if it closes the\nstring, but is actually meant as part of the string, an\napostrophe. The backslash character helps in situations like\nthis:\n \n\'MariaDB\\\'s new features\'\n \nis now a valid string, and if displayed, will appear without\nthe backslash.\n \nSELECT \'MariaDB\\\'s new features\';\n+------------------------+\n| MariaDB\'s new features |\n+------------------------+\n| MariaDB\'s new features |\n+------------------------+\n \nAnother way to escape the quoting character is repeating it\ntwice:\n \nSELECT \'I\'\'m here\', \"\"\"Double\"\"\";\n+----------+----------+\n| I\'m here | \"Double\" |\n+----------+----------+\n| I\'m here | \"Double\" |\n+----------+----------+\n \nEscape sequences\n \nThere are other escape sequences also. Here is a full list:\n \nEscape sequence | Character | \n \n\\0 | ASCII NUL (0x00). | \n \n\\\' | Single quote (“\'”). | \n \n\\\" | Double quote (“\"”). | \n \n\\b | Backspace. | \n \n\\n | Newline, or linefeed,. | \n \n\\r | Carriage return. | \n \n\\t | Tab. | \n \n\\Z | ASCII 26 (Control+Z). See note following the table. | \n \n\\\\ | Backslash (“\\”). | \n \n\\% | “%” character. See note following the table. | \n \n\\_ | A “_” character. See note following the table. | \n \nEscaping the % and _ characters can be necessary when using\nthe LIKE operator, which treats them as special characters.\n \nThe ASCII 26 character (\\Z) needs to be escaped when\nincluded in a batch file which needs to be executed in\nWindows. The reason is that ASCII 26, in Windows, is the end\nof file (EOF).\n \nBackslash (\\), if not used as an escape character, must\nalways be escaped. When followed by a character that is not\nin the above table, backslashes will simply be ignored.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/string-literals/','','https://mariadb.com/kb/en/string-literals/'),(291,'TEXT',22,'Syntax\n------ \nTEXT[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA TEXT column with a maximum length of 65,535 (216 - 1)\ncharacters. The effective maximum length is less if the\nvalue contains\nmulti-byte characters. Each TEXT value is stored using a\ntwo-byte length\nprefix that indicates the number of bytes in the value. If\nyou need a bigger storage, consider using MEDIUMTEXT\ninstead.\n \nAn optional length M can be given for this type. If this is\ndone, MariaDB\ncreates the column as the smallest TEXT type large enough to\nhold values\nM characters long.\n \nBefore MariaDB 10.2, all MariaDB collations were of type\nPADSPACE, meaning that TEXT (as well as VARCHAR and CHAR\nvalues) are compared without regard for trailing spaces.\nThis does not apply to the LIKE pattern-matching operator,\nwhich takes into account trailing spaces.\n \nBefore MariaDB 10.2.1, BLOB and TEXT columns could not be\nassigned a DEFAULT value. This restriction was lifted in\nMariaDB 10.2.1.\n \nExamples\n-------- \nTrailing spaces:\n \nCREATE TABLE strtest (d TEXT(10));\nINSERT INTO strtest VALUES(\'Maria \');\n \nSELECT d=\'Maria\',d=\'Maria \' FROM strtest;\n+-----------+--------------+\n| d=\'Maria\' | d=\'Maria \' |\n+-----------+--------------+\n| 1 | 1 |\n+-----------+--------------+\n \nSELECT d LIKE \'Maria\',d LIKE \'Maria \' FROM strtest;\n+----------------+-------------------+\n| d LIKE \'Maria\' | d LIKE \'Maria \' |\n+----------------+-------------------+\n| 0 | 1 |\n+----------------+-------------------+\n \nDifference between VARCHAR and TEXT\n \nVARCHAR columns can be fully indexed. TEXT columns can only\nbe indexed over a specified length.\nUsing TEXT or BLOB in a SELECT query that uses temporary\ntables for storing intermediate results will force the\ntemporary table to be disk based (using the Aria storage\nengine instead of the memory storage engine, which is a bit\nslower. This is not that bad as the Aria storage engine\ncaches the rows in memory. To get the benefit of this, one\nshould ensure that the aria_pagecache_buffer_size variable\nis big enough to hold most of the row and index data for\ntemporary tables.\n \nFor Storage Engine Developers\n \nInternally the full length of the VARCHAR column is\nallocated inside each TABLE objects record[] structure. As\nthere are three such buffers, each open table will allocate\n3 times max-length-to-store-varchar bytes of memory.\nTEXT and BLOB columns are stored with a pointer (4 or 8\nbytes) + a 1-4 bytes length. The TEXT data is only stored\nonce. This means that internally TEXT uses less memory for\neach open table but instead has the additional overhead that\neach TEXT object needs to be allocated and freed for each\nrow access (with some caching in between).\n \n\n\nURL: https://mariadb.com/kb/en/text/','','https://mariadb.com/kb/en/text/'),(577,'ST_IsSimple',36,'Syntax\n------ \nST_IsSimple(g)\nIsSimple(g)\n \nDescription\n----------- \nReturns true if the given Geometry has no anomalous\ngeometric points, false if it does, or NULL if given a NULL\nvalue.\n \nST_IsSimple() and IsSimple() are synonyms.\n \nExamples\n-------- \nA POINT is always simple.\n \nSET @g = \'Point(1 2)\';\n \nSELECT ST_ISSIMPLE(GEOMFROMTEXT(@g));\n+-------------------------------+\n| ST_ISSIMPLE(GEOMFROMTEXT(@g)) |\n+-------------------------------+\n| 1 |\n+-------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_issimple/','','https://mariadb.com/kb/en/st_issimple/'),(578,'ST_NUMGEOMETRIES',36,'Syntax\n------ \nST_NumGeometries(gc)\nNumGeometries(gc)\n \nDescription\n----------- \nReturns the number of geometries in the GeometryCollection\ngc.\n \nST_NumGeometries() and NumGeometries() are synonyms.\n \nExample\n \nSET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3\n3))\';\n \nSELECT NUMGEOMETRIES(GeomFromText(@gc));\n+----------------------------------+\n| NUMGEOMETRIES(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_numgeometries/','','https://mariadb.com/kb/en/st_numgeometries/'),(579,'ST_RELATE',36,'The ST_RELATE() function was introduced in MariaDB 10.1.2\n \nSyntax\n------ \nST_Relate(g1, g2, i)\n \nDescription\n----------- \nReturns true if Geometry g1 is spatially related to\nGeometryg2 by testing for intersections between the\ninterior, boundary and exterior of the two geometries as\nspecified by the values in intersection matrix pattern i.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_relate/','','https://mariadb.com/kb/en/st_relate/'),(580,'ST_SRID',36,'Syntax\n------ \nST_SRID(g)\nSRID(g)\n \nDescription\n----------- \nReturns an integer indicating the Spatial Reference System\nID for the\ngeometry value g.\n \nIn MariaDB, the SRID value is just an integer associated\nwith the\ngeometry value. All calculations are done assuming Euclidean\n(planar)\ngeometry.\n \nST_SRID() and SRID() are synonyms.\n \nExamples\n-------- \nSELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_srid/','','https://mariadb.com/kb/en/st_srid/'),(292,'TIME',22,'Syntax\n------ \nTIME [()]\n \nDescription\n----------- \nA time. The range is \'-838:59:59.999999\' to\n\'838:59:59.999999\'. Microsecond precision can be from 0-6;\nif not specified 0 is used. Microseconds have been available\nsince MariaDB 5.3. \n \nMariaDB displays TIME values in \'HH:MM:SS.ssssss\' format,\nbut allows assignment of times in looser formats, including\n\'D HH:MM:SS\', \'HH:MM:SS\', \'HH:MM\', \'D HH:MM\', \'D\nHH\', \'SS\', or \'HHMMSS\', as well as permitting dropping\nof any leading zeros when a delimiter is provided, for\nexample \'3:9:10\'. For details, see date and time literals.\n \nMariaDB 10.1.2 introduced the --mysql56-temporal-format\noption, on by default, which allows MariaDB to store TIMEs\nusing the same low-level format MySQL 5.6 uses.\n \nInternal Format\n \nIn MariaDB 10.1.2 a new temporal format was introduced from\nMySQL 5.6 that alters how the TIME, DATETIME and TIMESTAMP\ncolumns operate at lower levels. These changes allow these\ntemporal data types to have fractional parts and negative\nvalues. You can disable this feature using the\nmysql56_temporal_format system variable.\n \nTables that include TIMESTAMP values that were created on an\nolder version of MariaDB or that were created while the\nmysql56_temporal_format system variable was disabled\ncontinue to store data using the older data type format.\n \nIn order to update table columns from the older format to\nthe newer format, execute an ALTER TABLE... MODIFY COLUMN\nstatement that changes the column to the *same* data type.\nThis change may be needed if you want to export the table\'s\ntablespace and import it onto a server that has\nmysql56_temporal_format=ON set (see MDEV-15225).\n \nFor instance, if you have a TIME column in your table: \n \nSHOW VARIABLES LIKE \'mysql56_temporal_format\';\n \n+-------------------------+-------+\n| Variable_name | Value |\n+-------------------------+-------+\n| mysql56_temporal_format | ON |\n+-------------------------+-------+\n \nALTER TABLE example_table MODIFY ts_col TIME;\n \nWhen MariaDB executes the ALTER TABLE statement, it converts\nthe data from the older temporal format to the newer one. \n \nIn the event that you have several tables and columns using\ntemporal data types that you want to switch over to the new\nformat, make sure the system variable is enabled, then\nperform a dump and restore using mysqldump. The columns\nusing relevant temporal data types are restored using the\nnew temporal format.\n \nExamples\n-------- \nINSERT INTO time VALUES (\'90:00:00\'), (\'800:00:00\'),\n(800), (22), (151413), (\'9:6:3\'), (\'12 09\');\n \nSELECT * FROM time;\n+-----------+\n| t |\n+-----------+\n| 90:00:00 |\n| 800:00:00 |\n| 00:08:00 |\n| 00:00:22 |\n| 15:14:13 |\n| 09:06:03 |\n| 297:00:00 |\n+-----------+\n \n\n\nURL: https://mariadb.com/kb/en/time/','','https://mariadb.com/kb/en/time/'),(295,'TINYINT',22,'Syntax\n------ \nTINYINT[(M)] [SIGNED | UNSIGNED | ZEROFILL]\n \nDescription\n----------- \nA very small integer. The signed range is -128 to 127. The\nunsigned range is 0 to 255. For details on the attributes,\nsee Numeric Data Type Overview.\n \nExamples\n-------- \nCREATE TABLE tinyints (a TINYINT,b TINYINT UNSIGNED,c\nTINYINT ZEROFILL);\nQuery OK, 0 rows affected (0.43 sec)\n \nINSERT INTO tinyints VALUES (-10,-10,-10);\nQuery OK, 1 row affected, 2 warnings (0.08 sec)\nWarning (Code 1264): Out of range value for column \'b\' at\nrow 1\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO tinyints VALUES (-10,10,-10);\nQuery OK, 1 row affected, 1 warning (0.11 sec)\nWarning (Code 1264): Out of range value for column \'c\' at\nrow 1\n \nINSERT INTO tinyints VALUES (-10,10,10);\n \nSELECT * FROM tinyints;\n+------+------+------+\n| a | b | c |\n+------+------+------+\n| -10 | 0 | 000 |\n| -10 | 10 | 000 |\n| -10 | 10 | 010 |\n+------+------+------+\n \nINSERT INTO tinyints VALUES (128,128,128);\nQuery OK, 1 row affected, 1 warning (0.19 sec)\nWarning (Code 1264): Out of range value for column \'a\' at\nrow 1\n \nINSERT INTO tinyints VALUES (127,128,128);\n \nSELECT * FROM tinyints;\n+------+------+------+\n| a | b | c |\n+------+------+------+\n| -10 | 0 | 000 |\n| -10 | 10 | 000 |\n| -10 | 10 | 010 |\n| 127 | 128 | 128 |\n| 127 | 128 | 128 |\n+------+------+------+\n \n\n\nURL: https://mariadb.com/kb/en/tinyint/','','https://mariadb.com/kb/en/tinyint/'),(297,'VARBINARY',22,'Syntax\n------ \nVARBINARY(M)\n \nDescription\n----------- \nThe VARBINARY type is similar to the VARCHAR type, but\nstores binary byte strings rather than non-binary character\nstrings. M represents the maximum column length in bytes. \n \nIt contains no character set, and comparison and sorting are\nbased on the numeric value of the bytes.\n \nIf the maximum length is exceeded, and SQL strict mode is\nnot enabled , the extra characters will be dropped with a\nwarning. If strict mode is enabled, an error will occur.\n \nUnlike BINARY values, VARBINARYs are not right-padded when\ninserting.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, RAW is a synonym for\nVARBINARY.\n \nExamples\n-------- \nInserting too many characters, first with strict mode off,\nthen with it on:\n \nCREATE TABLE varbins (a VARBINARY(10));\n \nINSERT INTO varbins VALUES(\'12345678901\');\nQuery OK, 1 row affected, 1 warning (0.04 sec)\n \nSELECT * FROM varbins;\n \n+------------+\n| a |\n+------------+\n| 1234567890 |\n+------------+\n \nSET sql_mode=\'STRICT_ALL_TABLES\';\n \nINSERT INTO varbins VALUES(\'12345678901\');\nERROR 1406 (22001): Data too long for column \'a\' at row 1\n \nSorting is performed with the byte value:\n \nTRUNCATE varbins;\n \nINSERT INTO varbins VALUES(\'A\'),(\'B\'),(\'a\'),(\'b\');\n \nSELECT * FROM varbins ORDER BY a;\n \n+------+\n| a |\n+------+\n| A |\n| B |\n| a |\n| b |\n+------+\n \nUsing CAST to sort as a CHAR instead:\n \nSELECT * FROM varbins ORDER BY CAST(a AS CHAR);\n+------+\n| a |\n+------+\n| a |\n| A |\n| b |\n| B |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/varbinary/','','https://mariadb.com/kb/en/varbinary/'),(581,'ASCII',37,'Syntax\n------ \nASCII(str)\n \nDescription\n----------- \nReturns the numeric ASCII value of the leftmost character of\nthe string argument. Returns 0 if the given string is empty\nand NULL if it is NULL.\n \nASCII() works for 8-bit characters.\n \nExamples\n-------- \nSELECT ASCII(9);\n+----------+\n| ASCII(9) |\n+----------+\n| 57 |\n+----------+\n \nSELECT ASCII(\'9\');\n+------------+\n| ASCII(\'9\') |\n+------------+\n| 57 |\n+------------+\n \nSELECT ASCII(\'abc\');\n+--------------+\n| ASCII(\'abc\') |\n+--------------+\n| 97 |\n+--------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ascii/','','https://mariadb.com/kb/en/ascii/'),(582,'BIN',37,'Syntax\n------ \nBIN(N)\n \nDescription\n----------- \nReturns a string representation of the binary value of the\ngiven longlong (that is, BIGINT) number. This is equivalent\nto CONV(N,10,2). The argument should be positive. If it is a\nFLOAT, it will be truncated. Returns NULL if the argument is\nNULL.\n \nExamples\n-------- \nSELECT BIN(12);\n+---------+\n| BIN(12) |\n+---------+\n| 1100 |\n+---------+\n \n\n\nURL: https://mariadb.com/kb/en/bin/','','https://mariadb.com/kb/en/bin/'),(584,'BIT_LENGTH',37,'Syntax\n------ \nBIT_LENGTH(str)\n \nDescription\n----------- \nReturns the length of the given string argument in bits. If\nthe argument is not a string, it will be converted to\nstring. If the argument is NULL, it returns NULL.\n \nExamples\n-------- \nSELECT BIT_LENGTH(\'text\');\n+--------------------+\n| BIT_LENGTH(\'text\') |\n+--------------------+\n| 32 |\n+--------------------+\n \nSELECT BIT_LENGTH(\'\');\n+----------------+\n| BIT_LENGTH(\'\') |\n+----------------+\n| 0 |\n+----------------+\n \nCompatibility\n \nPostgreSQL and Sybase support BIT_LENGTH().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/bit_length/','','https://mariadb.com/kb/en/bit_length/'),(298,'VARCHAR',22,'Syntax\n------ \n[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n \nDescription\n----------- \nA variable-length string. M represents the maximum column\nlength in\ncharacters. The range of M is 0 to 65,532. The effective\nmaximum\nlength of a VARCHAR is subject to the maximum row size and\nthe character set used. For\nexample, utf8 characters can require up to three bytes per\ncharacter,\nso a VARCHAR column that uses the utf8 character set can be\ndeclared\nto be a maximum of 21,844 characters.\n \nMariaDB stores VARCHAR values as a one-byte or two-byte\nlength prefix\nplus data. The length prefix indicates the number of bytes\nin the\nvalue. A VARCHAR column uses one length byte if values\nrequire no more\nthan 255 bytes, two length bytes if values may require more\nthan 255\nbytes.\n \nNote: MariaDB 5.1 and later follow the standard SQL\nspecification, \nand do not remove trailing spaces from VARCHAR values.\n \nVARCHAR(0) columns can contain 2 values: an empty string or\nNULL. Such columns cannot be part of an index. The CONNECT\nstorage engine does not support VARCHAR(0).\n \nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR\nis the\nstandard SQL way to define that a VARCHAR column should use\nsome\npredefined character set. MariaDB uses utf8 as this\npredefined character set, as does MySQL 4.1 and up.\nNVARCHAR is shorthand for NATIONAL VARCHAR.\n \nBefore MariaDB 10.2, all MariaDB collations were of type\nPADSPACE, meaning that VARCHAR (as well as CHAR and TEXT\nvalues) are compared without regard for trailing spaces.\nThis does not apply to the LIKE pattern-matching operator,\nwhich takes into account trailing spaces. From MariaDB 10.2,\na number of NO PAD collations are available.\n \nIf a unique index consists of a column where trailing pad\ncharacters are stripped or ignored, inserts into that column\nwhere values differ only by the number of trailing pad\ncharacters will result in a duplicate-key error.\n \nExamples\n-------- \nThe following are equivalent:\n \nVARCHAR(30) CHARACTER SET utf8\nNATIONAL VARCHAR(30)\nNVARCHAR(30)\nNCHAR VARCHAR(30)\nNATIONAL CHARACTER VARYING(30)\nNATIONAL CHAR VARYING(30)\n \nTrailing spaces:\n \nCREATE TABLE strtest (v VARCHAR(10));\nINSERT INTO strtest VALUES(\'Maria \');\n \nSELECT v=\'Maria\',v=\'Maria \' FROM strtest;\n+-----------+--------------+\n| v=\'Maria\' | v=\'Maria \' |\n+-----------+--------------+\n| 1 | 1 |\n+-----------+--------------+\n \nSELECT v LIKE \'Maria\',v LIKE \'Maria \' FROM strtest;\n+----------------+-------------------+\n| v LIKE \'Maria\' | v LIKE \'Maria \' |\n+----------------+-------------------+\n| 0 | 1 |\n+----------------+-------------------+\n \nTruncation\n \nDepending on whether or not strict sql mode is set, you will\neither get a warning or an error if you try to insert a\nstring that is too long into a VARCHAR column. If the extra\ncharacters are spaces, the spaces that can\'t fit will be\nremoved and you will always get a warning, regardless of the\nsql mode setting.\n \nDifference Between VARCHAR and TEXT\n \nVARCHAR columns can be fully indexed. TEXT columns can only\nbe indexed over a specified length.\nUsing TEXT or BLOB in a SELECT query that uses temporary\ntables for storing intermediate results will force the\ntemporary table to be disk based (using the Aria storage\nengine instead of the memory storage engine, which is a bit\nslower. This is not that bad as the Aria storage engine\ncaches the rows in memory. To get the benefit of this, one\nshould ensure that the aria_pagecache_buffer_size variable\nis big enough to hold most of the row and index data for\ntemporary tables.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, VARCHAR2 is a synonym.\n \nFor Storage Engine Developers\n \nInternally the full length of the VARCHAR column is\nallocated inside each TABLE objects record[] structure. As\nthere are three such buffers, each open table will allocate\n3 times max-length-to-store-varchar bytes of memory.\nTEXT and BLOB columns are stored with a pointer (4 or 8\nbytes) + a 1-4 bytes length. The TEXT data is only stored\nonce. This means that internally TEXT uses less memory for\neach open table but instead has the additional overhead that\neach TEXT object needs to be allocated and freed for each\nrow access (with some caching in between).\n \n\n\nURL: https://mariadb.com/kb/en/varchar/','','https://mariadb.com/kb/en/varchar/'),(299,'YEAR Data Type',22,'Syntax\n------ \nYEAR[(4)]\n \nDescription\n----------- \nA year in two-digit or four-digit format. The default is\nfour-digit format. Note that the two-digit format has been\ndeprecated since 5.5.27. \n \nIn four-digit format, the allowable values are 1901 to 2155,\nand 0000. In two-digit format, the allowable values are 70\nto 69,\nrepresenting years from 1970 to 2069. MariaDB displays YEAR\nvalues in\nYYYY format, but allows you to assign values to YEAR columns\nusing\neither strings or numbers.\n \nInserting numeric zero has a different result for YEAR(4)\nand YEAR(2). For YEAR(2), the value 00 reflects the year\n2000. For YEAR(4), the value 0000 reflects the year zero.\nThis only applies to numeric zero. String zero always\nreflects the year 2000.\n \nExamples\n-------- \nAccepting a string or a number:\n \nCREATE TABLE y(y YEAR);\n \nINSERT INTO y VALUES (1990),(\'2012\');\n \nSELECT * FROM y;\n+------+\n| y |\n+------+\n| 1990 |\n| 2012 |\n+------+\n \nOut of range:\n \nINSERT INTO y VALUES (1005),(\'3080\');\nQuery OK, 2 rows affected, 2 warnings (0.05 sec)\nRecords: 2 Duplicates: 0 Warnings: 2\n \nSHOW WARNINGS;\n+---------+------+--------------------------------------------+\n| Level | Code | Message |\n+---------+------+--------------------------------------------+\n| Warning | 1264 | Out of range value for column \'y\' at\nrow 1 |\n| Warning | 1264 | Out of range value for column \'y\' at\nrow 2 |\n+---------+------+--------------------------------------------+\n \nSELECT * FROM y;\n+------+\n| y |\n+------+\n| 1990 |\n| 2012 |\n| 0000 |\n| 0000 |\n+------+\n \nTruncating:\n \nINSERT INTO y VALUES (\'2013-12-12\');\nQuery OK, 1 row affected, 1 warning (0.05 sec)\n \nSHOW WARNINGS;\n+---------+------+----------------------------------------+\n| Level | Code | Message |\n+---------+------+----------------------------------------+\n| Warning | 1265 | Data truncated for column \'y\' at row 1\n|\n+---------+------+----------------------------------------+\n \nSELECT * FROM y;\n+------+\n| y |\n+------+\n| 1990 |\n| 2012 |\n| 0000 |\n| 0000 |\n| 2013 |\n+------+\n \nDifference between YEAR(2) and YEAR(4), and string and\nnumeric zero:\n \nCREATE TABLE y2(y YEAR(4), y2 YEAR(2));\nQuery OK, 0 rows affected, 1 warning (0.40 sec)\n \nNote (Code 1287): \'YEAR(2)\' is deprecated and will be\nremoved in a future release. Please use YEAR(4) instead\n \nINSERT INTO y2 VALUES(0,0),(\'0\',\'0\');\n \nSELECT YEAR(y),YEAR(y2) FROM y;\n+---------+----------+\n| YEAR(y) | YEAR(y2) |\n+---------+----------+\n| 0 | 2000 |\n| 2000 | 2000 |\n+---------+----------+\n \n\n\nURL: https://mariadb.com/kb/en/year-data-type/','','https://mariadb.com/kb/en/year-data-type/'),(587,'CHARACTER_LENGTH',37,'Syntax\n------ \nCHARACTER_LENGTH(str)\n \nDescription\n----------- \nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/character_length/','','https://mariadb.com/kb/en/character_length/'),(602,'INSTR',37,'Syntax\n------ \nINSTR(str,substr)\n \nDescription\n----------- \nReturns the position of the first occurrence of substring\nsubstr in\nstring str. This is the same as the two-argument form of\nLOCATE(),\nexcept that the order of the arguments is reversed.\n \nINSTR() performs a case-insensitive search.\n \nIf any argument is NULL, returns NULL.\n \nExamples\n-------- \nSELECT INSTR(\'foobarbar\', \'bar\');\n+---------------------------+\n| INSTR(\'foobarbar\', \'bar\') |\n+---------------------------+\n| 4 |\n+---------------------------+\n \nSELECT INSTR(\'My\', \'Maria\');\n+----------------------+\n| INSTR(\'My\', \'Maria\') |\n+----------------------+\n| 0 |\n+----------------------+\n \n\n\nURL: https://mariadb.com/kb/en/instr/','','https://mariadb.com/kb/en/instr/'),(300,'BEGIN END',23,'Syntax\n------ \n[begin_label:] BEGIN [NOT ATOMIC]\n [statement_list]\nEND [end_label]\n \nNOT ATOMIC is required when used outside of a stored\nprocedure. Inside stored procedures or within an anonymous\nblock, BEGIN alone starts a new anonymous block.\n \nDescription\n----------- \nBEGIN ... END syntax is used for writing compound\nstatements. A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords.\nstatement_list represents a list of one or more statements,\neach\nterminated by a semicolon (i.e., ;) statement delimiter.\nstatement_list is\noptional, which means that the empty compound statement\n(BEGIN END) is\nlegal.\n \nNote that END will perform a commit. If you are running in\nautocommit mode, every statement will be committed\nseparately. If you are not running in autocommit mode, you\nmust execute a COMMIT or ROLLBACK after END to get the\ndatabase up to date.\n \nUse of multiple statements requires that a client is able to\nsend statement strings containing the ; statement delimiter.\nThis is handled in the mysql command-line client with the\nDELIMITER command.\nChanging the ; end-of-statement delimiter (for example, to\n//) allows ; to be used in a program body.\n \nA compound statement within a stored program can be\nlabeled. end_label cannot be given unless begin_label also\nis present. If both are present, they must be the same.\n \nBEGIN ... END constructs can be nested. Each block can\ndefine its own variables, a CONDITION, a HANDLER and a\nCURSOR, which don\'t exist in the outer blocks. The most\nlocal declarations override the outer objects which use the\nsame name (see example below).\n \nThe declarations order is the following:\nDECLARE local variables;\nDECLARE CONDITIONs;\nDECLARE CURSORs;\nDECLARE HANDLERs;\n \nNote that DECLARE HANDLER contains another BEGIN ... END\nconstruct.\n \nHere is an example of a very simple, anonymous block:\n \nBEGIN NOT ATOMIC\nSET @a=1;\n \nCREATE TABLE test.t1(a INT);\nEND|\n \nBelow is an example of nested blocks in a stored procedure:\n \nCREATE PROCEDURE t( )\nBEGIN\n DECLARE x TINYINT UNSIGNED DEFAULT 1;\n \n BEGIN\n DECLARE x CHAR(2) DEFAULT \'02\';\n \n DECLARE y TINYINT UNSIGNED DEFAULT 10;\n \n SELECT x, y;\n \n END;\n \n SELECT x;\n \nEND;\n \nIn this example, a TINYINT variable, x is declared in the\noutter block. But in the inner block x is re-declared as a\nCHAR and an y variable is declared. The inner SELECT shows\nthe \"new\" value of x, and the value of y. But when x is\nselected in the outer block, the \"old\" value is returned.\nThe final SELECT doesn\'t try to read y, because it doesn\'t\nexist in that context.\n \n\n\nURL: https://mariadb.com/kb/en/begin-end/','','https://mariadb.com/kb/en/begin-end/'),(301,'CASE Statement',23,'Syntax\n------ \nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n \nOr:\n \nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list] \nEND CASE\n \nDescription\n----------- \nThe CASE statement for stored programs implements a complex\nconditional\nconstruct. If a search_condition evaluates to true, the\ncorresponding SQL\nstatement list is executed. If no search condition matches,\nthe statement list\nin the ELSE clause is executed. Each statement_list consists\nof one or\nmore statements.\n \nIf no when_value or search_condition matches the value\ntested and the CASE\nstatement contains no ELSE clause, a Case not found for CASE\nstatement\nerror results.\n \nEach statement_list consists of one or more statements; an\nempty\nstatement_list is not allowed. To handle situations where no\nvalue is\nmatched by any WHEN clause, use an ELSE containing an\nempty BEGIN ... END block, as shown in this example:\n \nDELIMITER |\nCREATE PROCEDURE p()\nBEGIN\n DECLARE v INT DEFAULT 1;\n \n CASE v\n WHEN 2 THEN SELECT v;\n \n WHEN 3 THEN SELECT 0;\n \n ELSE BEGIN END;\n \n END CASE;\n \nEND;\n \n|\n \nThe indentation used here in the ELSE clause is for purposes\nof clarity only,\nand is not otherwise significant. See Delimiters in the\nmysql client for more on the use of the delimiter command.\n \nNote: The syntax of the CASE statement used inside stored\nprograms\ndiffers slightly from that of the SQL CASE expression\ndescribed in\nCASE OPERATOR.\nThe CASE statement cannot have an ELSE NULL clause, and it\nis\nterminated with END CASE instead of END.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/case-statement/','','https://mariadb.com/kb/en/case-statement/'),(303,'DECLARE CONDITION',23,'Syntax\n------ \nDECLARE condition_name CONDITION FOR condition_value\n \ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | mysql_error_code\n \nDescription\n----------- \nThe DECLARE ... CONDITION statement defines a named error\ncondition.\nIt specifies a condition that needs specific handling and\nassociates a\nname with that condition. Later, the name can be used in a\nDECLARE ... HANDLER, SIGNAL or RESIGNAL statement (as long\nas the statement is located in the same BEGIN ... END\nblock).\n \nConditions must be declared after local variables, but\nbefore CURSORs and HANDLERs.\n \nA condition_value for DECLARE ... CONDITION can be an\nSQLSTATE value (a\n5-character string literal) or a MySQL error code (a\nnumber). You should not\nuse SQLSTATE value \'00000\' or MySQL error code 0, because\nthose indicate sucess\nrather than an error condition. If you try, or if you\nspecify an invalid SQLSTATE value, an error like this is\nproduced:\n \nERROR 1407 (42000): Bad SQLSTATE: \'00000\'\n \nFor a list of SQLSTATE values and MariaDB error\ncodes, see MariaDB Error Codes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/declare-condition/','','https://mariadb.com/kb/en/declare-condition/'),(603,'LCASE',37,'Syntax\n------ \nLCASE(str)\n \nDescription\n----------- \nLCASE() is a synonym for LOWER().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/lcase/','','https://mariadb.com/kb/en/lcase/'),(604,'LEFT',37,'Syntax\n------ \nLEFT(str,len)\n \nDescription\n----------- \nReturns the leftmost len characters from the string str, or\nNULL if\nany argument is NULL.\n \nExamples\n-------- \nSELECT LEFT(\'MariaDB\', 5);\n+--------------------+\n| LEFT(\'MariaDB\', 5) |\n+--------------------+\n| Maria |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/left/','','https://mariadb.com/kb/en/left/'),(606,'LENGTHB',37,'Introduced in MariaDB 10.3.1 as part of the Oracle\ncompatibility enhancements.\n \nSyntax\n------ \nLENGTHB(str)\n \nDescription\n----------- \nLENGTHB() is a synonym for LENGTH().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/lengthb/','','https://mariadb.com/kb/en/lengthb/'),(615,'MID',37,'Syntax\n------ \nMID(str,pos,len)\n \nDescription\n----------- \nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n \nExamples\n-------- \nSELECT MID(\'abcd\',4,1);\n+-----------------+\n| MID(\'abcd\',4,1) |\n+-----------------+\n| d |\n+-----------------+\n \nSELECT MID(\'abcd\',2,2);\n+-----------------+\n| MID(\'abcd\',2,2) |\n+-----------------+\n| bc |\n+-----------------+\n \nA negative starting position:\n \nSELECT MID(\'abcd\',-2,4);\n+------------------+\n| MID(\'abcd\',-2,4) |\n+------------------+\n| cd |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mid/','','https://mariadb.com/kb/en/mid/'),(616,'NOT LIKE',37,'Syntax\n------ \nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n \nDescription\n----------- \nThis is the same as NOT (expr LIKE pat [ESCAPE\n\'escape_char\']).\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not-like/','','https://mariadb.com/kb/en/not-like/'),(305,'DECLARE HANDLER',23,'Syntax\n------ \nDECLARE handler_type HANDLER\n FOR condition_value [, condition_value] ...\n statement\n \nhandler_type:\n CONTINUE\n | EXIT \n | UNDO\n \ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n | mariadb_error_code\n \nDescription\n----------- \nThe DECLARE ... HANDLER statement specifies handlers that\neach may\ndeal with one or more conditions. If one of these conditions\noccurs,\nthe specified statement is executed. statement can be a\nsimple\nstatement (for example, SET var_name = value), or it can be\na compound\nstatement written using BEGIN and END.\n \nHandlers must be declared after local variables, a CONDITION\nand a CURSOR.\n \nFor a CONTINUE handler, execution of the current program\ncontinues\nafter execution of the handler statement. For an EXIT\nhandler,\nexecution terminates for the BEGIN ... END compound\nstatement in which\nthe handler is declared. (This is true even if the condition\noccurs in\nan inner block.) The UNDO handler type statement is not\nsupported.\n \nIf a condition occurs for which no handler has been\ndeclared, the\ndefault action is EXIT.\n \nA condition_value for DECLARE ... HANDLER can be any of the\nfollowing\nvalues:\nAn SQLSTATE value (a 5-character string literal) or a\nMariaDB error\ncode (a number). You should not use SQLSTATE value \'00000\'\nor MariaDB\nerror code 0, because those indicate sucess rather than an\nerror\ncondition. For a list of SQLSTATE values and MariaDB error\ncodes, see\nMariaDB Error Codes.\nA condition name previously specified with DECLARE ...\nCONDITION. It must be in the same stored program. See\nDECLARE CONDITION.\nSQLWARNING is shorthand for the class of SQLSTATE values\nthat begin\nwith \'01\'.\nNOT FOUND is shorthand for the class of SQLSTATE values that\nbegin\nwith \'02\'. This is relevant only the context of cursors\nand is used to\ncontrol what happens when a cursor reaches the end of a data\nset. If\nno more rows are available, a No Data condition occurs with\nSQLSTATE\nvalue 02000. To detect this condition, you can set up a\nhandler for it\n(or for a NOT FOUND condition). An example is shown in\nCursor Overview. This condition also occurs for SELECT ...\nINTO var_list statements that retrieve no\nrows.\nSQLEXCEPTION is shorthand for the class of SQLSTATE values\nthat do\nnot begin with \'00\', \'01\', or \'02\'.\n \nWhen an error raises, in some cases it could be handled by\nmultiple HANDLERs. For example, there may be an handler for\n1050 error, a separate handler for the 42S01 SQLSTATE, and\nanother separate handler for the SQLEXCEPTION class: in\ntheory all occurrences of HANDLER may catch the 1050 error,\nbut MariaDB chooses the HANDLER with the highest precedence.\nHere are the precedence rules:\nHandlers which refer to an error code have the highest\nprecedence.\nHandlers which refer to a SQLSTATE come next.\nHandlers which refer to an error class have the lowest\nprecedence.\n \nIn some cases, a statement could produce multiple errors. If\nthis happens, in some cases multiple handlers could have the\nhighest precedence. In such cases, the choice of the handler\nis indeterminate.\n \nNote that if an error occurs within a CONTINUE HANDLER\nblock, it can be handled by another HANDLER. However, a\nHANDLER which is already in the stack (that is, it has been\ncalled to handle an error and its execution didn\'t finish\nyet) cannot handle new errors—this prevents endless loops.\nFor example, suppose that a stored procedure contains a\nCONTINUE HANDLER for SQLWARNING and another CONTINUE HANDLER\nfor NOT FOUND. At some point, a NOT FOUND error occurs, and\nthe execution enters the NOT FOUND HANDLER. But within that\nhandler, a warning occurs, and the execution enters the\nSQLWARNING HANDLER. If another NOT FOUND error occurs, it\ncannot be handled again by the NOT FOUND HANDLER, because\nits execution is not finished.\n \nWhen a DECLARE HANDLER block can handle more than one error\ncondition, it may be useful to know which errors occurred.\nTo do so, you can use the GET DIAGNOSTICS statement.\n \nAn error that is handled by a DECLARE HANDLER construct can\nbe issued again using the RESIGNAL statement.\n \nBelow is an example using DECLARE HANDLER:\n \nCREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\n \nDELIMITER //\n \nCREATE PROCEDURE handlerdemo ( )\n BEGIN\n DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 =\n1;\n \n SET @x = 1;\n \n INSERT INTO test.t VALUES (1);\n SET @x = 2;\n \n INSERT INTO test.t VALUES (1);\n SET @x = 3;\n \n END;\n \n //\n \nDELIMITER ;\n \nCALL handlerdemo( );\n \nSELECT @x;\n \n+------+\n| @x |\n+------+\n| 3 |\n+------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/declare-handler/','','https://mariadb.com/kb/en/declare-handler/'),(306,'DECLARE Variable',23,'Syntax\n------ \nDECLARE var_name [, var_name] ... [[ROW] TYPE OF]] type\n[DEFAULT value]\n \nDescription\n----------- \nThis statement is used to declare local variables within\nstored programs. To\nprovide a default value for the variable, include a DEFAULT\nclause. The\nvalue can be specified as an expression (even subqueries are\npermitted); it need not be a constant. If the\nDEFAULT clause is missing, the initial value is NULL.\n \nLocal variables are treated like stored routine parameters\nwith respect to data\ntype and overflow checking. See CREATE PROCEDURE.\n \nLocal variables must be declared before CONDITIONs, CURSORs\nand HANDLERs.\n \nLocal variable names are not case sensitive.\n \nThe scope of a local variable is within the BEGIN ... END\nblock where it is\ndeclared. The variable can be referred to in blocks nested\nwithin the declaring\nblock, except those blocks that declare a variable with the\nsame name.\n \nTYPE OF / ROW TYPE OF\n \nTYPE OF and ROW TYPE OF anchored data types for stored\nroutines were introduced in MariaDB 10.3.\n \nAnchored data types allow a data type to be defined based on\nanother object, such as a table row, rather than\nspecifically set in the declaration. If the anchor object\nchanges, so will the anchored data type. This can lead to\nroutines being easier to maintain, so that if the data type\nin the table is changed, it will automatically be changed in\nthe routine as well.\n \nVariables declared with ROW TYPE OF will have the same\nfeatures as implicit ROW variables. It is not possible to\nuse ROW TYPE OF variables in a LIMIT clause.\n \nThe real data type of TYPE OF and ROW TYPE OF table_name\nwill become known at the very beginning of the stored\nroutine call. ALTER TABLE or DROP TABLE statements performed\ninside the current routine on the tables that appear in\nanchors won\'t affect the data type of the anchored\nvariables, even if the variable is declared after an ALTER\nTABLE or DROP TABLE statement.\n \nThe real data type of a ROW TYPE OF cursor_name variable\nwill become known when execution enters into the block where\nthe variable is declared. Data type instantiation will\nhappen only once. In a cursor ROW TYPE OF variable that is\ndeclared inside a loop, its data type will become known on\nthe very first iteration and won\'t change on further loop\niterations.\n \nThe tables referenced in TYPE OF and ROW TYPE OF\ndeclarations will be checked for existence at the beginning\nof the stored routine call. CREATE PROCEDURE or CREATE\nFUNCTION will not check the referenced tables for existence.\n \nExamples\n-------- \nTYPE OF and ROW TYPE OF from MariaDB 10.3:\n \nDECLARE tmp TYPE OF t1.a;\n -- Get the data type from the column {{a}} in the table\n{{t1}}\n \nDECLARE rec1 ROW TYPE OF t1;\n -- Get the row data type from the table {{t1}}\n \nDECLARE rec2 ROW TYPE OF cur1;\n -- Get the row data type from the cursor {{cur1}}\n \n\n\nURL: https://mariadb.com/kb/en/declare-variable/','','https://mariadb.com/kb/en/declare-variable/'),(308,'FOR',23,'FOR loops were introduced in MariaDB 10.3.\n \nSyntax\n------ \nInteger range FOR loop:\n \n[begin_label:]\nFOR var_name IN [ REVERSE ] lower_bound .. upper_bound\nDO statement_list\nEND FOR [ end_label ]\n \nExplicit cursor FOR loop\n \n[begin_label:]\nFOR record_name IN cursor_name [ (\ncursor_actual_parameter_list)]\nDO statement_list\nEND FOR [ end_label ]\n \nExplicit cursor FOR loop (Oracle mode)\n \n[begin_label:]\nFOR record_name IN cursor_name [ (\ncursor_actual_parameter_list)]\nLOOP\n statement_list\nEND LOOP [ end_label ]\n \nImplicit cursor FOR loop\n \n[begin_label:]\nFOR record_name IN ( select_statement )\nDO statement_list\nEND FOR [ end_label ]\n \nDescription\n----------- \nFOR loops allow code to be executed a fixed number of times.\n \nIn an integer range FOR loop, MariaDB will compare the lower\nbound and upper bound values, and assign the lower bound\nvalue to a counter. If REVERSE is not specified, and the\nupper bound value is greater than or equal to the counter,\nthe counter will be incremented and the statement will\ncontinue, after which the loop is entered again. If the\nupper bound value is greater than the counter, the loop will\nbe exited.\n \nIf REVERSE is specified, the counter is decremented, and the\nupper bound value needs to be less than or equal for the\nloop to continue.\n \nExamples\n-------- \nIntger range FOR loop:\n \nCREATE TABLE t1 (a INT);\n \nDELIMITER //\n \nFOR i IN 1..3\nDO\n INSERT INTO t1 VALUES (i);\nEND FOR;\n \n//\n \nDELIMITER ;\n \nSELECT * FROM t1;\n \n+------+\n| a |\n+------+\n| 1 |\n| 2 |\n| 3 |\n+------+\n \nREVERSE integer range FOR loop:\n \nCREATE OR REPLACE TABLE t1 (a INT);\n \nDELIMITER //\nFOR i IN REVERSE 12..4\n DO\n INSERT INTO t1 VALUES (i);\nEND FOR;\n \n//\nQuery OK, 9 rows affected (0.422 sec)\n \nDELIMITER ;\n \nSELECT * FROM t1;\n \n+------+\n| a |\n+------+\n| 12 |\n| 11 |\n| 10 |\n| 9 |\n| 8 |\n| 7 |\n| 6 |\n| 5 |\n| 4 |\n+------+\n \nExplicit cursor in Oracle mode:\n \nSET sql_mode=ORACLE;\n \nCREATE OR REPLACE TABLE t1 (a INT, b VARCHAR(32));\n \nINSERT INTO t1 VALUES (10,\'b0\');\nINSERT INTO t1 VALUES (11,\'b1\');\nINSERT INTO t1 VALUES (12,\'b2\');\n \nDELIMITER //\n \nCREATE OR REPLACE PROCEDURE p1(pa INT) AS \n CURSOR cur(va INT) IS\n SELECT a, b FROM t1 WHERE a=va;\n \nBEGIN\n FOR rec IN cur(pa)\n LOOP\n SELECT rec.a, rec.b;\n \n END LOOP;\n \nEND;\n \n//\n \nDELIMITER ;\n \nCALL p1(10);\n+-------+-------+\n| rec.a | rec.b |\n+-------+-------+\n| 10 | b0 |\n+-------+-------+\n \nCALL p1(11);\n+-------+-------+\n| rec.a | rec.b |\n+-------+-------+\n| 11 | b1 |\n+-------+-------+\n \nCALL p1(12);\n+-------+-------+\n| rec.a | rec.b |\n+-------+-------+\n| 12 | b2 |\n+-------+-------+\n \nCALL p1(13);\nQuery OK, 0 rows affected (0.000 sec)\n \n\n\nURL: https://mariadb.com/kb/en/for/','','https://mariadb.com/kb/en/for/'),(312,'Labels',23,'Syntax\n------ \nlabel: \n[label]\n \nLabels are MariaDB identifiers which can be used to identify\na BEGIN ... END construct or a loop. They have a maximum\nlength of 16 characters and can be quoted with backticks\n(i.e.., `).\n \nLabels have a start part and an end part. The start part\nmust precede the portion of code it refers to, must be\nfollowed by a colon (:) and can be on the same or different\nline. The end part is optional and adds nothing, but can\nmake the code more readable. If used, the end part must\nprecede the construct\'s delimiter (;). Constructs\nidentified by a label can be nested. Each construct can be\nidentified by only one label.\n \nLabels need not be unique in the stored program they belong\nto. However, a label for an inner loop cannot be identical\nto a label for an outer loop. In this case, the following\nerror would be produced:\n \nERROR 1309 (42000): Redefining label \n \nLEAVE and ITERATE statements can be used to exit or repeat a\nportion of code identified by a label. They must be in the\nsame Stored Routine, Trigger or Event which contains the\ntarget label.\n \nBelow is an example using a simple label that is used to\nexit a LOOP:\n \nCREATE PROCEDURE `test_sp`()\nBEGIN\n `my_label`:\n LOOP\n SELECT \'looping\';\n \n LEAVE `my_label`;\n \n END LOOP;\n \n SELECT \'out of loop\';\n \nEND;\n \nThe following label is used to exit a procedure, and has an\nend part:\n \nCREATE PROCEDURE `test_sp`()\n`my_label`:\nBEGIN\n IF @var = 1 THEN\n LEAVE `my_label`;\n \n END IF;\n \n DO something();\nEND `my_label`;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/labels/','','https://mariadb.com/kb/en/labels/'),(313,'LEAVE',23,'Syntax\n------ \nLEAVE label\n \nThis statement is used to exit the flow control construct\nthat has the\ngiven label. The label must be in the same stored program,\nnot in a caller procedure. LEAVE can be used within BEGIN\n... END or loop constructs\n(LOOP, REPEAT, WHILE). In Stored Procedures, Triggers and\nEvents, LEAVE can refer to the outmost BEGIN ... END\nconstruct; in that case, the program exits the procedure. In\nStored Functions, RETURN can be used instead.\n \nNote that LEAVE cannot be used to exit a DECLARE HANDLER\nblock.\n \nIf you try to LEAVE a non-existing label, or if you try to\nLEAVE a HANDLER block, the following error will be produced:\n \nERROR 1308 (42000): LEAVE with no matching label: \n \nThe following example uses LEAVE to exit the procedure if a\ncondition is true:\n \nCREATE PROCEDURE proc(IN p TINYINT)\nCONTAINS SQL\n`whole_proc`:\nBEGIN\n SELECT 1;\n \n IF p \n\nURL: https://mariadb.com/kb/en/leave/','','https://mariadb.com/kb/en/leave/'),(617,'NOT REGEXP',37,'Syntax\n------ \nexpr NOT REGEXP pat, expr NOT RLIKE pat\n \nDescription\n----------- \nThis is the same as NOT (expr REGEXP pat).\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/not-regexp/','','https://mariadb.com/kb/en/not-regexp/'),(618,'OCTET_LENGTH',37,'Syntax\n------ \nOCTET_LENGTH(str)\n \nDescription\n----------- \nOCTET_LENGTH() is normally a synonym for LENGTH(). When\nrunning Oracle mode from MariaDB 10.3, they are not\nsynonyms, but OCTET_LENGTH() behaves as LENGTH() would when\nnot in Oracle mode.\n \n\n\nURL: https://mariadb.com/kb/en/octet_length/','','https://mariadb.com/kb/en/octet_length/'),(619,'ORD',37,'Syntax\n------ \nORD(str)\n \nDescription\n----------- \nIf the leftmost character of the string str is a multi-byte\ncharacter,\nreturns the code for that character, calculated from the\nnumeric\nvalues of its constituent bytes using this formula:\n \n (1st byte code)\n+ (2nd byte code x 256)\n+ (3rd byte code x 256 x 256) ...\n \nIf the leftmost character is not a multi-byte character,\nORD() returns\nthe same value as the ASCII() function.\n \nExamples\n-------- \nSELECT ORD(\'2\');\n+----------+\n| ORD(\'2\') |\n+----------+\n| 50 |\n+----------+\n \n\n\nURL: https://mariadb.com/kb/en/ord/','','https://mariadb.com/kb/en/ord/'),(620,'POSITION',37,'Syntax\n------ \nPOSITION(substr IN str)\n \nDescription\n----------- \nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n \nIt\'s part of ODBC 3.0.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/position/','','https://mariadb.com/kb/en/position/'),(621,'QUOTE',37,'Syntax\n------ \nQUOTE(str)\n \nDescription\n----------- \nQuotes a string to produce a result that can be used as a\nproperly escaped data\nvalue in an SQL statement. The string is returned enclosed\nby single quotes and\nwith each instance of single quote (\"\'\"), backslash\n(\"\\\"),\nASCII NUL, and Control-Z preceded by a backslash. If the\nargument\nis NULL, the return value is the word \"NULL\" without\nenclosing single\nquotes.\n \nExamples\n-------- \nSELECT QUOTE(\"Don\'t!\");\n+-----------------+\n| QUOTE(\"Don\'t!\") |\n+-----------------+\n| \'Don\\\'t!\' |\n+-----------------+\n \nSELECT QUOTE(NULL); \n+-------------+\n| QUOTE(NULL) |\n+-------------+\n| NULL |\n+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/quote/','','https://mariadb.com/kb/en/quote/'),(316,'REPEAT LOOP',23,'Syntax\n------ \n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n \nThe statement list within a REPEAT statement is repeated\nuntil the\nsearch_condition is true. Thus, a REPEAT always enters the\nloop at\nleast once. statement_list consists of one or more\nstatements, each\nterminated by a semicolon (i.e., ;) statement delimiter.\n \nA REPEAT statement can be labeled. end_label cannot be given\nunless\nbegin_label also is present. If both are present, they must\nbe the\nsame.\n \nSee Delimiters in the mysql client for more on client\ndelimiter usage.\n \nDELIMITER //\n \nCREATE PROCEDURE dorepeat(p1 INT)\n BEGIN\n SET @x = 0;\n \n REPEAT SET @x = @x + 1;\n UNTIL @x > p1 END REPEAT;\n \n END\n//\n \nCALL dorepeat(1000)//\n \nSELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/repeat-loop/','','https://mariadb.com/kb/en/repeat-loop/'),(317,'RESIGNAL',23,'Syntax\n------ \nRESIGNAL [error_condition]\n [SET error_property\n [, error_property] ...]\n \nerror_condition:\n SQLSTATE [VALUE] \'sqlstate_value\'\n | condition_name\n \nerror_property:\n error_property_name = \n \nerror_property_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n \nDescription\n----------- \nThe syntax of RESIGNAL and its semantics are very similar to\nSIGNAL. This statement can only be used within an error\nHANDLER. It produces an error, like SIGNAL. RESIGNAL clauses\nare the same as SIGNAL, except that they all are optional,\neven SQLSTATE. All the properties which are not specified in\nRESIGNAL, will be identical to the properties of the error\nthat was received by the error HANDLER. For a description of\nthe clauses, see diagnostics area.\n \nNote that RESIGNAL does not empty the diagnostics area: it\njust appends another error condition.\n \nRESIGNAL, without any clauses, produces an error which is\nidentical to the error that was received by HANDLER.\n \nIf used out of a HANDLER construct, RESIGNAL produces the\nfollowing error:\n \nERROR 1645 (0K000): RESIGNAL when handler not active\n \nIn MariaDB 5.5, if a HANDLER contained a CALL to another\nprocedure, that procedure could use RESIGNAL. Since MariaDB\n10.0, trying to do this raises the above error.\n \nFor a list of SQLSTATE values and MariaDB error codes, see\nMariaDB Error Codes.\n \nThe following procedure tries to query two tables which\ndon\'t exist, producing a 1146 error in both cases. Those\nerrors will trigger the HANDLER. The first time the error\nwill be ignored and the client will not receive it, but the\nsecond time, the error is re-signaled, so the client will\nreceive it.\n \nCREATE PROCEDURE test_error( )\nBEGIN\n DECLARE CONTINUE HANDLER\n FOR 1146\n BEGIN\n IF @hide_errors IS FALSE THEN\n RESIGNAL;\n \n END IF;\n \n END;\n \n SET @hide_errors = TRUE;\n \n SELECT \'Next error will be ignored\' AS msg;\n \n SELECT `c` FROM `temptab_one`;\n \n SELECT \'Next error won\'\'t be ignored\' AS msg;\n \n SET @hide_errors = FALSE;\n \n SELECT `c` FROM `temptab_two`;\n \nEND;\n \nCALL test_error( );\n \n+----------------------------+\n| msg |\n+----------------------------+\n| Next error will be ignored |\n+----------------------------+\n \n+-----------------------------+\n| msg |\n+-----------------------------+\n| Next error won\'t be ignored |\n+-----------------------------+\n \nERROR 1146 (42S02): Table \'test.temptab_two\' doesn\'t\nexist\n \nThe following procedure re-signals an error, modifying only\nthe error message to clarify the cause of the problem.\n \nCREATE PROCEDURE test_error()\nBEGIN\n DECLARE CONTINUE HANDLER\n FOR 1146\n BEGIN\n RESIGNAL SET\n MESSAGE_TEXT = \'`temptab` does not exist\';\n \n END;\n \n SELECT `c` FROM `temptab`;\n \nEND;\n \nCALL test_error( );\nERROR 1146 (42S02): `temptab` does not exist\n \nAs explained above, this works on MariaDB 5.5, but produces\na 1645 error since 10.0.\n \nCREATE PROCEDURE handle_error()\nBEGIN\n RESIGNAL;\n \nEND;\n \nCREATE PROCEDURE p()\nBEGIN\n DECLARE EXIT HANDLER FOR SQLEXCEPTION CALL p();\n SIGNAL SQLSTATE \'45000\';\n \nEND;\n \n\n\nURL: https://mariadb.com/kb/en/resignal/','','https://mariadb.com/kb/en/resignal/'),(319,'SELECT INTO',23,'Syntax\n------ \nSELECT col_name [, col_name] ...\n INTO var_name [, var_name] ...\n table_expr\n \nDescription\n----------- \nSELECT ... INTO enables selected columns to be stored\ndirectly\ninto variables. No resultset is produced. The query should\nreturn a single row. If the query\nreturns no rows, a warning with error code 1329 occurs (No\ndata), and\nthe variable values remain unchanged. If the query returns\nmultiple\nrows, error 1172 occurs (Result consisted of more than one\nrow). If it\nis possible that the statement may retrieve multiple rows,\nyou can use\nLIMIT 1 to limit the result set to a single row.\n \nThe INTO clause can also be specified at the end of the\nstatement.\n \nIn the context of such statements that occur as part of\nevents\nexecuted by the Event Scheduler, diagnostics messages (not\nonly\nerrors, but also warnings) are written to the error log,\nand, on\nWindows, to the application event log.\n \nThis statement can be used with both local variables and\nuser-defined variables.\n \nFor the complete syntax, see SELECT.\n \nAnother way to set a variable\'s value is the SET statement.\n \nSELECT ... INTO results are not stored in the query cache\neven if SQL_CACHE is specified.\n \nExamples\n-------- \nSELECT id, data INTO @x,@y \nFROM test.t1 LIMIT 1;\n \n\n\nURL: https://mariadb.com/kb/en/selectinto/','','https://mariadb.com/kb/en/selectinto/'),(625,'REPEAT Function',37,'Syntax\n------ \nREPEAT(str,count)\n \nDescription\n----------- \nReturns a string consisting of the string str repeated count\ntimes. If\ncount is less than 1, returns an empty string. Returns NULL\nif str or\ncount are NULL.\n \nExamples\n-------- \nSELECT QUOTE(REPEAT(\'MariaDB \',4));\n+------------------------------------+\n| QUOTE(REPEAT(\'MariaDB \',4)) |\n+------------------------------------+\n| \'MariaDB MariaDB MariaDB MariaDB \' |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/repeat-function/','','https://mariadb.com/kb/en/repeat-function/'),(626,'REPLACE Function',37,'Syntax\n------ \nREPLACE(str,from_str,to_str)\n \nDescription\n----------- \nReturns the string str with all occurrences of the string\nfrom_str\nreplaced by the string to_str. REPLACE() performs a\ncase-sensitive\nmatch when searching for from_str.\n \nExamples\n-------- \nSELECT REPLACE(\'www.mariadb.org\', \'w\', \'Ww\');\n+---------------------------------------+\n| REPLACE(\'www.mariadb.org\', \'w\', \'Ww\') |\n+---------------------------------------+\n| WwWwWw.mariadb.org |\n+---------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/replace-function/','','https://mariadb.com/kb/en/replace-function/'),(627,'REVERSE',37,'Syntax\n------ \nREVERSE(str)\n \nDescription\n----------- \nReturns the string str with the order of the characters\nreversed.\n \nExamples\n-------- \nSELECT REVERSE(\'desserts\');\n+---------------------+\n| REVERSE(\'desserts\') |\n+---------------------+\n| stressed |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/reverse/','','https://mariadb.com/kb/en/reverse/'),(628,'RIGHT',37,'Syntax\n------ \nRIGHT(str,len)\n \nDescription\n----------- \nReturns the rightmost len characters from the string str, or\nNULL if\nany argument is NULL.\n \nExamples\n-------- \nSELECT RIGHT(\'MariaDB\', 2);\n+---------------------+\n| RIGHT(\'MariaDB\', 2) |\n+---------------------+\n| DB |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/right/','','https://mariadb.com/kb/en/right/'),(320,'SIGNAL',23,'Syntax\n------ \nSIGNAL error_condition\n [SET error_property\n [, error_property] ...]\n \nerror_condition:\n SQLSTATE [VALUE] \'sqlstate_value\'\n | condition_name\n \nerror_property:\n error_property_name = \n \nerror_property_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n \nSIGNAL empties the diagnostics area and produces a custom\nerror. This statement can be used anywhere, but is generally\nuseful when used inside a stored program. When the error is\nproduced, it can be caught by a HANDLER. If not, the current\nstored program, or the current statement, will terminate\nwith the specified error.\n \nSometimes an error HANDLER just needs to SIGNAL the same\nerror it received, optionally with some changes. Usually the\nRESIGNAL statement is the most convenient way to do this.\n \nerror_condition can be an SQLSTATE value or a named error\ncondition defined via DECLARE CONDITION. SQLSTATE must be a\nconstant string consisting of five characters. These codes\nare standard to ODBC and ANSI SQL. For customized errors,\nthe recommended SQLSTATE is \'45000\'. For a list of\nSQLSTATE values used by MariaDB, see the MariaDB Error Codes\npage. The SQLSTATE can be read via the API method\nmysql_sqlstate( ). \n \nTo specify error properties user-defined variables and local\nvariables can be used, as well as character set conversions\n(but you can\'t set a collation).\n \nThe error properties, their type and their default values\nare explained in the diagnostics area page.\n \nErrors\n \nIf the SQLSTATE is not valid, the following error like this\nwill be produced:\n \nERROR 1407 (42000): Bad SQLSTATE: \'123456\'\n \nIf a property is specified more than once, an error like\nthis will be produced:\n \nERROR 1641 (42000): Duplicate condition information item\n\'MESSAGE_TEXT\'\n \nIf you specify a condition name which is not declared, an\nerror like this will be produced:\n \nERROR 1319 (42000): Undefined CONDITION: cond_name\n \nIf MYSQL_ERRNO is out of range, you will get an error like\nthis:\n \nERROR 1231 (42000): Variable \'MYSQL_ERRNO\' can\'t be set\nto the value of \'0\'\n \nExamples\n-------- \nHere\'s what happens if SIGNAL is used in the client to\ngenerate errors:\n \nSIGNAL SQLSTATE \'01000\';\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+------------------------------------------+\n| Level | Code | Message |\n+---------+------+------------------------------------------+\n| Warning | 1642 | Unhandled user-defined warning condition\n|\n+---------+------+------------------------------------------+\n1 row in set (0.06 sec)\n \nSIGNAL SQLSTATE \'02000\';\n \nERROR 1643 (02000): Unhandled user-defined not found\ncondition\n \nHow to specify MYSQL_ERRNO and MESSAGE_TEXT properties:\n \nSIGNAL SQLSTATE \'45000\' SET MYSQL_ERRNO=30001,\nMESSAGE_TEXT=\'H\nello, world!\';\n \nERROR 30001 (45000): Hello, world!\n \nThe following code shows how to use user variables, local\nvariables and character set conversion with SIGNAL:\n \nCREATE PROCEDURE test_error(x INT)\nBEGIN\n DECLARE errno SMALLINT UNSIGNED DEFAULT 31001;\n \n SET @errmsg = \'Hello, world!\';\n \n IF x = 1 THEN\n SIGNAL SQLSTATE \'45000\' SET\n MYSQL_ERRNO = errno,\n MESSAGE_TEXT = @errmsg;\n \n ELSE\n SIGNAL SQLSTATE \'45000\' SET\n MYSQL_ERRNO = errno,\n MESSAGE_TEXT = _utf8\'Hello, world!\';\n \n END IF;\n \nEND;\n \nHow to use named error conditions:\n \nCREATE PROCEDURE test_error(n INT)\nBEGIN\n DECLARE `too_big` CONDITION FOR SQLSTATE \'45000\';\n \n IF n > 10 THEN\n SIGNAL `too_big`;\n \n END IF;\n \nEND;\n \nIn this example, we\'ll define a HANDLER for an error code.\nWhen the error occurs, we SIGNAL a more informative error\nwhich makes sense for our procedure:\n \nCREATE PROCEDURE test_error()\nBEGIN\n DECLARE EXIT HANDLER\n FOR 1146\n BEGIN\n SIGNAL SQLSTATE \'45000\' SET\n MESSAGE_TEXT = \'Temporary tables not found; did you call\ninit() procedure?\';\n \n END;\n \n -- this will produce a 1146 error\n SELECT `c` FROM `temptab`;\n \nEND;\n \n\n\nURL: https://mariadb.com/kb/en/signal/','','https://mariadb.com/kb/en/signal/'),(325,'LINESTRING',24,'Syntax\n------ \nLineString(pt1,pt2,...)\n \nDescription\n----------- \nConstructs a WKB LineString value from a number of WKB Point\narguments. If any argument is not a WKB Point, the return\nvalue is\nNULL. If the number of Point arguments is less than two, the\nreturn value is NULL.\n \nExamples\n-------- \nSET @ls = \'LineString(1 1,2 2,3 3)\';\n \nSELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n \nCREATE TABLE gis_line (g LINESTRING);\nINSERT INTO gis_line VALUES\n (LineFromText(\'LINESTRING(0 0,0 10,10 0)\')),\n (LineStringFromText(\'LINESTRING(10 10,20 10,20 20,10 20,10\n10)\')),\n (LineStringFromWKB(AsWKB(LineString(Point(10, 10),\nPoint(40, 10)))));\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/linestring/','','https://mariadb.com/kb/en/linestring/'),(632,'SOUNDS LIKE',37,'Syntax\n------ \nexpr1 SOUNDS LIKE expr2\n \nDescription\n----------- \nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n \nExample\n \nSELECT givenname, surname FROM users WHERE givenname SOUNDS\nLIKE \"robert\";\n \n+-----------+---------+\n| givenname | surname |\n+-----------+---------+\n| Roberto | Castro |\n+-----------+---------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sounds-like/','','https://mariadb.com/kb/en/sounds-like/'),(633,'SPACE',37,'Syntax\n------ \nSPACE(N)\n \nDescription\n----------- \nReturns a string consisting of N space characters. If N is\nNULL, returns NULL.\n \nExamples\n-------- \nSELECT QUOTE(SPACE(6));\n+-----------------+\n| QUOTE(SPACE(6)) |\n+-----------------+\n| \' \' |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/space/','','https://mariadb.com/kb/en/space/'),(634,'STRCMP',37,'Syntax\n------ \nSTRCMP(expr1,expr2)\n \nDescription\n----------- \nSTRCMP() returns 0 if the strings are the same, -1 if the\nfirst\nargument is smaller than the second according to the current\nsort order,\nand 1 otherwise.\n \nExamples\n-------- \nSELECT STRCMP(\'text\', \'text2\');\n+-------------------------+\n| STRCMP(\'text\', \'text2\') |\n+-------------------------+\n| -1 |\n+-------------------------+\n \nSELECT STRCMP(\'text2\', \'text\');\n+-------------------------+\n| STRCMP(\'text2\', \'text\') |\n+-------------------------+\n| 1 |\n+-------------------------+\n \nSELECT STRCMP(\'text\', \'text\');\n+------------------------+\n| STRCMP(\'text\', \'text\') |\n+------------------------+\n| 0 |\n+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/strcmp/','','https://mariadb.com/kb/en/strcmp/'),(635,'SUBSTR',37,'Description\n----------- \nSUBSTR() is a synonym for SUBSTRING().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/substr/','','https://mariadb.com/kb/en/substr/'),(640,'UCASE',37,'Syntax\n------ \nUCASE(str)\n \nDescription\n----------- \nUCASE() is a synonym for UPPER().\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ucase/','','https://mariadb.com/kb/en/ucase/'),(643,'UPPER',37,'Syntax\n------ \nUPPER(str)\n \nDescription\n----------- \nReturns the string str with all characters changed to\nuppercase\naccording to the current character set mapping. The default\nis latin1\n(cp1252 West European).\n \nSELECT UPPER(surname), givenname FROM users ORDER BY\nsurname;\n \n+----------------+------------+\n| UPPER(surname) | givenname |\n+----------------+------------+\n| ABEL | Jacinto |\n| CASTRO | Robert |\n| COSTA | Phestos |\n| MOSCHELLA | Hippolytos |\n+----------------+------------+\n \nUPPER() is ineffective when applied to binary strings\n(BINARY,\nVARBINARY, BLOB). The description of \nLOWER() shows how to\nperform lettercase conversion of binary strings.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/upper/','','https://mariadb.com/kb/en/upper/'),(331,'POLYGON',24,'Syntax\n------ \nPolygon(ls1,ls2,...)\n \nDescription\n----------- \nConstructs a WKB Polygon value from a number of WKB\nLineString\narguments. If any argument does not represent the WKB of a\nLinearRing (that is,\nnot a closed and simple LineString) the return value is\nNULL.\n \nNote that according to the OpenGIS standard, a POLYGON\nshould have exactly one ExteriorRing and all other rings\nshould lie within that ExteriorRing and thus be the\nInteriorRings. Practically, however, some systems, including\nMariaDB\'s, permit polygons to have several\n\'ExteriorRings\'. In the case of there being multiple,\nnon-overlapping exterior rings ST_NUMINTERIORRINGS() will\nreturn 1.\n \nExamples\n-------- \nSET @g = ST_GEOMFROMTEXT(\'POLYGON((1 1,1 5,4 9,6 9,9 3,7\n2,1 1))\');\n \nCREATE TABLE gis_polygon (g POLYGON);\nINSERT INTO gis_polygon VALUES\n (PolygonFromText(\'POLYGON((10 10,20 10,20 20,10 20,10\n10))\')),\n (PolyFromText(\'POLYGON((0 0,50 0,50 50,0 50,0 0), (10\n10,20 10,20 20,10 20,10 10))\')),\n (PolyFromWKB(AsWKB(Polygon(LineString(Point(0, 0),\nPoint(30, 0), Point(30, 30), Point(0, 0))))));\n \nNon-overlapping \'polygon\':\n \nSELECT ST_NumInteriorRings(ST_PolyFromText(\'POLYGON((0 0,10\n0,10 10,0 10,0 0),\n (-1 -1,-5 -1,-5 -5,-1 -5,-1 -1))\')) AS NumInteriorRings;\n \n+------------------+\n| NumInteriorRings |\n+------------------+\n| 1 |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/polygon/','','https://mariadb.com/kb/en/polygon/'),(332,'ST_BUFFER',24,'Syntax\n------ \nST_BUFFER(g1,r)\nBUFFER(g1,r)\n \nDescription\n----------- \nReturns a geometry that represents all points whose distance\nfrom geometry g1 is less than or equal to distance, or\nradius, r.\n \nUses for this function could include creating for example a\nnew geometry representing a buffer zone around an island.\n \nBUFFER() is a synonym.\n \nExamples\n-------- \nDetermining whether a point is within a buffer zone:\n \nSET @g1 = ST_GEOMFROMTEXT(\'POLYGON((10 10, 10 20, 20 20, 20\n10, 10 10))\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'POINT(8 8)\');\n \nSELECT ST_WITHIN(@g2,ST_BUFFER(@g1,5));\n+---------------------------------+\n| ST_WITHIN(@g2,ST_BUFFER(@g1,5)) |\n+---------------------------------+\n| 1 |\n+---------------------------------+\n \nSELECT ST_WITHIN(@g2,ST_BUFFER(@g1,1));\n+---------------------------------+\n| ST_WITHIN(@g2,ST_BUFFER(@g1,1)) |\n+---------------------------------+\n| 0 |\n+---------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_buffer/','','https://mariadb.com/kb/en/st_buffer/'),(333,'ST_CONVEXHULL',24,'ST_ConvexHull() was introduced in MariaDB 10.1.2\n \nSyntax\n------ \nST_ConvexHull(g)\nConvexHull(g)\n \nDescription\n----------- \nGiven a geometry, returns a geometry that is the minimum\nconvex geometry enclosing all geometries within the set.\nReturns NULL if the geometry value is NULL or an empty\nvalue.\n \nST_ConvexHull() and ConvexHull() are synonyms.\n \nExamples\n-------- \nThe ConvexHull of a single point is simply the single point:\n \nSET @g = ST_GEOMFROMTEXT(\'Point(0 0)\');\n \nSELECT ST_ASTEXT(ST_CONVEXHULL(@g));\n+------------------------------+\n| ST_ASTEXT(ST_CONVEXHULL(@g)) |\n+------------------------------+\n| POINT(0 0) |\n+------------------------------+\n \nSET @g = ST_GEOMFROMTEXT(\'MultiPoint(0 0, 1 2, 2 3)\');\n \nSELECT ST_ASTEXT(ST_CONVEXHULL(@g));\n+------------------------------+\n| ST_ASTEXT(ST_CONVEXHULL(@g)) |\n+------------------------------+\n| POLYGON((0 0,1 2,2 3,0 0)) |\n+------------------------------+\n \nSET @g = ST_GEOMFROMTEXT(\'MultiPoint( 1 1, 2 2, 5 3, 7 2, 9\n3, 8 4, 6 6, 6 9, 4 9, 1 5 )\');\n \nSELECT ST_ASTEXT(ST_CONVEXHULL(@g));\n+----------------------------------------+\n| ST_ASTEXT(ST_CONVEXHULL(@g)) |\n+----------------------------------------+\n| POLYGON((1 1,1 5,4 9,6 9,9 3,7 2,1 1)) |\n+----------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_convexhull/','','https://mariadb.com/kb/en/st_convexhull/'),(336,'ST_SYMDIFFERENCE',24,'Syntax\n------ \nST_SYMDIFFERENCE(g1,g2)\n \nDescription\n----------- \nReturns a geometry that represents the portions of geometry\ng1 and geometry g2 that don\'t intersect.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'LINESTRING(10 20, 10 40)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(10 15, 10 25)\');\n \nSELECT ASTEXT(ST_SYMDIFFERENCE(@g1,@g2));\n+----------------------------------------------+\n| ASTEXT(ST_SYMDIFFERENCE(@g1,@g2)) |\n+----------------------------------------------+\n| MULTILINESTRING((10 15,10 20),(10 25,10 40)) |\n+----------------------------------------------+\n \nSET @g2 = ST_GeomFromText(\'LINESTRING(10 20, 10 41)\');\n \nSELECT ASTEXT(ST_SYMDIFFERENCE(@g1,@g2));\n+-----------------------------------+\n| ASTEXT(ST_SYMDIFFERENCE(@g1,@g2)) |\n+-----------------------------------+\n| LINESTRING(10 40,10 41) |\n+-----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_symdifference/','','https://mariadb.com/kb/en/st_symdifference/'),(337,'ST_UNION',24,'Syntax\n------ \nST_UNION(g1,g2)\n \nDescription\n----------- \nReturns a geometry that is the union of the geometry g1 and\ngeometry g2.\n \nExamples\n-------- \nSET @g1 = GEOMFROMTEXT(\'POINT (0 2)\');\n \nSET @g2 = GEOMFROMTEXT(\'POINT (2 0)\');\n \nSELECT ASTEXT(ST_UNION(@g1,@g2));\n+---------------------------+\n| ASTEXT(ST_UNION(@g1,@g2)) |\n+---------------------------+\n| MULTIPOINT(2 0,0 2) |\n+---------------------------+\n \nSET @g1 = GEOMFROMTEXT(\'POLYGON((0 0,0 3,3 3,3 0,0 0))\');\n \nSET @g2 = GEOMFROMTEXT(\'POLYGON((2 2,4 2,4 4,2 4,2 2))\');\n \nSELECT ASTEXT(ST_UNION(@g1,@g2));\n+------------------------------------------------+\n| ASTEXT(ST_UNION(@g1,@g2)) |\n+------------------------------------------------+\n| POLYGON((0 0,0 3,2 3,2 4,4 4,4 2,3 2,3 0,0 0)) |\n+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_union/','','https://mariadb.com/kb/en/st_union/'),(648,'ALTER LOGFILE GROUP',39,'Syntax\n------ \nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n \nThe ALTER LOGFILE GROUP statement is not supported by\nMariaDB. It was originally inherited from MySQL NDB Cluster.\nSee MDEV-19295 for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/alter-logfile-group/','','https://mariadb.com/kb/en/alter-logfile-group/'),(651,'ALTER SERVER',39,'Syntax\n------ \nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n \nDescription\n----------- \nAlters the server information for server_name, adjusting the\nspecified\noptions as per the CREATE SERVER command. The corresponding\nfields in the mysql.servers table are updated accordingly.\nThis statement requires the SUPER privilege.\n \nExamples\n-------- \nALTER SERVER s OPTIONS (USER \'sally\');\n \n\n\nURL: https://mariadb.com/kb/en/alter-server/','','https://mariadb.com/kb/en/alter-server/'),(652,'ALTER TABLE',39,'Syntax\n------ \nALTER [ONLINE] [IGNORE] TABLE tbl_name\n [WAIT n | NOWAIT]\n alter_specification [, alter_specification] ...\n \nalter_specification:\n table_option ...\n | ADD [COLUMN] [IF NOT EXISTS] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] [IF NOT EXISTS] (col_name\ncolumn_definition,...)\n | ADD {INDEX|KEY} [IF NOT EXISTS] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [IF NOT EXISTS] [index_name]\n(index_col_name,...)\n reference_definition\n | ADD PERIOD FOR SYSTEM_TIME (start_column_name,\nend_column_name)\n | ALTER [COLUMN] col_name SET DEFAULT literal\n| (expression)\n | ALTER [COLUMN] col_name DROP DEFAULT\n | CHANGE [COLUMN] [IF EXISTS] old_col_name new_col_name\ncolumn_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] [IF EXISTS] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] [IF EXISTS] col_name [RESTRICT|CASCADE]\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} [IF EXISTS] index_name\n | DROP FOREIGN KEY [IF EXISTS] fk_symbol\n | DROP CONSTRAINT [IF EXISTS] constraint_name\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE\ncollation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | ALGORITHM [=] {DEFAULT|INPLACE|COPY|NOCOPY|INSTANT}\n | LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n | FORCE\n | partition_options\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO\n(partition_definitions)]\n | ANALYZE PARTITION partition_names\n | CHECK PARTITION partition_names\n | OPTIMIZE PARTITION partition_names\n | REBUILD PARTITION partition_names\n | REPAIR PARTITION partition_names\n | EXCHANGE PARTITION partition_name WITH TABLE tbl_name\n | REMOVE PARTITIONING\n | ADD SYSTEM VERSIONING\n | DROP SYSTEM VERSIONING\n \nindex_col_name:\n col_name [(length)] [ASC | DESC]\n \nindex_type:\n USING {BTREE | HASH | RTREE}\n \nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | CLUSTERING={YES| NO}\n \ntable_options:\n table_option [[,] table_option] ...\nIn MariaDB 10.0.2 and later, IF EXISTS and IF NOT EXISTS\nclauses have been added for the following:\n \nADD COLUMN [IF NOT EXISTS]\nADD INDEX [IF NOT EXISTS]\nADD FOREIGN KEY [IF NOT EXISTS]\nADD PARTITION [IF NOT EXISTS]\nCREATE INDEX [IF NOT EXISTS]\n \nDROP COLUMN [IF EXISTS]\nDROP INDEX [IF EXISTS]\nDROP FOREIGN KEY [IF EXISTS]\nDROP PARTITION [IF EXISTS]\nCHANGE COLUMN [IF EXISTS]\nMODIFY COLUMN [IF EXISTS]\nDROP INDEX [IF EXISTS]\nWhen IF EXISTS and IF NOT EXISTS are used in clauses,\nqueries will not\nreport errors when the condition is triggered for that\nclause. A warning with\nthe same message text will be issued and the ALTER will move\non to the next\nclause in the statement (or end if finished).\n \nThis was done in MDEV-318.\n \nDescription\n----------- \nALTER TABLE enables you to change the structure of an\nexisting table.\nFor example, you can add or delete columns, create or\ndestroy indexes,\nchange the type of existing columns, or rename columns or\nthe table\nitself. You can also change the comment for the table and\nthe storage engine of the\ntable.\n \nIf another connection is using the table, a metadata lock is\nactive, and this statement will wait until the lock is\nreleased. This is also true for non-transactional tables.\n \nWhen adding a UNIQUE index on a column (or a set of columns)\nwhich have duplicated values, an error will be produced and\nthe statement will be stopped. To suppress the error and\nforce the creation of UNIQUE indexes, discarding duplicates,\nthe IGNORE option can be specified. This can be useful if a\ncolumn (or a set of columns) should be UNIQUE but it\ncontains duplicate values; however, this technique provides\nno control on which rows are preserved and which are\ndeleted. Also, note that IGNORE is accepted but ignored in\nALTER TABLE ... EXCHANGE PARTITION statements.\n \nThis statement can also be used to rename a table. For\ndetails see RENAME TABLE.\n \nWhen an index is created, the storage engine may use a\nconfigurable buffer in the process. Incrementing the buffer\nspeeds up the index creation. Aria and MyISAM allocate a\nbuffer whose size is defined by aria_sort_buffer_size or\nmyisam_sort_buffer_size, also used for REPAIR TABLE.\nInnoDB/XtraDB allocates three buffers whose size is defined\nby innodb_sort_buffer_size.\n \nPrivileges\n \nExecuting the ALTER TABLE statement generally requires at\nleast the ALTER privilege for the table or the database..\n \nIf you are renaming a table, then it also requires the DROP,\nCREATE and INSERT privileges for the table or the database\nas well.\n \nOnline DDL\n \nIn MariaDB 10.0 and later, online DDL is supported with the\nALGORITHM and LOCK clauses.\n \nSee InnoDB Online DDL Overview for more information on\nonline DDL with InnoDB.\n \nALTER ONLINE TABLE\n \nALTER ONLINE TABLE has also worked for partitioned tables\nsince MariaDB 10.0.11.\n \nOnline ALTER TABLE is available by executing the following:\n \nALTER ONLINE TABLE ...;\n \nThis statement has the following semantics:\n \nIn MariaDB 10.0.12 and later, this statement is equivalent\nto the following:\n \nALTER TABLE ... LOCK=NONE;\n \nSee the LOCK alter specification for more information.\n \nIn MariaDB 10.0.11, this statement is equivalent to the\nfollowing:\n \nALTER TABLE ... ALGORITHM=INPLACE;\n \nSee the ALGORITHM alter specification for more information.\n \nMariaDB until 10.0.10\n \nIn MariaDB 10.0.10 and before, this statement ensures that\nthe ALTER TABLE statement does not make a copy of the table.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nColumn Definitions\n \nSee CREATE TABLE: Column Definitions for information about\ncolumn definitions.\n \nIndex Definitions\n \nSee CREATE TABLE: Index Definitions for information about\nindex definitions.\n \nThe CREATE INDEX and DROP INDEX statements can also be used\nto add or remove an index.\n \nCharacter Sets and Collations\n \nCONVERT TO CHARACTER SET charset_name [COLLATE\ncollation_name]\n[DEFAULT] CHARACTER SET [=] charset_name\n[DEFAULT] COLLATE [=] collation_name\nSee Setting Character Sets and Collations for details on\nsetting the character sets and collations.\n \nAlter Specifications\n \nTable Options\n \nSee CREATE TABLE: Table Options for information about table\noptions.\n \nADD COLUMN\n \n... ADD COLUMN [IF NOT EXISTS] (col_name\ncolumn_definition,...)\nAdds a column to the table. The syntax is the same as in\nCREATE TABLE.\nIf you are using IF NOT_EXISTS the column will not be added\nif it was not there already. This is very useful when doing\nscripts to modify tables.\n \nThe FIRST and AFTER clauses affect the physical order of\ncolumns in the datafile. Use FIRST to add a column in the\nfirst (leftmost) position, or AFTER followed by a column\nname to add the new column in any other position. Note that,\nnowadays, the physical position of a column is usually\nirrelevant.\n \nSee also Instant ADD COLUMN for InnoDB.\n \nDROP COLUMN\n \n... DROP COLUMN [IF EXISTS] col_name [CASCADE|RESTRICT]\nDrops the column from the table.\nIf you are using IF EXISTS you will not get an error if the\ncolumn didn\'t exist.\nIf the column is part of any index, the column will be\ndropped from them, except if you add a new column with\nidentical name at the same time. The index will be dropped\nif all columns from the index were dropped.\nIf the column was used in a view or trigger, you will get an\nerror next time the view or trigger is accessed.\n \nDropping a column that is part of a multi-column UNIQUE\nconstraint is not permitted. For example:\n \nCREATE TABLE a (\n a int,\n b int,\n primary key (a,b)\n);\n \nALTER TABLE x DROP COLUMN a;\n[42000][1072] Key column \'A\' doesn\'t exist in table\n \nThe reason is that dropping column a would result in the new\nconstraint that all values in column b be unique. In order\nto drop the column, an explicit DROP PRIMARY KEY and ADD\nPRIMARY KEY would be required. Up until MariaDB 10.2.7, the\ncolumn was dropped and the additional constraint applied,\nresulting in the following structure:\n \nALTER TABLE x DROP COLUMN a;\nQuery OK, 0 rows affected (0.46 sec)\n \nDESC x;\n+-------+---------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+---------+------+-----+---------+-------+\n| b | int(11) | NO | PRI | NULL | |\n+-------+---------+------+-----+---------+-------+\n \nMariaDB 10.4.0 supports instant DROP COLUMN. DROP COLUMN of\nan indexed column would imply DROP INDEX (and in the case of\na non-UNIQUE multi-column index, possibly ADD INDEX). These\nwill not be allowed with ALGORITHM=INSTANT, but unlike\nbefore, they can be allowed with ALGORITHM=NOCOPY\n \nRESTRICT and CASCADE are allowed to make porting from other\ndatabase systems easier. In MariaDB, they do nothing.\n \nMODIFY COLUMN\n \nAllows you to modify the type of a column. The column will\nbe at the same place as the original column and all indexes\non the column will be kept. Note that when modifying column,\nyou should specify all attributes for the new column.\n \nCREATE TABLE t1 (a INT UNSIGNED AUTO_INCREMENT, PRIMARY\nKEY((a));\nALTER TABLE t1 MODIFY a BIGINT UNSIGNED AUTO_INCREMENT;\n \nCHANGE COLUMN\n \nWorks like MODIFY COLUMN except that you can also change the\nname of the column. The column will be at the same place as\nthe original column and all index on the column will be\nkept.\n \nCREATE TABLE t1 (a INT UNSIGNED AUTO_INCREMENT, PRIMARY\nKEY(a));\nALTER TABLE t1 CHANGE a b BIGINT UNSIGNED AUTO_INCREMENT;\n \nALTER COLUMN\n \nThis lets you change column options.\n \nCREATE TABLE t1 (a INT UNSIGNED AUTO_INCREMENT, b\nvarchar(50), PRIMARY KEY(a));\nALTER TABLE t1 ALTER b SET DEFAULT \'hello\';\n \nADD PRIMARY KEY\n \nAdd a primary key.\n \nFor PRIMARY KEY indexes, you can specify a name for the\nindex, but it is silently ignored, and the name of the index\nis always PRIMARY.\n \nSee Getting Started with Indexes: Primary Key for more\ninformation.\n \nDROP PRIMARY KEY\n \nDrop a primary key.\n \nFor PRIMARY KEY indexes, you can specify a name for the\nindex, but it is silently ignored, and the name of the index\nis always PRIMARY.\n \nSee Getting Started with Indexes: Primary Key for more\ninformation.\n \nADD FOREIGN KEY\n \nAdd a foreign key.\n \nFor FOREIGN KEY indexes, a reference definition must be\nprovided.\n \nFor FOREIGN KEY indexes, you can specify a name for the\nconstraint, using the CONSTRAINT keyword. That name will be\nused in error messages.\n \nFirst, you have to specify the name of the target (parent)\ntable and a column or a column list which must be indexed\nand whose values must match to the foreign key\'s values.\nThe MATCH clause is accepted to improve the compatibility\nwith other DBMS\'s, but has no meaning in MariaDB. The ON\nDELETE and ON UPDATE clauses specify what must be done when\na DELETE (or a REPLACE) statements attempts to delete a\nreferenced row from the parent table, and when an UPDATE\nstatement attempts to modify the referenced foreign key\ncolumns in a parent table row, respectively. The following\noptions are allowed:\nRESTRICT: The delete/update operation is not performed. The\nstatement terminates with a 1451 error (SQLSTATE \'2300\').\nNO ACTION: Synonym for RESTRICT.\nCASCADE: The delete/update operation is performed in both\ntables.\nSET NULL: The update or delete goes ahead in the parent\ntable, and the corresponding foreign key fields in the child\ntable are set to NULL. (They must not be defined as NOT NULL\nfor this to succeed).\n \nMariaDB until 5.3\nSET DEFAULT: This option is currently implemented only for\nthe PBXT storage engine, which is disabled by default and no\nlonger maintained. It sets the child table\'s foreign key\nfields to their DEFAULT values when the referenced parent\ntable key entries are updated or deleted.\n \nIf either clause is omitted, the default behavior for the\nomitted clause is RESTRICT.\n \nSee Foreign Keys for more information.\n \nDROP FOREIGN KEY\n \nDrop a foreign key.\n \nSee Foreign Keys for more information.\n \nADD INDEX\n \nAdd a plain index.\n \nPlain indexes are regular indexes that are not unique, and\nare not acting as a primary key or a foreign key. They are\nalso not the \"specialized\" FULLTEXT or SPATIAL indexes.\n \nSee Getting Started with Indexes: Plain Indexes for more\ninformation.\n \nDROP INDEX\n \nDrop a plain index.\n \nPlain indexes are regular indexes that are not unique, and\nare not acting as a primary key or a foreign key. They are\nalso not the \"specialized\" FULLTEXT or SPATIAL indexes.\n \nSee Getting Started with Indexes: Plain Indexes for more\ninformation.\n \nADD UNIQUE INDEX\n \nAdd a unique index.\n \nThe UNIQUE keyword means that the index will not accept\nduplicated values, except for NULLs. An error will raise if\nyou try to insert duplicate values in a UNIQUE index.\n \nFor UNIQUE indexes, you can specify a name for the\nconstraint, using the CONSTRAINT keyword. That name will be\nused in error messages.\n \nSee Getting Started with Indexes: Unique Index for more\ninformation.\n \nDROP UNIQUE INDEX\n \nDrop a unique index.\n \nThe UNIQUE keyword means that the index will not accept\nduplicated values, except for NULLs. An error will raise if\nyou try to insert duplicate values in a UNIQUE index.\n \nFor UNIQUE indexes, you can specify a name for the\nconstraint, using the CONSTRAINT keyword. That name will be\nused in error messages.\n \nSee Getting Started with Indexes: Unique Index for more\ninformation.\n \nADD FULLTEXT INDEX\n \nAdd a FULLTEXT index.\n \nSee Full-Text Indexes for more information.\n \nDROP FULLTEXT INDEX\n \nDrop a FULLTEXT index.\n \nSee Full-Text Indexes for more information.\n \nADD SPATIAL INDEX\n \nAdd a SPATIAL index.\n \nSee SPATIAL INDEX for more information.\n \nDROP SPATIAL INDEX\n \nDrop a SPATIAL index.\n \nSee SPATIAL INDEX for more information.\n \nENABLE/ DISABLE KEYS\n \nDISABLE KEYS will disable all non unique keys for the table\nfor storage engines that support this (at least MyISAM and\nAria). This can be used to speed up inserts into empty\ntables.\n \nENABLE KEYS will enable all disabled keys.\n \nRENAME TO\n \nRenames the table. See also RENAME TABLE.\n \nADD CONSTRAINT\n \nModifies the table adding a constraint on a particular\ncolumn or columns.\n \nMariaDB 10.2.1 introduced new ways to define a constraint.\n \nNote: Before MariaDB 10.2.1, constraint expressions were\naccepted in syntax, but ignored.\n \nALTER TABLE table_name \nADD CONSTRAINT [constraint_name] CHECK(expression);\nBefore a row is inserted or updated, all constraints are\nevaluated in the order they are defined. If any constraint\nfails, then the row will not be updated. One can use most\ndeterministic functions in a constraint, including UDF\'s.\n \nCREATE TABLE account_ledger (\n id INT PRIMARY KEY AUTO_INCREMENT,\n transaction_name VARCHAR(100),\n credit_account VARCHAR(100),\n credit_amount INT,\n debit_account VARCHAR(100),\n debit_amount INT);\n \nALTER TABLE account_ledger \nADD CONSTRAINT is_balanced \n CHECK((debit_amount + credit_amount) = 0);\n \nThe constraint_name is optional. If you don\'t provide one\nin the ALTER TABLE statement, MariaDB auto-generates a name\nfor you. This is done so that you can remove it later using\nDROP CONSTRAINT clause.\n \nYou can disable all constraint expression checks by setting\nthe variable check_constraint_checks to OFF. You may find\nthis useful when loading a table that violates some\nconstraints that you want to later find and fix in SQL.\n \nTo view constraints on a table, query\ninformation_schema.TABLE_CONSTRAINTS:\n \nSELECT CONSTRAINT_NAME, TABLE_NAME, CONSTRAINT_TYPE \nFROM information_schema.TABLE_CONSTRAINTS\nWHERE TABLE_NAME = \'account_ledger\';\n \n+-----------------+----------------+-----------------+\n| CONSTRAINT_NAME | TABLE_NAME | CONSTRAINT_TYPE |\n+-----------------+----------------+-----------------+\n| is_balanced | account_ledger | CHECK |\n+-----------------+----------------+-----------------+\n \nDROP CONSTRAINT\n \nDROP CONSTRAINT for UNIQUE and FOREIGN KEY constraints was\nintroduced in MariaDB 10.2.22 and MariaDB 10.3.13.\n \nDROP CONSTRAINT for CHECK constraints was introduced in\nMariaDB 10.2.1\n \nModifies the table, removing the given constraint.\n \nALTER TABLE table_name\nDROP CONSTRAINT constraint_name;\n \nWhen you add a constraint to a table, whether through a\nCREATE TABLE or ALTER TABLE...ADD CONSTRAINT statement, you\ncan either set a constraint_name yourself, or allow MariaDB\nto auto-generate one for you. To view constraints on a\ntable, query information_schema.TABLE_CONSTRAINTS. For\ninstance,\n \nCREATE TABLE t (\n a INT,\n b INT,\n c INT,\n CONSTRAINT CHECK(a > b),\n CONSTRAINT check_equals CHECK(a = c)); \n \nSELECT CONSTRAINT_NAME, TABLE_NAME, CONSTRAINT_TYPE \nFROM information_schema.TABLE_CONSTRAINTS\nWHERE TABLE_NAME = \'t\';\n \n+-----------------+----------------+-----------------+\n| CONSTRAINT_NAME | TABLE_NAME | CONSTRAINT_TYPE |\n+-----------------+----------------+-----------------+\n| check_equals | t | CHECK |\n| CONSTRAINT_1 | t | CHECK |\n+-----------------+----------------+-----------------+\n \nTo remove a constraint from the table, issue an ALTER\nTABLE...DROP CONSTRAINT statement. For example,\n \nALTER TABLE t DROP CONSTRAINT is_unique;\n \nADD SYSTEM VERSIONING\n \nSystem-versioned tables was added in MariaDB 10.3.4.\n \nAdd system versioning.\n \nDROP SYSTEM VERSIONING\n \nSystem-versioned tables was added in MariaDB 10.3.4.\n \nDrop system versioning.\n \nADD PERIOD FOR SYSTEM_TIME\n \nSystem-versioned tables was added in MariaDB 10.3.4.\n \nFORCE\n \nALTER TABLE ... FORCE can force MariaDB to re-build the\ntable.\n \nIn MariaDB 5.5 and before, this could only be done by\nsetting the ENGINE table option to its old value. For\nexample, for an InnoDB table, one could execute the\nfollowing:\n \nALTER TABLE tab_name ENGINE = InnoDB;\n \nIn MariaDB 10.0 and later, the FORCE option can be used\ninstead. For example, :\n \nALTER TABLE tab_name FORCE;\n \nWith InnoDB, the table rebuild will only reclaim unused\nspace (i.e. the space previously used for deleted rows) if\nthe innodb_file_per_table system variable is set to ON. If\nthe system variable is OFF, then the space will not be\nreclaimed, but it will be-re-used for new data that\'s later\nadded.\n \nEXCHANGE PARTITION\n \nALTER TABLE ... EXCHANGE PARTITION was introduced in MariaDB\n10.0.4\n \nThis is used to exchange the tablespace files between a\npartition and another table.\n \nSee copying InnoDB\'s transportable tablespaces for more\ninformation.\n \nDISCARD TABLESPACE\n \nThis is used to discard an InnoDB table\'s tablespace.\n \nSee copying InnoDB\'s transportable tablespaces for more\ninformation.\n \nIMPORT TABLESPACE\n \nThis is used to import an InnoDB table\'s tablespace. The\ntablespace should have been copied from its original server\nafter executing FLUSH TABLES FOR EXPORT.\n \nSee copying InnoDB\'s transportable tablespaces for more\ninformation.\n \nALTER TABLE ... IMPORT only applies to InnoDB tables. Most\nother popular storage engines, such as Aria and MyISAM, will\nrecognize their data files as soon as they\'ve been placed\nin the proper directory under the datadir, and no special\nDDL is required to import them.\n \nALGORITHM\n \nIn MariaDB 5.5 and before, ALTER TABLE operations required\nmaking a temporary copy of the table, which can be slow for\nlarge tables.\n \nIn MariaDB 10.0 and later, the ALTER TABLE statement\nsupports the ALGORITHM clause. This clause is one of the\nclauses that is used to implement online DDL. ALTER TABLE\nsupports several different algorithms. An algorithm can be\nexplicitly chosen for an ALTER TABLE operation by setting\nthe ALGORITHM clause. The supported values are:\nALGORITHM=DEFAULT - This implies the default behavior for\nthe specific statement, such as if no ALGORITHM clause is\nspecified.\nALGORITHM=COPY\nALGORITHM=INPLACE\nALGORITHM=NOCOPY - This was added in MariaDB 10.3.7.\nALGORITHM=INSTANT - This was added in MariaDB 10.3.7.\n \nSee InnoDB Online DDL Overview: ALGORITHM for information on\nhow the ALGORITHM clause affects InnoDB.\n \nALGORITHM=DEFAULT\n \nThe default behavior, which occurs if ALGORITHM=DEFAULT is\nspecified, or if ALGORITHM is not specified at all, usually\nonly makes a copy if the operation doesn\'t support being\ndone in-place at all. In this case, the most efficient\navailable algorithm will usually be used.\n \nHowever, in MariaDB 10.3.6 and before, if the value of the\nold_alter_table system variable is set to ON, then the\ndefault behavior is to perform ALTER TABLE operations by\nmaking a copy of the table using the old algorithm.\n \nIn MariaDB 10.3.7 and later, the old_alter_table system\nvariable is deprecated. Instead, the alter_algorithm system\nvariable defines the default algorithm for ALTER TABLE\noperations.\n \nALGORITHM=COPY\n \nALGORITHM=COPY was introduced in MariaDB 10.0 as the name\nfor the original ALTER TABLE algorithm.\n \nWhen ALGORITHM=COPY is set, MariaDB essentially does the\nfollowing operations:\n \n-- Create a temporary table with the new definition\nCREATE TEMPORARY TABLE tmp_tab (\n...\n);\n \n-- Copy the data from the original table\nINSERT INTO tmp_tab\n SELECT * FROM original_tab;\n \n-- Drop the original table\nDROP TABLE original_tab;\n \n-- Rename the temporary table, so that it replaces the\noriginal one\nRENAME TABLE tmp_tab TO original_tab;\n \nThis algorithm is very inefficient, but it is generic, so it\nworks for all storage engines.\n \nIf ALGORITHM=COPY is specified, then the copy algorithm will\nbe used even if it is not necessary. This can result in a\nlengthy table copy. If multiple ALTER TABLE operations are\nrequired that each require the table to be rebuilt, then it\nis best to specify all operations in a single ALTER TABLE\nstatement, so that the table is only rebuilt once.\n \nALGORITHM=INPLACE\n \nALGORITHM=INPLACE was introduced in MariaDB 10.0.\n \nALGORITHM=COPY can be incredibly slow, because the whole\ntable has to be copied and rebuilt. ALGORITHM=INPLACE was\nintroduced as a way to avoid this by performing operations\nin-place and avoiding the table copy and rebuild, when\npossible.\n \nWhen ALGORITHM=INPLACE is set, the underlying storage engine\nuses optimizations to perform the operation while avoiding\nthe table copy and rebuild. However, INPLACE is a bit of a\nmisnomer, since some operations may still require the table\nto be rebuilt for some storage engines. Regardless, several\noperations can be performed without a full copy of the table\nfor some storage engines.\n \nA more accurate name would have been ALGORITHM=ENGINE, where\nENGINE refers to an \"engine-specific\" algorithm.\n \nIf an ALTER TABLE operation supports ALGORITHM=INPLACE, then\nit can be performed using optimizations by the underlying\nstorage engine, but it may rebuilt.\n \nSee InnoDB Online DDL Operations with ALGORITHM=INPLACE for\nmore.\n \nALGORITHM=NOCOPY\n \nALGORITHM=NOCOPY was introduced in MariaDB 10.3.7.\n \nALGORITHM=INPLACE can sometimes be surprisingly slow in\ninstances where it has to rebuild the clustered index,\nbecause when the clustered index has to be rebuilt, the\nwhole table has to be rebuilt. ALGORITHM=NOCOPY was\nintroduced as a way to avoid this. \n \nIf an ALTER TABLE operation supports ALGORITHM=NOCOPY, then\nit can be performed without rebuilding the clustered index.\n \nIf ALGORITHM=NOCOPY is specified for an ALTER TABLE\noperation that does not support ALGORITHM=NOCOPY, then an\nerror will be raised. In this case, raising an error is\npreferable, if the alternative is for the operation to\nrebuild the clustered index, and perform unexpectedly\nslowly.\n \nSee InnoDB Online DDL Operations with ALGORITHM=NOCOPY for\nmore.\n \nALGORITHM=INSTANT\n \nALGORITHM=INSTANT was introduced in MariaDB 10.3.7.\n \nALGORITHM=INPLACE can sometimes be surprisingly slow in\ninstances where it has to modify data files.\nALGORITHM=INSTANT was introduced as a way to avoid this.\n \nIf an ALTER TABLE operation supports ALGORITHM=INSTANT, then\nit can be performed without modifying any data files.\n \nIf ALGORITHM=INSTANT is specified for an ALTER TABLE\noperation that does not support ALGORITHM=INSTANT, then an\nerror will be raised. In this case, raising an error is\npreferable, if the alternative is for the operation to\nmodify data files, and perform unexpectedly slowly.\n \nSee InnoDB Online DDL Operations with ALGORITHM=INSTANT for\nmore.\n \nLOCK\n \nIn MariaDB 10.0 and later, the ALTER TABLE statement\nsupports the LOCK clause. This clause is one of the clauses\nthat is used to implement online DDL. ALTER TABLE supports\nseveral different locking strategies. A locking strategy can\nbe explicitly chosen for an ALTER TABLE operation by setting\nthe LOCK clause. The supported values are:\nDEFAULT: Acquire the least restrictive lock on the table\nthat is supported for the specific operation. Permit the\nmaximum amount of concurrency that is supported for the\nspecific operation.\nNONE: Acquire no lock on the table. Permit all concurrent\nDML. If this locking strategy is not permitted for an\noperation, then an error is raised.\nSHARED: Acquire a read lock on the table. Permit read-only\nconcurrent DML. If this locking strategy is not permitted\nfor an operation, then an error is raised.\nEXCLUSIVE: Acquire a write lock on the table. Do not permit\nconcurrent DML.\n \nDifferent storage engines support different locking\nstrategies for different operations. If a specific locking\nstrategy is chosen for an ALTER TABLE operation, and that\ntable\'s storage engine does not support that locking\nstrategy for that specific operation, then an error will be\nraised.\n \nIf the LOCK clause is not explicitly set, then the operation\nuses LOCK=DEFAULT.\n \nALTER ONLINE TABLE is equivalent to LOCK=NONE. Therefore,\nthe ALTER ONLINE TABLE statement can be used to ensure that\nyour ALTER TABLE operation allows all concurrent DML.\n \nSee InnoDB Online DDL Overview: LOCK for information on how\nthe LOCK clause affects InnoDB.\n \nProgress Reporting\n \nMariaDB provides progress reporting for ALTER TABLE\nstatement for clients\nthat support the new progress reporting protocol. For\nexample, if you were using the mysql client, then the\nprogress report might look like this::\n \nALTER TABLE test ENGINE=Aria;\nStage: 1 of 2 \'copy to tmp table\' 46% of stage\n \nThe progress report is also shown in the output of the SHOW\nPROCESSLIST statement and in the contents of the\ninformation_schema.PROCESSLIST table.\n \nSee Progress Reporting for more information.\n \nAborting ALTER TABLE Operations\n \nIf an ALTER TABLE operation is being performed and the\nconnection is killed, the changes will be rolled back in a\ncontrolled manner. The rollback can be a slow operation as\nthe time it takes is relative to how far the operation has\nprogressed.\n \nAborting ALTER TABLE ... ALGORITHM=COPY was made faster by\nremoving excessive undo logging (MDEV-11415). This\nsignificantly shortens the time it takes to abort a running\nALTER TABLE operation.\n \nExamples\n-------- \nAdding a new column:\n \nALTER TABLE t1 ADD x INT;\n \nDropping a column:\n \nALTER TABLE t1 DROP x;\n \nModifying the type of a column:\n \nALTER TABLE t1 MODIFY x bigint unsigned;\n \nChanging the name and type of a column:\n \nALTER TABLE t1 CHANGE a b bigint unsigned auto_increment;\n \nCombining multiple clauses in a single ALTER TABLE\nstatement, separated by commas:\n \nALTER TABLE t1 DROP x, ADD x2 INT, CHANGE y y2 INT;\n \nChanging the storage engine:\n \nALTER TABLE t1 ENGINE = InnoDB;\n \nRebuilding the table (the previous example will also rebuild\nthe table if it was already InnoDB):\n \nALTER TABLE t1 FORCE;\n \n\n\nURL: https://mariadb.com/kb/en/alter-table/','','https://mariadb.com/kb/en/alter-table/'),(653,'ALTER TABLESPACE',39,'The ALTER TABLESPACE statement is not supported by MariaDB.\nIt was originally inherited from MySQL NDB Cluster. In MySQL\n5.7 and later, the statement is also supported for InnoDB.\nHowever, MariaDB has chosen not to include that specific\nfeature. See MDEV-19294 for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/alter-tablespace/','','https://mariadb.com/kb/en/alter-tablespace/'),(658,'CREATE FUNCTION',39,'Syntax\n------ \nCREATE [OR REPLACE]\n [DEFINER = {user | CURRENT_USER | role | CURRENT_ROLE }]\n [AGGREGATE] FUNCTION [IF NOT EXISTS] func_name\n([func_parameter[,...]])\n RETURNS type\n [characteristic ...]\n RETURN func_body\n \nfunc_parameter:\n param_name type\n \ntype:\n Any valid MariaDB data type\n \ncharacteristic:\n LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL\nDATA }\n | SQL SECURITY { DEFINER | INVOKER }\n | COMMENT \'string\'\n \nfunc_body:\n Valid SQL procedure statement\n \nDescription\n----------- \nUse the CREATE FUNCTION statement to create a new stored\nfunction. You must have\nthe CREATE ROUTINE database privilege to use CREATE\nFUNCTION.\nA function takes any number of arguments and returns a value\nfrom the function body. The\nfunction body can be any valid SQL expression as you would\nuse, for example, in any select\nexpression. If you have the appropriate privileges, you can\ncall the function exactly as you\nwould any built-in function. See Security below for details\non privileges.\n \nYou can also use a variant of the CREATE FUNCTION statement\nto install a user-defined\nfunction (UDF) defined by a plugin. See CREATE FUNCTION\n(UDF)\nfor details.\n \nYou can use a SELECT statement for the function body by\nenclosing it in\nparentheses, exactly as you would to use a subselect for any\nother expression. The SELECT\nstatement must return a single value. If more than one\ncolumn is returned when the function is called,\nerror 1241 results. If more than one row is returned when\nthe function is called, error 1242\nresults. Use a LIMIT clause to ensure only one row is\nreturned.\n \nYou can also replace the RETURN clause with a BEGIN...END\ncompound\nstatement. The compound statement must contain a RETURN\nstatement. When the function is\ncalled, the RETURN statement immediately returns its result,\nand any statements after RETURN\nare effectively ignored.\n \nBy default, a function is associated with the default\ndatabase. To associate the function explicitly\nwith a given database, specify the fully-qualified name as\ndb_name.func_name\nwhen you create it. If the function name is the same as the\nname of a built-in function, you must\nuse the fully qualified name when you call it.\n \nThe parameter list enclosed within parentheses must always\nbe present.\nIf there are no parameters, an empty parameter list of ()\nshould be\nused. Parameter names are not case sensitive.\n \nEach parameter can be declared to use any valid data type,\nexcept that\nthe COLLATE attribute cannot be used.\n \nFor valid identifiers to use as function names, see\nIdentifier Names.\n \nAGGREGATE\n \nFrom MariaDB 10.3.3, it is possible to create stored\naggregate functions as well. See Stored Aggregate Functions\nfor details.\n \nRETURNS\n \nThe RETURNS clause specifies the return type of the\nfunction. NULL values are permitted with all return types.\n \nWhat happens if the RETURN clause returns a value of a\ndifferent type? It depends on the SQL_MODE in effect at the\nmoment of the function creation.\n \nIf the SQL_MODE is strict (STRICT_ALL_TABLES or\nSTRICT_TRANS_TABLES flags are specified), a 1366 error will\nbe produced.\n \nOtherwise, the value is coerced to the proper type. For\nexample, if a function\nspecifies an ENUM or SET value in the RETURNS clause, but\nthe RETURN\nclause returns an integer, the value returned from the\nfunction is the string for the corresponding ENUM\nmember of set of SET members.\n \nMariaDB stores the SQL_MODE system variable setting that is\nin effect at the\ntime a routine is created, and always executes the routine\nwith this setting in\nforce, regardless of the server SQL mode in effect when the\nroutine is invoked.\n \nLANGUAGE SQL\n \nLANGUAGE SQL is a standard SQL clause, and it can be used in\nMariaDB for portability. However that clause has no meaning,\nbecause SQL is the only supported language for stored\nfunctions.\n \nA function is deterministic if it can produce only one\nresult for a given list of parameters. If the result may be\naffected by stored data, server variables, random numbers or\nany value that is not explicitly passed, then the function\nis not deterministic. Also, a function is non-deterministic\nif it uses non-deterministic functions like NOW() or\nCURRENT_TIMESTAMP(). The optimizer may choose a faster\nexecution plan if it known that the function is\ndeterministic. In such cases, you should declare the routine\nusing the DETERMINISTIC keyword. If you want to explicitly\nstate that the function is not deterministic (which is the\ndefault) you can use the NOT DETERMINISTIC keywords.\n \nIf you declare a non-deterministic function as\nDETERMINISTIC, you may get incorrect results. If you declare\na deterministic function as NOT DETERMINISTIC, in some cases\nthe queries will be slower.\n \nOR REPLACE\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP FUNCTION IF EXISTS function_name;\n \nCREATE FUNCTION function_name ...;\n \nwith the exception that any existing privileges for the\nfunction are not dropped.\n \nIF NOT EXISTS\n \nIf the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the function already exists.\nCannot be used together with OR REPLACE.\n \n[NOT] DETERMINISTIC\n \nThe [NOT] DETERMINISTIC clause also affects binary logging,\nbecause the STATEMENT format can not be used to store or\nreplicate non-deterministic statements.\n \nCONTAINS SQL, NO SQL, READS SQL DATA, and MODIFIES SQL DATA\nare informative clauses that tell the server what the\nfunction does. MariaDB does not check in any way whether the\nspecified clause is correct. If none of these clauses are\nspecified, CONTAINS SQL is used by default.\n \nMODIFIES SQL DATA\n \nMODIFIES SQL DATA means that the function contains\nstatements that may modify data stored in databases. This\nhappens if the function contains statements like DELETE,\nUPDATE, INSERT, REPLACE or DDL.\n \nREADS SQL DATA\n \nREADS SQL DATA means that the function reads data stored in\ndatabases, but does not modify any data. This happens if\nSELECT statements are used, but there no write operations\nare executed.\n \nCONTAINS SQL\n \nCONTAINS SQL means that the function contains at least one\nSQL statement, but it does not read or write any data stored\nin a database. Examples include SET or DO.\n \nNO SQL\n \nNO SQL means nothing, because MariaDB does not currently\nsupport any language other than SQL.\n \nOracle Mode\n \nFrom MariaDB 10.3, a subset of Oracle\'s PL/SQL language has\nbeen supported in addition to the traditional SQL/PSM-based\nMariaDB syntax. See Oracle mode from MariaDB 10.3 for\ndetails on changes when running Oracle mode.\n \nSecurity\n \nYou must have the EXECUTE privilege on a function to call\nit.\nMariaDB automatically grants the EXECUTE and ALTER ROUTINE\nprivileges to the\naccount that called CREATE FUNCTION, even if the DEFINER\nclause was used.\n \nEach function has an account associated as the definer. By\ndefault, the definer is the account\nthat created the function. Use the DEFINER clause to specify\na different account as the\ndefiner. You must have the SUPER privilege to use the\nDEFINER\nclause. See Account Names for details on specifying\naccounts.\n \nThe SQL SECURITY clause specifies what privileges are used\nwhen a function is called.\nIf SQL SECURITY is INVOKER, the function body will be\nevaluated using the privileges\nof the user calling the function. If SQL SECURITY is\nDEFINER, the function body is\nalways evaluated using the privileges of the definer\naccount. DEFINER is the default.\n \nThis allows you to create functions that grant limited\naccess to certain data. For example, say\nyou have a table that stores some employee information, and\nthat you\'ve granted SELECT\nprivileges only on certain columns to the user account\nroger.\n \nCREATE TABLE employees (name TINYTEXT, dept TINYTEXT, salary\nINT);\nGRANT SELECT (name, dept) ON employees TO roger;\n \nTo allow the user the get the maximum salary for a\ndepartment, define a function and grant\nthe EXECUTE privilege:\n \nCREATE FUNCTION max_salary (dept TINYTEXT) RETURNS INT\nRETURN\n (SELECT MAX(salary) FROM employees WHERE employees.dept =\ndept);\nGRANT EXECUTE ON FUNCTION max_salary TO roger;\n \nSince SQL SECURITY defaults to DEFINER, whenever the user\nroger calls\nthis function, the subselect will execute with your\nprivileges. As long as you have privileges to\nselect the salary of each employee, the caller of the\nfunction will be able to get the maximum\nsalary for each department without being able to see\nindividual salaries.\n \nCharacter sets and collations\n \nFunction return types can be declared to use any valid\ncharacter set and collation. If used, the COLLATE attribute\nneeds to be preceded by a CHARACTER SET attribute.\n \nIf the character set and collation are not specifically set\nin the statement, the database defaults at the time of\ncreation will be used. If the database defaults change at a\nlater stage, the stored function character set/collation\nwill not be changed at the same time; the stored function\nneeds to be dropped and recreated to ensure the same\ncharacter set/collation as the database is used.\n \nExamples\n-------- \nThe following example function takes a parameter, performs\nan operation using\nan SQL function, and returns the result.\n \nCREATE FUNCTION hello (s CHAR(20))\n RETURNS CHAR(50) DETERMINISTIC\n RETURN CONCAT(\'Hello, \',s,\'!\');\n \nSELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n \nYou can use a compound statement in a function to manipulate\ndata with statements\nlike INSERT and UPDATE. The following example creates a\ncounter function\nthat uses a temporary table to store the current value.\nBecause the compound statement\ncontains statements terminated with semicolons, you have to\nfirst change the statement\ndelimiter with the DELIMITER statement to allow the\nsemicolon to be used in the\nfunction body. See Delimiters in the mysql client for more.\n \nCREATE TEMPORARY TABLE counter (c INT);\nINSERT INTO counter VALUES (0);\nDELIMITER //\nCREATE FUNCTION counter () RETURNS INT\n BEGIN\n UPDATE counter SET c = c + 1;\n \n RETURN (SELECT c FROM counter LIMIT 1);\n END //\nDELIMITER ;\n \nCharacter set and collation:\n \nCREATE FUNCTION hello2 (s CHAR(20))\n RETURNS CHAR(50) CHARACTER SET \'utf8\' COLLATE\n\'utf8_bin\' DETERMINISTIC\n RETURN CONCAT(\'Hello, \',s,\'!\');\n \n\n\nURL: https://mariadb.com/kb/en/create-function/','','https://mariadb.com/kb/en/create-function/'),(662,'CREATE PROCEDURE',39,'Syntax\n------ \nCREATE\n [OR REPLACE]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n \nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n \ntype:\n Any valid MariaDB data type\n \ncharacteristic:\n LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL\nDATA }\n | SQL SECURITY { DEFINER | INVOKER }\n | COMMENT \'string\'\n \nroutine_body:\n Valid SQL procedure statement\n \nDescription\n----------- \nCreates a stored procedure. By default, a routine is\nassociated with the default database. To associate the\nroutine\nexplicitly with a given database, specify the name as\ndb_name.sp_name\nwhen you create it.\n \nWhen the routine is invoked, an implicit USE db_name is\nperformed (and\nundone when the routine terminates). The causes the routine\nto have\nthe given default database while it executes. USE statements\nwithin\nstored routines are disallowed.\n \nWhen a stored procedure has been created, you invoke it by\nusing the CALL statement (see CALL).\n \nTo execute the CREATE PROCEDURE statement, it is\nnecessary to have the CREATE ROUTINE privilege. By default,\nMariaDB\nautomatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the\nroutine creator. See also Stored Routine Privileges.\n \nThe DEFINER and SQL SECURITY clauses specify the security\ncontext to\nbe used when checking access privileges at routine execution\ntime, as\ndescribed later.\n \nIf the routine name is the same as the name of a built-in\nSQL\nfunction, you must use a space between the name and the\nfollowing\nparenthesis when defining the routine, or a syntax error\noccurs. This\nis also true when you invoke the routine later. For this\nreason, we\nsuggest that it is better to avoid re-using the names of\nexisting SQL\nfunctions for your own stored routines.\n \nThe IGNORE_SPACE SQL mode applies to built-in functions, not\nto stored\nroutines. It is always allowable to have spaces after a\nroutine name,\nregardless of whether IGNORE_SPACE is enabled.\n \nThe parameter list enclosed within parentheses must always\nbe present.\nIf there are no parameters, an empty parameter list of ()\nshould be\nused. Parameter names are not case sensitive.\n \nEach parameter can be declared to use any valid data type,\nexcept that\nthe COLLATE attribute cannot be used.\n \nFor valid identifiers to use as procedure names, see\nIdentifier Names.\n \nIN/OUT/INOUT\n \nEach parameter is an IN parameter by default. To specify\notherwise for\na parameter, use the keyword OUT or INOUT before the\nparameter name.\n \nAn IN parameter passes a value into a procedure. The\nprocedure might\nmodify the value, but the modification is not visible to the\ncaller\nwhen the procedure returns. An OUT parameter passes a value\nfrom the\nprocedure back to the caller. Its initial value is NULL\nwithin the\nprocedure, and its value is visible to the caller when the\nprocedure\nreturns. An INOUT parameter is initialized by the caller,\ncan be\nmodified by the procedure, and any change made by the\nprocedure is\nvisible to the caller when the procedure returns.\n \nFor each OUT or INOUT parameter, pass a user-defined\nvariable in the\nCALL statement that invokes the procedure so that you can\nobtain its\nvalue when the procedure returns. If you are calling the\nprocedure\nfrom within another stored procedure or function, you can\nalso pass a\nroutine parameter or local routine variable as an IN or\nINOUT\nparameter.\n \nDETERMINISTIC/NOT DETERMINISTIC\n \nDETERMINISTIC and NOT DETERMINISTIC apply only to functions.\nSpecifying DETERMINISTC or NON-DETERMINISTIC in procedures\nhas no effect. The default value is NOT DETERMINISTIC.\nFunctions are DETERMINISTIC when they always return the same\nvalue for the same input. For example, a truncate or\nsubstring function. Any function involving data, therefore,\nis always NOT DETERMINISTIC.\n \nCONTAINS SQL/NO SQL/READS SQL DATA/MODIFIES SQL DATA\n \nCONTAINS SQL, NO SQL, READS SQL DATA, and MODIFIES SQL DATA\nare informative clauses that tell the server what the\nfunction does. MariaDB does not check in any way whether the\nspecified clause is correct. If none of these clauses are\nspecified, CONTAINS SQL is used by default.\n \nMODIFIES SQL DATA means that the function contains\nstatements that may modify data stored in databases. This\nhappens if the function contains statements like DELETE,\nUPDATE, INSERT, REPLACE or DDL.\n \nREADS SQL DATA means that the function reads data stored in\ndatabases, but does not modify any data. This happens if\nSELECT statements are used, but there no write operations\nare executed.\n \nCONTAINS SQL means that the function contains at least one\nSQL statement, but it does not read or write any data stored\nin a database. Examples include SET or DO.\n \nNO SQL means nothing, because MariaDB does not currently\nsupport any language other than SQL.\n \nThe routine_body consists of a valid SQL procedure\nstatement. This can\nbe a simple statement such as SELECT or INSERT, or it can be\na\ncompound statement written using BEGIN and END. Compound\nstatements\ncan contain declarations, loops, and other control structure\nstatements. See Programmatic and Compound Statements for\nsyntax details.\n \nMariaDB allows routines to contain DDL statements, such as\nCREATE and\nDROP. MariaDB also allows stored procedures (but not stored\nfunctions)\nto contain SQL transaction statements such as COMMIT.\n \nFor additional information about statements that are not\nallowed in\nstored routines, see Stored Routine Limitations.\n \nInvoking stored procedure from within programs\n \nFor information about invoking stored procedures from within\nprograms written in a language that has a MariaDB/MySQL\ninterface, see CALL.\n \nOR REPLACE\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP PROCEDURE IF EXISTS name;\n \nCREATE PROCEDURE name ...;\n \nwith the exception that any existing privileges for the\nprocedure are not dropped.\n \nsql_mode\n \nMariaDB stores the sql_mode system variable setting that is\nin effect at the time a routine is created, and always\nexecutes the routine with this setting in force, regardless\nof the server SQL mode in effect when the routine is\ninvoked.\n \nCharacter Sets and Collations\n \nProcedure parameters can be declared with any character\nset/collation. If the character set and collation are not\nspecifically set, the database defaults at the time of\ncreation will be used. If the database defaults change at a\nlater stage, the stored procedure character set/collation\nwill not be changed at the same time; the stored procedure\nneeds to be dropped and recreated to ensure the same\ncharacter set/collation as the database is used.\n \nOracle Mode\n \nFrom MariaDB 10.3, a subset of Oracle\'s PL/SQL language has\nbeen supported in addition to the traditional SQL/PSM-based\nMariaDB syntax. See Oracle mode from MariaDB 10.3 for\ndetails on changes when running Oracle mode.\n \nExamples\n-------- \nThe following example shows a simple stored procedure that\nuses an OUT\nparameter. It uses the DELIMITER command to set a new\ndelimiter for the duration of the process — see Delimiters\nin the mysql client.\n \nDELIMITER //\n \nCREATE PROCEDURE simpleproc (OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END;\n//\n \nDELIMITER ;\n \nCALL simpleproc(@a);\n \nSELECT @a;\n+------+\n| @a |\n+------+\n| 1 |\n+------+\n \nCharacter set and collation:\n \nDELIMITER //\n \nCREATE PROCEDURE simpleproc2 (\n OUT param1 CHAR(10) CHARACTER SET \'utf8\' COLLATE\n\'utf8_bin\'\n)\n BEGIN\n SELECT CONCAT(\'a\'),f1 INTO param1 FROM t;\n END;\n//\n \nDELIMITER ;\n \nCREATE OR REPLACE:\n \nDELIMITER //\n \nCREATE PROCEDURE simpleproc2 (\n OUT param1 CHAR(10) CHARACTER SET \'utf8\' COLLATE\n\'utf8_bin\'\n)\n BEGIN\n SELECT CONCAT(\'a\'),f1 INTO param1 FROM t;\n \n END;\n \n//\nERROR 1304 (42000): PROCEDURE simpleproc2 already exists\n \nDELIMITER ;\n \nDELIMITER //\n \nCREATE OR REPLACE PROCEDURE simpleproc2 (\n OUT param1 CHAR(10) CHARACTER SET \'utf8\' COLLATE\n\'utf8_bin\'\n)\n BEGIN\n SELECT CONCAT(\'a\'),f1 INTO param1 FROM t;\n \n END;\n \n//\nERROR 1304 (42000): PROCEDURE simpleproc2 already exists\n \nDELIMITER ;\n \nQuery OK, 0 rows affected (0.03 sec)\n \n\n\nURL: https://mariadb.com/kb/en/create-procedure/','','https://mariadb.com/kb/en/create-procedure/'),(665,'CREATE TABLE',39,'Syntax\n------ \nCREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS]\ntbl_name\n (create_definition,...) [table_options ]...\n[partition_options]\nCREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS]\ntbl_name\n [(create_definition,...)] [table_options ]...\n[partition_options]\n select_statement\nCREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS]\ntbl_name\n { LIKE old_table_name | (LIKE old_table_name) }\n \nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some legal select\nstatement)\n \nDescription\n----------- \nUse the CREATE TABLE statement to create a table with the\ngiven name.\n \nIn its most basic form, the CREATE TABLE statement provides\na table name\nfollowed by a list of columns, indexes, and constraints. By\ndefault, the table\nis created in the default database. Specify a database with\ndb_name.tbl_name.\nIf you quote the table name, you must quote the database\nname and table name\nseparately as `db_name`.`tbl_name`. This is particularly\nuseful for CREATE TABLE ... SELECT, because it allows to\ncreate a table into a database, which contains data from\nother databases. See Identifier Qualifiers.\n \nIf a table with the same name exists, error 1050 results.\nUse IF NOT EXISTS\nto suppress this error and issue a note instead. Use SHOW\nWARNINGS\nto see notes.\n \nThe CREATE TABLE statement automatically commits the current\ntransaction,\nexcept when using the TEMPORARY keyword.\n \nFor valid identifiers to use as table names, see Identifier\nNames.\n \nNote: if the default_storage_engine is set to ColumnStore\nthen it needs setting on all UMs. Otherwise when the tables\nusing the default engine are replicated across UMs they will\nuse the wrong engine. You should therefore not use this\noption as a session variable with ColumnStore.\n \nMicrosecond precision can be between 0-6. If no precision is\nspecified it is assumed to be 0, for backward compatibility\nreasons.\n \nPrivileges\n \nExecuting the CREATE TABLE statement requires the CREATE\nprivilege for the table or the database.\n \nCREATE OR REPLACE TABLE ...\n \nThe OR REPLACE clause was added in MariaDB 10.0.8.\n \nIf the OR REPLACE clause is used and if the table already\nexists, then instead of returning an error, the server will\ndrop the existing table and replace it with the newly\ndefined table.\n \nThis syntax was originally added to make replication more\nrobust if it has to rollback and repeat statements such as\nCREATE ... SELECT on slaves.\n \nCREATE OR REPLACE TABLE table_name (a int);\n \nis basically the same as:\n \nDROP TABLE IF EXISTS table_name;\nCREATE TABLE table_name (a int);\n \nwith the following exceptions:\nIf table_name was locked with LOCK TABLES it will continue\nto be locked after the statement.\nTemporary tables are only dropped if the TEMPORARY keyword\nwas used. (With DROP TABLE, temporary tables are preferred\nto be dropped before normal tables).\n \nThings to be Aware of With CREATE OR REPLACE\n \nThe table is dropped first (if it existed), after that the\nCREATE is done. Because of this, if the CREATE fails, then\nthe table will not exist anymore after the statement. If the\ntable was used with LOCK TABLES it will be unlocked.\nOne can\'t use OR REPLACE together with IF EXISTS.\nSlaves in replication will by default use CREATE OR REPLACE\nwhen replicating CREATE statements that don\'\'t use IF\nEXISTS. This can be changed by setting the variable\nslave-ddl-exec-mode to STRICT.\n \nCREATE TABLE IF NOT EXISTS ...\n \nIf the IF NOT EXISTS clause is used, then the index will\nonly be created if an index with the same name does not\nalready exist. If the index already exists, then a warning\nwill be triggered by default.\n \nCREATE TEMPORARY TABLE ...\n \nUse the TEMPORARY keyword to create a temporary table that\nis only available to your current session. Temporary tables\nare dropped when the your session ends. Temporary table\nnames are specific to your session. They will not conflict\nwith other temporary tables from other session even if they\nshare the same name. They will shadow names of non-temporary\ntables or views, if they are identical. A temporary table\ncan have the same name as a non-temporary table which is\nlocated in the same database. In that case, their name will\nreference the temporary table when used in SQL statements.\nYou must have the CREATE TEMPORARY TABLES privilege on the\ndatabase to create temporary tables. If no storage engine is\nspecified, the default_tmp_storage_engine setting will\ndetermine the engine.\n \nCREATE TABLE ... LIKE\n \nUse the LIKE clause instead of a full table definition to\ncreate a table with the same definition as another table,\nincluding columns, indexes, and table options. Foreign key\ndefinitions, as well as any DATA DIRECTORY or INDEX\nDIRECTORY table options specified on the original table,\nwill not be created.\n \nCREATE TABLE ... SELECT\n \nYou can create a table containing data from other tables\nusing the CREATE ... SELECT statement. Columns will be\ncreated in the table for each field returned by the SELECT\nquery.\n \nYou can also define some columns normally and add other\ncolumns from a SELECT. You can also create columns in the\nnormal way and assign them some values using the query, this\nis done to force a certain type or other field\ncharacteristics. The columns that are not named in the query\nwill be placed before the others. For example:\n \nCREATE TABLE test (a INT NOT NULL, b CHAR(10)) ENGINE=MyISAM\n SELECT 5 AS b, c, d FROM another_table;\n \nRemember that the query just returns data. If you want to\nuse the same indexes, or the same columns attributes ([NOT]\nNULL, DEFAULT, AUTO_INCREMENT) in the new table, you need to\nspecify them manually. Types and sizes are not automatically\npreserved if no data returned by the SELECT requires the\nfull size, and VARCHAR could be converted into CHAR. The\nCAST() function can be used to forcee the new table to use\ncertain types.\n \nAliases (AS) are taken into account, and they should always\nbe used when you SELECT an expression (function,\narithmetical operation, etc).\n \nIf an error occurs during the query, the table will not be\ncreated at all.\n \nIf the new table has a primary key or UNIQUE indexes, you\ncan use the IGNORE or REPLACE keywords to handle duplicate\nkey errors during the query. IGNORE means that the newer\nvalues must not be inserted an identical value exists in the\nindex. REPLACE means that older values must be overwritten.\n \nIf the columns in the new table are more than the rows\nreturned by the query, the columns populated by the query\nwill be placed after other columns. Note that if the strict\nSQL_MODE is on, and the columns that are not names in the\nquery do not have a DEFAULT value, an error will raise and\nno rows will be copied.\n \nConcurrent inserts are not used during the execution of a\nCREATE ... SELECT.\n \nIf the table already exists, an error similar to the\nfollowing will be returned:\n \nERROR 1050 (42S01): Table \'t\' already exists\n \nIf the IF NOT EXISTS clause is used and the table exists, a\nnote will be produced instead of an error.\n \nTo insert rows from a query into an existing table, INSERT\n... SELECT can be used.\n \nColumn Definitions\n \ncreate_definition:\n { col_name column_definition | index_definition |\nperiod_definition | CHECK (expr) }\n \ncolumn_definition:\n data_type\n [NOT NULL | NULL] [DEFAULT default_value | (expression)]\n [AUTO_INCREMENT] [ZEROFILL] [UNIQUE [KEY] | [PRIMARY] KEY]\n [INVISIBLE] [{WITH|WITHOUT} SYSTEM VERSIONING]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [reference_definition]\n | data_type [GENERATED ALWAYS] \n AS { { ROW {START|END} } | { (expression) [VIRTUAL |\nPERSISTENT | STORED] } }\n [UNIQUE [KEY]] [COMMENT \'string\']\n \nconstraint_definition:\n CONSTRAINT [constraint_name] CHECK (expression)\nNote: MariaDB accepts the REFERENCES clause in ALTER TABLE\nand CREATE TABLE column definitions, but that syntax does\nnothing. MariaDB simply parses it without returning any\nerror or warning, for compatibility with other DBMS\'s.\nBefore MariaDB 10.2.1 this was also true for CHECK\nconstraints. Only the syntax for indexes described below\ncreates foreign keys.\n \nEach definition either creates a column in the table or\nspecifies and index or\nconstraint on one or more columns. See Indexes below for\ndetails\non creating indexes.\n \nCreate a column by specifying a column name and a data type,\noptionally\nfollowed by column options. See Data Types for a full list\nof data types allowed in MariaDB.\n \nNULL and NOT NULL\n \nUse the NULL or NOT NULL options to specify that values in\nthe column\nmay or may not be NULL, respectively. By default, values may\nbe NULL. See also NULL Values in MariaDB.\n \nDEFAULT Column Option\n \nThe DEFAULT clause was enhanced in MariaDB 10.2.1. Some\nenhancements include\nBLOB and TEXT columns now support DEFAULT.\nThe DEFAULT clause can now be used with an expression or\nfunction.\n \nSpecify a default value using the DEFAULT clause. If you\ndon\'t specify DEFAULT then the following rules apply:\nIf the column is not defined with NOT NULL, AUTO_INCREMENT\nor TIMESTAMP, an explicit DEFAULT NULL will be added.\nNote that in MySQL and in MariaDB before 10.1.6, you may get\nan explicit DEFAULT for primary key parts, if not specified\nwith NOT NULL.\n \nThe default value will be used if you INSERT a row without\nspecifying a value for that column, or if you specify\nDEFAULT for that column.\nBefore MariaDB 10.2.1 you couldn\'t usually provide an\nexpression or function to evaluate at\ninsertion time. You had to provide a constant default value\ninstead. The one\nexception is that you may use CURRENT_TIMESTAMP as\nthe default value for a TIMESTAMP column to use the current\ntimestamp at insertion time.\n \nCURRENT_TIMESTAMP may also be used as\nthe default value for a DATETIME\n \nFrom MariaDB 10.2.1 you can use most functions in DEFAULT.\nExpressions should have parentheses around them. If you use\na non deterministic function in DEFAULT then all inserts to\nthe table will be replicated in row mode. You can even refer\nto earlier columns in the DEFAULT expression:\n \nCREATE TABLE t1 (a int DEFAULT (1+1), b int DEFAULT (a+1));\nCREATE TABLE t2 (a bigint primary key DEFAULT UUID_SHORT());\n \nThe DEFAULT clause cannot contain any stored functions or\nsubqueries, and a column used in the clause must already\nhave been defined earlier in the statement.\n \nSince MariaDB 10.2.1, it is possible to assign BLOB or TEXT\ncolumns a DEFAULT value. In earlier versions, assigning a\ndefault to these columns was not possible.\n \nStarting from 10.3.3 you can also use DEFAULT (NEXT VALUE\nFOR sequence)\n \nAUTO_INCREMENT Column Option\n \nUse AUTO_INCREMENT to create a column whose value can\ncan be set automatically from a simple counter. You can only\nuse AUTO_INCREMENT\non a column with an integer type. The column must be a key,\nand there can only be\none AUTO_INCREMENT column in a table. If you insert a row\nwithout specifying\na value for that column (or if you specify 0, NULL, or\nDEFAULT\nas the value), the actual value will be taken from the\ncounter, with each insertion\nincrementing the counter by one. You can still insert a\nvalue explicitly. If you\ninsert a value that is greater than the current counter\nvalue, the counter is\nset based on the new value. An AUTO_INCREMENT column is\nimplicitly NOT NULL.\nUse LAST_INSERT_ID to get the AUTO_INCREMENT value\nmost recently used by an INSERT statement.\n \nZEROFILL Column Option\n \nIf the ZEROFILL column option is specified for a column\nusing a numeric data type, then the column will be set to\nUNSIGNED and the spaces used by default to pad the field are\nreplaced with zeros. ZEROFILL is ignored in expressions or\nas part of a UNION. ZEROFILL is a non-standard MySQL and\nMariaDB enhancement.\n \nPRIMARY KEY Column Option\n \nUse PRIMARY KEY (or just KEY) to make a column a primary\nkey. A primary key is a special type of a unique key. There\ncan be at most one primary key per table, and it is\nimplicitly NOT NULL.\n \nSpecifying a column as a unique key creates a unique index\non that column. See the Index Definitions section below for\nmore information.\n \nUNIQUE KEY Column Option\n \nUse UNIQUE KEY (or just UNIQUE) to specify that all values\nin the column\nmust be distinct from each other. Unless the column is NOT\nNULL, there may be\nmultiple rows with NULL in the column. \n \nSpecifying a column as a unique key creates a unique index\non that column. See the Index Definitions section below for\nmore information.\n \nCOMMENT Column Option\n \nYou can provide a comment for each column using the COMMENT\nclause. The maximum length is 1024 characters (it was 255\ncharacters before MariaDB 5.5). Use\nthe SHOW FULL COLUMNS statement to see column comments.\n \nGenerated Columns\n \nA generated column is a column in a table that cannot\nexplicitly be set to a specific value in a DML query.\nInstead, its value is automatically generated based on an\nexpression. This expression might generate the value based\non the values of other columns in the table, or it might\ngenerate the value by calling built-in functions or\nuser-defined functions (UDFs).\n \nThere are two types of generated columns:\nPERSISTENT or STORED: This type\'s value is actually stored\nin the table.\nVIRTUAL: This type\'s value is not stored at all. Instead,\nthe value is generated dynamically when the table is\nqueried. This type is the default.\n \nGenerated columns are also sometimes called computed columns\nor virtual columns.\n \nFor a complete description about generated columns and their\nlimitations, see Generated (Virtual and Persistent/Stored)\nColumns.\n \nCOLUMN_FORMAT\n \nCOLUMN_FORMAT is only used by MySQL Cluster, and is silently\nignored in MariaDB.\n \nCOMPRESSED\n \nCertain columns may be compressed. See Storage-Engine\nIndependent Column Compression.\n \nINVISIBLE\n \nColumns may be made invisible, and hidden in certain\ncontexts. See Invisible Columns.\n \nWITH SYSTEM VERSIONING Column Option\n \nColumns may be explicitly marked as included from system\nversioning. See System-versioned tables for details.\n \nWITHOUT SYSTEM VERSIONING Column Option\n \nColumns may be explicitly marked as excluded from system\nversioning. See System-versioned tables for details.\n \nIndex Definitions\n \nindex_definition:\n {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n[index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name]\n(index_col_name,...) [index_option] ...\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type]\n(index_col_name,...) [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name]\n[index_type] (index_col_name,...) [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY [index_name]\n(index_col_name,...) reference_definition\n \nindex_col_name:\n col_name [(length)] [ASC | DESC]\n \nindex_type:\n USING {BTREE | HASH | RTREE}\n \nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | CLUSTERING={YES| NO}\n \nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n \nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\nINDEX and KEY are synonyms. \n \nIndex names are optional, if not specified an automatic name\nwill be assigned. Index name are needed to drop indexes and\nappear in error messages when a constraint is violated.\n \nIndex Categories\n \nPlain Indexes\n \nPlain indexes are regular indexes that are not unique, and\nare not acting as a primary key or a foreign key. They are\nalso not the \"specialized\" FULLTEXT or SPATIAL indexes.\n \nSee Getting Started with Indexes: Plain Indexes for more\ninformation.\n \nPRIMARY KEY\n \nFor PRIMARY KEY indexes, you can specify a name for the\nindex, but it is silently ignored, and the name of the index\nis always PRIMARY.\n \nSee Getting Started with Indexes: Primary Key for more\ninformation.\n \nUNIQUE\n \nThe UNIQUE keyword means that the index will not accept\nduplicated values, except for NULLs. An error will raise if\nyou try to insert duplicate values in a UNIQUE index.\n \nFor UNIQUE indexes, you can specify a name for the\nconstraint, using the CONSTRAINT keyword. That name will be\nused in error messages.\n \nSee Getting Started with Indexes: Unique Index for more\ninformation.\n \nFOREIGN KEY\n \nFor FOREIGN KEY indexes, a reference definition must be\nprovided.\n \nFor FOREIGN KEY indexes, you can specify a name for the\nconstraint, using the CONSTRAINT keyword. That name will be\nused in error messages.\n \nFirst, you have to specify the name of the target (parent)\ntable and a column or a column list which must be indexed\nand whose values must match to the foreign key\'s values.\nThe MATCH clause is accepted to improve the compatibility\nwith other DBMS\'s, but has no meaning in MariaDB. The ON\nDELETE and ON UPDATE clauses specify what must be done when\na DELETE (or a REPLACE) statements attempts to delete a\nreferenced row from the parent table, and when an UPDATE\nstatement attempts to modify the referenced foreign key\ncolumns in a parent table row, respectively. The following\noptions are allowed:\nRESTRICT: The delete/update operation is not performed. The\nstatement terminates with a 1451 error (SQLSTATE \'2300\').\nNO ACTION: Synonym for RESTRICT.\nCASCADE: The delete/update operation is performed in both\ntables.\nSET NULL: The update or delete goes ahead in the parent\ntable, and the corresponding foreign key fields in the child\ntable are set to NULL. (They must not be defined as NOT NULL\nfor this to succeed).\nSET DEFAULT: This option is currently implemented only for\nthe PBXT storage engine, which is disabled by default and no\nlonger maintained. It sets the child table\'s foreign key\nfields to their DEFAULT values when the referenced parent\ntable key entries are updated or deleted.\n \nIf either clause is omitted, the default behavior for the\nomitted clause is RESTRICT.\n \nSee Foreign Keys for more information.\n \nFULLTEXT\n \nUse the FULLTEXT keyword to create full-text indexes.\n \nSee Full-Text Indexes for more information.\n \nSPATIAL\n \nUse the SPATIAL keyword to create geometric indexes.\n \nSee SPATIAL INDEX for more information.\n \nIndex Options\n \nKEY_BLOCK_SIZE Index Option\n \nThe KEY_BLOCK_SIZE index option is similar to the\nKEY_BLOCK_SIZE table option.\n \nWith the InnoDB storage engine, if you specify a non-zero\nvalue for the KEY_BLOCK_SIZE table option for the whole\ntable, then the table will implicitly be created with the\nROW_FORMAT table option set to COMPRESSED. However, this\ndoes not happen if you just set the KEY_BLOCK_SIZE index\noption for one or more indexes in the table. The InnoDB\nstorage engine ignores the KEY_BLOCK_SIZE index option.\nHowever, the SHOW CREATE TABLE statement may still report it\nfor the index.\n \nFor information about the KEY_BLOCK_SIZE index option, see\nthe KEY_BLOCK_SIZE table option below.\n \nIndex Types\n \nEach storage engine supports some or all index types. See\nStorage Engine Index Types for details on permitted index\ntypes for each storage engine.\n \nDifferent index types are optimized for different kind of\noperations:\nBTREE is the default type, and normally is the best choice.\nIt is supported by all storage engines. It can be used to\ncompare a column\'s value with a value using the =, >, >=,\n0) ,b int check (b> 0), constraint abc check (a>b));\n \nIf you use the second format and you don\'t give a name to\nthe constraint, then the constraint will get a auto\ngenerated name. This is done so that you can later delete\nthe constraint with ALTER TABLE DROP constraint_name.\n \nOne can disable all constraint expression checks by setting\nthe variable check_constraint_checks to OFF. This is useful\nfor example when loading a table that violates some\nconstraints that you want to later find and fix in SQL.\n \nSee CONSTRAINT for more information.\n \nTable Options\n \nFor each individual table you create (or alter), you can set\nsome table options. The general syntax for setting options\nis:\n \n = , [ = ...]\n \nThe equal sign is optional.\n \nSome options are supported by the server and can be used for\nall tables, no matter what storage engine they use; other\noptions can be specified for all storage engines, but have a\nmeaning only for some engines. Also, engines can extend\nCREATE TABLE with new options.\n \nIf the IGNORE_BAD_TABLE_OPTIONS SQL_MODE is enabled, wrong\ntable options generate a warning; otherwise, they generate\nan error.\n \ntable_option: \n [STORAGE] ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | ENCRYPTED [=] {YES | NO}\n | ENCRYPTION_KEY_ID [=] value\n | IETF_QUOTES [=] {YES | NO}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PAGE_CHECKSUM [=] {0 | 1}\n | PAGE_COMPRESSED [=] {0 | 1}\n | PAGE_COMPRESSION_LEVEL [=] {0 .. 9}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=]\n{DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT|PAGE}\n | SEQUENCE [=] {0|1}\n | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n | STATS_PERSISTENT [=] {DEFAULT|0|1}\n | STATS_SAMPLE_PAGES [=] {DEFAULT|value}\n | TABLESPACE tablespace_name\n | TRANSACTIONAL [=] {0 | 1}\n | UNION [=] (tbl_name[,tbl_name]...)\n | WITH SYSTEM VERSIONING\n \n[STORAGE] ENGINE\n \n[STORAGE] ENGINE specifies a storage engine for the table.\nIf this option is not used, the default storage engine is\nused instead. That is, the storage_engine session option\nvalue if it is set, or the value specified for the\n--default-storage-engine mysqld startup options, or InnoDB.\nIf the specified storage engine is not installed and active,\nthe default value will be used, unless the\nNO_ENGINE_SUBSTITUTION SQL MODE is set (default since\nMariaDB 10.0). This is only true for CREATE TABLE, not for\nALTER TABLE. For a list of storage engines that are present\nin your server, issue a SHOW ENGINES.\n \nAUTO_INCREMENT\n \nAUTO_INCREMENT specifies the initial value for the\nAUTO_INCREMENT primary key. This works for MyISAM, Aria,\nInnoDB/XtraDB, MEMORY, and ARCHIVE tables. You can change\nthis option with ALTER TABLE, but in that case the new value\nmust be higher than the highest value which is present in\nthe AUTO_INCREMENT column. If the storage engine does not\nsupport this option, you can insert (and then delete) a row\nhaving the wanted value - 1 in the AUTO_INCREMENT column.\n \nAVG_ROW_LENGTH\n \nAVG_ROW_LENGTH is the average rows size. It only applies to\ntables using MyISAM and Aria storage engines that have the\nROW_FORMAT table option set to FIXED format.\n \nMyISAM uses MAX_ROWS and AVG_ROW_LENGTH to decide the\nmaximum size of a table (default: 256TB, or the maximum file\nsize allowed by the system).\n \n[DEFAULT] CHARACTER SET/CHARSET\n \n[DEFAULT] CHARACTER SET (or [DEFAULT] CHARSET) is used to\nset a default character set for the table. This is the\ncharacter set used for all columns where an explicit\ncharacter set is not specified. If this option is omitted or\nDEFAULT is specified, database\'s default character set will\nbe used. See Setting Character Sets and Collations for\ndetails on setting the character sets.\n \nCHECKSUM/TABLE_CHECKSUM\n \nCHECKSUM (or TABLE_CHECKSUM) can be set to 1 to maintain a\nlive checksum for all table\'s rows. This makes write\noperations slower, but CHECKSUM TABLE will be very fast.\nThis option is only supported for MyISAM and Aria tables.\n \n[DEFAULT] COLLATE\n \n[DEFAULT] COLLATE is used to set a default collation for the\ntable. This is the collation used for all columns where an\nexplicit character set is not specified. If this option is\nomitted or DEFAULT is specified, database\'s default option\nwill be used. See Setting Character Sets and Collations for\ndetails on setting the collations\n \nCOMMENT\n \nCOMMENT is a comment for the table. Maximum length is 2048\ncharacters (before mariaDB 5.5 it was 60 characters). Also\nused to define table parameters when creating a Spider\ntable.\n \nCONNECTION\n \nCONNECTION is used to specify a server name or a connection\nstring for a Spider, CONNECT, Federated or FederatedX table.\n \nDATA DIRECTORY/INDEX DIRECTORY\n \nDATA DIRECTORY and INDEX DIRECTORY were only supported for\nMyISAM and Aria, before MariaDB 5.5. Since 5.5, DATA\nDIRECTORY has also been supported by InnoDB if the\ninnodb_file_per_table server system variable is enabled, but\nonly in CREATE TABLE, not in ALTER TABLE. So, carefully\nchoose a path for InnoDB tables at creation time, because it\ncannot be changed without dropping and re-creating the\ntable. These options specify the paths for data files and\nindex files, respectively. If these options are omitted, the\ndatabase\'s directory will be used to store data files and\nindex files. Note that these table options do not work for\npartitioned tables (use the partition options instead), or\nif the server has been invoked with the\n--skip-symbolic-links startup option. To avoid the\noverwriting of old files with the same name that could be\npresent in the directories, you can use the\n--keep_files_on_create option (an error will be issued if\nfiles already exist). These options are ignored if the\nNO_DIR_IN_CREATE SQL_MODE is enabled (useful for replication\nslaves). Also note that symbolic links cannot be used for\nInnoDB tables.\n \nDATA DIRECTORY works by creating symlinks from where the\ntable would normally have been (inside the datadir) to where\nthe option specifies. For security reasons, to avoid\nbypassing the privilege system, the server does not permit\nsymlinks inside the datadir. Therefore, DATA DIRECTORY\ncannot be used to specify a location inside the datadir. An\nattempt to do so will result in an error 1210 (HY000)\nIncorrect arguments to DATA DIRECTORY.\n \nDELAY_KEY_WRITE\n \nDELAY_KEY_WRITE is supported by MyISAM and Aria, and can be\nset to 1 to speed up write operations. In that case, when\ndata are modified, the indexes are not updated until the\ntable is closed. Writing the changes to the index file\naltogether can be much faster. However, note that this\noption is applied only if the delay_key_write server\nvariable is set to \'ON\'. If it is \'OFF\' the delayed\nindex writes are always disabled, and if it is \'ALL\' the\ndelayed index writes are always used, disregarding the value\nof DELAY_KEY_WRITE.\n \nENCRYPTED\n \nThe ENCRYPTED table option was added in MariaDB 10.1.4\n \nThe ENCRYPTED table option can be used to manually set the\nencryption status of an InnoDB table. See InnoDB / XtraDB\nEncryption for more information.\n \nAria does not currently support the ENCRYPTED table option.\nSee MDEV-18049 about that.\n \nSee Data-at-Rest Encryption for more information.\n \nENCRYPTION_KEY_ID\n \nThe ENCRYPTION_KEY_ID table option was added in MariaDB\n10.1.4\n \nThe ENCRYPTION_KEY_ID table option can be used to manually\nset the encryption key of an InnoDB table. See InnoDB /\nXtraDB Encryption for more information.\n \nAria does not currently support the ENCRYPTION_KEY_ID table\noption. See MDEV-18049 about that.\n \nSee Data-at-Rest Encryption for more information.\n \nIETF_QUOTES\n \nThe IETF_QUOTES option was added in MariaDB 10.1.8\n \nFor the CSV storage engine, the IETF_QUOTES option, when set\nto YES, enables IETF-compatible parsing of embedded quote\nand comma characters. Enabling this option for a table\nimproves compatibility with other tools that use CSV, but is\nnot compatible with MySQL CSV tables, or MariaDB CSV tables\ncreated without this option. Disabled by default.\n \nINSERT_METHOD\n \nINSERT_METHOD is only used with MERGE tables. This option\ndetermines in which underlying table the new rows should be\ninserted. If you set it to \'NO\' (which is the default) no\nnew rows can be added to the table (but you will still be\nable to perform INSERTs directly against the underlying\ntables). FIRST means that the rows are inserted into the\nfirst table, and LAST means that thet are inserted into the\nlast table.\n \nKEY_BLOCK_SIZE\n \nKEY_BLOCK_SIZE is used to determine the size of key blocks,\nin bytes or kilobytes. However, this value is just a hint,\nand the storage engine could modify or ignore it. If\nKEY_BLOCK_SIZE is set to 0, the storage engine\'s default\nvalue will be used.\n \nWith the InnoDB storage engine, if you specify a non-zero\nvalue for the KEY_BLOCK_SIZE table option for the whole\ntable, then the table will implicitly be created with the\nROW_FORMAT table option set to COMPRESSED.\n \nMIN_ROWS/MAX_ROWS\n \nMIN_ROWS and MAX_ROWS let the storage engine know how many\nrows you are planning to store as a minimum and as a\nmaximum. These values will not be used as real limits, but\nthey help the storage engine to optimize the table. MIN_ROWS\nis only used by MEMORY storage engine to decide the minimum\nmemory that is always allocated. MAX_ROWS is used to decide\nthe minimum size for indexes.\n \nPACK_KEYS\n \nPACK_KEYS can be used to determine whether the indexes will\nbe compressed. Set it to 1 to compress all keys. With a\nvalue of 0, compression will not be used. With the DEFAULT\nvalue, only long strings will be compressed. Uncompressed\nkeys are faster.\n \nPAGE_CHECKSUM\n \nPAGE_CHECKSUM is only applicable to Aria tables, and\ndetermines whether indexes and data should use page\nchecksums for extra safety. \n \nPAGE_COMPRESSED\n \nPAGE_COMPRESSED is used to enable InnoDB page compression\nfor InnoDB tables.\n \nPAGE_COMPRESSION_LEVEL\n \nPAGE_COMPRESSION_LEVEL is used to set the compression level\nfor InnoDB page compression for InnoDB tables. The table\nmust also have the PAGE_COMPRESSED table option set to 1.\n \nValid values for PAGE_COMPRESSION_LEVEL are 1 (the best\nspeed) through 9 (the best compression), .\n \nPASSWORD\n \nPASSWORD is unused.\n \nRAID_TYPE\n \nRAID_TYPE is an obsolete option, as the raid support has\nbeen disabled since MySQL 5.0.\n \nROW_FORMAT\n \nThe ROW_FORMAT table option specifies the row format for the\ndata file. Possible values are engine-dependent.\n \nSupported MyISAM Row Formats\n \nFor MyISAM, the supported row formats are: \nFIXED\nDYNAMIC\nCOMPRESSED\n \nThe COMPRESSED row format can only be set by the myisampack\ncommand line tool.\n \nSee MyISAM Storage Formats for more information.\n \nSupported Aria Row Formats\n \nFor Aria, the supported row formats are:\nPAGE\nFIXED\nDYNAMIC.\n \nSee Aria Storage Formats for more information.\n \nSupported InnoDB Row Formats\n \nFor InnoDB/XtraDB, the supported row formats are:\nCOMPACT\nREDUNDANT\nCOMPRESSED\nDYNAMIC.\n \nIf the ROW_FORMAT table option is set to FIXED for an InnoDB\ntable, then the server will either return an error or a\nwarning depending on the value of the innodb_strict_mode\nsystem variable. If the innodb_strict_mode system variable\nis set to OFF, then a warning is issued, and MariaDB will\ncreate the table using the default row format for the\nspecific MariaDB server version. If the innodb_strict_mode\nsystem variable is set to ON, then an error will be raised.\n \nSee XtraDB/InnoDB Storage Formats for more information.\n \nOther Storage Engines and ROW_FORMAT\n \nOther storage engines do not support the ROW_FORMAT table\noption.\n \nSEQUENCE\n \nIf the table is a sequence, then it will have the SEQUENCE\nset to 1.\n \nSTATS_AUTO_RECALC\n \nSTATS_AUTO_RECALC is available only in MariaDB 10.0+. It\nindicates whether to automatically recalculate persistent\nstatistics (see STATS_PERSISTENT, below) for an InnoDB\ntable.\nIf set to 1, statistics will be recalculated when more than\n10% of the data has changed. When set to 0, stats will be\nrecalculated only when an ANALYZE TABLE is run. If set to\nDEFAULT, or left out, the value set by the\ninnodb_stats_auto_recalc system variable applies. See InnoDB\nPersistent Statistics.\n \nSTATS_PERSISTENT\n \nSTATS_PERSISTENT is available only in MariaDB 10.0+. It\nindicates whether the InnoDB statistics created by ANALYZE\nTABLE will remain on disk or not. It can be set to 1 (on\ndisk), 0 (not on disk, the pre-MariaDB 10 behavior), or\nDEFAULT (the same as leaving out the option), in which case\nthe value set by the innodb_stats_persistent system variable\nwill apply. Persistent statistics stored on disk allow the\nstatistics to survive server restarts, and provide better\nquery plan stability. See InnoDB Persistent Statistics.\n \nSTATS_SAMPLE_PAGES\n \nSTATS_SAMPLE_PAGES is available only in MariaDB 10.0+. It\nindicates how many pages are used to sample index\nstatistics. If 0 or DEFAULT, the default value, the\ninnodb_stats_sample_pages value is used. See InnoDB\nPersistent Statistics.\n \nTRANSACTIONAL\n \nTRANSACTIONAL is only applicable for Aria tables. In future\nAria tables created with this option will be fully\ntransactional, but currently this provides a form of crash\nprotection. See Aria Storage Engine for more details.\n \nUNION\n \nUNION must be specified when you create a MERGE table. This\noption contains a comma-separated list of MyISAM tables\nwhich are accessed by the new table. The list is enclosed\nbetween parenthesis. Example: UNION = (t1,t2)\n \nWITH SYSTEM VERSIONING\n \nWITH SYSTEM VERSIONING is used for creating System-versioned\ntables.\n \nPartitions\n \npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE(expr)\n | LIST(expr)\n | SYSTEM_TIME [INTERVAL time_quantity time_unit] [LIMIT\nnum] }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n \npartition_definition:\n PARTITION partition_name\n [VALUES {LESS THAN {(expr) | MAXVALUE} | IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n \nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\nIf the PARTITION BY clause is used, the table will be\npartitioned. A partition method must be explicitly indicated\nfor partitions and subpartitions. Partition methods are:\n[LINEAR] HASH creates a hash key which will be used to read\nand write rows. The partition function can be any valid SQL\nexpression which returns an INTEGER number. Thus, it is\npossible to use the HASH method on an integer column, or on\nfunctions which accept integer columns as an argument.\nHowever, VALUES LESS THAN and VALUES IN clauses can not be\nused with HASH. An example:\n \nCREATE TABLE t1 (a INT, b CHAR(5), c DATETIME)\n PARTITION BY HASH ( YEAR(c) );\n \n [LINEAR] HASH can be used for subpartitions, too.\n[LINEAR] KEY is similar to HASH, but the index has an even\ndistribution of data. Also, the expression can only be a\ncolumn or a list of columns. VALUES LESS THAN and VALUES IN\nclauses can not be used with KEY.\nRANGE partitions the rows using on a range of values, using\nthe VALUES LESS THAN operator. VALUES IN is not allowed with\nRANGE. The partition function can be any valid SQL\nexpression which returns a single value.\nLIST assignes partitions based on a table\'s column with a\nrestricted set of possible values. It is similar to RANGE,\nbut VALUES IN must be used for at least 1 columns, and\nVALUES LESS THAN is disallowed.\nSYSTEM_TIME partitioning is used for System-versioned tables\nto store historical data separately from current data.\n \nOnly HASH and KEY can be used for subpartitions, and they\ncan be [LINEAR].\n \nIt is possible to define up to 1024 partitions and\nsubpartitions.\n \nThe number of defined partitions can be optionally specified\nas PARTITION count. This can be done to avoid specifying all\npartitions individually. But you can also declare each\nindividual partition and, additionally, specify a PARTITIONS\ncount clause; in the case, the number of PARTITIONs must\nequal count.\n \nAlso see Partitioning Types Overview.\n \nSequences\n \nCREATE TABLE can also be used to create a SEQUENCE. See\nCREATE SEQUENCE and Sequence Overview.\n \nExamples\n-------- \ncreate table if not exists test (\na bigint auto_increment primary key,\nname varchar(128) charset utf8,\nkey name (name(32))\n) engine=InnoDB default charset latin1;\n \nThis example shows a couple of things:\nUsage of IF NOT EXISTS; If the table already existed, it\nwill not be created. There will not be any error for the\nclient, just a warning.\nHow to create a PRIMARY KEY that is automatically generated.\nHow to specify a table-specific character set and another\nfor a column.\nHow to create an index (name) that is only partly indexed\n(to save space).\n \nThe following clauses will work from MariaDB 10.2.1 only.\n \nCREATE TABLE t1(\n a int DEFAULT (1+1),\n b int DEFAULT (a+1),\n expires DATETIME DEFAULT(NOW() + INTERVAL 1 YEAR),\n x BLOB DEFAULT USER()\n);\n \n\n\nURL: https://mariadb.com/kb/en/create-table/','','https://mariadb.com/kb/en/create-table/'),(338,'BACKUP STAGE',26,'BACKUP STAGE commands are a set of commands to make it\npossible to make an efficient external backup tool. \n \nThe BACKUP STAGE command was introduced in MariaDB 10.4.1.\n \nSyntax\n------ \nBACKUP STAGE [START | FLUSH | BLOCK_DDL | BLOCK_COMMIT | END\n]\n \nIn the following text, a transactional table means InnoDB or\n\"InnoDB-like engine with redo log that can lock redo purges\nand can be copied without locks by an outside process\".\n \nIn the text we refer to mariabackup as the backup tool to\nuse. However the description should work for any tools that\nsupport BACKUP STAGEs.\n \nGoals with BACKUP STAGE Commands\n \nTo be able to do a majority of the backup with the minimum\npossible server locks. Especially for transactional tables\n(InnoDB, MyRocks etc) there is only need for a very short\nblock of new commits while copying statistics and log\ntables.\nDDL are only needed to be blocked for a very short duration\nof the backup while mariabackup is copying the tables\naffected by DDL during the initial part of the backup.\nMost non transactional tables (those that are not in use)\nwill be copied during BACKUP STAGE START. The exceptions are\nsystem statistic and log tables that are not blocked during\nthe backup until BLOCK_COMMIT.\nShould work efficiently with backup tools that use disk\nsnapshots.\nShould work as efficiently as possible for all table types\nthat store data on the local disks.\nAs little copying as possible under higher level\nstages/locks. For example, .frm (dictionary) and .trn\n(trigger) files should be copying while copying the table\ndata.\n \nBACKUP STAGE Commands\n \nBACKUP STAGE START\n \nThings Done by STAGE START\n \nBlocks purge of redo files for storage engines that needs\nthis (Aria)\nStart logging of DDL commands into \'datadir\'/ddl.log. This\nmay take a short time as the command has to wait until there\nall now active DDL commands.\n \nmariabackup Under START\n \nmariabackup can, under START:\nCopy all transactional tables, aria_log_control, aria_log.#\nand\nother engines redo logs.\nCall BACKUP STAGE FLUSH while copying the last set of files.\n \nTo copy InnoDB tables, mariabackup has to start to watch the\nInnoDB backup redo log and copy all changes to the backup to\nbe able to run the redos later on in the final backup.\n \nBACKUP STAGE FLUSH\n \nThings Done by STAGE FLUSH\n \nFLUSH all changes for inactive non-transactional tables,\nexcept for statistics and log tables.\nClose all tables that are not in use, to ensure they are\nmarked as closed for the backup.\nBLOCK all new write locks for all non transactional tables\n(except statistics and log tables). The command will not\nwait for tables that are in use by read-only transactions.\n \nDDLs don\'t have to be blocked at this stage as they can\'t\ncause the table to be in an inconsistent state. This is true\nalso for non-transactional tables.\n \nmariabackup under STAGE_FLUSH\n \nmariabackup can, under STAGE FLUSH:\nCopy all non-transactional tables that are not in use. This\nlist of used tables can be found with SHOW OPEN TABLES\nCopy all new changes to the aria_log.# tables\n \nAt this point data for all old tables should have been\ncopied (except for some system tables).\n \nBACKUP STAGE BLOCK_DDL\n \nThings Done by BLOCK_DDL\n \nWait for all statements using write locked non-transactional\ntables to end.\nBlocks CREATE TABLE, DROP TABLE, TRUNCATE TABLE, and RENAME\nTABLE.\nBlocks also start off a new ALTER TABLE and the final rename\nphase of ALTER TABLE. Running ALTER TABLES are not blocked.\n \nmariabackup under BLOCK_DDL\n \nmariabackup can, under BLOCK_DDL:\nCopy the non-transactional tables that were in use during\nSTAGE FLUSH\nCopy new tables created before BLOCK DDL. The file names can\nbe read from ddl.log. The log also allows the backup to\nexecute renames of files for which RENAME TABLE was done\ninstead of copying them.\nAdd markers to backup stream of tables that were dropped\nduring the earlier BACKUP STAGEs.\nCopy changes to system log tables (this is easy as these are\nappend only)\nCopy changes to aria_log.# tables (this is easy as these are\nappend only)\n \nBACKUP STAGE BLOCK_COMMIT\n \nThings Done by BLOCK_COMMIT\n \nLock the binary log and commit/rollback to ensure that no\nchanges are committed to any tables. If there are active\ncommits or data to be copied to the binary log this will be\nallowed to finish.\nThis doesn\'t lock temporary tables that are not used by\nreplication. However these will be blocked when it\'s time\nto write to the binary log.\nLock system log tables and statistics tables, flush them and\nmark them closed.\n \nWhen the BLOCK_COMMIT\'s stages return, this is the \'backup\ntime\'. Everything committed will be in the backup and\neverything not committed will roll back.\n \nTransactional engines will continue to do changes to the\nredo log during the BLOCK COMMIT stage, but this is not\nimportant as all of these will roll back later as the\nchanges will not be committed.\n \nmariabackup Under BLOCK_COMMIT\n \nmariabackup can, under BLOCK_COMMIT:\nCopy the last changes to the redo files for InnoDB and Aria\n(aria_log.#), and the part of the binary log that was not\ncopied before.\nMyRocks files can also be hard linked to the backup\ndirectory\nEnd of system log tables (slow_log and general_log) and all\nstatistics tables (table_stats, column_stats and\nindex_stats) should also be copied.\n \nBACKUP STAGE END\n \nThings Done by END\n \nEnd DDL logging\nFree resources\n \nmariabackup After END\n \nmariabackup can, after END:\nCopy MyRocks tables\n \nUsing BACKUP STAGE With Disk Snapshots\n \nA tool that is using disk snapshots for copying MariaDB\nfiles should do\n \nBACKUP STAGE START\nBACKUP STAGE BLOCK_COMMIT\n \ndisk snapshot\n \nBACKUP STAGE END\n \nThe above ensures that all non-transactional tables are\nproperly flushed to disk before the snapshot is done.\nUsing BACKUP STAGEs is also more efficient than using FLUSH\nTABLES WITH READ LOCK as the above set of commands will not\nblock or be blocked by write operations to transactional\ntables.\n \nNote that when the backup is completed, one should delete\nall files with the \"#sql\" prefix, as these are files used\nby concurrent running ALTER TABLE. Note that InnoDB will on\nserver restart automatically delete any tables with the\n\"#sql\" prefix.\n \nPrivileges\n \nBACKUP STAGE requires the RELOAD privilege.\n \nOther Things\n \nOnly one connection can run BACKUP STAGE START. If a second\nconnection tries, it will wait until the first one has\nexecuted BACKUP STAGE END.\nIf the user skips a BACKUP STAGE, all intermediate backup\nstages will automatically be run. This will allow us to add\nnew BACKUP STAGEs in the future with even more precise locks\nwithout causing problems for tools using an earlier version\nof BACKUP STAGEs\nWhile opening files for a table, mariabackup should use\nBACKUP LOCK to ensure that all files for a table are from\nthe same generation, that is, created at the same time.\nOne can use the max_statement_time or lock_wait_timeout\nvariables to ensure that a BACKUP STAGE command doesn\'t\nblock the server too long.\nDDL logging will only be available in MariaDB Enterprise\nserver 10.2, 10.3 and 10.4.\n \n\n\nURL: https://mariadb.com/kb/en/backup-stage/','','https://mariadb.com/kb/en/backup-stage/'),(666,'CREATE TABLESPACE',39,'The CREATE TABLESPACE statement is not supported by MariaDB.\nIt was originally inherited from MySQL NDB Cluster. In MySQL\n5.7 and later, the statement is also supported for InnoDB.\nHowever, MariaDB has chosen not to include that specific\nfeature. See MDEV-19294 for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/create-tablespace/','','https://mariadb.com/kb/en/create-tablespace/'),(339,'BACKUP LOCK',26,'The BACKUP LOCK command was introduced in MariaDB 10.4.2.\n \nBACKUP LOCK blocks a table from DDL statements. This is\nmainly intended to be used by tools like mariabackup that\nneed to ensure there are no DDLs on a table while the table\nfiles are opened. For example, for an Aria table that stores\ndata in 3 files with extensions .frm, .MAI and .MAD.\nNormal read/write operations can continue as normal.\n \nSyntax\n------ \nTo lock a table:\n \nBACKUP LOCK table_name\n \nTo unlock a table:\n \nBACKUP UNLOCK\n \nUsage in a Backup Tool\n \nBACKUP LOCK [database.]table_name;\n - Open all files related to a table (for example, t.frm,\nt.MAI and t.MYD)\nBACKUP UNLOCK;\n- Copy data\n- Close files\n \nThis ensures that all files are from the same generation,\nthat is created at the same time by the MariaDB server.\n \nPrivileges\n \nBACKUP LOCK requires the RELOAD privilege.\n \nNotes\n \nThe idea is that the BACKUP LOCK should be held for as short\na time as possible by the backup tool. The time to take an\nuncontested lock is very short! One can easily do 50,000\nlocks/unlocks per second on low end hardware.\nOne should use different connections for BACKUP STAGE\ncommands and BACKUP LOCK. \n \nImplementation\n \nInternally, BACKUP LOCK is implemented by taking an\nMDLSHARED_HIGH_PRIO MDL lock on the table object, which\nprotects the table from any DDL operations.\n \n\n\nURL: https://mariadb.com/kb/en/backup-lock/','','https://mariadb.com/kb/en/backup-lock/'),(341,'CACHE INDEX',26,'Syntax\n------ \nCACHE INDEX \n tbl_index_list [, tbl_index_list] ...\n IN key_cache_name \n \ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n \nDescription\n----------- \nThe CACHE INDEX statement assigns table indexes to a\nspecific key\ncache. It is used only for MyISAM tables.\n \nA default key cache exists and cannot be destroyed. To\ncreate more key caches, the key_buffer_size server system\nvariable.\n \nThe associations between tables indexes and key caches are\nlost on server restart. To recreate them automatically, it\nis necessary to configure caches in a configuration file and\ninclude some CACHE INDEX (and optionally LOAD INDEX)\nstatements in the init file.\n \nExamples\n-------- \nThe following statement assigns indexes from the tables t1,\nt2, and t3\nto the key cache named hot_cache:\n \nCACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n \nImplementation (for MyISAM)\n \nNormally CACHE INDEX should not take a long time to execute.\nInternally it\'s implemented the following way:\nFind the right key cache (under\nLOCK_global_system_variables)\nOpen the table with a TL_READ_NO_INSERT lock.\nFlush the original key cache for the given file (under key\ncache lock)\nFlush the new key cache for the given file (safety)\nMove the file to the new key cache (under file share lock)\n \nThe only possible long operations are getting the locks for\nthe table and flushing the original key cache, if there were\nmany key blocks for the file in it.\n \nWe plan to also add CACHE INDEX for Aria tables if there is\na need for this.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/cache-index/','','https://mariadb.com/kb/en/cache-index/'),(344,'FLUSH TABLES FOR EXPORT',26,'FLUSH TABLES ... FOR EXPORT was introduced in MariaDB\n10.0.8.\n \nSyntax\n------ \nFLUSH TABLES table_name [, table_name] FOR EXPORT\n \nDescription\n----------- \nFLUSH TABLES ... FOR EXPORT flushes changes to the specified\ntables to disk so that binary copies can be made while the\nserver is still running. This works for Archive, Aria, CSV,\nInnoDB, MyISAM, MERGE, and XtraDB tables.\n \nThe table is read locked until one has issued UNLOCK TABLES.\n \nIf a storage engine does not support FLUSH TABLES FOR\nEXPORT, a 1031 error (SQLSTATE \'HY000\') is produced.\n \nIf FLUSH TABLES ... FOR EXPORT is in effect in the session,\nthe following statements will produce an error if attempted:\nFLUSH TABLES WITH READ LOCK\nFLUSH TABLES ... WITH READ LOCK\nFLUSH TABLES ... FOR EXPORT\nAny statement trying to update any table\n \nIf any of the following statements is in effect in the\nsession, attempting FLUSH TABLES ... FOR EXPORT will\nproduce an error.\nFLUSH TABLES ... WITH READ LOCK\nFLUSH TABLES ... FOR EXPORT\nLOCK TABLES ... READ\nLOCK TABLES ... WRITE\n \nFLUSH FOR EXPORT is not written to the binary log.\n \nThis statement requires the RELOAD and the LOCK TABLES\nprivileges.\n \nIf one of the specified tables cannot be locked, none of the\ntables will be locked.\n \nIf a table does not exist, an error like the following will\nbe produced:\n \nERROR 1146 (42S02): Table \'test.xxx\' doesn\'t exist\n \nIf a table is a view, an error like the following will be\nproduced:\n \nERROR 1347 (HY000): \'test.v\' is not BASE TABLE\n \nExample\n \nFLUSH TABLES test.t1 FOR EXPORT;\n# Copy files related to the table (see below)\nUNLOCK TABLES;\n \nFor a full description, please see copying MariaDB tables.\n \n\n\nURL: https://mariadb.com/kb/en/flush-tables-for-export/','','https://mariadb.com/kb/en/flush-tables-for-export/'),(668,'CREATE VIEW',39,'Syntax\n------ \nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW [IF NOT EXISTS] view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n \nDescription\n----------- \nThe CREATE VIEW statement creates a new view, or replaces an\nexisting\none if the OR REPLACE clause is given. If the view does not\nexist, CREATE OR\nREPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR\nREPLACE VIEW is the same as ALTER VIEW.\n \nThe select_statement is a SELECT statement that provides the\ndefinition of\nthe view. (When you select from the view, you select in\neffect using the SELECT\nstatement.) select_statement can select from base tables or\nother views.\n \nThe view definition is \"frozen\" at creation time, so\nchanges to the underlying\ntables afterwards do not affect the view definition. For\nexample, if a view is\ndefined as SELECT * on a table, new columns added to the\ntable later do not\nbecome part of the view. A SHOW CREATE VIEW shows that\nsuch queries are rewritten and column names are included in\nthe view\ndefinition.\n \nThe view definition must be a query that does not return\nerrors at view\ncreation times. However, the base tables used by the views\nmight be altered\nlater and the query may not be valid anymore. In this case,\nquerying the view\nwill result in an error. CHECK TABLE helps in finding this\nkind\nof problems.\n \nThe ALGORITHM clause affects how MariaDB processes the\nview. The DEFINER and SQL SECURITY clauses specify the\nsecurity context to be\nused when checking access privileges at view invocation\ntime. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates\nto rows in tables\nreferenced by the view. These clauses are described later in\nthis section.\n \nThe CREATE VIEW statement requires the CREATE VIEW privilege\nfor the\nview, and some privilege for each column selected by the\nSELECT\nstatement. For columns used elsewhere in the SELECT\nstatement you must\nhave the SELECT privilege. If the OR REPLACE clause is\npresent, you\nmust also have the DROP privilege for the view.\n \nA view belongs to a database. By default, a new view is\ncreated in the\ndefault database. To create the view explicitly in a given\ndatabase,\nspecify the name as db_name.view_name when you create it.\n \nCREATE VIEW test.v AS SELECT * FROM t;\n \nBase tables and views share the same namespace within a\ndatabase, so a\ndatabase cannot contain a base table and a view that have\nthe same\nname.\n \nViews must have unique column names with no duplicates, just\nlike base\ntables. By default, the names of the columns retrieved by\nthe SELECT\nstatement are used for the view column names. To define\nexplicit names\nfor the view columns, the optional column_list clause can be\ngiven as\na list of comma-separated identifiers. The number of names\nin\ncolumn_list must be the same as the number of columns\nretrieved by the\nSELECT statement.\n \nMySQL until 5.1.28\n \nPrior to MySQL 5.1.29, When you modify an existing view, the\ncurrent view definition is backed up and saved. It is stored\nin that\ntable\'s database directory, in a subdirectory named arc.\nThe backup\nfile for a view v is named v.frm-00001. If you alter the\nview again,\nthe next backup is named v.frm-00002. The three latest view\nbackup\ndefinitions are stored. Backed up view definitions are not\npreserved\nby mysqldump, or any other such programs, but you can retain\nthem\nusing a file copy operation. However, they are not needed\nfor anything\nbut to provide you with a backup of your previous view\ndefinition. It\nis safe to remove these backup definitions, but only while\nmysqld is\nnot running. If you delete the arc subdirectory or its files\nwhile\nmysqld is running, you will receive an error the next time\nyou try to\nalter the view: \n \nMariaDB [test]> ALTER VIEW v AS SELECT * FROM t; \nERROR 6 (HY000): Error on delete of\n\'.\\test\\arc/v.frm-0004\' (Errcode: 2)\n \nColumns retrieved by the SELECT statement can be simple\nreferences to\ntable columns. They can also be expressions that use\nfunctions,\nconstant values, operators, and so forth.\n \nUnqualified table or view names in the SELECT statement are\ninterpreted with respect to the default database. A view can\nrefer to\ntables or views in other databases by qualifying the table\nor view\nname with the proper database name.\n \nA view can be created from many kinds of SELECT statements.\nIt can\nrefer to base tables or other views. It can use joins,\nUNION, and\nsubqueries. The SELECT need not even refer to any tables.\nThe\nfollowing example defines a view that selects two columns\nfrom another\ntable, as well as an expression calculated from those\ncolumns:\n \nCREATE TABLE t (qty INT, price INT);\n \nINSERT INTO t VALUES(3, 50);\n \nCREATE VIEW v AS SELECT qty, price, qty*price AS value FROM\nt;\n \nSELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n \nA view definition is subject to the following restrictions:\nThe SELECT statement cannot contain a subquery in the FROM\nclause.\nThe SELECT statement cannot refer to system or user\nvariables.\nWithin a stored program, the definition cannot refer to\nprogram parameters or local variables.\nThe SELECT statement cannot refer to prepared statement\nparameters.\nAny table or view referred to in the definition must exist.\nHowever, after a view has been created, it is possible to\ndrop a table or view that the definition refers to. In this\ncase, use of the view results in an error. To check a view\ndefinition for problems of this kind, use the CHECK TABLE\nstatement.\nThe definition cannot refer to a TEMPORARY table, and you\ncannot create a TEMPORARY view.\nAny tables named in the view definition must exist at\ndefinition time.\nYou cannot associate a trigger with a view.\nFor valid identifiers to use as view names, see Identifier\nNames.\n \nORDER BY is allowed in a view definition, but it is ignored\nif you\nselect from a view using a statement that has its own ORDER\nBY.\n \nFor other options or clauses in the definition, they are\nadded to the\noptions or clauses of the statement that references the\nview, but the\neffect is undefined. For example, if a view definition\nincludes a\nLIMIT clause, and you select from the view using a statement\nthat has\nits own LIMIT clause, it is undefined which limit applies.\nThis same\nprinciple applies to options such as ALL, DISTINCT, or\nSQL_SMALL_RESULT that follow the SELECT keyword, and to\nclauses such\nas INTO, FOR UPDATE, and LOCK IN SHARE MODE.\n \nThe PROCEDURE clause cannot be used in a view definition,\nand it cannot be used if a view is referenced in the FROM\nclause.\n \nIf you create a view and then change the query processing\nenvironment\nby changing system variables, that may affect the results\nthat you get\nfrom the view:\n \nCREATE VIEW v (mycol) AS SELECT \'abc\';\n \nSET sql_mode = \'\';\n \nSELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol | \n+-------+\n \nSET sql_mode = \'ANSI_QUOTES\';\n \nSELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc | \n+-------+\n \nThe DEFINER and SQL SECURITY clauses determine which MariaDB\naccount to\nuse when checking access privileges for the view when a\nstatement is\nexecuted that references the view. They were added in MySQL\n5.1.2.\nThe legal SQL SECURITY characteristic values are DEFINER and\nINVOKER.\nThese indicate that the required privileges must be held by\nthe user\nwho defined or invoked the view, respectively. The default\nSQL\nSECURITY value is DEFINER.\n \nIf a user value is given for the DEFINER clause, it should\nbe a MariaDB\naccount in \'user_name\'@\'host_name\' format (the same\nformat used in the\nGRANT statement). The user_name and host_name values both\nare\nrequired. The definer can also be given as CURRENT_USER or\nCURRENT_USER(). The default DEFINER value is the user who\nexecutes the\nCREATE VIEW statement. This is the same as specifying\nDEFINER =\nCURRENT_USER explicitly.\n \nIf you specify the DEFINER clause, these rules determine the\nlegal\nDEFINER user values:\nIf you do not have the SUPER privilege, the only legal user\nvalue is your own account, either specified literally or by\nusing CURRENT_USER. You cannot set the definer to some other\naccount.\nIf you have the SUPER privilege, you can specify any\nsyntactically legal account name. If the account does not\nactually exist, a warning is generated.\nIf the SQL SECURITY value is DEFINER but the definer account\ndoes not exist when the view is referenced, an error occurs.\n \nWithin a view definition, CURRENT_USER returns the view\'s\nDEFINER\nvalue by default. Before MySQL 5.1.12, and for views\ndefined with the SQL SECURITY INVOKER characteristic,\nCURRENT_USER\nreturns the account for the view\'s invoker. For information\nabout user\nauditing within views, see\nhttp://dev.mysql.com/doc/refman/5.1/en/account-activity-auditing.html.\n \nWithin a stored routine that is defined with the SQL\nSECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER\nvalue. This\nalso affects a view defined within such a program, if the\nview\ndefinition contains a DEFINER value of CURRENT_USER.\n \nView privileges are checked like this:\nAt view definition time, the view creator must have the\nprivileges needed to use the top-level objects accessed by\nthe view. For example, if the view definition refers to\ntable columns, the creator must have privileges for the\ncolumns, as described previously. If the definition refers\nto a stored function, only the privileges needed to invoke\nthe function can be checked. The privileges required when\nthe function runs can be checked only as it executes: For\ndifferent invocations of the function, different execution\npaths within the function might be taken.\nWhen a view is referenced, privileges for objects accessed\nby the view are checked against the privileges held by the\nview creator or invoker, depending on whether the SQL\nSECURITY characteristic is DEFINER or INVOKER, respectively.\nIf reference to a view causes execution of a stored\nfunction, privilege checking for statements executed within\nthe function depend on whether the function is defined with\na SQL SECURITY characteristic of DEFINER or INVOKER. If the\nsecurity characteristic is DEFINER, the function runs with\nthe privileges of its creator. If the characteristic is\nINVOKER, the function runs with the privileges determined by\nthe view\'s SQL SECURITY characteristic.\n \nMySQL until 5.1.1\n \nPrior to MySQL 5.1.2 (before the DEFINER and SQL SECURITY\nclauses were\nimplemented), privileges required for objects used in a view\nare\nchecked at view creation time.\n \nExample: A view might depend on a stored function, and that\nfunction\nmight invoke other stored routines. For example, the\nfollowing view\ninvokes a stored function f():\n \nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n \nSuppose that f() contains a statement such as this:\n \nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n \nThe privileges required for executing statements within f()\nneed to be\nchecked when f() executes. This might mean that privileges\nare needed\nfor p1() or p2(), depending on the execution path within\nf(). Those\nprivileges must be checked at runtime, and the user who must\npossess\nthe privileges is determined by the SQL SECURITY values of\nthe view v\nand the function f().\n \nThe DEFINER and SQL SECURITY clauses for views are\nextensions to\nstandard SQL. In standard SQL, views are handled using the\nrules for\nSQL SECURITY INVOKER.\n \nIf you invoke a view that was created before MySQL 5.1.2, it\nis\ntreated as though it was created with a SQL SECURITY DEFINER\nclause\nand with a DEFINER value that is the same as your account.\nHowever,\nbecause the actual definer is unknown, MySQL issues a\nwarning. To make\nthe warning go away, it is sufficient to re-create the view\nso that\nthe view definition includes a DEFINER clause.\n \nThe optional ALGORITHM clause is an extension to standard\nSQL. It\naffects how MariaDB processes the view. ALGORITHM takes\nthree values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is\nUNDEFINED if\nno ALGORITHM clause is present. See View Algorithms for more\ninformation.\n \nSome views are updatable. That is, you can use them in\nstatements such\nas UPDATE, DELETE, or INSERT to update the contents of the\nunderlying\ntable. For a view to be updatable, there must be a\none-to-one\nrelationship between the rows in the view and the rows in\nthe\nunderlying table. There are also certain other constructs\nthat make a\nview non-updatable. See Inserting and Updating with Views.\n \nWITH CHECK OPTION\n \nThe WITH CHECK OPTION clause can be given for an updatable\nview to\nprevent inserts or updates to rows except those for which\nthe WHERE\nclause in the select_statement is true.\n \nIn a WITH CHECK OPTION clause for an updatable view, the\nLOCAL and\nCASCADED keywords determine the scope of check testing when\nthe view\nis defined in terms of another view. The LOCAL keyword\nrestricts the\nCHECK OPTION only to the view being defined. CASCADED causes\nthe\nchecks for underlying views to be evaluated as well. When\nneither\nkeyword is given, the default is CASCADED.\n \nFor more information about updatable views and the WITH\nCHECK OPTION\nclause, see\nInserting and Updating with Views.\n \nIF NOT EXISTS\n \nThe IF NOT EXISTS clause was added in MariaDB 10.1.3\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the specified view already\nexists. Cannot be used together with the OR REPLACE clause.\n \nExamples\n-------- \nCREATE TABLE t (a INT, b INT) ENGINE = InnoDB;\n \nINSERT INTO t VALUES (1,1), (2,2), (3,3);\n \nCREATE VIEW v AS SELECT a, a*2 AS a2 FROM t;\n \nSELECT * FROM v;\n \n+------+------+\n| a | a2 |\n+------+------+\n| 1 | 2 |\n| 2 | 4 |\n| 3 | 6 |\n+------+------+\n \nOR REPLACE and IF NOT EXISTS:\n \nCREATE VIEW v AS SELECT a, a*2 AS a2 FROM t;\n \nERROR 1050 (42S01): Table \'v\' already exists\n \nCREATE OR REPLACE VIEW v AS SELECT a, a*2 AS a2 FROM t;\n \nQuery OK, 0 rows affected (0.04 sec)\n \nCREATE VIEW IF NOT EXISTS v AS SELECT a, a*2 AS a2 FROM t;\n \nQuery OK, 0 rows affected, 1 warning (0.01 sec)\n \nSHOW WARNINGS;\n \n+-------+------+--------------------------+\n| Level | Code | Message |\n+-------+------+--------------------------+\n| Note | 1050 | Table \'v\' already exists |\n+-------+------+--------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-view/','','https://mariadb.com/kb/en/create-view/'),(673,'DROP PACKAGE',39,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nDROP PACKAGE [IF EXISTS] [ db_name . ] package_name\n \nDescription\n----------- \nThe DROP PACKAGE statement can be used when Oracle SQL_MODE\nis set.\n \nThe DROP PACKAGE statement drops a stored package entirely:\nDrops the package specification (earlier created using the\nCREATE PACKAGE statement).\nDrops the package implementation, if the implementation was\nalready created using the CREATE PACKAGE BODY statement.\n \n\n\nURL: https://mariadb.com/kb/en/drop-package/','','https://mariadb.com/kb/en/drop-package/'),(674,'DROP PACKAGE BODY',39,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nDROP PACKAGE BODY [IF EXISTS] [ db_name . ] package_name\n \nDescription\n----------- \nThe DROP PACKAGE BODY statement can be used when Oracle\nSQL_MODE is set.\n \nThe DROP PACKAGE BODY statement drops the package body (i.e\nthe implementation), previously created using the CREATE\nPACKAGE BODY statement.\n \nNote, DROP PACKAGE BODY drops only the package\nimplementation, but does not drop the package specification.\nUse DROP PACKAGE to drop the package entirely (i.e. both\nimplementation and specification).\n \n\n\nURL: https://mariadb.com/kb/en/drop-package-body/','','https://mariadb.com/kb/en/drop-package-body/'),(679,'DROP TABLESPACE',39,'The DROP TABLESPACE statement is not supported by MariaDB.\nIt was originally inherited from MySQL NDB Cluster. In MySQL\n5.7 and later, the statement is also supported for InnoDB.\nHowever, MariaDB has chosen not to include that specific\nfeature. See MDEV-19294 for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/drop-tablespace/','','https://mariadb.com/kb/en/drop-tablespace/'),(687,'Generated (Virtual and Persistent/Stored) Columns',39,'Syntax\n------ \n [GENERATED ALWAYS] AS ( )\n[VIRTUAL | PERSISTENT | STORED] [UNIQUE] [UNIQUE KEY]\n[COMMENT ]\n \nMariaDB\'s generated columns syntax is designed to be\nsimilar to the syntax for Microsoft SQL Server\'s computed\ncolumns and Oracle Database\'s virtual columns. In MariaDB\n10.2 and later, the syntax is also compatible with the\nsyntax for MySQL\'s generated columns.\n \nDescription\n----------- \nA generated column is a column in a table that cannot\nexplicitly be set to a specific value in a DML query.\nInstead, its value is automatically generated based on an\nexpression. This expression might generate the value based\non the values of other columns in the table, or it might\ngenerate the value by calling built-in functions or\nuser-defined functions (UDFs).\n \nThere are two types of generated columns:\nPERSISTENT or STORED: This type\'s value is actually stored\nin the table.\nVIRTUAL: This type\'s value is not stored at all. Instead,\nthe value is generated dynamically when the table is\nqueried. This type is the default.\n \nGenerated columns are also sometimes called computed columns\nor virtual columns.\n \nSupported Features\n \nStorage Engine Support\n \nGenerated columns can only be used with storage engines\nwhich support them. If you try to use a storage engine that\ndoes not support them, then you will see an error similar to\nthe following:\n \nERROR 1910 (HY000): TokuDB storage engine does not support\ncomputed columns\nInnoDB, Aria, MyISAM and CONNECT support generated columns.\n \nA column in a MERGE table can be built on a PERSISTENT\ngenerated column.\nHowever, a column in a MERGE table can not be defined as a\nVIRTUAL and PERSISTENT generated column.\n \n\nData Type Support\n \nAll data types are supported when defining generated\ncolumns.\n \nUsing the ZEROFILL column option is supported when defining\ngenerated columns.\n \nIn MariaDB 10.2.6 and later, the following statements apply\nto data types for generated columns:\nUsing the AUTO_INCREMENT column option is not supported when\ndefining generated columns. Previously, it was supported,\nbut this support was removed, because it would not work\ncorrectly. See MDEV-11117.\n \nIndex Support\n \nUsing a generated column as a table\'s primary key is not\nsupported. See MDEV-5590 for more information. If you try to\nuse one as a primary key, then you will see an error similar\nto the following:\n \nERROR 1903 (HY000): Primary key cannot be defined upon a\ncomputed column\nUsing PERSISTENT generated columns as part of a foreign key\nis supported.\n \nReferencing PERSISTENT generated columns as part of a\nforeign key is also supported.\nHowever, using the ON UPDATE CASCADE, ON UPDATE SET NULL, or\nON DELETE SET NULL clauses is not supported. If you try to\nuse an unsupported clause, then you will see an error\nsimilar to the following:\n \nERROR 1905 (HY000): Cannot define foreign key with ON UPDATE\nSET NULL clause on a computed column\n \nIn MariaDB 10.2.3 and later, the following statements apply\nto indexes for generated columns:\nDefining indexes on both VIRTUAL and PERSISTENT generated\ncolumns is supported.\nIf an index is defined on a generated column, then the\noptimizer considers using it in the same way as indexes\nbased on \"real\" columns.\n \n\nMariaDB until 10.2.2\n \nIn MariaDB 10.2.2 and before, the following statements apply\nto indexes for generated columns:\nDefining indexes on VIRTUAL generated columns is not\nsupported.\n \nDefining indexes on PERSISTENT generated columns is\nsupported.\nIf an index is defined on a generated column, then the\noptimizer considers using it in the same way as indexes\nbased on \"real\" columns.\n \n\nStatement Support\n \nGenerated columns are used in DML queries just as if they\nwere \"real\" columns.\nHowever, VIRTUAL and PERSISTENT generated columns differ in\nhow their data is stored.\nValues for PERSISTENT generated columns are generated\nwhenever a DML queries inserts or updates the row with the\nspecial DEFAULT value. This generates the columns value, and\nit is stored in the table like the other \"real\" columns.\nThis value can be read by other DML queries just like the\nother \"real\" columns.\nValues for VIRTUAL generated columns are not stored in the\ntable. Instead, the value is generated dynamically whenever\nthe column is queried. If other columns in a row are\nqueried, but the VIRTUAL generated column is not one of the\nqueried columns, then the column\'s value is not generated.\n \nThe SELECT statement supports generated columns.\n \nGenerated columns can be referenced in the INSERT, UPDATE,\nand DELETE statements.\nHowever, VIRTUAL or PERSISTENT generated columns cannot be\nexplicitly set to any other values than NULL or DEFAULT. If\na generated column is explicitly set to any other value,\nthen the outcome depends on whether strict mode is enabled\nin SQL_MODE. If it is not enabled, then a warning will be\nraised and the default generated value will be used instead.\nIf it is enabled, then an error will be raised instead.\n \nThe CREATE TABLE statement has limited support for generated\ncolumns.\nIt supports defining generated columns in a new table.\nIt supports using generated columns to partition tables.\nIt does not support using the versioning clauses with\ngenerated columns.\n \nThe ALTER TABLE statement has limited support for generated\ncolumns.\nIt supports the MODIFY and CHANGE clauses for PERSISTENT\ngenerated columns.\nIt does not support the MODIFY clause for VIRTUAL generated\ncolumns if ALGORITHM is not set to COPY. See MDEV-15476 for\nmore information.\nIt does not support the CHANGE clause for VIRTUAL generated\ncolumns if ALGORITHM is not set to COPY. See MDEV-17035 for\nmore information.\nIt does not support altering a table if ALGORITHM is not set\nto COPY if the table has a VIRTUAL generated column that is\nindexed. See MDEV-14046 for more information.\nIt does not support adding a VIRTUAL generated column with\nthe ADD clause if the same statement is also adding other\ncolumns if ALGORITHM is not set to COPY. See MDEV-17468 for\nmore information.\nIt also does not support altering an existing column into a\nVIRTUAL generated column.\nIt supports using generated columns to partition tables.\nIt does not support using the versioning clauses with\ngenerated columns.\n \nThe SHOW CREATE TABLE statement supports generated columns.\n \nThe DESCRIBE statement can be used to check whether a table\nhas generated columns.\nYou can tell which columns are generated by looking for the\nones where the Extra column is set to either VIRTUAL or\nPERSISTENT. For example:\n \nDESCRIBE table1;\n \n+-------+-------------+------+-----+---------+------------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+-------------+------+-----+---------+------------+\n| a | int(11) | NO | | NULL | |\n| b | varchar(32) | YES | | NULL | |\n| c | int(11) | YES | | NULL | VIRTUAL |\n| d | varchar(5) | YES | | NULL | PERSISTENT |\n+-------+-------------+------+-----+---------+------------+\nGenerated columns can be properly referenced in the NEW and\nOLD rows in triggers.\n \nStored procedures support generated columns.\n \nThe HANDLER statement supports generated columns.\n \nExpression Support\n \nMost legal, deterministic expressions which can be\ncalculated are supported in expressions for generated\ncolumns.\n \nMost built-in functions are supported in expressions for\ngenerated columns.\nHowever, some built-in functions can\'t be supported for\ntechnical reasons. For example, If you try to use an\nunsupported function in an expression, then you will see an\nerror similar to the following:\n \nERROR 1901 (HY000): Function or expression \'dayname()\'\ncannot be used in the GENERATED ALWAYS AS clause of `v`\nSubqueries are not supported in expressions for generated\ncolumns because the underlying data can change.\n \nUsing anything that depends on data outside the row is not\nsupported in expressions for generated columns.\n \nStored functions are not supported in expressions for\ngenerated columns. See MDEV-17587 for more information.\n \nIn MariaDB 10.2.1 and later, the following statements apply\nto expressions for generated columns:\nNon-deterministic built-in functions are supported in\nexpressions for PERSISTENT generated columns.\nIf a non-deterministic function is used for a PERSISTENT\ngenerated column, then any changes made to this table should\nbe logged to the binary log in the row-based logging format\nwhen the binlog_format system variable is set to MIXED.\nHowever, this does not always happen. Therefore, it is\nrecommended to set the binlog_format system variable to ROW.\nSee MDEV-10436 for more information.\n \nNon-deterministic built-in functions are not supported in\nexpressions for VIRTUAL generated columns.\n \nUser-defined functions (UDFs) are supported in expressions\nfor generated columns.\nHowever, MariaDB can\'t check whether a UDF is\ndeterministic, so it is up to the user to be sure that they\ndo not use non-deterministic UDFs with VIRTUAL generated\ncolumns.\n \nDefining a generated column based on other generated columns\ndefined before it in the table definition is supported. For\nexample:\n \nCREATE TABLE t1 (a int as (1), b int as (a));\nHowever, defining a generated column based on other\ngenerated columns defined after in the table definition is\nnot supported in expressions for generation columns because\ngenerated columns are calculated in the order they are\ndefined.\n \nUsing an expression that exceeds 255 characters in length is\nsupported in expressions for generated columns. The new\nlimit for the entire table definition, including all\nexpressions for generated columns, is 65,535 bytes.\n \nUsing constant expressions is supported in expressions for\ngenerated columns. For example:\n \nCREATE TABLE t1 (a int as (1));\n \nMariaDB until 10.2.0\n \nIn MariaDB 10.2.0 and before, the following statements apply\nto expressions for generated columns:\nNon-deterministic built-in functions are not supported in\nexpressions for generated columns.\n \nUser-defined functions (UDFs) are not supported in\nexpressions for generated columns.\n \nDefining a generated column based on other generated columns\ndefined in the table is not supported. Otherwise, it would\ngenerate errors like this:\n \nERROR 1900 (HY000): A computed column cannot be based on a\ncomputed column\nUsing an expression that exceeds 255 characters in length is\nnot supported in expressions for generated columns.\n \nUsing constant expressions is not supported in expressions\nfor generated columns. Otherwise, it would generate errors\nlike this:\n \nERROR 1908 (HY000): Constant expression in computed column\nfunction is not allowed\n \nMySQL Compatibility Support\n \nIn MariaDB 10.2.1 and later, the following statements apply\nto MySQL compatibility for generated columns:\nThe STORED keyword is supported as an alias for the\nPERSISTENT keyword.\n \nTables created with MySQL 5.7 or later that contain MySQL\'s\ngenerated columns can be imported into MariaDB without a\ndump and restore.\n \nMariaDB until 10.2.0\n \nIn MariaDB 10.2.0 and before, the following statements apply\nto MySQL compatibility for generated columns:\nThe STORED keyword is not supported as an alias for the\nPERSISTENT keyword.\n \nTables created with MySQL 5.7 or later that contain MySQL\'s\ngenerated columns can not be imported into MariaDB without a\ndump and restore.\n \nImplementation Differences\n \nGenerated columns are subject to various constraints in\nother DBMSs that are not present in MariaDB\'s\nimplementation. Generated columns may also be called\ncomputed columns or virtual columns in different\nimplementations. The various details for a specific\nimplementation can be found in the documentation for each\nspecific DBMS.\n \nImplementation Differences Compared to Microsoft SQL Server\n \nMariaDB\'s generated columns implementation does not enforce\nthe following\nrestrictions that are present in Microsoft SQL Server\'s\ncomputed columns implementation:\nMariaDB allows server variables in generated column\nexpressions, including those that change dynamically, such\nas warning_count.\nMariaDB allows the CONVERT_TZ() function to be called with a\nnamed time zone as an argument, even though time zone names\nand time offsets are configurable.\nMariaDB allows the CAST() function to be used with\nnon-unicode character sets, even though character sets are\nconfigurable and differ between binaries/versions.\nMariaDB allows FLOAT expressions to be used in generated\ncolumns. Microsoft SQL Server considers these expressions to\nbe \"imprecise\" due to potential cross-platform differences\nin floating-point implementations and precision.\nMicrosoft SQL Server requires the ARITHABORT mode to be set,\nso that division by zero returns an error, and not a NULL.\nMicrosoft SQL Server requires QUOTED_IDENTIFIER to be set in\nSQL_MODE. In MariaDB, if data is inserted without\nANSI_QUOTES set in SQL_MODE, then it will be processed and\nstored differently in a generated column that contains\nquoted identifiers.\nIn MariaDB 10.2.0 and before, it does not allow user-defined\nfunctions (UDFs) to be used in expressions for generated\ncolumns.\n \nMicrosoft SQL Server enforces the above restrictions by\ndoing one of the following things:\nRefusing to create computed columns.\nRefusing to allow updates to a table containing them.\nRefusing to use an index over such a column if it can not be\nguaranteed that the expression is fully deterministic.\n \nIn MariaDB, as long as the SQL_MODE, language, and other\nsettings that were in effect during the CREATE TABLE remain\nunchanged, the generated column expression will always be\nevaluated the same. If any of these things change, then\nplease be aware that the generated column expression might\nnot be\nevaluated the same way as it previously was.\n \nIn MariaDB 5.2, you will get a warning if you try to update\na virtual column. In MariaDB 5.3 and later, this warning\nwill be converted to an error if strict mode is enabled in\nSQL_MODE.\n \nDevelopment History\n \nGenerated columns was originally developed by Andrey Zhakov.\nIt was then modified by Sanja Byelkin and Igor Babaev at\nMonty Program for inclusion in MariaDB. Monty did the work\non MariaDB 10.2 to lift a some of the old limitations.\n \nExamples\n-------- \nHere is an example table that uses both VIRTUAL and\nPERSISTENT virtual columns:\n \nUSE TEST;\n \nCREATE TABLE table1 (\n a INT NOT NULL,\n b VARCHAR(32),\n c INT AS (a mod 10) VIRTUAL,\n d VARCHAR(5) AS (left(b,5)) PERSISTENT);\n \nIf you describe the table, you can easily see which columns\nare virtual by\nlooking in the \"Extra\" column:\n \nDESCRIBE table1;\n \n+-------+-------------+------+-----+---------+------------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+-------------+------+-----+---------+------------+\n| a | int(11) | NO | | NULL | |\n| b | varchar(32) | YES | | NULL | |\n| c | int(11) | YES | | NULL | VIRTUAL |\n| d | varchar(5) | YES | | NULL | PERSISTENT |\n+-------+-------------+------+-----+---------+------------+\n \nTo find out what function(s) generate the value of the\nvirtual column you can use SHOW CREATE TABLE:\n \nSHOW CREATE TABLE table1;\n \n| table1 | CREATE TABLE `table1` (\n `a` int(11) NOT NULL,\n `b` varchar(32) DEFAULT NULL,\n `c` int(11) AS (a mod 10) VIRTUAL,\n `d` varchar(5) AS (left(b,5)) PERSISTENT\n) ENGINE=MyISAM DEFAULT CHARSET=latin1 |\n \nIf you try to insert non-default values into a virtual\ncolumn, you will receive\na warning and what you tried to insert will be ignored and\nthe derived value\ninserted instead:\n \nWARNINGS;\nShow warnings enabled.\n \nINSERT INTO table1 VALUES (1, \'some\ntext\',default,default);\nQuery OK, 1 row affected (0.00 sec)\n \nINSERT INTO table1 VALUES (2, \'more text\',5,default);\nQuery OK, 1 row affected, 1 warning (0.00 sec)\n \nWarning (Code 1645): The value specified for computed column\n\'c\' in table \'table1\' has been ignored.\n \nINSERT INTO table1 VALUES (123, \'even more\ntext\',default,\'something\');\nQuery OK, 1 row affected, 2 warnings (0.00 sec)\n \nWarning (Code 1645): The value specified for computed column\n\'d\' in table \'table1\' has been ignored.\nWarning (Code 1265): Data truncated for column \'d\' at row\n1\n \nSELECT * FROM table1;\n+-----+----------------+------+-------+\n| a | b | c | d |\n+-----+----------------+------+-------+\n| 1 | some text | 1 | some |\n| 2 | more text | 2 | more |\n| 123 | even more text | 3 | even |\n+-----+----------------+------+-------+\n3 rows in set (0.00 sec)\n \nIf the ZEROFILL clause is specified, it should be placed\ndirectly after the type definition, before the AS ():\n \nCREATE TABLE table2 (a INT, b INT ZEROFILL AS (a*2)\nVIRTUAL);\nINSERT INTO table2 (a) VALUES (1);\n \nSELECT * FROM table2;\n \n+------+------------+\n| a | b |\n+------+------------+\n| 1 | 0000000002 |\n+------+------------+\n1 row in set (0.00 sec)\n \nYou can also use virtual columns to implement a \"poor\nman\'s partial index\". See example at the end of Unique\nIndex.\n \n\n\nURL: https://mariadb.com/kb/en/generated-columns/','','https://mariadb.com/kb/en/generated-columns/'),(688,'LASTVAL',40,'LASTVAL is a synonym for PREVIOUS VALUE for sequence_name.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/lastval/','','https://mariadb.com/kb/en/lastval/'),(690,'NEXTVAL',40,'NEXTVAL is a synonym for NEXT VALUE for sequence_name.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/nextval/','','https://mariadb.com/kb/en/nextval/'),(345,'HELP Command',26,'Syntax\n------ \nHELP search_string\n \nDescription\n----------- \nThe HELP command can be used in any MariaDB client, such as\nthe mysql command-line client, to get basic syntax help and\na short description for most commands and functions. \n \nIf you provide an argument to the HELP command, the mysql\nclient uses it as a search string to access server-side\nhelp. The proper operation of this command requires that the\nhelp tables in the mysql database be initialized with help\ntopic information.\n \nIf there is no match for the search string, the search\nfails. Use help contents to see a list of the help\ncategories:\n \nHELP contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing\ncategories:\n Account Management\n Administration\n Compound Statements\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Help Metadata\n Language Structure\n Plugins\n Procedures\n Sequences\n Table Maintenance\n Transactions\n User-Defined Functions\n Utility\n \nIf a search string matches multiple items, MariaDB shows a\nlist of matching topics:\n \nHELP drop\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following\ntopics:\n ALTER TABLE\n DROP DATABASE\n DROP EVENT\n DROP FUNCTION\n DROP FUNCTION UDF\n DROP INDEX\n DROP PACKAGE\n DROP PACKAGE BODY\n DROP PROCEDURE\n DROP ROLE\n DROP SEQUENCE\n DROP SERVER\n DROP TABLE\n DROP TRIGGER\n DROP USER\n DROP VIEW\n \nThen you can enter a topic as the search string to see the\nhelp entry for that topic.\n \nThe help is provided with the MariaDB server and makes use\nof four help tables found in the mysql database:\nhelp_relation, help_topic, help_category and help_keyword.\nThese tables are populated by the mysql_install_db or\nfill_help_table.sql scripts which, until MariaDB 10.4.7,\ncontain data generated from an old version of MySQL.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/help-command/','','https://mariadb.com/kb/en/help-command/'),(346,'KILL [CONNECTION | QUERY]',26,'Syntax\n------ \nKILL [HARD | SOFT] [CONNECTION | QUERY [ID] ] [thread_id |\nUSER user_name | query_id]\n \nMariaDB 5.3.2\n \nThe options HARD | SOFT and USER username were introduced in\nMariaDB 5.3.2\n \nMariaDB 10.0.5\n \nKILL QUERY ID query_id, which permits killing a query by\nquery id rather than thread id, was introduced in MariaDB\n10.0.5.\n \nDescription\n----------- \nEach connection to mysqld runs in a separate thread. You can\nsee which threads\nare running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement. \nKILL allows the optional CONNECTION or\nQUERY modifier:\nKILL CONNECTION is the same as KILL with no\n modifier: It terminates the connection associated with the\ngiven thread or query id.\nKILL QUERY terminates the statement that the connection\nthread_id is\n currently executing, but leaves the connection itself\nintact.\nKILL QUERY ID (introduced in MariaDB 10.0.5) terminates the\nquery by query_id, leaving the connection intact.\n \nIf a connection is terminated that has an active\ntransaction, the transaction will be rolled back. If only a\nquery is killed, the current transaction will stay active.\nSee also idle_transaction_timeout.\n \nIf you have the PROCESS privilege, you can see all threads.\nIf\nyou have the SUPER privilege, you can kill all threads and\nstatements. Otherwise, you can see and kill only your own\nthreads and\nstatements.\n \nKilling queries that repair or create indexes on MyISAM and\nAria tables may result in corrupted tables. Use the SOFT\noption to avoid this!\n \nThe HARD option (default) kills a command as soon as\npossible. If you use\nSOFT, then critical operations that may leave a table in an\ninconsistent state will not be interrupted. Such operations\ninclude REPAIR and INDEX creation for MyISAM and Aria tables\n(REPAIR TABLE, OPTIMIZE TABLE).\n \nKILL ... USER username will kill all connections/queries for\na\ngiven user. USER can be specified one of the following ways:\nusername (Kill without regard to hostname)\nusername@hostname\nCURRENT_USER or CURRENT_USER()\n \nIf you specify a thread id and that thread does not exist,\nyou get the following error:\n \nERROR 1094 (HY000): Unknown thread id: \n \nIf you specify a query id that doesn\'t exist, you get the\nfollowing error:\n \nERROR 1957 (HY000): Unknown query id: \n \nHowever, if you specify a user name, no error is issued for\nnon-connected (or even non-existing) users. To check if the\nconnection/query has been killed, you can use the\nROW_COUNT() function.\n \nA client whose connection is killed receives the following\nerror:\n \nERROR 1317 (70100): Query execution was interrupted\n \nTo obtain a list of existing sessions, use the SHOW\nPROCESSLIST statement or query the Information Schema\nPROCESSLIST table.\n \nNote: You cannot use KILL with the Embedded MySQL Server\nlibrary because the embedded server merely runs inside the\nthreads of the host\napplication. It does not create any connection threads of\nits own.\n \nNote: You can also use \nmysqladmin kill thread_id [,thread_id...]\nto kill connections. To get a list of running queries,\nuse mysqladmin processlist. See mysqladmin.\n \nPercona Toolkit contains a program, pt-kill that can be used\nto automatically kill connections that match certain\ncriteria. For example, it can be used to terminate idle\nconnections, or connections that have been busy for more\nthan 60 seconds.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/data-manipulation-kill-connection-query/','','https://mariadb.com/kb/en/data-manipulation-kill-connection-query/'),(695,'JSON_ARRAY',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_ARRAY([value[, value2] ...])\n \nDescription\n----------- \nReturns a JSON array containing the listed values. The list\ncan be empty.\n \nExample\n \nSELECT Json_Array(56, 3.1416, \'My name is \"Foo\"\', NULL);\n+--------------------------------------------------+\n| Json_Array(56, 3.1416, \'My name is \"Foo\"\', NULL) |\n+--------------------------------------------------+\n| [56, 3.1416, \"My name is \\\"Foo\\\"\", null] |\n+--------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_array/','','https://mariadb.com/kb/en/json_array/'),(698,'JSON_COMPACT',41,'This function was added in MariaDB 10.2.4.\n \nSyntax\n------ \nJSON_COMPACT(json_doc)\n \nDescription\n----------- \nRemoves all unnecessary spaces so the json document is as\nshort as possible.\n \nExample\n \nSET @j = \'{ \"A\": 1, \"B\": [2, 3]}\';\n \nSELECT JSON_COMPACT(@j), @j;\n+-------------------+------------------------+\n| JSON_COMPACT(@j) | @j |\n+-------------------+------------------------+\n| {\"A\":1,\"B\":[2,3]} | { \"A\": 1, \"B\": [2, 3]} |\n+-------------------+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_compact/','','https://mariadb.com/kb/en/json_compact/'),(702,'JSON_DETAILED',41,'This function was added in MariaDB 10.2.4.\n \nSyntax\n------ \nJSON_DETAILED(json_doc[, tab_size])\n \nDescription\n----------- \nRepresents JSON in the most understandable way emphasizing\nnested structures.\n \nExample\n \nSET @j = \'{ \"A\":1,\"B\":[2,3]}\';\n \nSELECT @j;\n+--------------------+\n| @j |\n+--------------------+\n| { \"A\":1,\"B\":[2,3]} |\n+--------------------+\n \nSELECT JSON_DETAILED(@j);\n+------------------------------------------------------------+\n| JSON_DETAILED(@j) |\n+------------------------------------------------------------+\n| {\n \"A\": 1,\n \"B\": \n [\n 2,\n 3\n ]\n} |\n+------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_detailed/','','https://mariadb.com/kb/en/json_detailed/'),(348,'RESET',26,'Syntax\n------ \nRESET reset_option [, reset_option] ...\n \nDescription\n----------- \nThe RESET statement is used to clear the state of various\nserver\noperations. You must have the RELOAD privilege to execute\nRESET.\n \nRESET acts as a stronger version of the FLUSH statement.\n \nThe different RESET options are:\n \nOption | Description | \n \nSLAVE [\"connection_name\"] [ALL] | Deletes all relay logs\nfrom the slave and reset the replication position in the\nmaster binary log. | \n \nMASTER | Deletes all old binary logs, makes the binary index\nfile (--log-bin-index) empty and creates a new binary log\nfile. This is useful when you want to reset the master to an\ninitial state. If you want to just delete old, not used\nbinary logs, you should use the PURGE BINARY LOGS command. |\n\n \nQUERY CACHE | Removes all queries from the query cache. See\nalso FLUSH QUERY CACHE. | \n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/reset/','','https://mariadb.com/kb/en/reset/'),(349,'SET',26,'Syntax\n------ \nSET variable_assignment [, variable_assignment] ...\n \nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n \nOne can also set a user variable in any expression with this\nsyntax:\n \nuser_var_name:= expr\n \nDescription\n----------- \nThe SET statement assigns values to different types of\nvariables that affect the operation of the server or your\nclient. Older\nversions of MySQL employed SET OPTION, but this syntax was\ndeprecated in favor of SET without OPTION, and was removed\nin MariaDB 10.0.\n \nChanging a system variable by using the SET statement does\nnot make the change permanently. To do so, the change must\nbe made in a configuration file.\n \nFor setting variables on a per-query basis (from MariaDB\n10.1.2), see SET STATEMENT.\n \nSee SHOW VARIABLES for documentation on viewing server\nsystem variables.\n \nSee Server System Variables for a list of all the system\nvariables.\n \nGLOBAL / SESSION\n \nWhen setting a system variable, the scope can be specified\nas either GLOBAL or SESSION.\n \nA global variable change affects all new sessions. It does\nnot affect any currently open sessions, including the one\nthat made the change. \n \nA session variable change affects the current session only.\n \nIf the variable has a session value, not specifying either\nGLOBAL or SESSION will be the same as specifying SESSION. If\nthe variable only has a global value, not specifying GLOBAL\nor SESSION will apply to the change to the global value.\n \nDEFAULT\n \nSetting a global variable to DEFAULT will restore it to the\nserver default, and setting a session variable to DEFAULT\nwill restore it to the current global value.\n \nExamples\n-------- \ninnodb_sync_spin_loops is a global variable.\nskip_parallel_replication is a session variable.\nmax_error_count is both global and session.\n \nSELECT VARIABLE_NAME, SESSION_VALUE, GLOBAL_VALUE FROM\n INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE \n VARIABLE_NAME LIKE \'max_error_count\' OR \n VARIABLE_NAME LIKE \'skip_parallel_replication\' OR \n VARIABLE_NAME LIKE \'innodb_sync_spin_loops\';\n \n+---------------------------+---------------+--------------+\n| VARIABLE_NAME | SESSION_VALUE | GLOBAL_VALUE |\n+---------------------------+---------------+--------------+\n| MAX_ERROR_COUNT | 64 | 64 |\n| SKIP_PARALLEL_REPLICATION | OFF | NULL |\n| INNODB_SYNC_SPIN_LOOPS | NULL | 30 |\n+---------------------------+---------------+--------------+\n \nSetting the session values:\n \nSET max_error_count=128;\nQuery OK, 0 rows affected (0.000 sec)\n \nSET skip_parallel_replication=ON;\nQuery OK, 0 rows affected (0.000 sec)\n \nSET innodb_sync_spin_loops=60;\n \nERROR 1229 (HY000): Variable \'innodb_sync_spin_loops\' is a\nGLOBAL variable \n and should be set with SET GLOBAL\n \nSELECT VARIABLE_NAME, SESSION_VALUE, GLOBAL_VALUE FROM\n INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE \n VARIABLE_NAME LIKE \'max_error_count\' OR \n VARIABLE_NAME LIKE \'skip_parallel_replication\' OR \n VARIABLE_NAME LIKE \'innodb_sync_spin_loops\';\n \n+---------------------------+---------------+--------------+\n| VARIABLE_NAME | SESSION_VALUE | GLOBAL_VALUE |\n+---------------------------+---------------+--------------+\n| MAX_ERROR_COUNT | 128 | 64 |\n| SKIP_PARALLEL_REPLICATION | ON | NULL |\n| INNODB_SYNC_SPIN_LOOPS | NULL | 30 |\n+---------------------------+---------------+--------------+\n \nSetting the global values:\n \nSET GLOBAL max_error_count=256;\n \nSET GLOBAL skip_parallel_replication=ON;\n \nERROR 1228 (HY000): Variable \'skip_parallel_replication\'\nis a SESSION variable \n and can\'t be used with SET GLOBAL\n \nSET GLOBAL innodb_sync_spin_loops=120;\n \nSELECT VARIABLE_NAME, SESSION_VALUE, GLOBAL_VALUE FROM\n INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE \n VARIABLE_NAME LIKE \'max_error_count\' OR \n VARIABLE_NAME LIKE \'skip_parallel_replication\' OR \n VARIABLE_NAME LIKE \'innodb_sync_spin_loops\';\n \n+---------------------------+---------------+--------------+\n| VARIABLE_NAME | SESSION_VALUE | GLOBAL_VALUE |\n+---------------------------+---------------+--------------+\n| MAX_ERROR_COUNT | 128 | 256 |\n| SKIP_PARALLEL_REPLICATION | ON | NULL |\n| INNODB_SYNC_SPIN_LOOPS | NULL | 120 |\n+---------------------------+---------------+--------------+\n \nSHOW VARIABLES will by default return the session value\nunless the variable is global only.\n \nSHOW VARIABLES LIKE \'max_error_count\';\n \n+-----------------+-------+\n| Variable_name | Value |\n+-----------------+-------+\n| max_error_count | 128 |\n+-----------------+-------+\n \nSHOW VARIABLES LIKE \'skip_parallel_replication\';\n \n+---------------------------+-------+\n| Variable_name | Value |\n+---------------------------+-------+\n| skip_parallel_replication | ON |\n+---------------------------+-------+\n \nSHOW VARIABLES LIKE \'innodb_sync_spin_loops\';\n \n+------------------------+-------+\n| Variable_name | Value |\n+------------------------+-------+\n| innodb_sync_spin_loops | 120 |\n+------------------------+-------+\n \nUsing the inplace syntax:\n \nSELECT (@a:=1);\n+---------+\n| (@a:=1) |\n+---------+\n| 1 |\n+---------+\n \nSELECT @a;\n \n+------+\n| @a |\n+------+\n| 1 |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/set/','','https://mariadb.com/kb/en/set/'),(708,'JSON_LOOSE',41,'This function was added in MariaDB 10.2.4.\n \nSyntax\n------ \nJSON_LOOSE(json_doc)\n \nDescription\n----------- \nAdds spaces to a JSON document to make it look more\nreadable.\n \nExample\n \nSET @j = \'{ \"A\":1,\"B\":[2,3]}\';\n \nSELECT JSON_LOOSE(@j), @j;\n+-----------------------+--------------------+\n| JSON_LOOSE(@j) | @j |\n+-----------------------+--------------------+\n| {\"A\": 1, \"B\": [2, 3]} | { \"A\":1,\"B\":[2,3]} |\n+-----------------------+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_loose/','','https://mariadb.com/kb/en/json_loose/'),(712,'JSON_OBJECT',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_OBJECT([key, value[, key, value] ...])\n \nDescription\n----------- \nReturns a JSON object containing the given key/value pairs.\nThe key/value list can be empty.\n \nAn error will occur if there are an odd number of arguments,\nor any key name is NULL.\n \nExample\n \nSELECT JSON_OBJECT(\"id\", 1, \"name\", \"Monty\");\n+---------------------------------------+\n| JSON_OBJECT(\"id\", 1, \"name\", \"Monty\") |\n+---------------------------------------+\n| {\"id\": 1, \"name\": \"Monty\"} |\n+---------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_object/','','https://mariadb.com/kb/en/json_object/'),(350,'About SHOW',26,'SHOW has many forms that provide information about\ndatabases, tables, columns, or status information about the\nserver. These include:\nSHOW AUTHORS\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name]\n[like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE PACKAGE package_name\nSHOW CREATE PACKAGE BODY package_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW [FULL] EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW INNODB STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n \nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n \nIf the syntax for a given SHOW statement includes a\nLIKE \'pattern\' part, \'pattern\' is a\nstring that can contain the SQL \"%\" and\n\"_\" wildcard characters. The pattern is useful for\nrestricting statement output to matching values.\n \nSeveral SHOW statements also accept a\nWHERE clause that provides more flexibility in specifying\nwhich rows to display. See Extended Show.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/about-show/','','https://mariadb.com/kb/en/about-show/'),(351,'SHOW AUTHORS',26,'Syntax\n------ \nSHOW AUTHORS\n \nDescription\n----------- \nThe SHOW AUTHORS statement displays information about the\npeople who work on MariaDB. For each author, it displays\nName, Location, and\nComment values. All columns are encoded as latin1.\n \nIn MariaDB 5.5 this is in somewhat random order.\n \nIn MariaDB 10.0.5 and later you have:\nFirst the active people in MariaDB are listed.\nThen the active people in MySQL.\nLast the people that has contributed to MariaDB/MySQL in the\npast.\n \nThe order is somewhat related to importance of the\ncontribution given to the MariaDB project, but this is not\n100% accurate. There is still room for improvements and\ndebate...\n \nExample\n \nSHOW AUTHORS;\n+--------------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n| Name | Location | Comment |\n+--------------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n| Michael (Monty) Widenius | Tusby, Finland | Lead developer\nand main author |\n| Sergei Golubchik | Kerpen, Germany | Architect, Full-text\nsearch, precision math, plugin framework, merges etc |\n| Igor Babaev | Bellevue, USA | Optimizer, keycache, core\nwork |\n| Sergey Petrunia | St. Petersburg, Russia | Optimizer |\n| Oleksandr Byelkin | Lugansk, Ukraine | Query Cache (4.0),\nSubqueries (4.1), Views (5.0) |\n| Timour Katchaounov | Sofia , Bulgaria | Optimizer |\n| Kristian Nielsen | Copenhagen, Denmark | Replication,\nAsync client prototocol, General buildbot stuff |\n| Alexander (Bar) Barkov | Izhevsk, Russia | Unicode and\ncharacter sets |\n| Alexey Botchkov (Holyfoot) | Izhevsk, Russia | GIS\nextensions, embedded server, precision math |\n| Daniel Bartholomew | Raleigh, USA | MariaDB documentation\n|\n| Colin Charles | Selangor, Malesia | MariaDB documentation,\ntalks at a LOT of conferences |\n| Sergey Vojtovich | Izhevsk, Russia | initial\nimplementation of plugin architecture, maintained native\nstorage engines (MyISAM, MEMORY, ARCHIVE, etc), rewrite of\ntable cache |\n| Vladislav Vaintroub | Mannheim, Germany | MariaDB Java\nconnector, new thread pool, Windows optimizations |\n| Elena Stepanova | Sankt Petersburg, Russia | QA, test\ncases |\n| Georg Richter | Heidelberg, Germany | New LGPL C\nconnector, PHP connector |\n| Jan Lindström | Ylämylly, Finland | Working on InnoDB |\n| Lixun Peng | Hangzhou, China | Multi Source replication |\n| Percona | CA, USA | XtraDB, microslow patches, extensions\nto slow log \n...\n \nSee Also\n \nSHOW CONTRIBUTORS. This list all members and sponsors of the\nMariaDB Foundation and other sponsors.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-authors/','','https://mariadb.com/kb/en/show-authors/'),(352,'SHOW BINARY LOGS',26,'Syntax\n------ \nSHOW BINARY LOGS\nSHOW MASTER LOGS\n \nDescription\n----------- \nLists the binary log files on the server. This statement is\nused as part of the\nprocedure described in \nPURGE BINARY LOGS, that shows how to\ndetermine which logs can be purged.\n \nExamples\n-------- \nSHOW BINARY LOGS;\n+--------------------+-----------+\n| Log_name | File_size |\n+--------------------+-----------+\n| mariadb-bin.000001 | 19039 |\n| mariadb-bin.000002 | 717389 |\n| mariadb-bin.000003 | 300 |\n| mariadb-bin.000004 | 333 |\n| mariadb-bin.000005 | 899 |\n| mariadb-bin.000006 | 125 |\n| mariadb-bin.000007 | 18907 |\n| mariadb-bin.000008 | 19530 |\n| mariadb-bin.000009 | 151 |\n| mariadb-bin.000010 | 151 |\n| mariadb-bin.000011 | 125 |\n| mariadb-bin.000012 | 151 |\n| mariadb-bin.000013 | 151 |\n| mariadb-bin.000014 | 125 |\n| mariadb-bin.000015 | 151 |\n| mariadb-bin.000016 | 314 |\n+--------------------+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-binary-logs/','','https://mariadb.com/kb/en/show-binary-logs/'),(718,'JSON_SET',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_SET(json_doc, path, val[, path, val] ...)\n \nDescription\n----------- \nUpdates or inserts data into a JSON document, returning the\nresult, or NULL if any of the arguments are NULL or the\noptional path fails to find an object.\n \nAn error will occur if the JSON document is invalid, the\npath is invalid or if the path contains a * or wildcard.\n \nJSON_SET can update or insert data, while JSON_REPLACE can\nonly update, and JSON_INSERT only insert. \n \nExamples\n-------- \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_set/','','https://mariadb.com/kb/en/json_set/'),(724,'Aggregate Functions as Window Functions',42,'Window functions were first introduced in MariaDB 10.2.0.\n \nIt is possible to use aggregate functions as window\nfunctions. An aggregate function used as a window function\nmust have the OVER clause. For example, here\'s COUNT() used\nas a window function:\n \nselect COUNT(*) over (order by column) from table;\n \nMariaDB currently allows these aggregate functions to be\nused as window functions: \nAVG\nBIT_AND\nBIT_OR\nBIT_XOR\nCOUNT\nMAX\nMIN\nSTD\nSTDDEV\nSTDDEV_POP\nSTDDEV_SAMP\nSUM\nVAR_POP\nVAR_SAMP\nVARIANCE\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/library/aggregate-functions-as-window-functions/','','https://mariadb.com/kb/en/library/aggregate-functions-as-window-functions/'),(726,'CUME_DIST',42,'The CUME_DIST() function was first introduced with window\nfunctions in MariaDB 10.2.0.\n \nSyntax\n------ \nCUME_DIST() OVER ( \n [ PARTITION BY partition_expression ] \n [ ORDER BY order_list ]\n)\n \nDescription\n----------- \nCUME_DIST() is a window function that returns the cumulative\ndistribution of a given row. The following formula is used\nto calculate the value:\n \n(number of rows \n\nURL: https://mariadb.com/kb/en/cume_dist/','','https://mariadb.com/kb/en/cume_dist/'),(353,'SHOW BINLOG EVENTS',26,'Syntax\n------ \nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n \nDescription\n----------- \nShows the events in the binary log. If you do not specify\n\'log_name\',\nthe first binary log is displayed.\n \nExample\n \nSHOW BINLOG EVENTS IN \'mysql_sandbox10019-bin.000002\';\n+-------------------------------+-----+-------------------+-----------+-------------+------------------------------------------------+\n| Log_name | Pos | Event_type | Server_id | End_log_pos |\nInfo |\n+-------------------------------+-----+-------------------+-----------+-------------+------------------------------------------------+\n| mysql_sandbox10019-bin.000002 | 4 | Format_desc | 1 | 248\n| Server ver: 10.0.19-MariaDB-log, Binlog ver: 4 |\n| mysql_sandbox10019-bin.000002 | 248 | Gtid_list | 1 | 273\n| [] |\n| mysql_sandbox10019-bin.000002 | 273 | Binlog_checkpoint |\n1 | 325 | mysql_sandbox10019-bin.000002 |\n| mysql_sandbox10019-bin.000002 | 325 | Gtid | 1 | 363 |\nGTID 0-1-1 |\n| mysql_sandbox10019-bin.000002 | 363 | Query | 1 | 446 |\nCREATE DATABASE blog |\n| mysql_sandbox10019-bin.000002 | 446 | Gtid | 1 | 484 |\nGTID 0-1-2 |\n| mysql_sandbox10019-bin.000002 | 484 | Query | 1 | 571 |\nuse `blog`; CREATE TABLE bb (id INT) |\n+-------------------------------+-----+-------------------+-----------+-------------+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-binlog-events/','','https://mariadb.com/kb/en/show-binlog-events/'),(354,'SHOW CHARACTER SET',26,'Syntax\n------ \nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThe SHOW CHARACTER SET statement shows all available\ncharacter sets. The LIKE clause, if present on its own,\nindicates which character\nset names to match. The WHERE and LIKE clauses can be given\nto select rows using more general conditions, as discussed\nin Extended SHOW.\n \nThe same information can be queried from the\ninformation_schema.CHARACTER_SETS table.\n \nSee Setting Character Sets and Collations for details on\nspecifying the character set at the server, database, table\nand column levels.\n \nExamples\n-------- \nSHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci |\n1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n \nSHOW CHARACTER SET WHERE Maxlen LIKE \'2\';\n+---------+---------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+---------------------------+-------------------+--------+\n| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |\n| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |\n| euckr | EUC-KR Korean | euckr_korean_ci | 2 |\n| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2\n|\n| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |\n| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |\n| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2\n|\n+---------+---------------------------+-------------------+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-character-set/','','https://mariadb.com/kb/en/show-character-set/'),(355,'SHOW CLIENT_STATISTICS',26,'MariaDB 5.2 introduced the User Statistics feature.\n \nSyntax\n------ \nSHOW CLIENT_STATISTICS\n \nDescription\n----------- \nThe SHOW CLIENT_STATISTICS statement was introduced in\nMariaDB 5.2 as part of the User Statistics feature. It was\nremoved as a separate statement in MariaDB 10.1.1, but\neffectively replaced by the generic SHOW\ninformation_schema_table statement. The\ninformation_schema.CLIENT_STATISTICS table holds statistics\nabout client connections.\n \nThe userstat system variable must be set to 1 to activate\nthis feature. See the User Statistics and\ninformation_schema.CLIENT_STATISTICS articles for more\ninformation.\n \nExample\n \nFrom MariaDB 10.0:\n \nSHOW CLIENT_STATISTICS\\G\n*************************** 1. row\n***************************\n Client: localhost\n Total_connections: 35\nConcurrent_connections: 0\n Connected_time: 708\n Busy_time: 2.5557979999999985\n Cpu_time: 0.04123740000000002\n Bytes_received: 3883\n Bytes_sent: 21595\n Binlog_bytes_written: 0\n Rows_read: 18\n Rows_sent: 115\n Rows_deleted: 0\n Rows_inserted: 0\n Rows_updated: 0\n Select_commands: 70\n Update_commands: 0\n Other_commands: 0\n Commit_transactions: 1\n Rollback_transactions: 0\n Denied_connections: 0\n Lost_connections: 0\n Access_denied: 0\n Empty_queries: 35\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-client-statistics/','','https://mariadb.com/kb/en/show-client-statistics/'),(356,'SHOW COLLATION',26,'Syntax\n------ \nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThe output from SHOW COLLATION includes all available\ncollations. The LIKE clause, if present on its own,\nindicates which collation names to match. The WHERE and LIKE\nclauses can be given to select rows using more general\nconditions, as discussed in Extended SHOW.\n \nThe same information can be queried from the\ninformation_schema.COLLATIONS table.\n \nSee Setting Character Sets and Collations for details on\nspecifying the collation at the server, database, table and\ncolumn levels.\n \nExamples\n-------- \nSHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | Yes | 1 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |\n| latin1_danish_ci | latin1 | 15 | | Yes | 1 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 1 |\n| latin1_general_ci | latin1 | 48 | | Yes | 1 |\n| latin1_general_cs | latin1 | 49 | | Yes | 1 |\n| latin1_spanish_ci | latin1 | 94 | | Yes | 1 |\n+-------------------+---------+----+---------+----------+---------+\n \nSHOW COLLATION WHERE Sortlen LIKE \'8\' AND Charset LIKE\n\'utf8\';\n+--------------------+---------+-----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+--------------------+---------+-----+---------+----------+---------+\n| utf8_unicode_ci | utf8 | 192 | | Yes | 8 |\n| utf8_icelandic_ci | utf8 | 193 | | Yes | 8 |\n| utf8_latvian_ci | utf8 | 194 | | Yes | 8 |\n| utf8_romanian_ci | utf8 | 195 | | Yes | 8 |\n| utf8_slovenian_ci | utf8 | 196 | | Yes | 8 |\n| utf8_polish_ci | utf8 | 197 | | Yes | 8 |\n| utf8_estonian_ci | utf8 | 198 | | Yes | 8 |\n| utf8_spanish_ci | utf8 | 199 | | Yes | 8 |\n| utf8_swedish_ci | utf8 | 200 | | Yes | 8 |\n| utf8_turkish_ci | utf8 | 201 | | Yes | 8 |\n| utf8_czech_ci | utf8 | 202 | | Yes | 8 |\n| utf8_danish_ci | utf8 | 203 | | Yes | 8 |\n| utf8_lithuanian_ci | utf8 | 204 | | Yes | 8 |\n| utf8_slovak_ci | utf8 | 205 | | Yes | 8 |\n| utf8_spanish2_ci | utf8 | 206 | | Yes | 8 |\n| utf8_roman_ci | utf8 | 207 | | Yes | 8 |\n| utf8_persian_ci | utf8 | 208 | | Yes | 8 |\n| utf8_esperanto_ci | utf8 | 209 | | Yes | 8 |\n| utf8_hungarian_ci | utf8 | 210 | | Yes | 8 |\n| utf8_sinhala_ci | utf8 | 211 | | Yes | 8 |\n| utf8_croatian_ci | utf8 | 213 | | Yes | 8 |\n+--------------------+---------+-----+---------+----------+---------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-collation/','','https://mariadb.com/kb/en/show-collation/'),(357,'SHOW COLUMNS',26,'Syntax\n------ \nSHOW [FULL] {COLUMNS | FIELDS} FROM tbl_name [FROM db_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nSHOW COLUMNS displays information about the columns in a\ngiven table. It also works for views. The LIKE clause, if\npresent on its own, indicates which column names to match.\nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nIf the data types differ from what you expect them to be\nbased on a\nCREATE TABLE statement, note that MariaDB sometimes changes\ndata types when you create or alter a table. The conditions\nunder which this\noccurs are described in the Silent Column Changes article.\n \nThe FULL keyword causes the output to include the column\ncollation and comments, as well as the privileges you have\nfor each column.\n \nYou can use db_name.tbl_name as an alternative to the\ntbl_name FROM db_name syntax. In other words, these two\nstatements are equivalent:\n \nSHOW COLUMNS FROM mytable FROM mydb;\nSHOW COLUMNS FROM mydb.mytable;\n \nSHOW COLUMNS displays the following values for each table\ncolumn:\n \nField indicates the column name.\n \nType indicates the column data type.\n \nCollation indicates the collation for non-binary string\ncolumns, or\nNULL for other columns. This value is displayed only if you\nuse the\nFULL keyword.\n \nThe Null field contains YES if NULL values can be stored in\nthe column,\nNO if not.\n \nThe Key field indicates whether the column is indexed:\nIf Key is empty, the column either is not indexed or is\nindexed only as a\n secondary column in a multiple-column, non-unique index.\nIf Key is PRI, the column is a PRIMARY KEY or\n is one of the columns in a multiple-column PRIMARY KEY.\nIf Key is UNI, the column is the first column of a\nunique-valued\n index that cannot contain NULL values.\nIf Key is MUL, multiple occurrences of a given value are\nallowed\n within the column. The column is the first column of a\nnon-unique index or a\n unique-valued index that can contain NULL values.\n \nIf more than one of the Key values applies to a given column\nof a\ntable, Key displays the one with the highest priority, in\nthe order\nPRI, UNI, MUL.\n \nA UNIQUE index may be displayed as PRI if\nit cannot contain NULL values and there is no\nPRIMARY KEY in the table. A UNIQUE index\nmay display as MUL if several columns form a composite\nUNIQUE index; although the combination of the columns is\nunique, each column can still hold multiple occurrences of a\ngiven value.\n \nThe Default field indicates the default value that is\nassigned to the\ncolumn.\n \nThe Extra field contains any additional information that is\navailable about a given column.\n \nValue | Description | \n \nAUTO_INCREMENT | The column was created with the\nAUTO_INCREMENT keyword. | \n \nPERSISTENT | The column was created with the PERSISTENT\nkeyword. (New in 5.3) | \n \nVIRTUAL | The column was created with the VIRTUAL keyword.\n(New in 5.3) | \n \non update CURRENT_TIMESTAMP | The column is a TIMESTAMP\ncolumn that is automatically updated on INSERT and UPDATE. |\n\n \nPrivileges indicates the privileges you have for the column.\nThis\nvalue is displayed only if you use the FULL keyword.\n \nComment indicates any comment the column has. This value is\ndisplayed\nonly if you use the FULL keyword.\n \nSHOW FIELDS is a synonym for\nSHOW COLUMNS. Also DESCRIBE and EXPLAIN can be used as\nshortcuts.\n \nYou can also list a table\'s columns with: \n \nmysqlshow db_name tbl_name\n \nSee the mysqlshow command for more details.\n \nThe DESCRIBE statement provides information similar to SHOW\nCOLUMNS. The information_schema.COLUMNS table provides\nsimilar, but more complete, information.\n \nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX\nstatements also provide information about tables.\n \nExamples\n-------- \nSHOW COLUMNS FROM city;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n \nSHOW COLUMNS FROM employees WHERE Type LIKE \'Varchar%\';\n+---------------+-------------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+---------------+-------------+------+-----+---------+-------+\n| first_name | varchar(30) | NO | MUL | NULL | |\n| last_name | varchar(40) | NO | | NULL | |\n| position | varchar(25) | NO | | NULL | |\n| home_address | varchar(50) | NO | | NULL | |\n| home_phone | varchar(12) | NO | | NULL | |\n| employee_code | varchar(25) | NO | UNI | NULL | |\n+---------------+-------------+------+-----+---------+-------+\n \n\n\nURL: https://mariadb.com/kb/en/show-columns/','','https://mariadb.com/kb/en/show-columns/'),(732,'NTH_VALUE',42,'The NTH_VALUE() function was first introduced with other\nwindow functions in MariaDB 10.2.\n \nSyntax\n------ \nNTH_VALUE (expr[, num_row]) OVER ( \n [ PARTITION BY partition_expression ] \n [ ORDER BY order_list ]\n)\n \nDescription\n----------- \nThe NTH_VALUE function returns the value evaluated at row\nnumber num_row of the window frame, starting from 1, or NULL\nif the row does not exist.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/nth_value/','','https://mariadb.com/kb/en/nth_value/'),(742,'SPIDER_FLUSH_TABLE_MON_CACHE',43,'Syntax\n------ \nSPIDER_FLUSH_TABLE_MON_CACHE()\n \nDescription\n----------- \nA UDF installed with the Spider Storage Engine, this\nfunction is used for refreshing monitoring server\ninformation. It returns a value of 1.\n \nExamples\n-------- \nSELECT SPIDER_FLUSH_TABLE_MON_CACHE();\n+--------------------------------+\n| SPIDER_FLUSH_TABLE_MON_CACHE() |\n+--------------------------------+\n| 1 |\n+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/spider_flush_table_mon_cache/','','https://mariadb.com/kb/en/spider_flush_table_mon_cache/'),(744,'COLUMN_CHECK',44,'The COLUMN_CHECK function was added in MariaDB 10.0.1.\n \nSyntax\n------ \nCOLUMN_CHECK(dyncol_blob);\n \nDescription\n----------- \nCheck if dyncol_blob is a valid packed dynamic columns blob.\nReturn value of 1 means the blob is valid, return value of 0\nmeans it is not.\n \nRationale:\nNormally, one works with valid dynamic column blobs.\nFunctions like COLUMN_CREATE, COLUMN_ADD, COLUMN_DELETE\nalways return valid dynamic column blobs. However, if a\ndynamic column blob is accidentally truncated, or transcoded\nfrom one character set to another, it will be corrupted.\nThis function can be used to check if a value in a blob\nfield is a valid dynamic column blob.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_check/','','https://mariadb.com/kb/en/column_check/'),(746,'COLUMN_DELETE',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_DELETE(dyncol_blob, column_nr, column_nr...);\nCOLUMN_DELETE(dyncol_blob, column_name, column_name...);\n \nDescription\n----------- \nDeletes a dynamic column with the specified name. Multiple\nnames can be given. The return value is a dynamic column\nblob after the modification.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_delete/','','https://mariadb.com/kb/en/column_delete/'),(747,'COLUMN_EXISTS',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_EXISTS(dyncol_blob, column_nr);\nCOLUMN_EXISTS(dyncol_blob, column_name);\n \nDescription\n----------- \nChecks if a column with name column_name exists in\ndyncol_blob. If yes, return 1, otherwise return 0. See\ndynamic columns for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_exists/','','https://mariadb.com/kb/en/column_exists/'),(358,'SHOW CONTRIBUTORS',26,'Syntax\n------ \nSHOW CONTRIBUTORS\n \nDescription\n----------- \nThe SHOW CONTRIBUTORS statement displays information about\nthe companies and people who financially contribute to\nMariaDB. For each contributor, it displays Name, Location,\nand Comment values. All columns are encoded as latin1.\n \nIn MariaDB 5.5 this is in somewhat random order, and the\nfeature was deprecated.\n \nIn MariaDB 10.0.5 it was un-deprecated, and since then\ndisplays all members and sponsors of the MariaDB Foundation\nas well as other financial contributors.\n \nExample\n \nSHOW CONTRIBUTORS;\n+---------------------+-------------------------------+-------------------------------------------------------------+\n| Name | Location | Comment |\n+---------------------+-------------------------------+-------------------------------------------------------------+\n| Booking.com | https://www.booking.com | Founding member,\nPlatinum Sponsor of the MariaDB Foundation |\n| Alibaba Cloud | https://www.alibabacloud.com/ | Platinum\nSponsor of the MariaDB Foundation |\n| Tencent Cloud | https://cloud.tencent.com | Platinum\nSponsor of the MariaDB Foundation |\n| Microsoft | https://microsoft.com/ | Platinum Sponsor of\nthe MariaDB Foundation |\n| MariaDB Corporation | https://mariadb.com | Founding\nmember, Platinum Sponsor of the MariaDB Foundation |\n| Visma | https://visma.com | Gold Sponsor of the MariaDB\nFoundation |\n| DBS | https://dbs.com | Gold Sponsor of the MariaDB\nFoundation |\n| IBM | https://www.ibm.com | Gold Sponsor of the MariaDB\nFoundation |\n| Tencent Games | http://game.qq.com/ | Gold Sponsor of the\nMariaDB Foundation |\n| Nexedi | https://www.nexedi.com | Silver Sponsor of the\nMariaDB Foundation |\n| Acronis | https://www.acronis.com | Silver Sponsor of the\nMariaDB Foundation |\n| Verkkokauppa.com | https://www.verkkokauppa.com | Bronze\nSponsor of the MariaDB Foundation |\n| Virtuozzo | https://virtuozzo.com | Bronze Sponsor of the\nMariaDB Foundation |\n| Tencent Game DBA | http://tencentdba.com/about | Bronze\nSponsor of the MariaDB Foundation |\n| Tencent TDSQL | http://tdsql.org | Bronze Sponsor of the\nMariaDB Foundation |\n| Percona | https://www.percona.com/ | Bronze Sponsor of the\nMariaDB Foundation |\n| Google | USA | Sponsoring encryption, parallel replication\nand GTID |\n| Facebook | USA | Sponsoring non-blocking API, LIMIT ROWS\nEXAMINED etc |\n| Ronald Bradford | Brisbane, Australia | EFF contribution\nfor UC2006 Auction |\n| Sheeri Kritzer | Boston, Mass. USA | EFF contribution for\nUC2006 Auction |\n| Mark Shuttleworth | London, UK. | EFF contribution for\nUC2006 Auction |\n+---------------------+-------------------------------+-------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-contributors/','','https://mariadb.com/kb/en/show-contributors/'),(359,'SHOW CREATE DATABASE',26,'Syntax\n------ \nSHOW CREATE {DATABASE | SCHEMA} db_name\n \nDescription\n----------- \nShows the CREATE DATABASE statement that\ncreates the given database. SHOW CREATE SCHEMA is a synonym\nfor SHOW CREATE DATABASE. SHOW CREATE DATABASE quotes\ndatabase names according to the value of the\nsql_quote_show_create server system variable.\n \nExamples\n-------- \nSHOW CREATE DATABASE test;\n+----------+-----------------------------------------------------------------+\n| Database | Create Database |\n+----------+-----------------------------------------------------------------+\n| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER\nSET latin1 */ |\n+----------+-----------------------------------------------------------------+\n \nSHOW CREATE SCHEMA test;\n+----------+-----------------------------------------------------------------+\n| Database | Create Database |\n+----------+-----------------------------------------------------------------+\n| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER\nSET latin1 */ |\n+----------+-----------------------------------------------------------------+\n \nWith sql_quote_show_create off:\n \nSHOW CREATE DATABASE test;\n+----------+---------------------------------------------------------------+\n| Database | Create Database |\n+----------+---------------------------------------------------------------+\n| test | CREATE DATABASE test /*!40100 DEFAULT CHARACTER SET\nlatin1 */ |\n+----------+---------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-create-database/','','https://mariadb.com/kb/en/show-create-database/'),(360,'SHOW CREATE EVENT',26,'Syntax\n------ \nSHOW CREATE EVENT event_name\n \nDescription\n----------- \nThis statement displays the CREATE EVENT\nstatement needed to re-create a given event, as well as the\nSQL_MODE that was used when the trigger has been created and\nthe character set used by the connection.. To find out which\nevents are present, use SHOW EVENTS.\n \nThe output of this statement is unreliably affected by the\nsql_quote_show_create server system variable - see\nhttp://bugs.mysql.com/bug.php?id=12719\n \nThe information_schema.EVENTS table provides similar, but\nmore complete, information.\n \nExamples\n-------- \nSHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row\n***************************\n Event: e_daily\n sql_mode: \n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*) \n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-create-event/','','https://mariadb.com/kb/en/show-create-event/'),(750,'COLUMN_LIST',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_LIST(dyncol_blob);\n \nDescription\n----------- \nSince MariaDB 10.0.1, this function returns a\ncomma-separated list of column names. The names are quoted\nwith backticks.\n \nBefore MariaDB 10.0.1, it returned a comma-separated list of\ncolumn numbers, not names.\n \nSee dynamic columns for more information.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_list/','','https://mariadb.com/kb/en/column_list/'),(361,'SHOW CREATE FUNCTION',26,'Syntax\n------ \nSHOW CREATE FUNCTION func_name\n \nDescription\n----------- \nThis statement is similar to \nSHOW CREATE PROCEDURE but for\nstored functions.\n \nThe output of this statement is unreliably affected by the\nsql_quote_show_create server system variable - see\nhttp://bugs.mysql.com/bug.php?id=12719\n \nExample\n \nMariaDB [test]> SHOW CREATE FUNCTION VatCents\\G\n*************************** 1. row\n***************************\n Function: VatCents\n sql_mode: \n Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION\n`VatCents`(price DECIMAL(10,2)) RETURNS int(11)\n DETERMINISTIC\nBEGIN\n DECLARE x INT;\n SET x = price * 114;\n RETURN x;\nEND\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-create-function/','','https://mariadb.com/kb/en/show-create-function/'),(362,'SHOW CREATE PACKAGE',26,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nSHOW CREATE PACKAGE [ db_name . ] package_name\n \nDescription\n----------- \nThe SHOW CREATE PACKAGE statement can be used when Oracle\nSQL_MODE is set.\n \nShows the CREATE statement that creates the given package\nspecification.\n \nExamples\n-------- \nSHOW CREATE PACKAGE employee_tools\\G\n*************************** 1. row\n***************************\n Package: employee_tools\n sql_mode:\nPIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER\n Create Package: CREATE DEFINER=\"root\"@\"localhost\"\nPACKAGE \"employee_tools\" AS\n FUNCTION getSalary(eid INT) RETURN DECIMAL(10,2);\n PROCEDURE raiseSalary(eid INT, amount DECIMAL(10,2));\n PROCEDURE raiseSalaryStd(eid INT);\n PROCEDURE hire(ename TEXT, esalary DECIMAL(10,2));\nEND\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-create-package/','','https://mariadb.com/kb/en/show-create-package/'),(363,'SHOW CREATE PACKAGE BODY',26,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nSHOW CREATE PACKAGE BODY [ db_name . ] package_name\n \nDescription\n----------- \nThe SHOW CREATE PACKAGE BODY statement can be used when\nOracle SQL_MODE is set.\n \nShows the CREATE statement that creates the given package\nbody (i.e. the implementation).\n \nExamples\n-------- \nSHOW CREATE PACKAGE BODY employee_tools\\G\n*************************** 1. row\n***************************\n Package body: employee_tools\n sql_mode:\nPIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER\n Create Package Body: CREATE DEFINER=\"root\"@\"localhost\"\nPACKAGE BODY \"employee_tools\" AS\n \n stdRaiseAmount DECIMAL(10,2):=500;\n \n PROCEDURE log (eid INT, ecmnt TEXT) AS\n BEGIN\n INSERT INTO employee_log (id, cmnt) VALUES (eid, ecmnt);\n END;\n \n PROCEDURE hire(ename TEXT, esalary DECIMAL(10,2)) AS\n eid INT;\n BEGIN\n INSERT INTO employee (name, salary) VALUES (ename,\nesalary);\n eid:= last_insert_id();\n log(eid, \'hire \' || ename);\n END;\n \n FUNCTION getSalary(eid INT) RETURN DECIMAL(10,2) AS\n nSalary DECIMAL(10,2);\n BEGIN\n SELECT salary INTO nSalary FROM employee WHERE id=eid;\n log(eid, \'getSalary id=\' || eid || \' salary=\' ||\nnSalary);\n RETURN nSalary;\n END;\n \n PROCEDURE raiseSalary(eid INT, amount DECIMAL(10,2)) AS\n BEGIN\n UPDATE employee SET salary=salary+amount WHERE id=eid;\n log(eid, \'raiseSalary id=\' || eid || \' amount=\' ||\namount);\n END;\n \n PROCEDURE raiseSalaryStd(eid INT) AS\n BEGIN\n raiseSalary(eid, stdRaiseAmount);\n log(eid, \'raiseSalaryStd id=\' || eid);\n END;\n \nBEGIN \n log(0, \'Session \' || connection_id() || \' \' ||\ncurrent_user || \' started\');\nEND\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-create-package-body/','','https://mariadb.com/kb/en/show-create-package-body/'),(364,'SHOW CREATE PROCEDURE',26,'Syntax\n------ \nSHOW CREATE PROCEDURE proc_name\n \nDescription\n----------- \nThis statement is a MariaDB extension. It returns the exact\nstring that\ncan be used to re-create the named stored procedure, as well\nas the SQL_MODE that was used when the trigger has been\ncreated and the character set used by the connection.. A\nsimilar\nstatement, SHOW CREATE FUNCTION,\ndisplays information about stored functions.\n \nBoth statements require that you are the owner of the\nroutine or have the SELECT privilege on the mysql.proc\ntable. When neither is true, the statements display NULL for\nthe Create Procedure or Create Function field.\n \nWarning Users with SELECT privileges on mysql.proc or USAGE\nprivileges on *.* can view the text of routines, even when\nthey do not have privileges for the function or procedure\nitself.\n \nThe output of these statements is unreliably affected by the\nsql_quote_show_create server system variable - see\nhttp://bugs.mysql.com/bug.php?id=12719\n \nExamples\n-------- \nHere\'s a comparison of the SHOW CREATE PROCEDURE and SHOW\nCREATE FUNCTION statements.\n \nSHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row\n***************************\n Procedure: simpleproc\n sql_mode: \n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1\nINT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n \nSHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row\n***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n \nWhen the user issuing the statement does not have privileges\non the routine, attempting to CALL the procedure raises\nError 1370.\n \nCALL test.prc1();\nError 1370 (42000): execute command denieed to user\n\'test_user\'@\'localhost\' for routine \'test\'.\'prc1\'\n \nIf the user neither has privilege to the routine nor the\nSELECT privilege on mysql.proc table, it raises Error 1305,\ninforming them that the procedure does not exist.\n \nSHOW CREATE TABLES test.prc1\\G\nError 1305 (42000): PROCEDURE prc1 does not exist\n \n\n\nURL: https://mariadb.com/kb/en/show-create-procedure/','','https://mariadb.com/kb/en/show-create-procedure/'),(365,'SHOW CREATE SEQUENCE',26,'Sequences were introduced in MariaDB 10.3.\n \nSyntax\n------ \nSHOW CREATE SEQUENCE sequence_name;\n \nDescription\n----------- \nShows the CREATE SEQUENCE statement that created the given\nsequence. The statement requires the SELECT privilege for\nthe table.\n \nExample\n \nCREATE SEQUENCE s1 START WITH 50;\n \nSHOW CREATE SEQUENCE s1\\G;\n \n*************************** 1. row\n***************************\n Table: t1\nCreate Table: CREATE SEQUENCE `s1` start with 50 minvalue 1\nmaxvalue 9223372036854775806\nincrement by 1 cache 1000 nocycle ENGINE=Aria\n \nNotes\n \nIf you want to see the underlying table structure used for\nthe SEQUENCE\nyou can use SHOW CREATE TABLE on the SEQUENCE. You can also\nuse SELECT to read the current recorded state of the\nSEQUENCE:\n \nCREATE SEQUENCE t1;\n \nSHOW CREATE TABLE s1\\G\n*************************** 1. row\n***************************\n Table: s1\nCreate Table: CREATE TABLE `s1` (\n `next_value` bigint(21) NOT NULL COMMENT \'next not cached\nvalue\',\n `min_value` bigint(21) NOT NULL COMMENT \'min value\',\n `max_value` bigint(21) NOT NULL COMMENT \'max value\',\n `start` bigint(21) NOT NULL COMMENT \'start value\',\n `increment` bigint(21) NOT NULL COMMENT \'increment\nvalue\',\n `cache` bigint(21) NOT NULL COMMENT \'cache size\',\n `cycle` tinyint(1) unsigned NOT NULL COMMENT \'cycle\nstate\',\n `round` bigint(21) NOT NULL COMMENT \'How many cycles has\nbeen done\'\n) ENGINE=Aria SEQUENCE=1\n \nSELECT * FROM s1;\n \n+------------+-----------+---------------------+-------+-----------+-------+-------+-------+\n| next_value | min_value | max_value | start | increment |\ncache | cycle | round |\n+------------+-----------+---------------------+-------+-----------+-------+-------+-------+\n| 1 | 1 | 9223372036854775806 | 1 | 1 | 1000 | 0 | 0 |\n+------------+-----------+---------------------+-------+-----------+-------+-------+-------+\n \n\n\nURL: https://mariadb.com/kb/en/show-create-sequence/','','https://mariadb.com/kb/en/show-create-sequence/'),(366,'SHOW CREATE TABLE',26,'Syntax\n------ \nSHOW CREATE TABLE tbl_name\n \nDescription\n----------- \nShows the CREATE TABLE statement that created the given\ntable. The statement requires the SELECT privilege for the\ntable. This statement also works with views and SEQUENCE.\n \nSHOW CREATE TABLE quotes table and\ncolumn names according to the value of the\nsql_quote_show_create server system variable.\n \nMariaDB and MySQL-specific table options, column options,\nand index options are not included in the output of this\nstatement if the NO_TABLE_OPTIONS, NO_FIELD_OPTIONS and\nNO_KEY_OPTIONS SQL_MODE flags are used.\n \nInvalid table options, column options and index options are\nnormally commented out (note, that it is possible to create\na table with invalid options, by altering a table of a\ndifferent engine, where these options were valid). To have\nthem uncommented, enable IGNORE_BAD_TABLE_OPTIONS SQL_MODE.\nRemember that replaying a CREATE TABLE statement with\nuncommented invalid options will fail with an error, unless\nIGNORE_BAD_TABLE_OPTIONS SQL_MODE is in effect.\n \nNote that SHOW CREATE TABLE is not meant to provide metadata\nabout a table. It provides information about how the table\nwas declared, but the real table structure could differ a\nbit. For example, if an index has been declared as HASH, the\nCREATE TABLE statement returned by SHOW CREATE TABLE will\ndeclare that index as HASH; however, it is possible that the\nindex is in fact a BTREE, because the storage engine does\nnot support HASH.\n \nMariaDB 10.2.1 permits TEXT and BLOB data types to be\nassigned a DEFAULT value. As a result, from MariaDB 10.2.1,\nSHOW CREATE TABLE will append a DEFAULT NULL to nullable\nTEXT or BLOB fields if no specific default is provided. \n \nFrom MariaDB 10.2.2, numbers are no longer quoted in the\nDEFAULT clause in SHOW CREATE statement. Previously, MariaDB\nquoted numbers. \n \nExamples\n-------- \nSHOW CREATE TABLE t\\G\n*************************** 1. row\n***************************\n Table: t\nCreate Table: CREATE TABLE `t` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `s` char(60) DEFAULT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1\n \nWith sql_quote_show_create off:\n \nSHOW CREATE TABLE t\\G\n*************************** 1. row\n***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id int(11) NOT NULL AUTO_INCREMENT,\n s char(60) DEFAULT NULL,\n PRIMARY KEY (id)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1\n \nUnquoted numeric DEFAULTs, from MariaDB 10.2.2:\n \nCREATE TABLE td (link TINYINT DEFAULT 1);\n \nSHOW CREATE TABLE td\\G\n*************************** 1. row\n***************************\n Table: td\nCreate Table: CREATE TABLE `td` (\n `link` tinyint(4) DEFAULT 1\n) ENGINE=InnoDB DEFAULT CHARSET=latin1\n \nQuoted numeric DEFAULTs, until MariaDB 10.2.1:\n \nCREATE TABLE td (link TINYINT DEFAULT 1);\n \nSHOW CREATE TABLE td\\G\n*************************** 1. row\n***************************\n Table: td\nCreate Table: CREATE TABLE `td` (\n `link` tinyint(4) DEFAULT \'1\'\n) ENGINE=InnoDB DEFAULT CHARSET=latin1\n \n\n\nURL: https://mariadb.com/kb/en/show-create-table/','','https://mariadb.com/kb/en/show-create-table/'),(367,'SHOW CREATE TRIGGER',26,'Syntax\n------ \nSHOW CREATE TRIGGER trigger_name\n \nDescription\n----------- \nThis statement shows a CREATE TRIGGER\nstatement that creates the given trigger, as well as the\nSQL_MODE that was used when the trigger has been created and\nthe character set used by the connection.\n \nThe output of this statement is unreliably affected by the\nsql_quote_show_create server system variable - see\nhttp://bugs.mysql.com/bug.php?id=12719\n \nExamples\n-------- \nSHOW CREATE TRIGGER example\\G\n*************************** 1. row\n***************************\n Trigger: example\n sql_mode:\nONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,STRICT_ALL_TABLES\n,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_\nENGINE_SUBSTITUTION\nSQL Original Statement: CREATE DEFINER=`root`@`localhost`\nTRIGGER example BEFORE\n INSERT ON t FOR EACH ROW\nBEGIN\n SET NEW.c = NEW.c * 2;\nEND\n character_set_client: cp850\n collation_connection: cp850_general_ci\n Database Collation: utf8_general_ci\n Created: 2016-09-29 13:53:34.35\n \nThe Created column was added in MySQL 5.7 and MariaDB 10.2.3\nas part of introducing multiple trigger events per action.\n \n\n\nURL: https://mariadb.com/kb/en/show-create-trigger/','','https://mariadb.com/kb/en/show-create-trigger/'),(368,'SHOW CREATE USER',26,'SHOW CREATE USER was introduced in MariaDB 10.2.0\n \nSyntax\n------ \nSHOW CREATE USER user_name\n \nDescription\n----------- \nShows the CREATE USER statement that created the given\nuser. The statement requires the SELECT privilege for the\nmysql database, except for the current user.\n \nExamples\n-------- \nCREATE USER foo4@test require cipher \'text\' \n issuer \'foo_issuer\' subject \'foo_subject\';\n \nSHOW CREATE USER foo4@test\\G\n*************************** 1. row\n***************************\nCREATE USER \'foo4\'@\'test\' \n REQUIRE ISSUER \'foo_issuer\' \n SUBJECT \'foo_subject\' \n CIPHER \'text\'\n \nUser Password Expiry:\n \nCREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE INTERVAL\n120 DAY;\n \nSHOW CREATE USER \'monty\'@\'localhost\';\n \n+------------------------------------------------------------------+\n| CREATE USER for monty@localhost |\n+------------------------------------------------------------------+\n| CREATE USER \'monty\'@\'localhost\' PASSWORD EXPIRE\nINTERVAL 120 DAY |\n+------------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-create-user/','','https://mariadb.com/kb/en/show-create-user/'),(369,'SHOW CREATE VIEW',26,'Syntax\n------ \nSHOW CREATE VIEW view_name\n \nDescription\n----------- \nThis statement shows a CREATE VIEW statement that creates\nthe given view, as well as the character set used by the\nconnection when the view was created. This statement\nalso works with views.\n \nSHOW CREATE VIEW quotes table, column and stored function\nnames according to the value of the sql_quote_show_create\nserver system variable.\n \nExamples\n-------- \nSHOW CREATE VIEW example\\G\n*************************** 1. row\n***************************\n View: example\n Create View: CREATE ALGORITHM=UNDEFINED\nDEFINER=`root`@`localhost` SQL\nSECURITY DEFINER VIEW `example` AS (select `t`.`id` AS\n`id`,`t`.`s` AS `s` from\n`t`)\ncharacter_set_client: cp850\ncollation_connection: cp850_general_ci\n \nWith sql_quote_show_create off:\n \nSHOW CREATE VIEW example\\G\n*************************** 1. row\n***************************\n View: example\n Create View: CREATE ALGORITHM=UNDEFINED\nDEFINER=root@localhost SQL SECU\nRITY DEFINER VIEW example AS (select t.id AS id,t.s AS s\nfrom t)\ncharacter_set_client: cp850\ncollation_connection: cp850_general_ci\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-create-view/','','https://mariadb.com/kb/en/show-create-view/'),(370,'SHOW DATABASES',26,'Syntax\n------ \nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nSHOW DATABASES lists the databases on the MariaDB server\nhost.\nSHOW SCHEMAS is a synonym for \nSHOW DATABASES. The LIKE clause, if\npresent on its own, indicates which database names to match.\nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nYou see only those databases for which you have some kind of\nprivilege, unless you have the global \nSHOW DATABASES privilege. You\ncan also get this list using the mysqlshow command.\n \nIf the server was started with the --skip-show-database\noption, you cannot use this statement at all unless you have\nthe\nSHOW DATABASES privilege.\n \nExample\n \nSHOW DATABASES;\n+--------------------+\n| Database |\n+--------------------+\n| information_schema |\n| mysql |\n| performance_schema |\n| test |\n+--------------------+\n \nSHOW DATABASES LIKE \'m%\';\n+---------------+\n| Database (m%) |\n+---------------+\n| mysql |\n+---------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-databases/','','https://mariadb.com/kb/en/show-databases/'),(373,'SHOW ENGINES',26,'Syntax\n------ \nSHOW [STORAGE] ENGINES\n \nDescription\n----------- \nSHOW ENGINES displays status information about the server\'s\nstorage engines. This is particularly useful for checking\nwhether a storage\nengine is supported, or to see what the default engine is. \nSHOW TABLE TYPES is a deprecated synonym.\n \nThe information_schema.ENGINES table provides the same\ninformation.\n \nSince storage engines are plugins, different information\nabout them is also shown in the information_schema.PLUGINS\ntable and by the SHOW PLUGINS statement.\n \nNote that both MySQL\'s InnoDB and Percona\'s XtraDB\nreplacement are labeled as InnoDB. However, if XtraDB is in\nuse, it will be specified in the COMMENT field. See XtraDB\nand InnoDB. The same applies to FederatedX.\n \nThe output consists of the following columns:\nEngine indicates the engine\'s name.\nSupport indicates whether the engine is installed, and\nwhether it is the default engine for the current session.\nComment is a brief description.\nTransactions, XA and Savepoints indicate whether\ntransactions, XA transactions and transaction savepoints are\nsupported by the engine.\n \nExamples\n-------- \nSHOW ENGINES\\G\n*************************** 1. row\n***************************\n Engine: InnoDB\n Support: DEFAULT\n Comment: Supports transactions, row-level locking, and\nforeign keys\nTransactions: YES\n XA: YES\n Savepoints: YES\n*************************** 2. row\n***************************\n Engine: CSV\n Support: YES\n Comment: CSV storage engine\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 3. row\n***************************\n Engine: MyISAM\n Support: YES\n Comment: MyISAM storage engine\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 4. row\n***************************\n Engine: BLACKHOLE\n Support: YES\n Comment: /dev/null storage engine (anything you write to it\ndisappears)\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 5. row\n***************************\n Engine: FEDERATED\n Support: YES\n Comment: FederatedX pluggable storage engine\nTransactions: YES\n XA: NO\n Savepoints: YES\n*************************** 6. row\n***************************\n Engine: MRG_MyISAM\n Support: YES\n Comment: Collection of identical MyISAM tables\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 7. row\n***************************\n Engine: ARCHIVE\n Support: YES\n Comment: Archive storage engine\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 8. row\n***************************\n Engine: MEMORY\n Support: YES\n Comment: Hash based, stored in memory, useful for temporary\ntables\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 9. row\n***************************\n Engine: PERFORMANCE_SCHEMA\n Support: YES\n Comment: Performance Schema\nTransactions: NO\n XA: NO\n Savepoints: NO\n*************************** 10. row\n***************************\n Engine: Aria\n Support: YES\n Comment: Crash-safe tables with MyISAM heritage\nTransactions: NO\n XA: NO\n Savepoints: NO\n10 rows in set (0.00 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-engines/','','https://mariadb.com/kb/en/show-engines/'),(371,'SHOW ENGINE',26,'Syntax\n------ \nSHOW ENGINE engine_name {STATUS | MUTEX}\n \nDescription\n----------- \nSHOW ENGINE displays operational information about a storage\nengine. The following statements currently are supported:\n \nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n \nIf the Sphinx Storage Engine is installed, the following is\nalso supported:\n \nSHOW ENGINE SPHINX STATUS\n \nSee SHOW ENGINE SPHINX STATUS.\n \nOlder (and now removed) synonyms were SHOW INNODB STATUS\nfor SHOW ENGINE INNODB STATUS and \nSHOW MUTEX STATUS for \nSHOW ENGINE INNODB MUTEX.\n \nSHOW ENGINE BDB LOGS formerly displayed status information\nabout BDB log files. It was deprecated in MySQL 5.1.12 and\nremoved in MariaDB and MySQL 5.5, so now produces an error.\n \nSHOW ENGINE INNODB STATUS\n \nSHOW ENGINE INNODB STATUS displays extensive information\nfrom the standard InnoDB Monitor about the state of the\nInnoDB storage engine.\nSee SHOW ENGINE INNODB STATUS for more.\n \nSHOW ENGINE INNODB MUTEX\n \nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics.\n \nThe statement displays the following output fields:\nType: Always InnoDB.\nName: The source file where the mutex is implemented, and\nthe line number\n in the file where the mutex is created. The line number is\ndependent on the MariaDB version.\nStatus: This field displays the following values if\nUNIV_DEBUG was defined at compilation time (for example, in\ninclude/univ.h in the InnoDB part of the source tree). Only\nthe os_waits value is displayed if UNIV_DEBUG was not\ndefined. Without UNIV_DEBUG, the information on which the\noutput is based is insufficient to distinguish regular\nmutexes and mutexes that protect\n rw-locks (which allow multiple readers or a single writer).\nConsequently, the\n output may appear to contain multiple rows for the same\nmutex.\ncount indicates how many times the mutex was requested.\nspin_waits indicates how many times the spinlock had to run.\nspin_rounds indicates the number of spinlock rounds.\n(spin_rounds divided by\n spin_waits provides the average round count.)\nos_waits indicates the number of operating system waits.\nThis occurs when\n the spinlock did not work (the mutex was not locked during\nthe spinlock and\n it was necessary to yield to the operating system and\nwait).\nos_yields indicates the number of times a the thread trying\nto lock a mutex\n gave up its timeslice and yielded to the operating system\n(on the\n presumption that allowing other threads to run will free\nthe mutex so that\n it can be locked).\nos_wait_times indicates the amount of time (in ms) spent in\noperating system\n waits, if the timed_mutexes system variable is 1 (ON). If\ntimed_mutexes is 0\n (OFF), timing is disabled, so os_wait_times is 0.\ntimed_mutexes is off by\n default.\n \nInformation from this statement can be used to diagnose\nsystem problems. For\nexample, large values of spin_waits and spin_rounds may\nindicate scalability\nproblems.\n \nThe information_schema.INNODB_MUTEXES table provides similar\ninformation.\n \nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n \nThis statement shows how much memory is used for\nperformance_schema tables and internal buffers.\n \nThe output contains the following fields:\nType: Always performance_schema.\nName: The name of a table, the name of an internal buffer,\nor the performance_schema word, followed by a dot and an\nattribute. Internal buffers names are enclosed by\nparenthesis. performance_schema means that the attribute\nrefers to the whole database (it is a total). \nStatus: The value for the attribute.\n \nThe following attributes are shown, in this order, for all\ntables:\nrow_size: The memory used for an individual record. This\nvalue will never change.\nrow_count: The number of rows in the table or buffer. For\nsome tables, this value depends on a server system variable.\nmemory: For tables and performance_schema, this is the\nresult of row_size * row_count.\n \nFor internal buffers, the attributes are:\ncount\nsize\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-engine/','','https://mariadb.com/kb/en/show-engine/'),(374,'SHOW ERRORS',26,'Syntax\n------ \nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW ERRORS [LIMIT row_count OFFSET offset]\nSHOW COUNT(*) ERRORS\n \nDescription\n----------- \nThis statement is similar to SHOW WARNINGS, except that\ninstead of\ndisplaying errors, warnings, and notes, it displays only\nerrors.\n \nThe LIMIT clause has the same syntax as for the\nSELECT statement.\n \nThe SHOW COUNT(*) ERRORS statement displays the number of\nerrors. You can also retrieve this number from the\nerror_count variable.\n \nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n \nThe value of error_count might be greater than the number of\nmessages displayed by SHOW WARNINGS if the max_error_count\nsystem variable is set so low that not all messages are\nstored.\n \nFor a list of MariaDB error codes, see MariaDB Error Codes.\n \nExamples\n-------- \nSELECT f();\nERROR 1305 (42000): FUNCTION f does not exist\n \nSHOW COUNT(*) ERRORS;\n \n+-----------------------+\n| @@session.error_count |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSHOW ERRORS;\n \n+-------+------+---------------------------+\n| Level | Code | Message |\n+-------+------+---------------------------+\n| Error | 1305 | FUNCTION f does not exist |\n+-------+------+---------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-errors/','','https://mariadb.com/kb/en/show-errors/'),(372,'SHOW ENGINE INNODB STATUS',26,'SHOW ENGINE INNODB STATUS is a specific form of the SHOW\nENGINE statement that displays the InnoDB Monitor output,\nwhich is extensive InnoDB information which can be useful in\ndiagnosing problems.\n \nThe following sections are displayed\nStatus: Shows the timestamp, monitor name and the number of\nseconds, or the elapsed time between the current time and\nthe time the InnoDB Monitor output was last displayed. The\nper-second averages are based upon this time.\nBACKGROUND THREAD: srv_master_thread lines show work\nperformed by the main background thread.\nSEMAPHORES: Threads waiting for a semaphore and stats on how\nthe number of times threads have needed a spin or a wait on\na mutex or rw-lock semaphore. If this number of threads is\nlarge, there may be I/O or contention issues. Reducing the\nsize of the innodb_thread_concurrency system variable may\nhelp if contention is related to thread scheduling. Spin\nrounds per wait shows the number of spinlock rounds per OS\nwait for a mutex. \nLATEST FOREIGN KEY ERROR: Only shown if there has been a\nforeign key constraint error, it displays the failed\nstatement and information about the constraint and the\nrelated tables.\nLATEST DETECTED DEADLOCK: Only shown if there has been a\ndeadlock, it displays the transactions involved in the\ndeadlock and the statements being executed, held and\nrequired locked and the transaction rolled back to.\nTRANSACTIONS: The output of this section can help identify\nlock contention, as well as reasons for the deadlocks.\nFILE I/O: InnoDB thread information as well as pending I/O\noperations and I/O performance statistics.\nINSERT BUFFER AND ADAPTIVE HASH INDEX: InnoDB insert buffer\nand adaptive hash index status information, including the\nnumber of each type of operation performed, and adaptive\nhash index performance.\nLOG: InnoDB log information, including current log sequence\nnumber, how far the log has been flushed to disk, the\nposition at which InnoDB last took a checkpoint, pending\nwrites and write performance statistics.\nBUFFER POOL AND MEMORY: Information on buffer pool pages\nread and written, which allows you to see the number of data\nfile I/O operations performed by your queries. See InnoDB\nBuffer Pool for more. Similar information is also available\nfrom the INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS table.\nROW OPERATIONS:Information about the main thread, including\nthe number and performance rate for each type of row\noperation. \n \nIf the innodb_status_output_locks system variable is set to\n1, extended lock information will be displayed.\n \nExample output:\n \n=====================================\n2016-09-12 04:42:15 7f226145fb00 INNODB MONITOR OUTPUT\n=====================================\nPer second averages calculated from the last 29 seconds\n-----------------\nBACKGROUND THREAD\n-----------------\nsrv_master_thread loops: 0 srv_active, 0 srv_shutdown, 527\nsrv_idle\nsrv_master_thread log flush and writes: 527\n----------\nSEMAPHORES\n----------\nOS WAIT ARRAY INFO: reservation count 4\nOS WAIT ARRAY INFO: signal count 4\nMutex spin waits 2, rounds 60, OS waits 2\nRW-shared spins 2, rounds 60, OS waits 2\nRW-excl spins 0, rounds 0, OS waits 0\nSpin rounds per wait: 30.00 mutex, 30.00 RW-shared, 0.00\nRW-excl\n------------\nTRANSACTIONS\n------------\nTrx id counter 2308\nPurge done for trx\'s n:o < 0 undo n:o < 0 state: running\nbut idle\nHistory list length 0\nLIST OF TRANSACTIONS FOR EACH SESSION:\n---TRANSACTION 0, not started\nMySQL thread id 3, OS thread handle 0x7f226145fb00, query id\n4 localhost root init\nSHOW ENGINE INNODB STATUS\n--------\nFILE I/O\n--------\nI/O thread 0 state: waiting for completed aio requests\n(insert buffer thread)\nI/O thread 1 state: waiting for completed aio requests (log\nthread)\nI/O thread 2 state: waiting for completed aio requests (read\nthread)\nI/O thread 3 state: waiting for completed aio requests (read\nthread)\nI/O thread 4 state: waiting for completed aio requests (read\nthread)\nI/O thread 5 state: waiting for completed aio requests (read\nthread)\nI/O thread 6 state: waiting for completed aio requests\n(write thread)\nI/O thread 7 state: waiting for completed aio requests\n(write thread)\nI/O thread 8 state: waiting for completed aio requests\n(write thread)\nI/O thread 9 state: waiting for completed aio requests\n(write thread)\nPending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0,\n0, 0, 0] ,\n ibuf aio reads: 0, log i/o\'s: 0, sync i/o\'s: 0\nPending flushes (fsync) log: 0; buffer pool: 0\n172 OS file reads, 5 OS file writes, 5 OS fsyncs\n0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s\n-------------------------------------\nINSERT BUFFER AND ADAPTIVE HASH INDEX\n-------------------------------------\nIbuf: size 1, free list len 0, seg size 2, 0 merges\nmerged operations:\n insert 0, delete mark 0, delete 0\ndiscarded operations:\n insert 0, delete mark 0, delete 0\n0.00 hash searches/s, 0.00 non-hash searches/s\n---\nLOG\n---\nLog sequence number 1616829\nLog flushed up to 1616829\nPages flushed up to 1616829\nLast checkpoint at 1616829\nMax checkpoint age 80826164\nCheckpoint age target 78300347\nModified age 0\nCheckpoint age 0\n0 pending log writes, 0 pending chkp writes\n8 log i/o\'s done, 0.00 log i/o\'s/second\n----------------------\nBUFFER POOL AND MEMORY\n----------------------\nTotal memory allocated 140771328; in additional pool\nallocated 0\nTotal memory allocated by read views 88\nInternal hash tables (constant factor + variable factor)\n Adaptive hash index 2217568 (2213368 + 4200)\n Page hash 139112 (buffer pool 0 only)\n Dictionary cache 630703 (554768 + 75935)\n File system 817648 (812272 + 5376)\n Lock system 333232 (332872 + 360)\n Recovery system 0 (0 + 0)\nDictionary memory allocated 75935\nBuffer pool size 8191\nBuffer pool size, bytes 134201344\nFree buffers 8037\nDatabase pages 154\nOld database pages 0\nModified db pages 0\nPercent of dirty pages(LRU & free pages): 0.000\nMax dirty pages percent: 75.000\nPending reads 0\nPending writes: LRU 0, flush list 0, single page 0\nPages made young 0, not young 0\n0.00 youngs/s, 0.00 non-youngs/s\nPages read 154, created 0, written 1\n0.00 reads/s, 0.00 creates/s, 0.00 writes/s\nNo buffer pool page gets since the last printout\nPages read ahead 0.00/s, evicted without access 0.00/s,\nRandom read ahead 0.00/s\nLRU len: 154, unzip_LRU len: 0\nI/O sum[0]:cur[0], unzip sum[0]:cur[0]\n--------------\nROW OPERATIONS\n--------------\n0 queries inside InnoDB, 0 queries in queue\n0 read views open inside InnoDB\n0 RW transactions active inside InnoDB\n0 RO transactions active inside InnoDB\n0 out of 1000 descriptors used\nMain thread process no. 3337, id 139784957703936, state:\nsleeping\nNumber of rows inserted 0, updated 0, deleted 0, read 0\n0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s\nNumber of system rows inserted 0, updated 0, deleted 0, read\n0\n0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s\n----------------------------\nEND OF INNODB MONITOR OUTPUT\n============================\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-engine-innodb-status/','','https://mariadb.com/kb/en/show-engine-innodb-status/'),(375,'SHOW EVENTS',26,'Syntax\n------ \nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nShows information about Event Manager events (created with\nCREATE EVENT). Requires the EVENT privilege. Without any\narguments, SHOW EVENTS lists all of the events in the\ncurrent schema:\n \nSELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n \nSHOW EVENTS\\G\n*************************** 1. row\n***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n \nTo see the event action, use SHOW CREATE EVENT instead, or\nlook at the information_schema.EVENTS table.\n \nTo see events for a specific schema, use the FROM clause.\nFor example, to see events for the test schema, use the\nfollowing statement:\n \nSHOW EVENTS FROM test;\n \nThe LIKE clause, if present, indicates which event names to\nmatch. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in Extended Show.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-events/','','https://mariadb.com/kb/en/show-events/'),(376,'SHOW EXPLAIN',26,'The SHOW EXPLAIN command is a new feature in MariaDB 10.0.0.\n \nCommand description\n \nThe SHOW EXPLAIN command allows one to get an EXPLAIN (that\nis, a\ndescription of a query plan) of a query running in a certain\nthread.\n \nThe syntax is:\n \nSHOW EXPLAIN FOR ;\n \nwhich will produce an EXPLAIN output for the query that\nthread number thread_id is running. The thread id can be\nobtained with SHOW PROCESSLIST.\n \nSHOW EXPLAIN FOR 1;\n \n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | Extra |\n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n| 1 | SIMPLE | tbl | index | NULL | a | 5 | NULL | 1000107 |\nUsing index |\n+------+-------------+-------+-------+---------------+------+---------+------+---------+-------------+\n1 row in set, 1 warning (0.00 sec)\n \nThe output is always accompanied with a warning which shows\nthe query the\ntarget thread is running (this shows what the EXPLAIN is\nfor):\n \nSHOW WARNINGS;\n \n+-------+------+------------------------+\n| Level | Code | Message |\n+-------+------+------------------------+\n| Note | 1003 | select sum(a) from tbl |\n+-------+------+------------------------+\n1 row in set (0.00 sec)\n \nPossible errors\n \nThe output can be only produced if the target thread is\ncurrently running a\nquery, which has a ready query plan. If this is not the\ncase, the output will\nbe:\n \nSHOW EXPLAIN FOR 2;\n \nERROR 1932 (HY000): Target is not running an EXPLAINable\ncommand\n \nYou will get this error when:\nthe target thread is not running a command for which one can\nrun EXPLAIN\nthe target thread is running a command for which one can run\nEXPLAIN, but\nthere is no query plan yet (for example, tables are open and\nlocks are\n acquired before the query plan is produced)\n \n\nDifferences between SHOW EXPLAIN and EXPLAIN outputs\n \nBackground\n \nIn MySQL, EXPLAIN execution takes a slightly different route\nfrom the way\nthe real query (typically the SELECT) is optimized. This is\nunfortunate,\nand has caused a number of bugs in EXPLAIN. (For example,\nsee\nMDEV-326, MDEV-410, and\nlp:1013343.\nlp:992942 is not directly\nabout EXPLAIN, but it also would not have existed if MySQL\ndidn\'t try to delete\nparts of a query plan in the middle of the query) \n \nSHOW EXPLAIN examines a running SELECT, and hence its output\nmay be\nslightly different from what EXPLAIN SELECT would produce.\nWe did our best\nto make sure that either the difference is negligible, or\nSHOW EXPLAIN\'s\noutput is closer to reality than EXPLAIN\'s output.\n \nList of recorded differences\n \nSHOW EXPLAIN may have Extra=\'no matching row in const\ntable\', where EXPLAIN would produce Extra=\'Impossible\nWHERE ...\'\nFor queries with subqueries, SHOW EXPLAIN may print\nselect_type==PRIMARY where regular EXPLAIN used to print\nselect_type==SIMPLE, or vice versa.\n \nRequired permissions\n \nRunning SHOW EXPLAIN requires the same permissions as\nrunning SHOW PROCESSLIST would.\n \n\n\nURL: https://mariadb.com/kb/en/show-explain/','','https://mariadb.com/kb/en/show-explain/'),(378,'SHOW FUNCTION STATUS',26,'Syntax\n------ \nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThis statement is similar to \nSHOW PROCEDURE STATUS but for\nstored functions.\n \nThe LIKE clause, if present on its own, indicates which\nfunction names to match. \n \nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nThe information_schema.ROUTINES table contains more detailed\ninformation.\n \nExamples\n-------- \nShowing all stored functions:\n \nSHOW FUNCTION STATUS\\G\n*************************** 1. row\n***************************\n Db: test\n Name: VatCents\n Type: FUNCTION\n Definer: root@localhost\n Modified: 2013-06-01 12:40:31\n Created: 2013-06-01 12:40:31\n Security_type: DEFINER\n Comment: \ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \nStored functions whose name starts with \'V\': \n \nSHOW FUNCTION STATUS LIKE \'V%\' \\G\n*************************** 1. row\n***************************\n Db: test\n Name: VatCents\n Type: FUNCTION\n Definer: root@localhost\n Modified: 2013-06-01 12:40:31\n Created: 2013-06-01 12:40:31\n Security_type: DEFINER\n Comment: \ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \nStored functions with a security type of \'DEFINER\':\n \nSHOW FUNCTION STATUS WHERE Security_type LIKE \'DEFINER\'\n\\G\n*************************** 1. row\n***************************\n Db: test\n Name: VatCents\n Type: FUNCTION\n Definer: root@localhost\n Modified: 2013-06-01 12:40:31\n Created: 2013-06-01 12:40:31\n Security_type: DEFINER\n Comment: \ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-function-status/','','https://mariadb.com/kb/en/show-function-status/'),(379,'SHOW GRANTS',26,'Users\n \nSyntax\n------ \nSHOW GRANTS [FOR user]\n \nDescription\n----------- \nThis statement lists the GRANT statement or\nstatements that must be issued to duplicate the privileges\nthat are granted to\na MariaDB user account. The account is named using the same\nformat as for the\nGRANT statement; for example,\n\'jeffrey\'@\'localhost\'. If you specify only the user name\npart\nof the account name, a host name part of \'%\' is used. For\nadditional information about specifying account names, see\nGRANT.\n \nSHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH\nGRANT OPTION |\n+---------------------------------------------------------------------+\n \nTo list the privileges granted to the account that you are\nusing to\nconnect to the server, you can use any of the following\nstatements:\n \nSHOW GRANTS;\n \nSHOW GRANTS FOR CURRENT_USER;\n \nSHOW GRANTS FOR CURRENT_USER();\n \nIf SHOW GRANTS FOR CURRENT_USER (or any\nof the equivalent syntaxes) is used in DEFINER context (such\nas within a stored procedure that is defined with \n SQL SECURITY DEFINER), the grants displayed are those of\nthe\ndefiner and not the invoker.\n \nNote that the DELETE HISTORY privilege, introduced in\nMariaDB 10.3.4, is displayed as DELETE VERSIONING ROWS when\nrunning SHOW GRANTS (MDEV-17655).\n \nRoles\n \nRoles were introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nSHOW GRANTS [FOR role]\n \nDescription\n----------- \nFrom MariaDB 10.0.5, SHOW GRANTS can also be used to view\nthe privileges granted to a role.\n \nExample\n \nSHOW GRANTS FOR journalist;\n+------------------------------------------+\n| Grants for journalist |\n+------------------------------------------+\n| GRANT USAGE ON *.* TO \'journalist\' |\n| GRANT DELETE ON `test`.* TO \'journalist\' |\n+------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-grants/','','https://mariadb.com/kb/en/show-grants/'),(380,'SHOW INDEX',26,'Syntax\n------ \nSHOW {INDEX | INDEXES | KEYS} \n FROM tbl_name [FROM db_name]\n [WHERE expr]\n \nDescription\n----------- \nSHOW INDEX returns table index information. The format\nresembles that of the SQLStatistics call in ODBC.\n \nYou can use db_name.tbl_name as an alternative to the\n tbl_name FROM db_name syntax. These two statements are\n equivalent:\n \nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n \nSHOW KEYS and SHOW INDEXES are synonyms for SHOW INDEX.\n \nYou can also list a table\'s indexes with the following\ncommand: \n \nmysqlshow -k db_name tbl_name\n \nSee mysqlshow for more details.\n \nThe information_schema.STATISTICS table stores similar\ninformation.\n \nThe following fields are returned by SHOW INDEX.\n \nField | Description | \n \nTable | Table name | \n \nNon_unique | 1 if the index permits duplicate values, 0 if\nvalues must be unique. | \n \nKey_name | Index name. The primary key is always named\nPRIMARY. | \n \nSeq_in_index | The column\'s sequence in the index,\nbeginning with 1. | \n \nColumn_name | Column name. | \n \nCollation | Either A, if the column is sorted in ascending\norder in the index, or NULL if it\'s not sorted. | \n \nCardinality | Estimated number of unique values in the\nindex. The cardinality statistics are calculated at various\ntimes, and can help the optimizer make improved decisions. |\n\n \nSub_part | NULL if the entire column is included in the\nindex, or the number of included characters if not. | \n \nPacked | NULL if the index is not packed, otherwise how the\nindex is packed. | \n \nNull | NULL if NULL values are permitted in the column, an\nempty string if NULL\'s are not permitted. | \n \nIndex_type | The index type, which can be BTREE, FULLTEXT,\nHASH or RTREE. See Storage Engine Index Types. | \n \nComment | Other information, such as whether the index is\ndisabled. | \n \nIndex_comment | Contents of the COMMENT attribute when the\nindex was created. | \n \nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nExamples\n-------- \nCREATE TABLE IF NOT EXISTS `employees_example` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `first_name` varchar(30) NOT NULL,\n `last_name` varchar(40) NOT NULL,\n `position` varchar(25) NOT NULL,\n `home_address` varchar(50) NOT NULL,\n `home_phone` varchar(12) NOT NULL,\n `employee_code` varchar(25) NOT NULL,\n PRIMARY KEY (`id`),\n UNIQUE KEY `employee_code` (`employee_code`),\n KEY `first_name` (`first_name`,`last_name`)\n) ENGINE=Aria;\n \nINSERT INTO `employees_example` (`first_name`, `last_name`,\n`position`, `home_address`, `home_phone`, `employee_code`)\n VALUES\n (\'Mustapha\', \'Mond\', \'Chief Executive Officer\', \'692\nPromiscuous Plaza\', \'326-555-3492\', \'MM1\'),\n (\'Henry\', \'Foster\', \'Store Manager\', \'314 Savage\nCircle\', \'326-555-3847\', \'HF1\'),\n (\'Bernard\', \'Marx\', \'Cashier\', \'1240 Ambient\nAvenue\', \'326-555-8456\', \'BM1\'),\n (\'Lenina\', \'Crowne\', \'Cashier\', \'281 Bumblepuppy\nBoulevard\', \'328-555-2349\', \'LC1\'),\n (\'Fanny\', \'Crowne\', \'Restocker\', \'1023 Bokanovsky\nLane\', \'326-555-6329\', \'FC1\'),\n (\'Helmholtz\', \'Watson\', \'Janitor\', \'944 Soma\nCourt\', \'329-555-2478\', \'HW1\');\n \nSHOW INDEXES FROM employees_example;\n \n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n| Table | Non_unique | Key_name | Seq_in_index | Column_name\n| Collation | Cardinality | Sub_part | Packed | Null |\nIndex_type | Comment | Index_comment |\n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n| employees_example | 0 | PRIMARY | 1 | id | A | 7 | NULL |\nNULL | | BTREE | | |\n| employees_example | 0 | employee_code | 1 | employee_code\n| A | 7 | NULL | NULL | | BTREE | | |\n| employees_example | 1 | first_name | 1 | first_name | A |\nNULL | NULL | NULL | | BTREE | | |\n| employees_example | 1 | first_name | 2 | last_name | A |\nNULL | NULL | NULL | | BTREE | | |\n+-------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-index/','','https://mariadb.com/kb/en/show-index/'),(381,'SHOW LOCALES',26,'SHOW LOCALES was introduced as part of the Information\nSchema plugin extension in MariaDB 10.1.1.\n \nSHOW LOCALES is used to return locales information as part\nof the Locales plugin. While the information_schema.LOCALES\ntable has 8 columns, the SHOW LOCALES statement will only\ndisplay 4 of them:\n \nExample\n \nSHOW LOCALES;\n+-----+-------+-------------------------------------+------------------------+\n| Id | Name | Description | Error_Message_Language |\n+-----+-------+-------------------------------------+------------------------+\n| 0 | en_US | English - United States | english |\n| 1 | en_GB | English - United Kingdom | english |\n| 2 | ja_JP | Japanese - Japan | japanese |\n| 3 | sv_SE | Swedish - Sweden | swedish |\n...\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-locales/','','https://mariadb.com/kb/en/show-locales/'),(382,'SHOW MASTER STATUS',26,'Syntax\n------ \nSHOW MASTER STATUS\n \nDescription\n----------- \nProvides status information about the binary log files of\nthe master.\n \nThis statement requires the SUPER or the REPLICATION_CLIENT\nprivilege.\n \nTo see information about the current GTIDs in the binary\nlog, use the\ngtid_binlog_pos variable.\n \nExample\n \nSHOW MASTER STATUS;\n+--------------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+--------------------+----------+--------------+------------------+\n| mariadb-bin.000016 | 475 | | |\n+--------------------+----------+--------------+------------------+\nSELECT @@global.gtid_binlog_pos;\n+--------------------------+\n| @@global.gtid_binlog_pos |\n+--------------------------+\n| 0-1-2 |\n+--------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-master-status/','','https://mariadb.com/kb/en/show-master-status/'),(383,'SHOW OPEN TABLES',26,'Syntax\n------ \nSHOW OPEN TABLES [FROM db_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \n SHOW OPEN TABLES lists the non-TEMPORARY\ntables that are currently open in the table cache. See\nhttp://dev.mysql.com/doc/refman/5.1/en/table-cache.html.\n \nThe FROM and LIKE clauses may be used.\n \nThe FROM\nclause, if present, restricts the tables shown to those\npresent in the\ndb_name database. \n \nThe LIKE clause, if\npresent on its own, indicates which table names to match.\nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nThe following information is returned:\n \nColumn | Description | \n \nDatabase | Database name. | \n \nName | Table name. | \n \nIn_use | Number of table instances being used. | \n \nName_locked | 1 if the table is name-locked, e.g. if it is\nbeing dropped or renamed, otherwise 0. | \n \nBefore MariaDB 5.5, each use of, for example, LOCK TABLE ...\nWRITE would increment In_use for that table. With the\nimplementation of the metadata locking improvements in\nMariaDB 5.5, LOCK TABLE... WRITE acquires a strong MDL lock,\nand concurrent connections will wait on this MDL lock, so\nany subsequent LOCK TABLE... WRITE will not increment\nIn_use.\n \nExample\n \nSHOW OPEN TABLES;\n \n+----------+---------------------------+--------+-------------+\n| Database | Table | In_use | Name_locked |\n+----------+---------------------------+--------+-------------+\n...\n| test | xjson | 0 | 0 |\n| test | jauthor | 0 | 0 |\n| test | locks | 1 | 0 |\n...\n+----------+---------------------------+--------+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-open-tables/','','https://mariadb.com/kb/en/show-open-tables/'),(384,'SHOW PACKAGE BODY STATUS',26,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nSHOW PACKAGE BODY STATUS\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThe SHOW PACKAGE BODY STATUS statement returns\ncharacteristics of stored package bodies (implementations),\nsuch as the database, name, type, creator, creation and\nmodification dates, and character set information. A similar\nstatement, SHOW PACKAGE STATUS, displays information about\nstored package specifications.\n \nThe LIKE clause, if present, indicates which package names\nto match. The WHERE and LIKE clauses can be given to select\nrows using more general conditions, as discussed in Extended\nSHOW.\n \nThe ROUTINES table in the INFORMATION_SCHEMA database\ncontains more detailed information.\n \nExamples\n-------- \nSHOW PACKAGE BODY STATUS LIKE \'pkg1\'\\G\n*************************** 1. row\n***************************\n Db: test\n Name: pkg1\n Type: PACKAGE BODY\n Definer: root@localhost\n Modified: 2018-02-27 14:44:14\n Created: 2018-02-27 14:44:14\n Security_type: DEFINER\n Comment: This is my first package body\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-package-body-status/','','https://mariadb.com/kb/en/show-package-body-status/'),(385,'SHOW PACKAGE STATUS',26,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nSHOW PACKAGE STATUS\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThe SHOW PACKAGE STATUS statement returns characteristics of\nstored package specifications, such as the database, name,\ntype, creator, creation and modification dates, and\ncharacter set information. A similar statement, SHOW PACKAGE\nBODY STATUS, displays information about stored package\nbodies (i.e. implementations).\n \nThe LIKE clause, if present, indicates which package names\nto match. The WHERE and LIKE clauses can be given to select\nrows using more general conditions, as discussed in Extended\nSHOW.\n \nThe ROUTINES table in the INFORMATION_SCHEMA database\ncontains more detailed information.\n \nExamples\n-------- \nSHOW PACKAGE STATUS LIKE \'pkg1\'\\G\n*************************** 1. row\n***************************\n Db: test\n Name: pkg1\n Type: PACKAGE\n Definer: root@localhost\n Modified: 2018-02-27 14:38:15\n Created: 2018-02-27 14:38:15\n Security_type: DEFINER\n Comment: This is my first package\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-package-status/','','https://mariadb.com/kb/en/show-package-status/'),(386,'SHOW PLUGINS',26,'Syntax\n------ \nSHOW PLUGINS;\n \nDescription\n----------- \n SHOW PLUGINS displays information about installed plugins.\nThe Library column indicates the plugin library - if it is\nNULL, the plugin is built-in and cannot be uninstalled.\n \nThe PLUGINS table in the information_schema database\ncontains more detailed information.\n \nFor specific information about storage engines (a particular\ntype of plugin), see the information_schema.ENGINES table\nand the SHOW ENGINES statement.\n \nExamples\n-------- \nSHOW PLUGINS;\n+----------------------------+----------+--------------------+-------------+---------+\n| Name | Status | Type | Library | License |\n+----------------------------+----------+--------------------+-------------+---------+\n| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| mysql_native_password | ACTIVE | AUTHENTICATION | NULL |\nGPL |\n| mysql_old_password | ACTIVE | AUTHENTICATION | NULL | GPL\n|\n| MRG_MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| FEDERATED | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL\n|\n| Aria | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |\n...\n| INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL |\nGPL |\n| INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA |\nNULL | GPL |\n| SPHINX | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| FEEDBACK | DISABLED | INFORMATION SCHEMA | NULL | GPL |\n| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |\n| pam | ACTIVE | AUTHENTICATION | auth_pam.so | GPL |\n+----------------------------+----------+--------------------+-------------+---------+\n \n\n\nURL: https://mariadb.com/kb/en/show-plugins/','','https://mariadb.com/kb/en/show-plugins/'),(387,'SHOW PLUGINS SONAME',26,'MariaDB 10.0.2\n \nSHOW PLUGINS SONAME was introduced in MariaDB 10.0.2\n \nSyntax\n------ \nSHOW PLUGINS SONAME { library | LIKE \'pattern\' | WHERE\nexpr };\n \nDescription\n----------- \nSHOW PLUGINS SONAME displays information about compiled-in\nand all server plugins in the plugin_dir directory,\nincluding plugins that haven\'t been installed.\n \nExamples\n-------- \nSHOW PLUGINS SONAME \'ha_example.so\';\n+----------+---------------+----------------+---------------+---------+\n| Name | Status | Type | Library | License |\n+----------+---------------+----------------+---------------+---------+\n| EXAMPLE | NOT INSTALLED | STORAGE ENGINE | ha_example.so |\nGPL |\n| UNUSABLE | NOT INSTALLED | DAEMON | ha_example.so | GPL |\n+----------+---------------+----------------+---------------+---------+\n \nThere is also a corresponding information_schema table,\ncalled ALL_PLUGINS, which contains more complete\ninformation.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-plugins-soname/','','https://mariadb.com/kb/en/show-plugins-soname/'),(388,'SHOW PRIVILEGES',26,'Syntax\n------ \nSHOW PRIVILEGES\n \nDescription\n----------- \n SHOW PRIVILEGES shows the list of system privileges that\nthe MariaDB server supports. The exact list of privileges\ndepends on the version of your server.\n \nNote that the Delete history privilege displays as Delete\nversioning rows (MDEV-20382).\n \nExamples\n-------- \nSHOW PRIVILEGES;\n+-------------------------+---------------------------------------+-------------------------------------------------------+\n| Privilege | Context | Comment |\n+-------------------------+---------------------------------------+-------------------------------------------------------+\n| Alter | Tables | To alter the table |\n| Alter routine | Functions,Procedures | To alter or drop\nstored functions/procedures |\n| Create | Databases,Tables,Indexes | To create new\ndatabases and tables |\n| Create routine | Databases | To use CREATE\nFUNCTION/PROCEDURE |\n| Create temporary tables | Databases | To use CREATE\nTEMPORARY TABLE |\n| Create view | Tables | To create new views |\n| Create user | Server Admin | To create new users |\n| Delete | Tables | To delete existing rows |\n| Delete versioning rows | Tables | To delete versioning\ntable historical rows |\n| Drop | Databases,Tables | To drop databases, tables, and\nviews |\n| Event | Server Admin | To create, alter, drop and execute\nevents |\n| Execute | Functions,Procedures | To execute stored\nroutines |\n| File | File access on server | To read and write files on\nthe server |\n| Grant option | Databases,Tables,Functions,Procedures | To\ngive to other users those privileges you possess |\n| Index | Tables | To create or drop indexes |\n| Insert | Tables | To insert data into tables |\n| Lock tables | Databases | To use LOCK TABLES (together\nwith SELECT privilege) |\n| Process | Server Admin | To view the plain text of\ncurrently executing queries |\n| Proxy | Server Admin | To make proxy user possible |\n| References | Databases,Tables | To have references on\ntables |\n| Reload | Server Admin | To reload or refresh tables, logs\nand privileges |\n| Replication client | Server Admin | To ask where the slave\nor master servers are |\n| Replication slave | Server Admin | To read binary log\nevents from the master |\n| Select | Tables | To retrieve rows from table |\n| Show databases | Server Admin | To see all databases with\nSHOW DATABASES |\n| Show view | Tables | To see views with SHOW CREATE VIEW |\n| Shutdown | Server Admin | To shut down the server |\n| Super | Server Admin | To use KILL thread, SET GLOBAL,\nCHANGE MASTER, etc. |\n| Trigger | Tables | To use triggers |\n| Create tablespace | Server Admin | To create/alter/drop\ntablespaces |\n| Update | Tables | To update existing rows |\n| Usage | Server Admin | No privileges - allow connect only\n|\n+-------------------------+---------------------------------------+-------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-privileges/','','https://mariadb.com/kb/en/show-privileges/'),(389,'SHOW PROCEDURE CODE',26,'Syntax\n------ \nSHOW PROCEDURE CODE proc_name\n \nDescription\n----------- \nThis statement is a MariaDB extension that is available only\nfor servers that\nhave been built with debugging support. It displays a\nrepresentation of the\ninternal implementation of the named stored procedure. A\nsimilar statement,\n SHOW FUNCTION CODE, displays\ninformation about stored functions.\n \nBoth statements require that you be the owner of the routine\nor have\n SELECT access to the mysql.proc table.\n \nIf the named routine is available, each statement produces a\nresult\nset. Each row in the result set corresponds to one\n\"instruction\" in\nthe routine. The first column is Pos, which is an ordinal\nnumber\nbeginning with 0. The second column is Instruction, which\ncontains an\nSQL statement (usually changed from the original source), or\na\ndirective which has meaning only to the stored-routine\nhandler.\n \nExamples\n-------- \nDELIMITER //\n \nCREATE PROCEDURE p1 ()\n BEGIN\n DECLARE fanta INT DEFAULT 55;\n DROP TABLE t2;\n LOOP\n INSERT INTO t3 VALUES (fanta);\n END LOOP;\n END//\nQuery OK, 0 rows affected (0.00 sec)\n \nSHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-procedure-code/','','https://mariadb.com/kb/en/show-procedure-code/'),(390,'SHOW PROCEDURE STATUS',26,'Syntax\n------ \nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nThis statement is a MariaDB extension. It returns\ncharacteristics of a stored\nprocedure, such as the database, name, type, creator,\ncreation and modification\ndates, and character set information. A similar statement, \n SHOW FUNCTION STATUS, displays\ninformation about stored functions.\n \nThe LIKE clause, if present, indicates which procedure or\nfunction names to match. The WHERE and LIKE clauses can be\ngiven to select rows using more general conditions, as\ndiscussed in Extended SHOW.\n \nThe ROUTINES table in the INFORMATION_SCHEMA database\ncontains more detailed information.\n \nExamples\n-------- \nSHOW PROCEDURE STATUS LIKE \'p1\'\\G\n*************************** 1. row\n***************************\n Db: test\n Name: p1\n Type: PROCEDURE\n Definer: root@localhost\n Modified: 2010-08-23 13:23:03\n Created: 2010-08-23 13:23:03\n Security_type: DEFINER\n Comment: \ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n \n\n\nURL: https://mariadb.com/kb/en/show-procedure-status/','','https://mariadb.com/kb/en/show-procedure-status/'),(395,'SHOW RELAYLOG EVENTS',26,'Syntax\n------ \nSHOW RELAYLOG [\'connection_name\'] EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n \nDescription\n----------- \nOn replication slaves this command shows the events in the\nrelay log. If \'log_name\' is not specified, the first relay\nlog is shown.\n \nSyntax for the LIMIT clause is the same as for SELECT ...\nLIMIT.\n \nUsing the LIMIT clause is highly recommended because the\nSHOW RELAYLOG EVENTS command returns the complete contents\nof the relay log, which can be quite large.\n \nThis command does not return events related to setting user\nand system variables. If you need those, use mysqlbinlog.\n \nOn the replication master, this command does nothing.\n \nconnection_name\n \nconnection_name was added as part of multi-source\nreplication added in MariaDB 10.0.1\n \nIf there is only one nameless master, or the default master\n(as specified by the default_master_connection system\nvariable) is intended, connection_name can be omitted. If\nprovided, the SHOW RELAYLOG statement will apply to the\nspecified master. connection_name is case-insensitive.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-relaylog-events/','','https://mariadb.com/kb/en/show-relaylog-events/'),(396,'SHOW SLAVE HOSTS',26,'Syntax\n------ \nSHOW SLAVE HOSTS\n \nDescription\n----------- \nThis command is run on the master and displays a list of\nreplication slaves that are currently registered with it.\nOnly slaves started with the --report-host=host_name option\nare visible in this list.\n \nThe list is displayed on any server (not just the master\nserver). The output\nlooks like this:\n \nSHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\nServer_id: The unique server ID of the slave server, as\nconfigured in the server\'s option file, or on the command\nline with --server-id=value.\nHost: The host name of the slave server, as configured in\nthe server\'s option file, or on the command line with\n--report-host=host_name. Note that this can differ from the\nmachine name as configured in the operating system.\nPort: The port the slave server is listening on.\nMaster_id: The unique server ID of the master server that\nthe slave server is replicating from.\n \nSome MariaDB and MySQL versions report another variable,\nrpl_recovery_rank. This\nvariable was never used, and was eventually removed in\nMariaDB 10.1.2 and MySQL 5.6.\n \n\n\nURL: https://mariadb.com/kb/en/show-slave-hosts/','','https://mariadb.com/kb/en/show-slave-hosts/'),(391,'SHOW PROCESSLIST',26,'Syntax\n------ \nSHOW [FULL] PROCESSLIST\n \nDescription\n----------- \n SHOW PROCESSLIST shows you which threads are running. You\ncan also get this information from the\ninformation_schema.PROCESSLIST table or the mysqladmin\nprocesslist command. If you have the \nPROCESS privilege, you can see all threads.\nOtherwise, you can see only your own threads (that is,\nthreads associated with\nthe MariaDB account that you are using). If you do not use\nthe\nFULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n \nThe columns shown in SHOW PROCESSLIST\n are:\n \nName | Description | Introduced | \n \nID | The client\'s process ID. | | \n \nUSER | The username associated with the process. | | \n \nHOST | The host the client is connected to. | | \n \nDB | The default database of the process (NULL if no\ndefault). | | \n \nCOMMAND | The command type. See Thread Command Values. | | \n \nTIME | The amount of time, in seconds, the process has been\nin its current state. For a slave SQL thread before MariaDB\n10.1, this is the time in seconds between the last\nreplicated event\'s timestamp and the slave machine\'s real\ntime. | | \n \nSTATE | See Thread States. | | \n \nINFO | The statement being executed. | | \n \nPROGRESS | The total progress of the process (0-100%) (see\nProgress Reporting). | MariaDB 5.3 | \n \nSee TIME_MS column in information_schema.PROCESSLIST for\ndifferences in the TIME column between MariaDB and MySQL.\n \nThe information_schema.PROCESSLIST table contains the\nfollowing additional columns:\n \nName | Description | Introduced | \n \nTIME_MS | The amount of time, in milliseconds, the process\nhas been in its current state. | MariaDB 5.1 | \n \nSTAGE | The stage the process is currently in. |\nMariaDB 5.3 | \n \nMAX_STAGE | The maximum number of stages. | MariaDB 5.3 | \n \nPROGRESS | The progress of the process within the current\nstage (0-100%). | MariaDB 5.3 | \n \nMEMORY_USED | The amount of memory used by the process. |\nMariaDB 10.0.1 | \n \nEXAMINED_ROWS | The number of rows the process has examined.\n| MariaDB 10.0.1 | \n \nQUERY_ID | Query ID. | MariaDB 10.0.5 | \n \nNote that the PROGRESS field from the information schema,\nand the PROGRESS field from SHOW PROCESSLIST display\ndifferent results. SHOW PROCESSLIST shows the total\nprogress, while the information schema shows the progress\nfor the current stage only.\n \nThreads can be killed using their thread_id, or, since\nMariaDB 10.0.5, their query_id, with the KILL statement.\n \nSince queries on this table are locking, if the\nperformance_schema is enabled, you may want to query the\nTHREADS table instead.\n \nExamples\n-------- \nFrom MariaDB 5.1.x\n \nSHOW FULL PROCESSLIST;\n+---------+-------+-----------+------+---------+------+-------+-----------------------+\n| Id | User | Host | db | Command | Time | State | Info |\n+---------+-------+-----------+------+---------+------+-------+-----------------------+\n| 1988880 | dbart | localhost | NULL | Query | 0 | NULL |\nSHOW FULL PROCESSLIST |\n+---------+-------+-----------+------+---------+------+-------+-----------------------+\n \nSELECT * FROM information_schema.processlist;\n+---------+-------+-----------+------+---------+------+-----------+----------------------------------------------+---------+\n| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |\nTIME_MS |\n+---------+-------+-----------+------+---------+------+-----------+----------------------------------------------+---------+\n| 1988880 | dbart | localhost | NULL | Query | 0 | executing\n| SELECT * FROM information_schema.processlist | 0.444 |\n+---------+-------+-----------+------+---------+------+-----------+----------------------------------------------+---------+\n \nFrom MariaDB 5.5.x\n \nSHOW FULL PROCESSLIST;\n+-----+------+-----------+------+---------+------+-------+-----------------------+----------+\n| Id | User | Host | db | Command | Time | State | Info |\nProgress |\n+-----+------+-----------+------+---------+------+-------+-----------------------+----------+\n| 126 | root | localhost | NULL | Query | 0 | NULL | SHOW\nFULL PROCESSLIST | 0.000 |\n+-----+------+-----------+------+---------+------+-------+-----------------------+----------+\n \nSELECT * FROM information_schema.processlist;\n+-----+--------+-----------+------+---------+------+-----------+----------------------------------------------+---------+-------+-----------+----------+\n| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |\nTIME_MS | STAGE | MAX_STAGE | PROGRESS |\n+-----+--------+-----------+------+---------+------+-----------+----------------------------------------------+---------+-------+-----------+----------+\n| 126 | root | localhost | NULL | Query | 0 | executing |\nSELECT * FROM information_schema.processlist | 344.718 | 0 |\n0 | 0.000 |\n+-----+--------+-----------+------+---------+------+-----------+----------------------------------------------+---------+-------+-----------+----------+\n \nFrom MariaDB 10.0.x\n \nSHOW PROCESSLIST;\n+----+-----------------+-----------+------+---------+------+------------------------+------------------+----------+\n| Id | User | Host | db | Command | Time | State | Info |\nProgress |\n+----+-----------------+-----------+------+---------+------+------------------------+------------------+----------+\n| 2 | event_scheduler | localhost | NULL | Daemon | 2693 |\nWaiting on empty queue | NULL | 0.000 |\n| 4 | root | localhost | NULL | Query | 0 | Table lock |\nSHOW PROCESSLIST | 0.000 |\n+----+-----------------+-----------+------+---------+------+------------------------+------------------+----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-processlist/','','https://mariadb.com/kb/en/show-processlist/'),(392,'SHOW PROFILE',26,'Syntax\n------ \nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n \ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n \nDescription\n----------- \nThe SHOW PROFILE and \nSHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements\nexecuted during the\ncourse of the current session.\n \nProfiling is controlled by the profiling session variable,\nwhich has a default value of 0 (OFF). Profiling is enabled\nby setting profiling to 1 or ON:\n \nSET profiling = 1;\n \nSHOW PROFILES displays a list of the most recent statements\nsent to the master. The size of the list is controlled by\nthe\nprofiling_history_size session variable, which has a default\nvalue of 15. The maximum value is 100. Setting the value to\n0 has the practical effect of disabling profiling.\n \nAll statements are profiled except SHOW PROFILES and \nSHOW PROFILE, so you will find neither of those statements\nin the profile list. Malformed statements are profiled. For\nexample, \n SHOW PROFILING is an illegal statement, and a syntax error\noccurs if you try to execute it, but it will show up in the\nprofiling list.\n \n SHOW PROFILE displays detailed information about a single\nstatement. Without the FOR QUERY n clause, the output\npertains to the most recently executed statement. If \n FOR QUERY n is included,\n SHOW PROFILE displays information for statement n. The\nvalues of n correspond to\nthe Query_ID values displayed by SHOW PROFILES.\n \nThe LIMIT row_count clause may be given to limit the\noutput to row_count rows. If LIMIT is given, \n OFFSET offset may be added to begin the output offset\nrows into the full set of rows.\n \nBy default, SHOW PROFILE displays Status and Duration\ncolumns. The Status values are like the State values\ndisplayed by \nSHOW PROCESSLIST,\nalthough there might be some minor differences in\ninterpretation for\nthe two statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.6/en/thread-information.html).\n \nOptional type values may be specified to display specific\nadditional\ntypes of information:\nALL displays all information\nBLOCK IO displays counts for block input and output\noperations\nCONTEXT SWITCHES displays counts for voluntary and\ninvoluntary context switches\nCPU displays user and system CPU usage times\nIPC displays counts for messages sent and received\nMEMORY is not currently implemented\nPAGE FAULTS displays counts for major and minor page faults\nSOURCE displays the names of functions from the source code,\ntogether with the name and line number of the file in which\nthe function occurs\nSWAPS displays swap counts\n \nProfiling is enabled per session. When a session ends, its\nprofiling information is lost.\n \nThe information_schema.PROFILING table contains similar\ninformation.\n \nExamples\n-------- \nSELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n \nSET profiling = 1;\n \nUSE test;\n \nDROP TABLE IF EXISTS t1;\n \nCREATE TABLE T1 (id INT);\n \nSHOW PROFILES;\n+----------+------------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+------------+--------------------------+\n| 1 | 0.00009200 | SELECT DATABASE() |\n| 2 | 0.00023800 | show databases |\n| 3 | 0.00018900 | show tables |\n| 4 | 0.00014700 | DROP TABLE IF EXISTS t1 |\n| 5 | 0.24476900 | CREATE TABLE T1 (id INT) |\n+----------+------------+--------------------------+\n \nSHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| starting | 0.000042 |\n| checking permissions | 0.000044 |\n| creating table | 0.244645 |\n| After create | 0.000013 |\n| query end | 0.000003 |\n| freeing items | 0.000016 |\n| logging slow query | 0.000003 |\n| cleaning up | 0.000003 |\n+----------------------+----------+\n \nSHOW PROFILE FOR QUERY 4;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| starting | 0.000126 |\n| query end | 0.000004 |\n| freeing items | 0.000012 |\n| logging slow query | 0.000003 |\n| cleaning up | 0.000002 |\n+--------------------+----------+\n \nSHOW PROFILE CPU FOR QUERY 5;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| starting | 0.000042 | 0.000000 | 0.000000 |\n| checking permissions | 0.000044 | 0.000000 | 0.000000 |\n| creating table | 0.244645 | 0.000000 | 0.000000 |\n| After create | 0.000013 | 0.000000 | 0.000000 |\n| query end | 0.000003 | 0.000000 | 0.000000 |\n| freeing items | 0.000016 | 0.000000 | 0.000000 |\n| logging slow query | 0.000003 | 0.000000 | 0.000000 |\n| cleaning up | 0.000003 | 0.000000 | 0.000000 |\n+----------------------+----------+----------+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-profile/','','https://mariadb.com/kb/en/show-profile/'),(399,'SHOW TABLE STATUS',26,'Syntax\n------ \nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \n SHOW TABLE STATUS works like \n SHOW TABLES, but provides more extensive information about\neach non-TEMPORARY table.\n \nThe LIKE clause, if present on its own, indicates which\ntable names to\nmatch. The WHERE and LIKE clauses can be given to select\nrows using more general conditions, as discussed in Extended\nSHOW.\n \nThe following information is returned:\n \nColumn | Description | \n \nName | Table name. | \n \nEngine | Table storage engine. | \n \nVersion | Version number from the table\'s .frm file. | \n \nRow_format | Row format (see InnoDB, Aria and MyISAM row\nformats). | \n \nRows | Number of rows in the table. Some engines, such as\nXtraDB and InnoDB may store an estimate. | \n \nAvg_row_length | Average row length in the table. | \n \nData_length | For InnoDB/XtraDB, the index size, in pages,\nmultiplied by the page size. For Aria and MyISAM, length of\nthe data file, in bytes. For MEMORY, the approximate\nallocated memory. | \n \nMax_data_length | Maximum length of the data file, ie the\ntotal number of bytes that could be stored in the table. Not\nused in XtraDB and InnoDB. | \n \nIndex_length | Length of the index file. | \n \nData_free | Bytes allocated but unused. For InnoDB tables in\na shared tablespace, the free space of the shared tablespace\nwith small safety margin. An estimate in the case of\npartitioned tables - see the PARTITIONS table. | \n \nAuto_increment | Next AUTO_INCREMENT value. | \n \nCreate_time | Time the table was created. | \n \nUpdate_time | Time the table was last updated. On Windows,\nthe timestamp is not updated on update, so MyISAM values\nwill be inaccurate. In InnoDB, if shared tablespaces are\nused, will be NULL, while buffering can also delay the\nupdate, so the value will differ from the actual time of the\nlast UPDATE, INSERT or DELETE. | \n \nCheck_time | Time the table was last checked. Not kept by\nall storage engines, in which case will be NULL. | \n \nCollation | Character set and collation. | \n \nChecksum | Live checksum value, if any. | \n \nCreate_options | Extra CREATE TABLE options. | \n \nComment | Table comment provided when MariaDB created the\ntable. | \n \nSimilar information can be found in the\ninformation_schema.TABLES table as well as by using\nmysqlshow:\n \nmysqlshow --status db_name\n \nExample\n \nshow table status\\G\n*************************** 1. row\n***************************\n Name: bus_routes\n Engine: InnoDB\n Version: 10\n Row_format: Dynamic\n Rows: 5\n Avg_row_length: 3276\n Data_length: 16384\nMax_data_length: 0\n Index_length: 0\n Data_free: 0\n Auto_increment: NULL\n Create_time: 2017-05-24 11:17:46\n Update_time: NULL\n Check_time: NULL\n Collation: latin1_swedish_ci\n Checksum: NULL\n Create_options: \n Comment:\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-table-status/','','https://mariadb.com/kb/en/show-table-status/'),(400,'SHOW TABLES',26,'Syntax\n------ \nSHOW [FULL] TABLES [FROM db_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nSHOW TABLES lists the non-TEMPORARY tables, sequences and\nviews in a given database. \n \nThe LIKE clause, if present on its own, indicates which\ntable names to match. The WHERE and LIKE clauses can be\ngiven to select rows using more general conditions, as\ndiscussed in Extended SHOW. For example, when searching for\ntables in the test database, the column name for use in the\nWHERE and LIKE clauses will be Tables_in_test\n \nThe FULL modifier is supported such that SHOW FULL TABLES\ndisplays a second output column. Values for the second\ncolumn. Table_type, are BASE TABLE for a table, VIEW for a\nview and SEQUENCE for a sequence.\n \nYou can also get this information using:\n \nmysqlshow db_name\n \nSee mysqlshow for more details.\n \nIf you have no privileges for a base table or view, it does\nnot show up in the output from SHOW TABLES or mysqlshow\ndb_name.\n \nThe information_schema.TABLES table, as well as the SHOW\nTABLE STATUS statement, provide extended information about\ntables.\n \nExamples\n-------- \nSHOW TABLES;\n+----------------------+\n| Tables_in_test |\n+----------------------+\n| animal_count |\n| animals |\n| are_the_mooses_loose |\n| aria_test2 |\n| t1 |\n| view1 |\n+----------------------+\n \nShowing the tables beginning with a only.\n \nSHOW TABLES WHERE Tables_in_test LIKE \'a%\';\n+----------------------+\n| Tables_in_test |\n+----------------------+\n| animal_count |\n| animals |\n| are_the_mooses_loose |\n| aria_test2 |\n+----------------------+\n \nShowing tables and table types:\n \nSHOW FULL TABLES;\n+----------------+------------+\n| Tables_in_test | Table_type |\n+----------------+------------+\n| s1 | SEQUENCE |\n| student | BASE TABLE |\n| v1 | VIEW |\n+----------------+------------+\n \n\n\nURL: https://mariadb.com/kb/en/show-tables/','','https://mariadb.com/kb/en/show-tables/'),(401,'SHOW TABLE_STATISTICS',26,'MariaDB 5.2 introduced the User Statistics feature.\n \nSyntax\n------ \nSHOW TABLE_STATISTICS\n \nDescription\n----------- \nThe SHOW TABLE_STATISTICS statement was introduced in\nMariaDB 5.2 as part of the User Statistics feature. It was\nremoved as a separate statement in MariaDB 10.1.1, but\neffectively replaced by the generic SHOW\ninformation_schema_table statement. The\ninformation_schema.TABLE_STATISTICS table shows statistics\non table usage\n \nThe userstat system variable must be set to 1 to activate\nthis feature. See the User Statistics and\ninformation_schema.TABLE_STATISTICS articles for more\ninformation.\n \nExample\n \nFrom MariaDB 10.0\n \nSHOW TABLE_STATISTICS\\G\n*************************** 1. row\n***************************\n Table_schema: mysql\n Table_name: proxies_priv\n Rows_read: 2\n Rows_changed: 0\nRows_changed_x_#indexes: 0\n*************************** 2. row\n***************************\n Table_schema: test\n Table_name: employees_example\n Rows_read: 7\n Rows_changed: 0\nRows_changed_x_#indexes: 0\n*************************** 3. row\n***************************\n Table_schema: mysql\n Table_name: user\n Rows_read: 16\n Rows_changed: 0\nRows_changed_x_#indexes: 0\n*************************** 4. row\n***************************\n Table_schema: mysql\n Table_name: db\n Rows_read: 2\n Rows_changed: 0\nRows_changed_x_#indexes: 0\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-table-statistics/','','https://mariadb.com/kb/en/show-table-statistics/'),(402,'SHOW TRIGGERS',26,'Syntax\n------ \nSHOW TRIGGERS [FROM db_name]\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \n SHOW TRIGGERS lists the triggers currently defined for\ntables in a database (the default database unless a FROM\nclause is given). This statement requires the\nTRIGGER privilege (prior to MySQL\n5.1.22, it required the SUPER privilege). \n \nThe LIKE clause, if present on its own, indicates which\ntable names to\nmatch and causes the statement to display triggers for those\ntables. The WHERE and LIKE clauses can be given to select\nrows using more general conditions, as discussed in Extended\nSHOW.\n \nSimilar information is stored in the\ninformation_schema.TRIGGERS table.\n \nIf there are multiple triggers for the same action, then the\ntriggers are shown in action order.\n \nExamples\n-------- \nFor the trigger defined at Trigger Overview:\n \nSHOW triggers Like \'animals\' \\G\n*************************** 1. row\n***************************\n Trigger: the_mooses_are_loose\n Event: INSERT\n Table: animals\n Statement: BEGIN\n IF NEW.name = \'Moose\' THEN\n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+100;\n ELSE \n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n END IF;\nEND\n Timing: AFTER\n Created: 2016-09-29 13:53:34.35\n sql_mode: \n Definer: root@localhost\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \nListing all triggers associated with a certain table:\n \nSHOW TRIGGERS FROM test WHERE `Table` = \'user\' \\G\n*************************** 1. row\n***************************\n Trigger: user_ai\n Event: INSERT\n Table: user\n Statement: BEGIN END\n Timing: AFTER\n Created: 2016-09-29 13:53:34.35\n sql_mode: \n Definer: root@%\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\n \nSHOW triggers WHERE Event Like \'Insert\' \\G\n*************************** 1. row\n***************************\n Trigger: the_mooses_are_loose\n Event: INSERT\n Table: animals\n Statement: BEGIN\n IF NEW.name = \'Moose\' THEN\n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+100;\n ELSE \n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n END IF;\nEND\n Timing: AFTER\n Created: 2016-09-29 13:53:34.35\n sql_mode: \n Definer: root@localhost\ncharacter_set_client: utf8\ncollation_connection: utf8_general_ci\n Database Collation: latin1_swedish_ci\ncharacter_set_client is the session value of the\ncharacter_set_client system variable when the trigger was\ncreated. \ncollation_connection is the session value of the\ncollation_connection system variable when the trigger was\n created. \nDatabase Collation is the collation of the database \n with which the trigger is associated.\n \nThese columns were added in MariaDB/MySQL 5.1.21.\n \nOld triggers created before MySQL 5.7 and MariaDB 10.2.3 has\nNULL in the Created column.\n \n\n\nURL: https://mariadb.com/kb/en/show-triggers/','','https://mariadb.com/kb/en/show-triggers/'),(403,'SHOW USER_STATISTICS',26,'MariaDB 5.2 introduced the User Statistics feature.\n \nSyntax\n------ \nSHOW USER_STATISTICS\n \nDescription\n----------- \nThe SHOW USER_STATISTICS statement was introduced in MariaDB\n5.2 as part of the User Statistics feature. It was removed\nas a separate statement in MariaDB 10.1.1, but effectively\nreplaced by the generic SHOW information_schema_table\nstatement. The information_schema.USER_STATISTICS table\nholds statistics about user activity. You can use this table\nto find out such things as which user is causing the most\nload and which users are being abusive. You can also use\nthis table to measure how close to capacity the server may\nbe.\n \nThe userstat system variable must be set to 1 to activate\nthis feature. See the User Statistics and\ninformation_schema.USER_STATISTICS table for more\ninformation.\n \nExample\n \nFrom MariaDB 10.0:\n \nSHOW USER_STATISTICS\\G\n*************************** 1. row\n***************************\n User: root\n Total_connections: 1\nConcurrent_connections: 0\n Connected_time: 3297\n Busy_time: 0.14113400000000006\n Cpu_time: 0.017637000000000003\n Bytes_received: 969\n Bytes_sent: 22355\n Binlog_bytes_written: 0\n Rows_read: 10\n Rows_sent: 67\n Rows_deleted: 0\n Rows_inserted: 0\n Rows_updated: 0\n Select_commands: 7\n Update_commands: 0\n Other_commands: 0\n Commit_transactions: 1\n Rollback_transactions: 0\n Denied_connections: 0\n Lost_connections: 0\n Access_denied: 0\n Empty_queries: 7\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-user-statistics/','','https://mariadb.com/kb/en/show-user-statistics/'),(404,'SHOW VARIABLES',26,'Syntax\n------ \nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n \nDescription\n----------- \nSHOW VARIABLES shows the values of MariaDB system variables.\nThis\ninformation also can be obtained using the mysqladmin\nvariables\ncommand. The LIKE clause, if present, indicates which\nvariable names\nto match. The WHERE clause can be given to select rows using\nmore\ngeneral conditions.\n \nWith the GLOBAL modifier, SHOW VARIABLES displays the values\nthat are\nused for new connections to MariaDB. With SESSION, it\ndisplays the\nvalues that are in effect for the current connection. If no\nmodifier\nis present, the default is SESSION. LOCAL is a synonym for\nSESSION.\nWith a LIKE clause, the statement displays only rows for\nthose\nvariables with names that match the pattern. To obtain the\nrow for a\nspecific variable, use a LIKE clause as shown:\n \nSHOW VARIABLES LIKE \'maria_group_commit\';\n \nSHOW SESSION VARIABLES LIKE \'maria_group_commit\';\n \nTo get a list of variables whose name match a pattern, use\nthe \"%\"\nwildcard character in a LIKE clause:\n \nSHOW VARIABLES LIKE \'%maria%\';\n \nSHOW GLOBAL VARIABLES LIKE \'%maria%\';\n \nWildcard characters can be used in any position within the\npattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard\nthat matches\nany single character, you should escape it as \"\\_\" to\nmatch it\nliterally. In practice, this is rarely necessary.\n \nThe WHERE and LIKE clauses can be given to select rows using\nmore general conditions, as discussed in Extended SHOW.\n \nSee SET for information on setting server system variables.\n \nSee Server System Variables for a list of all the variables\nthat can be set.\n \nYou can also see the server variables by querying the\nInformation Schema GLOBAL_VARIABLES and SESSION_VARIABLES\ntables.\n \nExamples\n-------- \nSHOW VARIABLES LIKE \'aria%\';\n \n+------------------------------------------+---------------------+\n| Variable_name | Value |\n+------------------------------------------+---------------------+\n| aria_block_size | 8192 |\n| aria_checkpoint_interval | 30 |\n| aria_checkpoint_log_activity | 1048576 |\n| aria_force_start_after_recovery_failures | 0 |\n| aria_group_commit | none |\n| aria_group_commit_interval | 0 |\n| aria_log_file_size | 1073741824 |\n| aria_log_purge_type | immediate |\n| aria_max_sort_file_size | 9223372036853727232 |\n| aria_page_checksum | ON |\n| aria_pagecache_age_threshold | 300 |\n| aria_pagecache_buffer_size | 134217728 |\n| aria_pagecache_division_limit | 100 |\n| aria_recover | NORMAL |\n| aria_repair_threads | 1 |\n| aria_sort_buffer_size | 134217728 |\n| aria_stats_method | nulls_unequal |\n| aria_sync_log_dir | NEWFILE |\n| aria_used_for_temp_tables | ON |\n+------------------------------------------+---------------------+\n \nSELECT VARIABLE_NAME, SESSION_VALUE, GLOBAL_VALUE FROM\n INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE\n VARIABLE_NAME LIKE \'max_error_count\' OR\n VARIABLE_NAME LIKE \'innodb_sync_spin_loops\';\n \n+---------------------------+---------------+--------------+\n| VARIABLE_NAME | SESSION_VALUE | GLOBAL_VALUE |\n+---------------------------+---------------+--------------+\n| MAX_ERROR_COUNT | 64 | 64 |\n| INNODB_SYNC_SPIN_LOOPS | NULL | 30 |\n+---------------------------+---------------+--------------+\n \nSET GLOBAL max_error_count=128;\n \nSELECT VARIABLE_NAME, SESSION_VALUE, GLOBAL_VALUE FROM\n INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE\n VARIABLE_NAME LIKE \'max_error_count\' OR\n VARIABLE_NAME LIKE \'innodb_sync_spin_loops\';\n \n+---------------------------+---------------+--------------+\n| VARIABLE_NAME | SESSION_VALUE | GLOBAL_VALUE |\n+---------------------------+---------------+--------------+\n| MAX_ERROR_COUNT | 64 | 128 |\n| INNODB_SYNC_SPIN_LOOPS | NULL | 30 |\n+---------------------------+---------------+--------------+\n \nSET GLOBAL max_error_count=128;\n \nSHOW VARIABLES LIKE \'max_error_count\';\n \n+-----------------+-------+\n| Variable_name | Value |\n+-----------------+-------+\n| max_error_count | 64 |\n+-----------------+-------+\n \nSHOW GLOBAL VARIABLES LIKE \'max_error_count\';\n \n+-----------------+-------+\n| Variable_name | Value |\n+-----------------+-------+\n| max_error_count | 128 |\n+-----------------+-------+\n \nBecause the following variable only has a global scope, the\nglobal value is returned even when specifying SESSION (in\nthis case by default):\n \nSHOW VARIABLES LIKE \'innodb_sync_spin_loops\';\n \n+------------------------+-------+\n| Variable_name | Value |\n+------------------------+-------+\n| innodb_sync_spin_loops | 30 |\n+------------------------+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-variables/','','https://mariadb.com/kb/en/show-variables/'),(405,'SHOW WARNINGS',26,'Syntax\n------ \nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW ERRORS [LIMIT row_count OFFSET offset]\nSHOW COUNT(*) WARNINGS\n \nDescription\n----------- \n SHOW WARNINGS shows the error, warning, and note messages\nthat resulted from the last statement that generated\nmessages in the\ncurrent session. It shows nothing if the last statement used\na table\nand generated no messages. (That is, a statement that uses a\ntable but\ngenerates no messages clears the message list.) Statements\nthat do not\nuse tables and do not generate messages have no effect on\nthe message\nlist.\n \nA note is different to a warning in that it only appears if\nthe sql_notes variable is set to 1 (the default), and is not\nconverted to an error if strict mode is enabled.\n \nA related statement, SHOW ERRORS, shows only the errors.\n \nThe SHOW COUNT(*) WARNINGS statement displays the total\nnumber of errors, warnings, and notes. You can also retrieve\nthis number from\nthe warning_count variable:\n \nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n \nThe value of warning_count might be greater than the number\nof messages displayed by SHOW WARNINGS if the\nmax_error_count system variable is set so low that not all\nmessages are stored.\n \nThe LIMIT clause has the same syntax as for the\n SELECT statement.\n \nSHOW WARNINGS can be used after EXPLAIN EXTENDED to see how\na query is internally rewritten by MariaDB.\n \nIf the sql_notes server variable is set to 1, Notes are\nincluded in the output of SHOW WARNINGS; if it is set to 0,\nthis statement will not show (or count) Notes.\n \nThe results of SHOW WARNINGS and SHOW COUNT(*) WARNINGS are\ndirectly sent to the client. If you need to access those\ninformation in a stored program, you can use the GET\nDIAGNOSTICS statement instead.\n \nFor a list of MariaDB error codes, see MariaDB Error Codes.\n \nThe mysql client also has a number of options related to\nwarnings. The \\W command will show warnings after every\nstatement, while \\w will disable this. Starting the client\nwith the --show-warnings option will show warnings after\nevery statement.\n \nMariaDB 10.3.1 implements a stored routine error stack\ntrace. SHOW WARNINGS can also be used to show more\ninformation. See the example below.\n \nExamples\n-------- \nSELECT 1/0;\n+------+\n| 1/0 |\n+------+\n| NULL |\n+------+\n \nSHOW COUNT(*) WARNINGS;\n+-------------------------+\n| @@session.warning_count |\n+-------------------------+\n| 1 |\n+-------------------------+\n \nSHOW WARNINGS;\n+---------+------+---------------+\n| Level | Code | Message |\n+---------+------+---------------+\n| Warning | 1365 | Division by 0 |\n+---------+------+---------------+\n \nStack Trace\n \nFrom MariaDB 10.3.1, displaying a stack trace:\n \nDELIMITER $$\nCREATE OR REPLACE PROCEDURE p1()\n BEGIN\n DECLARE c CURSOR FOR SELECT * FROM not_existing;\n OPEN c;\n CLOSE c;\n END;\n$$\nCREATE OR REPLACE PROCEDURE p2()\n BEGIN\n CALL p1;\n END;\n$$\nDELIMITER ;\nCALL p2;\nERROR 1146 (42S02): Table \'test.not_existing\' doesn\'t\nexist\n \nSHOW WARNINGS;\n+-------+------+-----------------------------------------+\n| Level | Code | Message |\n+-------+------+-----------------------------------------+\n| Error | 1146 | Table \'test.not_existing\' doesn\'t exist\n|\n| Note | 4091 | At line 6 in test.p1 |\n| Note | 4091 | At line 4 in test.p2 |\n+-------+------+-----------------------------------------+\n \nSHOW WARNINGS displays a stack trace, showing where the\nerror actually happened:\nLine 4 in test.p1 is the OPEN command which actually raised\nthe error\nLine 3 in test.p2 is the CALL statement, calling p1 from p2.\n \n\n\nURL: https://mariadb.com/kb/en/show-warnings/','','https://mariadb.com/kb/en/show-warnings/'),(406,'SHOW WSREP_MEMBERSHIP',26,'MariaDB 10.1.2\n \nSHOW WSREP_MEMBERSHIP was introduced with the WSREP_INFO\nplugin in MariaDB 10.1.2.\n \nSyntax\n------ \nSHOW WSREP_MEMBERSHIP\n \nDescription\n----------- \nThe SHOW WSREP_MEMBERSHIP statement returns Galera node\ncluster membership information. It returns the same\ninformation as found in the\ninformation_schema.WSREP_MEMBERSHIP table. Only users with\nthe SUPER privilege can access this information.\n \nExamples\n-------- \nSHOW WSREP_MEMBERSHIP;\n+-------+--------------------------------------+----------+-----------------+\n| Index | Uuid | Name | Address |\n+-------+--------------------------------------+----------+-----------------+\n| 0 | 19058073-8940-11e4-8570-16af7bf8fced | my_node1 |\n10.0.2.15:16001 |\n| 1 | 19f2b0e0-8942-11e4-9cb8-b39e8ee0b5dd | my_node3 |\n10.0.2.15:16003 |\n| 2 | d85e62db-8941-11e4-b1ef-4bc9980e476d | my_node2 |\n10.0.2.15:16002 |\n+-------+--------------------------------------+----------+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-wsrep_membership/','','https://mariadb.com/kb/en/show-wsrep_membership/'),(407,'SHOW WSREP_STATUS',26,'MariaDB 10.1.2\n \nSHOW WSREP_STATUS was introduced with the WSREP_INFO plugin\nin MariaDB 10.1.2.\n \nSyntax\n------ \nSHOW WSREP_STATUS\n \nDescription\n----------- \nThe SHOW WSREP_STATUS statement returns Galera node and\ncluster status information. It returns the same information\nas found in the information_schema.WSREP_STATUS table. Only\nusers with the SUPER privilege can access this information.\n \nExamples\n-------- \nSHOW WSREP_STATUS;\n+------------+-------------+----------------+--------------+\n| Node_Index | Node_Status | Cluster_Status | Cluster_Size |\n+------------+-------------+----------------+--------------+\n| 0 | Synced | Primary | 3 |\n+------------+-------------+----------------+--------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/show-wsrep_status/','','https://mariadb.com/kb/en/show-wsrep_status/'),(408,'CALL',27,'Syntax\n------ \nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n \nDescription\n----------- \nThe CALL statement invokes a stored procedure that was\ndefined previously with CREATE PROCEDURE. \n \nStored procedure names can be specified as\ndatabase_name.procedure_name. Procedure names and database\nnames can be quoted with backticks (). This is necessary if\nthey are reserved words, or contain special characters. See\nidentifier qualifiers for details.\n \nBefore MySQL 5.1.13, stored procedures that take no\narguments required parentheses. In current releases of\nMariaDB, CALL p() and CALL p are equivalent.\n \nIf parentheses are used, any number of spaces, tab\ncharacters and new line characters is allowed between the\nprocedure\'s name and the open parenthesis.\n \nCALL can pass back values to its caller using parameters\nthat are declared as OUT or INOUT\nparameters. If no value is assigned to an OUT parameter,\nNULL is assigned (and its former value is lost). To pass\nsuch values from another stored program you can use\nuser-defined variables, local variables or routine\'s\nparameters; in other contexts, you can only use user-defined\nvariables. \n \nCALL can also be executed as a prepared statement.\nPlaceholders can be used for IN parameters in all versions\nof MariaDB; for OUT and INOUT parameters, placeholders can\nbe used since MariaDB 5.5.\n \nWhen the procedure returns, a client program can also obtain\nthe\nnumber of rows affected for the final statement executed\nwithin the routine: At\nthe SQL level, call the ROW_COUNT() function; from the C\nAPI, call the mysql_affected_rows() function.\n \nIf the CLIENT_MULTI_RESULTS API flag is set, CALL can return\nany number of resultsets and the called stored procedure can\nexecute prepared statements. If it is not set, at most one\nresultset can be returned and prepared statements cannot be\nused within procedures.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/call/','','https://mariadb.com/kb/en/call/'),(409,'Concurrent Inserts',27,'The MyISAM storage engine supports concurrent inserts. This\nfeature allows SELECT statements to be executed during\nINSERT operations, reducing contention.\n \nWhether concurrent inserts can be used or not depends on the\nvalue of the concurrent_insert server system variable:\nNEVER (0) disables concurrent inserts.\nAUTO (1) allows concurrent inserts only when the target\ntable has no free blocks (no data in the middle of the table\nhas been deleted after the last OPTIMIZE TABLE). This is the\ndefault.\nALWAYS (2) always enables concurrent inserts.\n \nIf the binary log is used, CREATE TABLE ... SELECT and\nINSERT ... SELECT statements cannot use concurrent inserts.\nThese statements acquire a read lock on the table, so\nconcurrent inserts will need to wait. This way the log can\nbe safely used to restore data.\n \nConcurrent inserts is not used by slaves with the row based\nreplication (see binary log formats).\n \nIf an INSERT statement contain the HIGH_PRIORITY clause,\nconcurrent inserts cannot be used. INSERT ... DELAYED is\nusually unneeded if concurrent inserts are enabled.\n \nLOAD DATA INFILE uses concurrent inserts if the CONCURRENT\nkeyword is specified and concurrent_insert is not NEVER.\nThis makes the statement slower (even if no other sessions\naccess the table) but reduces contention.\n \nLOCK TABLES allows non-conflicting concurrent inserts if a\nREAD LOCAL lock is used. Concurrent inserts are not allowed\nif the LOCAL keyword is omitted.\n \nNotes\n \nThe decision to enable concurrent insert for a table is done\nwhen the table is opened. If you change the value of\nconcurrent_insert it will only affect new opened tables. If\nyou want it to work for also for tables in use or cached,\nyou should do FLUSH TABLES after setting the variable.\n \n\n\nURL: https://mariadb.com/kb/en/concurrent-inserts/','','https://mariadb.com/kb/en/concurrent-inserts/'),(413,'EXCEPT',27,'EXCEPT was introduced in MariaDB 10.3.0.\n \nThe result of EXCEPT is all records of the left SELECT\nresult set except records which are in right SELECT result\nset, i.e. it is subtraction of two result sets.\n \nSyntax\n------ \nSELECT ...\n(INTERSECT | EXCEPT | UNION [ALL | DISTINCT]) SELECT ...\n[(INTERSECT | EXCEPT | UNION [ALL | DISTINCT]) SELECT ...]\n[ORDER BY [column [, column ...]]]\n[LIMIT {[offset,] row_count | row_count OFFSET offset}]\n \nPlease note:\nALL is not supported by EXCEPT (and it is difficult to make\nsense of ALL with EXCEPT).\nBrackets for explicit operation precedence are not\nsupported; use a subquery in the FROM clause as a\nworkaround).\n \nDescription\n----------- \nMariaDB has supported EXCEPT and INTERSECT in addition to\nUNION since MariaDB 10.3.\n \nAll behavior for naming columns, ORDER BY and LIMIT is the\nsame as for UNION.\n \nEXCEPT implicitly supposes a DISTINCT operation.\n \nThe result of EXCEPT is all records of the left SELECT\nresult except records which are in right SELECT result set,\ni.e. it is subtraction of two result sets.\n \nEXCEPT and UNION have the same operation precedence.\n \n\nParentheses\n \nFrom MariaDB 10.4.0, parentheses can be used to specify\nprecedence. Before this, a syntax error would be returned.\n \nExamples\n-------- \nShow customers which are not employees:\n \n(SELECT e_name AS name, email FROM customers)\nEXCEPT\n(SELECT c_name AS name, email FROM employees);\n \nDifference between UNION, EXCEPT and INTERSECT:\n \nCREATE TABLE seqs (i INT);\nINSERT INTO seqs VALUES (1),(2),(3),(4),(5),(6);\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 5 |\n| 6 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 3 |\n+------+\n \nParentheses for specifying precedence, from MariaDB 10.4.0\n \nCREATE OR REPLACE TABLE t1 (a INT);\nCREATE OR REPLACE TABLE t2 (b INT);\nCREATE OR REPLACE TABLE t3 (c INT);\n \nINSERT INTO t1 VALUES (1),(2),(3),(4);\nINSERT INTO t2 VALUES (5),(6);\nINSERT INTO t3 VALUES (1),(6);\n \n((SELECT a FROM t1) UNION (SELECT b FROM t2)) EXCEPT (SELECT\nc FROM t3);\n+------+\n| a |\n+------+\n| 2 |\n| 3 |\n| 4 |\n| 5 |\n+------+\n \n(SELECT a FROM t1) UNION ((SELECT b FROM t2) EXCEPT (SELECT\nc FROM t3));\n+------+\n| a |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 5 |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/except/','','https://mariadb.com/kb/en/except/'),(410,'DELETE',27,'Syntax\n------ \nSingle-table syntax:\n \nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] \n FROM tbl_name [PARTITION (partition_list)]\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n [RETURNING select_expr \n [, select_expr ...]]\n \nMultiple-table syntax:\n \nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n \nOr:\n \nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n \nTrimming history:\n \nDELETE HISTORY\n FROM tbl_name [PARTITION (partition_list)]\n [BEFORE SYSTEM_TIME [TIMESTAMP|TRANSACTION] expression]\n \nDescription\n----------- \nOption | Description | \n \nLOW_PRIORITY | Wait until all SELECT\'s are done before\nstarting the statement. Used with storage engines that uses\ntable locking (MyISAM, Aria etc). See HIGH_PRIORITY and\nLOW_PRIORITY clauses for details. | \n \nQUICK | Signal the storage engine that it should expect that\na lot of rows are deleted. The storage engine engine can do\nthings to speed up the DELETE like ignoring merging of data\nblocks until all rows are deleted from the block (instead of\nwhen a block is half full). This speeds up things at the\nexpanse of lost space in data blocks. At least MyISAM and\nAria support this feature. | \n \nIGNORE | Don\'t stop the query even if a not-critical error\noccurs (like data overflow). See How IGNORE works for a full\ndescription. | \n \nFor the single-table syntax, the DELETE statement deletes\nrows\nfrom tbl_name and returns a count of the number of deleted\nrows. This count can\nbe obtained by calling the ROW_COUNT() function. The\nWHERE clause, if given, specifies the conditions that\nidentify\nwhich rows to delete. With no WHERE clause, all rows are\ndeleted. If the ORDER BY clause is specified, the rows are\ndeleted in the order that is specified. The LIMIT clause\nplaces a limit on the number of rows that can be deleted.\n \nFor the multiple-table syntax, DELETE deletes from each\ntbl_name the rows that satisfy the conditions. In this case,\nORDER BY and LIMIT> cannot be used. A DELETE can also\nreference tables which are located in different databases;\nsee Identifier Qualifiers for the syntax.\n \nwhere_condition is an expression that evaluates to true for\neach row to be deleted. It is specified as described in\nSELECT.\n \nCurrently, you cannot delete from a table and select from\nthe same\ntable in a subquery.\n \nYou need the DELETE privilege on a table to delete rows from\nit. You need only the SELECT privilege for any columns that\nare only read, such as those named in the WHERE clause. See\nGRANT.\n \nThe PARTITION clause was introduced in MariaDB 10.0. See\nPartition Pruning and Selection for details.\n \nAs stated, a DELETE statement with no WHERE\nclause deletes all rows. A faster way to do this, when you\ndo not need to know\nthe number of deleted rows, is to use TRUNCATE TABLE.\nHowever,\nwithin a transaction or if you have a lock on the table, \nTRUNCATE TABLE cannot be used whereas DELETE\ncan. See TRUNCATE TABLE, and\nLOCK.\n \nFrom MariaDB 10.0.5, it is possible to return a resultset of\nthe deleted rows for a single table to the client by using\nthe syntax DELETE ... RETURNING select_expr [, select_expr2\n...]]\n \nAny of SQL expression that can be calculated from a single\nrow fields is allowed. Subqueries are allowed. The AS\nkeyword is allowed, so it is possible to use aliases.\n \nThe use of aggregate functions is not allowed. RETURNING\ncannot be used in multi-table DELETEs.\n \nSame Source and Target Table\n \nUntil MariaDB 10.3.1, deleting from a table with the same\nsource and target was not possible. From MariaDB 10.3.1,\nthis is now possible. For example:\n \nDELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE\nb.c2=0);\n \nOne can use DELETE HISTORY to delete historical information\nfrom System-versioned tables.\n \nExamples\n-------- \nHow to use the ORDER BY and LIMIT clauses:\n \nDELETE FROM page_hit ORDER BY timestamp LIMIT 1000000;\n \nHow to use the RETURNING clause:\n \nDELETE FROM t RETURNING f1;\n \n+------+\n| f1 |\n+------+\n| 5 |\n| 50 |\n| 500 |\n+------+ \n \nThe following statement joins two tables: one is only used\nto satisfy a WHERE condition, but no row is deleted from it;\nrows from the other table are deleted, instead.\n \nDELETE post FROM blog INNER JOIN post WHERE blog.id =\npost.blog_id;\n \nDeleting from the Same Source and Target\n \nCREATE TABLE t1 (c1 INT, c2 INT);\nDELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE\nb.c2=0);\n \nUntil MariaDB 10.3.1, this returned:\n \nERROR 1093 (HY000): Table \'t1\' is specified twice, both as\na target for \'DELETE\' \n and as a separate source for\n \nFrom MariaDB 10.3.1:\n \nQuery OK, 0 rows affected (0.00 sec)\n \n\n\nURL: https://mariadb.com/kb/en/delete/','','https://mariadb.com/kb/en/delete/'),(417,'HIGH_PRIORITY and LOW_PRIORITY',27,'The XtraDB/InnoDB storage engine uses row-level locking to\nensure data integrity. However some storage engines (such as\nMEMORY, MyISAM, Aria and MERGE) lock the whole table to\nprevent conflicts. These storage engines use two separate\nqueues to remember pending statements; one is for SELECTs\nand the other one is for write statements (INSERT, DELETE,\nUPDATE). By default, the latter has a higher priority.\n \nTo give write operations a lower priority, the\nlow_priority_updates server system variable can be set to\nON. The option is available on both the global and session\nlevels, and it can be set at startup or via the SET\nstatement.\n \nWhen too many table locks have been set by write statements,\nsome pending SELECTs are executed. The maximum number of\nwrite locks that can be acquired before this happens is\ndetermined by the max_write_lock_count server system\nvariable, which is dynamic.\n \nIf write statements have a higher priority (default), the\npriority of individual write statements (INSERT, REPLACE,\nUPDATE, DELETE) can be changed via the LOW_PRIORITY\nattribute, and the priority of a SELECT statement can be\nraised via the HIGH_PRIORITY attribute. Also, LOCK TABLES\nsupports a LOW_PRIORITY attribute for WRITE locks.\n \nIf read statements have a higher priority, the priority of\nan INSERT can be changed via the HIGH_PRIORITY attribute.\nHowever, the priority of other write statements cannot be\nraised individually.\n \nThe use of LOW_PRIORITY or HIGH_PRIORITY for an INSERT\nprevents Concurrent Inserts from being used.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/high_priority-and-low_priority/','','https://mariadb.com/kb/en/high_priority-and-low_priority/'),(415,'GROUP BY',27,'Use the GROUP BY clause in a SELECT statement to group rows\ntogether that have the same value in one or more column, or\nthe same computed value using expressions with any\nfunctions and operators except\ngrouping functions. When you\nuse a GROUP BY clause, you will get a single result row for\neach group of rows\nthat have the same value for the expression given in GROUP\nBY.\n \nWhen grouping rows, grouping values are compared as if by\nthe = operator.\nFor string values, the = operator ignores trailing\nwhitespace and may normalize\ncharacters and ignore case, depending on the collation in\nuse.\n \nYou can use any of the grouping functions in your select\nexpression. Their values will\nbe calculated based on all the rows that have been grouped\ntogether for each result\nrow. If you select a non-grouped column or a value computed\nfrom a non-grouped\ncolumn, it is undefined which row the returned value is\ntaken from. This is not permitted if the ONLY_FULL_GROUP_BY\nSQL_MODE is used.\n \nYou can use multiple expressions in the GROUP BY clause,\nseparated by commas.\nRows are grouped together if they match on each of the\nexpressions.\n \nYou can also use a single integer as the grouping\nexpression. If you use an integer n,\nthe results will be grouped by the nth column in the select\nexpression.\n \nThe WHERE clause is applied before the GROUP BY clause. It\nfilters non-aggregated\nrows before the rows are grouped together. To filter grouped\nrows based on aggregate values,\nuse the HAVING clause. The HAVING clause takes any\nexpression and evaluates it as\na boolean, just like the WHERE clause. You can use grouping\nfunctions in the HAVING\nclause. As with the select expression, if you reference\nnon-grouped columns in the HAVING\nclause, the behavior is undefined.\n \nBy default, if a GROUP BY clause is present, the rows in the\noutput will be sorted by the expressions used in the GROUP\nBY. You can also specify ASC or DESC (ascending, descending)\nafter those expressions, like in ORDER BY. The default is\nASC.\n \nIf you want the rows to be sorted by another field, you can\nadd an explicit ORDER BY. If you don\'t want the result to\nbe ordered, you can add ORDER BY NULL.\n \nWITH ROLLUP\n \nThe WITH ROLLUP modifer adds extra rows to the resultset\nthat represent super-aggregate summaries. For a full\ndescription with examples, see SELECT WITH ROLLUP.\n \nGROUP BY Examples\n \nConsider the following table that records how many times\neach user has played and won a game:\n \nCREATE TABLE plays (name VARCHAR(16), plays INT, wins INT);\nINSERT INTO plays VALUES \n (\"John\", 20, 5), \n (\"Robert\", 22, 8), \n (\"Wanda\", 32, 8), \n (\"Susan\", 17, 3);\n \nGet a list of win counts along with a count:\n \nSELECT wins, COUNT(*) FROM plays GROUP BY wins;\n \n+------+----------+\n| wins | COUNT(*) |\n+------+----------+\n| 3 | 1 |\n| 5 | 1 |\n| 8 | 2 |\n+------+----------+\n3 rows in set (0.00 sec)\n \nThe GROUP BY expression can be a computed value, and can\nrefer back to an identifer\nspecified with AS. Get a list of win averages along with a\ncount:\n \nSELECT (wins / plays) AS winavg, COUNT(*) FROM plays GROUP\nBY winavg;\n \n+--------+----------+\n| winavg | COUNT(*) |\n+--------+----------+\n| 0.1765 | 1 |\n| 0.2500 | 2 |\n| 0.3636 | 1 |\n+--------+----------+\n3 rows in set (0.00 sec)\n \nYou can use any grouping function\nin the select expression. For each win average as above, get\na list of the average play\ncount taken to get that average:\n \nSELECT (wins / plays) AS winavg, AVG(plays) FROM plays \n GROUP BY winavg;\n \n+--------+------------+\n| winavg | AVG(plays) |\n+--------+------------+\n| 0.1765 | 17.0000 |\n| 0.2500 | 26.0000 |\n| 0.3636 | 22.0000 |\n+--------+------------+\n3 rows in set (0.00 sec)\n \nYou can filter on aggregate information using the HAVING\nclause. The HAVING\nclause is applied after GROUP BY and allows you to filter on\naggregate data that is\nnot available to the WHERE clause. Restrict the above\nexample to results that involve\nan average number of plays over 20:\n \nSELECT (wins / plays) AS winavg, AVG(plays) FROM plays \n GROUP BY winavg HAVING AVG(plays) > 20;\n \n+--------+------------+\n| winavg | AVG(plays) |\n+--------+------------+\n| 0.2500 | 26.0000 |\n| 0.3636 | 22.0000 |\n+--------+------------+\n2 rows in set (0.00 sec)\n \nSee Also\n \nSELECT\nJoins and Subqueries\nLIMIT\nORDER BY\nCommon Table Expressions\nSELECT WITH ROLLUP\nSELECT INTO OUTFILE\nSELECT INTO DUMPFILE\nFOR UPDATE\nLOCK IN SHARE MODE\nOptimizer Hints\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/group-by/','','https://mariadb.com/kb/en/group-by/'),(418,'IGNORE',27,'The IGNORE option tells the server to ignore some common\nerrors.\n \nIGNORE can be used with the following statements:\nDELETE\nINSERT (see also INSERT IGNORE)\nLOAD DATA INFILE\nUPDATE\nALTER TABLE\nCREATE TABLE ... SELECT\nINSERT ... SELECT\n \nThe logic used:\nVariables out of ranges are replaced with the\nmaximum/minimum value.\n \nSQL_MODEs STRICT_TRANS_TABLES, STRICT_ALL_TABLES,\nNO_ZERO_IN_DATE, NO_ZERO_DATE are ignored.\n \nInserting NULL in a NOT NULL field will insert 0 ( in a\nnumerical\n field), 0000-00-00 ( in a date field) or an empty string (\nin a character\n field).\n \nRows that cause a duplicate key error or break a foreign key\nconstraint are\n not inserted, updated, or deleted.\n \nThe following errors are ignored:\n \nError number | Symbolic error name | Description | \n \n1022 | ER_DUP_KEY | Can\'t write; duplicate key in table\n\'%s\' | \n \n1048 | ER_BAD_NULL_ERROR | Column \'%s\' cannot be null | \n \n1062 | ER_DUP_ENTRY | Duplicate entry \'%s\' for key %d | \n \n1242 | ER_SUBQUERY_NO_1_ROW | Subquery returns more than 1\nrow | \n \n1264 | ER_WARN_DATA_OUT_OF_RANGE | Out of range value for\ncolumn \'%s\' at row %ld | \n \n1265 | WARN_DATA_TRUNCATED | Data truncated for column\n\'%s\' at row %ld | \n \n1292 | ER_TRUNCATED_WRONG_VALUE | Truncated incorrect %s\nvalue: \'%s\' | \n \n1366 | ER_TRUNCATED_WRONG_VALUE_FOR_FIELD | Incorrect\ninteger value | \n \n1369 | ER_VIEW_CHECK_FAILED | CHECK OPTION failed \'%s.%s\'\n| \n \n1451 | ER_ROW_IS_REFERENCED_2 | Cannot delete or update a\nparent row | \n \n1452 | ER_NO_REFERENCED_ROW_2 | Cannot add or update a child\nrow: a foreign key constraint fails (%s) | \n \n1526 | ER_NO_PARTITION_FOR_GIVEN_VALUE | Table has no\npartition for value %s | \n \n1586 | ER_DUP_ENTRY_WITH_KEY_NAME | Duplicate entry \'%s\'\nfor key \'%s\' | \n \n1591 | ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT | Table has no\npartition for some existing values | \n \n1748 | ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET | Found a\nrow not matching the given partition set | \n \nIgnored errors normally generate a warning.\n \nA property of the IGNORE clause consists in causing\ntransactional engines and non-transactional engines (like\nXtraDB and Aria) to behave the same way. For example,\nnormally a multi-row insert which tries to violate a UNIQUE\ncontraint is completely rolled back on XtraDB/InnoDB, but\nmight be partially executed on Aria. With the IGNORE clause,\nthe statement will be partially executed in both engines.\n \nStarting from MariaDB 5.5.28 duplicate key errors also\ngenerate warnings. The OLD_MODE server variable can be used\nto prevent this.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ignore/','','https://mariadb.com/kb/en/ignore/'),(419,'INSERT',27,'Syntax\n------ \nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nOr:\n \nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)]\n SET col={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nOr:\n \nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nThe INSERT statement is used to insert new rows into an\nexisting table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based\non explicitly specified values. The INSERT ... SELECT form\ninserts rows selected from another table or tables. INSERT\n... SELECT is discussed further in the INSERT ... SELECT\narticle.\n \nThe table name can be specified in the form db_name.tbl_name\nor, if a default database is selected, in the form tbl_name\n(see Identifier Qualifiers). This allows to use INSERT ...\nSELECT to copy rows between different databases.\n \nThe PARTITION clause was introduced in MariaDB 10.0. It can\nbe used in both the INSERT and the SELECT part. See\nPartition Pruning and Selection for details.\n \nThe columns list is optional. It specifies which values are\nexplicitly inserted, and in which order. If this clause is\nnot specified, all values must be explicitly specified, in\nthe same order they are listed in the table definition.\n \nThe list of value follow the VALUES or VALUE keyword (which\nare interchangeable, regardless how much values you want to\ninsert), and is wrapped by parenthesis. The values must be\nlisted in the same order as the columns list. It is possible\nto specify more than one list to insert more than one rows\nwith a single statement. If many rows are inserted, this is\na speed optimization.\n \nFor one-row statements, the SET clause may be more simple,\nbecause you don\'t need to remember the columns order. All\nvalues are specified in the form col = expr.\n \nValues can also be specified in the form of a SQL expression\nor subquery. However, the subquery cannot access the same\ntable that is named in the INTO clause.\n \nIf you use the LOW_PRIORITY keyword, execution of the INSERT\nis delayed until no other clients are reading from the\ntable. If you use the HIGH_PRIORITY keyword, the statement\nhas the same priority as SELECTs. This affects only storage\nengines that use only table-level locking (MyISAM, MEMORY,\nMERGE). However, if one of these keywords is specified,\nconcurrent inserts cannot be used. See HIGH_PRIORITY and\nLOW_PRIORITY clauses for details.\n \nINSERT DELAYED\n \nFor more details on the DELAYED option, see INSERT DELAYED.\n \nHIGH PRIORITY and LOW PRIORITY\n \nSee HIGH_PRIORITY and LOW_PRIORITY.\n \nDefaults and Duplicate Values\n \nSee INSERT - Default & Duplicate Values for details..\n \nINSERT IGNORE\n \nSee INSERT IGNORE.\n \nINSERT ON DUPLICATE KEY UPDATE\n \nSee INSERT ON DUPLICATE KEY UPDATE.\n \nExamples\n-------- \nSpecifying the column names:\n \nINSERT INTO person (first_name, last_name) VALUES (\'John\',\n\'Doe\');\n \nInserting more than 1 row at a time:\n \nINSERT INTO tbl_name VALUES (1, \"row 1\"), (2, \"row 2\");\n \nUsing the SET clause:\n \nINSERT INTO person SET first_name = \'John\', last_name =\n\'Doe\';\n \nSELECTing from another table:\n \nINSERT INTO contractor SELECT * FROM person WHERE status =\n\'c\';\n \nSee INSERT ON DUPLICATE KEY UPDATE and INSERT IGNORE for\nfurther examples.\n \n\n\nURL: https://mariadb.com/kb/en/insert/','','https://mariadb.com/kb/en/insert/'),(420,'INSERT - Default & Duplicate Values',27,'Default Values\n \nIf the SQL_MODE contains STRICT_TRANS_TABLES and you are\ninserting into a transactional table (like InnoDB), or if\nthe SQL_MODE contains STRICT_ALL_TABLES, all NOT NULL\ncolumns which does not have a DEFAULT value (and is not\nAUTO_INCREMENT) must be explicitly referenced in INSERT\nstatements. If not, an error like this is produced:\n \nERROR 1364 (HY000): Field \'col\' doesn\'t have a default\nvalue\n \nIn all other cases, if a NOT NULL column without a DEFAULT\nvalue is not referenced, an empty value will be inserted\n(for example, 0 for INTEGER columns and \'\' for CHAR\ncolumns). See NULL Values in MariaDB:Inserting for examples.\n \nIf a NOT NULL column having a DEFAULT value is not\nreferenced, NULL will be inserted.\n \nIf a NULL column having a DEFAULT value is not referenced,\nits default value will be inserted. It is also possible to\nexplicitly assign the default value using the DEFAULT\nkeyword or the DEFAULT() function.\n \nIf the DEFAULT keyword is used but the column does not have\na DEFAULT value, an error like this is produced:\n \nERROR 1364 (HY000): Field \'col\' doesn\'t have a default\nvalue\n \nDuplicate Values\n \nBy default, if you try to insert a duplicate row and there\nis a UNIQUE index, INSERT stops and an error like this is\nproduced:\n \nERROR 1062 (23000): Duplicate entry \'dup_value\' for key\n\'col\'\n \nTo handle duplicates you can use the IGNORE clause, INSERT\nON DUPLICATE KEY UPDATE or the REPLACE statement. Note that\nthe IGNORE and DELAYED options are ignored when you use ON\nDUPLICATE KEY UPDATE.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/insert-default-duplicate-values/','','https://mariadb.com/kb/en/insert-default-duplicate-values/'),(421,'INSERT DELAYED',27,'Syntax\n------ \nINSERT DELAYED ...\n \nDescription\n----------- \nThe DELAYED option for the INSERT\nstatement is a MariaDB/MySQL extension to standard SQL that\nis very useful if you have\nclients that cannot or need not wait for the INSERT to\ncomplete. This is a common situation when you use MariaDB\nfor logging and you\nalso periodically run SELECT and UPDATE\nstatements that take a long time to complete.\n \nWhen a client uses INSERT DELAYED, it gets an okay from the\nserver at once, and the row is queued to be inserted when\nthe table is not in\nuse by any other thread.\n \nAnother major benefit of using INSERT DELAYED is that\ninserts from many clients are bundled together and written\nin one block. This\nis much faster than performing many separate inserts.\n \nNote that INSERT DELAYED is slower than a normal\n INSERT if the table is not otherwise in use. There is also\nthe additional overhead for the server to handle a separate\nthread for each\ntable for which there are delayed rows. This means that you\nshould use\nINSERT DELAYED only when you are really sure that you need\nit.\n \nThe queued rows are held only in memory until they are\ninserted into the table.\nThis means that if you terminate mysqld forcibly (for\nexample, with kill -9) or\nif mysqld dies unexpectedly, any queued rows that have not\nbeen written to disk\nare lost.\n \nThe number of concurrent INSERT DELAYED threads is limited\nby the max_delayed_threads server system variables. If it is\nset to 0, INSERT DELAYED is disabled. The session value can\nbe equal to the global value, or 0 to disable this statement\nfor the current session. If this limit has been reached, the\nDELAYED clause will be silently ignore for subsequent\nstatements (no error will be produced).\n \nThere are some constraints on the use of DELAYED:\nINSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE,\n and BLACKHOLE tables. If you execute INSERT DELAYED with\nanother storage engine, you will get an error like this:\nERROR 1616 (HY000): DELAYED option not supported for table\n\'tab_name\'\nFor MyISAM tables, if there are no free blocks in the middle\nof the data\n file, concurrent SELECT and INSERT statements are\nsupported. Under these\n circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\nINSERT DELAYED should be used only for\n INSERT statements that specify value lists. The server\n ignores DELAYED for INSERT ... SELECT\n or INSERT ... ON DUPLICATE KEY UPDATE statements.\nBecause the INSERT DELAYED statement returns immediately,\n before the rows are inserted, you cannot use\n LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\nDELAYED rows are not visible to SELECT\n statements until they actually have been inserted.\nAfter INSERT DELAYED, ROW_COUNT() returns the number of the\nrows you tried to insert, not the number of the successful\nwrites.\nDELAYED is ignored on slave replication servers, so that \n INSERT DELAYED is treated as a normal\n INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than\n the master. INSERT DELAYED statements are not safe for\nreplication.\nPending INSERT DELAYED statements are lost if a table is\n write locked and ALTER TABLE is used to modify the table\nstructure.\nINSERT DELAYED is not supported for views. If you try, you\nwill get an error like this: ERROR 1347 (HY000):\n\'view_name\' is not BASE TABLE\nINSERT DELAYED is not supported for partitioned tables.\nINSERT DELAYED is not supported within stored programs.\n \n\n\nURL: https://mariadb.com/kb/en/insert-delayed/','','https://mariadb.com/kb/en/insert-delayed/'),(422,'INSERT IGNORE',27,'Ignoring Errors\n \nNormally INSERT stops and rolls back when it encounters an\nerror.\n \nBy using the IGNORE keyword all errors are converted to\nwarnings, which will not stop inserts of additional rows.\n \nThe IGNORE and DELAYED options are ignored when you use ON\nDUPLICATE KEY UPDATE.\n \nIncompatibilities\n \nMariaDB until 5.5.28\nMySQL and MariaDB before 5.5.28 didn\'t give warnings for\nduplicate key errors when using IGNORE.\nYou can get the old behaviour if you set OLD_MODE to\nNO_DUP_KEY_WARNINGS_WITH_IGNORE\n \nExamples\n-------- \nCREATE TABLE t1 (x INT UNIQUE);\n \nINSERT INTO t1 VALUES(1),(2);\n \nINSERT INTO t1 VALUES(2),(3);\nERROR 1062 (23000): Duplicate entry \'2\' for key \'x\'\nSELECT * FROM t1;\n \n+------+\n| x |\n+------+\n| 1 |\n| 2 |\n+------+\n2 rows in set (0.00 sec)\n \nINSERT IGNORE INTO t1 VALUES(2),(3);\nQuery OK, 1 row affected, 1 warning (0.04 sec)\n \nSHOW WARNINGS;\n \n+---------+------+---------------------------------+\n| Level | Code | Message |\n+---------+------+---------------------------------+\n| Warning | 1062 | Duplicate entry \'2\' for key \'x\' |\n+---------+------+---------------------------------+\n \nSELECT * FROM t1;\n \n+------+\n| x |\n+------+\n| 1 |\n| 2 |\n| 3 |\n+------+\n \nSee INSERT ON DUPLICATE KEY UPDATE for further examples\nusing that syntax.\n \n\n\nURL: https://mariadb.com/kb/en/insert-ignore/','','https://mariadb.com/kb/en/insert-ignore/'),(423,'INSERT ON DUPLICATE KEY UPDATE',27,'Syntax\n------ \nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nOr:\n \nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)]\n SET col={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nOr:\n \nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col=expr\n [, col=expr] ... ]\n \nDescription\n----------- \nINSERT ... ON DUPLICATE KEY UPDATE is a MariaDB/MySQL\nextension to the INSERT statement that, if it finds a\nduplicate unique or primary key, will instead perform an\nUPDATE.\n \nThe row/s affected value is reported as 1 if a row is\ninserted, and 2 if a row is updated, unless the API\'s\nCLIENT_FOUND_ROWS flag is set.\n \nIf more than one unique index is matched, only the first is\nupdated. It is not recommended to use this statement on\ntables with more than one unique index.\n \nIf the table has an AUTO_INCREMENT primary key and the\nstatement inserts or updates a row, the LAST_INSERT_ID()\nfunction returns its AUTO_INCREMENT value.\n \nThe VALUES() function can only be used in a ON DUPLICATE KEY\nUPDATE clause and has no meaning in any other context. It\nreturns the column values from the INSERT portion of the\nstatement. This function is particularly useful for\nmulti-rows inserts.\n \nThe IGNORE and DELAYED options are ignored when you use ON\nDUPLICATE KEY UPDATE.\n \nThe PARTITION clause was introduced in MariaDB 10.0. See\nPartition Pruning and Selection for details.\n \nThis statement activates INSERT and UPDATE triggers. See\nTrigger Overview for details.\n \nSee also a similar statement, REPLACE.\n \nExamples\n-------- \nCREATE TABLE ins_duplicate (id INT PRIMARY KEY, animal\nVARCHAR(30));\nINSERT INTO ins_duplicate VALUES (1,\'Aardvark\'),\n(2,\'Cheetah\'), (3,\'Zebra\');\n \nIf there is no existing key, the statement runs as a regular\nINSERT:\n \nINSERT INTO ins_duplicate VALUES (4,\'Gorilla\') ON\nDUPLICATE KEY UPDATE animal=\'Gorilla\';\nQuery OK, 1 row affected (0.07 sec)\n \nSELECT * FROM ins_duplicate;\n+----+----------+\n| id | animal |\n+----+----------+\n| 1 | Aardvark |\n| 2 | Cheetah |\n| 3 | Zebra |\n| 4 | Gorilla |\n+----+----------+\n \nA regular INSERT with a primary key value of 1 will fail,\ndue to the existing key:\n \nINSERT INTO ins_duplicate VALUES (1,\'Antelope\');\nERROR 1062 (23000): Duplicate entry \'1\' for key\n\'PRIMARY\'\n \nHowever, we can use an INSERT ON DUPLICATE KEY UPDATE\ninstead:\n \nINSERT INTO ins_duplicate VALUES (1,\'Antelope\') ON\nDUPLICATE KEY UPDATE animal=\'Antelope\';\nQuery OK, 2 rows affected (0.09 sec)\n \nNote that there are two rows reported as affected, but this\nrefers only to the UPDATE.\n \nSELECT * FROM ins_duplicate;\n+----+----------+\n| id | animal |\n+----+----------+\n| 1 | Antelope |\n| 2 | Cheetah |\n| 3 | Zebra |\n| 4 | Gorilla |\n+----+----------+\n \nAdding a second unique column:\n \nALTER TABLE ins_duplicate ADD id2 INT;\nUPDATE ins_duplicate SET id2=id+10;\nALTER TABLE ins_duplicate ADD UNIQUE KEY(id2);\n \nWhere two rows match the unique keys match, only the first\nis updated. This can be unsafe and is not recommended unless\nyou are certain what you are doing. Note that the warning\nshown below appears in MariaDB 5.5 and before, but has been\nremoved in MariaDB 10.0, as MariaDB now assumes that the\nkeys are checked in order, as shown in SHOW CREATE TABLE.\n \nINSERT INTO ins_duplicate VALUES (2,\'Lion\',13) ON\nDUPLICATE KEY UPDATE animal=\'Lion\';\nQuery OK, 2 rows affected, 1 warning (0.06 sec)\n \nSHOW WARNINGS;\n+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Level | Code | Message |\n+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Note | 1592 | Unsafe statement written to the binary log\nusing statement format since BINLOG_FORMAT = STATEMENT.\nINSERT... ON DUPLICATE KEY UPDATE on a table with more than\none UNIQUE KEY is unsafe |\n+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n \nSELECT * FROM ins_duplicate;\n+----+----------+------+\n| id | animal | id2 |\n+----+----------+------+\n| 1 | Antelope | 11 |\n| 2 | Lion | 12 |\n| 3 | Zebra | 13 |\n| 4 | Gorilla | 14 |\n+----+----------+------+\n \nAlthough the third row with an id of 3 has an id2 of 13,\nwhich also matched, it was not updated.\n \nChanging id to an auto_increment field. If a new row is\nadded, the auto_increment is moved forward. If the row is\nupdated, it remains the same.\n \nALTER TABLE `ins_duplicate` CHANGE `id` `id` INT( 11 ) NOT\nNULL AUTO_INCREMENT;\nALTER TABLE ins_duplicate DROP id2;\nSELECT Auto_increment FROM INFORMATION_SCHEMA.TABLES WHERE\nTABLE_NAME=\'ins_duplicate\';\n+----------------+\n| Auto_increment |\n+----------------+\n| 5 |\n+----------------+\n \nINSERT INTO ins_duplicate VALUES (2,\'Leopard\') ON\nDUPLICATE KEY UPDATE animal=\'Leopard\';\nQuery OK, 2 rows affected (0.00 sec)\n \nSELECT Auto_increment FROM INFORMATION_SCHEMA.TABLES WHERE\nTABLE_NAME=\'ins_duplicate\';\n+----------------+\n| Auto_increment |\n+----------------+\n| 5 |\n+----------------+\n \nINSERT INTO ins_duplicate VALUES (5,\'Wild Dog\') ON\nDUPLICATE KEY UPDATE animal=\'Wild Dog\';\nQuery OK, 1 row affected (0.09 sec)\n \nSELECT * FROM ins_duplicate;\n+----+----------+\n| id | animal |\n+----+----------+\n| 1 | Antelope |\n| 2 | Leopard |\n| 3 | Zebra |\n| 4 | Gorilla |\n| 5 | Wild Dog |\n+----+----------+\n \nSELECT Auto_increment FROM INFORMATION_SCHEMA.TABLES WHERE\nTABLE_NAME=\'ins_duplicate\';\n+----------------+\n| Auto_increment |\n+----------------+\n| 6 |\n+----------------+\n \nRefering to column values from the INSERT portion of the\nstatement: \n \nINSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n \nSee the VALUES() function for more.\n \n\n\nURL:\nhttps://mariadb.com/kb/en/insert-on-duplicate-key-update/','','https://mariadb.com/kb/en/insert-on-duplicate-key-update/'),(424,'INSERT SELECT',27,'Syntax\n------ \nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n \nDescription\n----------- \nWith INSERT ... SELECT, you can quickly insert many rows\ninto a table from one or more other tables. For example:\n \nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n \ntbl_name can also be specified in the form db_name.tbl_name\n(see Identifier Qualifiers). This allows to copy rows\nbetween different databases.\n \nIf the new table has a primary key or UNIQUE indexes, you\ncan use IGNORE to handle duplicate key errors during the\nquery. The newer values will not be inserted if an identical\nvalue already exists.\n \nREPLACE can be used instead of INSERT to prevent duplicates\non UNIQUE indexes by deleting old values. In that case, ON\nDUPLICATE KEY UPDATE cannot be used.\n \nINSERT ... SELECT works for tables which already exist. To\ncreate a table for a given resultset, you can use CREATE\nTABLE ... SELECT.\n \n\n\nURL: https://mariadb.com/kb/en/insert-select/','','https://mariadb.com/kb/en/insert-select/'),(425,'INTERSECT',27,'INTERSECT was introduced in MariaDB 10.3.0.\n \nThe result of an intersect is the intersection of right and\nleft SELECT results, i.e. only records that are present in\nboth result sets will be included in the result of the\noperation.\n \nSyntax\n------ \nSELECT ...\n(INTERSECT | EXCEPT | UNION [ALL | DISTINCT]) SELECT ...\n[(INTERSECT | EXCEPT | UNION [ALL | DISTINCT]) SELECT ...]\n[ORDER BY [column [, column ...]]]\n[LIMIT {[offset,] row_count | row_count OFFSET offset}]\n \nPlease note:\nALL is not supported by INTERSECT (and it is difficult to\nmake sense of ALL with INTERSECT).\nBrackets for explicit operation precedence are not\nsupported; use a subquery in the FROM clause as a\nworkaround).\n \nDescription\n----------- \nMariaDB has supported INTERSECT (as well as EXCEPT) in\naddition to UNION since MariaDB 10.3.\n \nAll behavior for naming columns, ORDER BY and LIMIT is the\nsame as for UNION.\n \nINTERSECT implicitly supposes a DISTINCT operation.\n \nThe result of an intersect is the intersection of right and\nleft SELECT results, i.e. only records that are present in\nboth result sets will be included in the result of the\noperation.\n \nINTERSECT has higher precedence than UNION and EXCEPT. If\npossible it will be executed linearly but if not it will be\ntranslated to a subquery in the FROM clause:\n \n(select a,b from t1)\nunion\n(select c,d from t2)\nintersect\n(select e,f from t3)\nunion\n(select 4,4);\n \nwill be translated to:\n \n(select a,b from t1)\nunion\nselect c,d from\n ((select c,d from t2)\n intersect\n (select e,f from t3)) dummy_subselect\nunion\n(select 4,4)\n \n\n \nParentheses\n \nFrom MariaDB 10.4.0, parentheses can be used to specify\nprecedence. Before this, a syntax error would be returned.\n \nExamples\n-------- \nShow customers which are employees:\n \n(SELECT e_name AS name, email FROM employees)\nINTERSECT\n(SELECT c_name AS name, email FROM customers);\n \nDifference between UNION, EXCEPT and INTERSECT:\n \nCREATE TABLE seqs (i INT);\nINSERT INTO seqs VALUES (1),(2),(3),(4),(5),(6);\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 5 |\n| 6 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 3 |\n+------+\n \nParentheses for specifying precedence, from MariaDB 10.4.0\n \nCREATE OR REPLACE TABLE t1 (a INT);\nCREATE OR REPLACE TABLE t2 (b INT);\nCREATE OR REPLACE TABLE t3 (c INT);\n \nINSERT INTO t1 VALUES (1),(2),(3),(4);\nINSERT INTO t2 VALUES (5),(6);\nINSERT INTO t3 VALUES (1),(6);\n \n((SELECT a FROM t1) UNION (SELECT b FROM t2)) INTERSECT\n(SELECT c FROM t3);\n+------+\n| a |\n+------+\n| 1 |\n| 6 |\n+------+\n \n(SELECT a FROM t1) UNION ((SELECT b FROM t2) INTERSECT\n(SELECT c FROM t3));\n+------+\n| a |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 6 |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/intersect/','','https://mariadb.com/kb/en/intersect/'),(426,'JOIN Syntax',27,'Description\n----------- \nMariaDB supports the following JOIN syntaxes for\nthe table_references part of SELECT statements and\nmultiple-table DELETE and UPDATE statements:\n \ntable_references:\n table_reference [, table_reference] ...\n \ntable_reference:\n table_factor\n | join_table\n \ntable_factor:\n tbl_name [PARTITION (partition_list)]\n [query_system_time_period_specification] [[AS] alias]\n[index_hint_list]\n | table_subquery [query_system_time_period_specification]\n[AS] alias\n | ( table_references )\n | { ON table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n \njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor\n[join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON\nconditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference\njoin_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN\ntable_factor\n \njoin_condition:\n ON conditional_expr\n | USING (column_list)\n \nquery_system_time_period_specification:\n FOR SYSTEM_TIME AS OF point_in_time\n | FOR SYSTEM_TIME BETWEEN point_in_time AND point_in_time\n | FOR SYSTEM_TIME FROM point_in_time TO point_in_time\n | FOR SYSTEM_TIME ALL\n \npoint_in_time:\n [TIMESTAMP] expression\n | TRANSACTION expression\n \nindex_hint_list:\n index_hint [, index_hint] ...\n \nindex_hint:\n USE {INDEX|KEY}\n [{FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n \nindex_list:\n index_name [, index_name] ...\n \nA table reference is also known as a join expression.\n \nEach table can also be specified as db_name.tabl_name. This\nallows to write queries which involve multiple databases.\nSee Identifier Qualifiers for syntax details.\n \nThe syntax of table_factor is extended in comparison with\nthe\nSQL Standard. The latter accepts only table_reference, not a\nlist of them inside a pair of parentheses.\n \nThis is a conservative extension if we consider each comma\nin a list of\ntable_reference items as equivalent to an inner join. For\nexample:\n \nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n \nis equivalent to:\n \nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n \nIn MariaDB, CROSS JOIN is a syntactic equivalent to\nINNER JOIN (they can replace each other). In standard SQL,\nthey are not equivalent. INNER JOIN is used with an\nON clause, CROSS JOIN is used otherwise.\n \nIn general, parentheses can be ignored in join expressions\ncontaining only\ninner join operations. MariaDB also supports nested joins\n(see\nhttp://dev.mysql.com/doc/refman/5.1/en/nested-join-optimization.html).\n \nSee System-versioned tables for more information\nabout FOR SYSTEM_TIME syntax.\n \nIndex hints can be specified to affect how the MariaDB\noptimizer makes\nuse of indexes. For more information, see How to force query\nplans.\n \nExamples\n-------- \nSELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id =\nright_tbl.id\n WHERE right_tbl.id IS NULL;\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/join-syntax/','','https://mariadb.com/kb/en/join-syntax/'),(427,'LIMIT',27,'Description\n----------- \nUse the LIMIT clause to restrict the number of returned\nrows. When you use a single\ninteger n with LIMIT, the first n rows will be returned. Use\nthe ORDER BY\nclause to control which rows come first. You can also select\na number of rows after an offset\nusing either of the following:\n \nLIMIT offset, row_count\nLIMIT row_count OFFSET offset\n \nWhen you provide an offset m with a limit n, the first m\nrows will be ignored, and the\nfollowing n rows will be returned.\n \nExecuting an UPDATE with the LIMIT clause is not safe for\nreplication.\n \nSince MariaDB 10.0.11, LIMIT 0 has been an exception to this\nrule (see MDEV-6170).\n \nBeginning in MariaDB 5.5.21, there is a LIMIT ROWS EXAMINED\noptimization which provides the\nmeans to terminate the execution of SELECT statements which\nexamine too\nmany rows, and thus use too many resources. See LIMIT ROWS\nEXAMINED.\n \nMulti-Table Updates\n \nUntil MariaDB 10.3.1, it was not possible to use LIMIT (or\nORDER BY) in a multi-table UPDATE statement. This\nrestriction was lifted in MariaDB 10.3.2.\n \nGROUP_CONCAT\n \nStarting from MariaDB 10.3.3, it is possible to use LIMIT\nwith GROUP_CONCAT().\n \nExamples\n-------- \nCREATE TABLE members (name VARCHAR(20));\nINSERT INTO members\nVALUES(\'Jagdish\'),(\'Kenny\'),(\'Rokurou\'),(\'Immaculada\');\n \nSELECT * FROM members;\n \n+------------+\n| name |\n+------------+\n| Jagdish |\n| Kenny |\n| Rokurou |\n| Immaculada |\n+------------+\n \nSelect the first two names (no ordering specified):\n \nSELECT * FROM members LIMIT 2;\n \n+---------+\n| name |\n+---------+\n| Jagdish |\n| Kenny |\n+---------+\n \nAll the names in alphabetical order:\n \nSELECT * FROM members ORDER BY name;\n \n+------------+\n| name |\n+------------+\n| Immaculada |\n| Jagdish |\n| Kenny |\n| Rokurou |\n+------------+\n \nThe first two names, ordered alphabetically:\n \nSELECT * FROM members ORDER BY name LIMIT 2;\n \n+------------+\n| name |\n+------------+\n| Immaculada |\n| Jagdish |\n+------------+\n \nThe third name, ordered alphabetically (the first name would\nbe offset zero, so the third is offset two):\n \nSELECT * FROM members ORDER BY name LIMIT 2,1;\n \n+-------+\n| name |\n+-------+\n| Kenny |\n+-------+\n \nFrom MariaDB 10.3.2, LIMIT can be used in a multi-table\nupdate:\n \nCREATE TABLE warehouse (product_id INT, qty INT);\nINSERT INTO warehouse VALUES\n(1,100),(2,100),(3,100),(4,100);\n \nCREATE TABLE store (product_id INT, qty INT);\nINSERT INTO store VALUES (1,5),(2,5),(3,5),(4,5);\n \nUPDATE warehouse,store SET warehouse.qty = warehouse.qty-2,\nstore.qty = store.qty+2 \n WHERE (warehouse.product_id = store.product_id AND\nstore.product_id >= 1) \n ORDER BY store.product_id DESC LIMIT 2;\n \nSELECT * FROM warehouse;\n \n+------------+------+\n| product_id | qty |\n+------------+------+\n| 1 | 100 |\n| 2 | 100 |\n| 3 | 98 |\n| 4 | 98 |\n+------------+------+\n \nSELECT * FROM store;\n \n+------------+------+\n| product_id | qty |\n+------------+------+\n| 1 | 5 |\n| 2 | 5 |\n| 3 | 7 |\n| 4 | 7 |\n+------------+------+\n \nFrom MariaDB 10.3.3, LIMIT can be used with GROUP_CONCAT,\nso, for example, given the following table:\n \nCREATE TABLE d (dd DATE, cc INT);\n \nINSERT INTO d VALUES (\'2017-01-01\',1);\nINSERT INTO d VALUES (\'2017-01-02\',2);\nINSERT INTO d VALUES (\'2017-01-04\',3);\n \nthe following query:\n \nSELECT SUBSTRING_INDEX(GROUP_CONCAT(CONCAT_WS(\":\",dd,cc)\nORDER BY cc DESC),\",\",1) FROM d;\n \n+----------------------------------------------------------------------------+\n| SUBSTRING_INDEX(GROUP_CONCAT(CONCAT_WS(\":\",dd,cc) ORDER\nBY cc DESC),\",\",1) |\n+----------------------------------------------------------------------------+\n| 2017-01-04:3 |\n+----------------------------------------------------------------------------+\n \ncan be more simply rewritten as:\n \nSELECT GROUP_CONCAT(CONCAT_WS(\":\",dd,cc) ORDER BY cc DESC\nLIMIT 1) FROM d;\n \n+-------------------------------------------------------------+\n| GROUP_CONCAT(CONCAT_WS(\":\",dd,cc) ORDER BY cc DESC LIMIT\n1) |\n+-------------------------------------------------------------+\n| 2017-01-04:3 |\n+-------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/limit/','','https://mariadb.com/kb/en/limit/'),(429,'LOAD XML',27,'Syntax\n------ \nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE\n\'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n \nDescription\n----------- \nThe LOAD XML statement reads data from an XML file into a\ntable. The\nfile_name must be given as a literal string. The tagname in\nthe\noptional ROWS IDENTIFIED BY clause must also be given as a\nliteral\nstring, and must be surrounded by angle brackets (< and >).\n \nLOAD XML acts as the complement of running the mysql client\nin XML\noutput mode (that is, starting the client with the --xml\noption). To\nwrite data from a table to an XML file, use a command such\nas the\nfollowing one from the system shell:\n \nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n \nTo read the file back into a table, use LOAD XML INFILE. By\ndefault,\nthe element is considered to be the equivalent of a\ndatabase\ntable row; this can be changed using the ROWS IDENTIFIED BY\nclause.\n \nThis statement supports three different XML formats:\nColumn names as attributes and column values as attribute\nvalues:\n \nColumn names as tags and column values as the content of\nthese tags:\n \n value1\n value2\n \nColumn names are the name attributes of tags, and values\nare\n the contents of these tags:\n \n value1\n value2\n \n This is the format used by other tools, such as mysqldump.\n \nAll 3 formats can be used in the same XML file; the import\nroutine\nautomatically detects the format for each row and interprets\nit\ncorrectly. Tags are matched based on the tag or attribute\nname and the\ncolumn name.\n \nThe following clauses work essentially the same way for LOAD\nXML as\nthey do for LOAD DATA:\nLOW_PRIORITY or CONCURRENT\nLOCAL\nREPLACE or IGNORE\nCHARACTER SET\n(column_or_user_var,...)\nSET\n \nSee LOAD DATA for more information about these clauses.\n \nThe IGNORE number LINES or IGNORE number ROWS clause causes\nthe first\nnumber rows in the XML file to be skipped. It is analogous\nto the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n \nIf the LOW_PRIORITY keyword is used, insertions are delayed\nuntil no other clients are reading from the table. The\nCONCURRENT keyword allowes the use of concurrent inserts.\nThese clauses cannot be specified together.\n \nThis statement activates INSERT triggers.\n \n\n\nURL: https://mariadb.com/kb/en/load-xml/','','https://mariadb.com/kb/en/load-xml/'),(428,'LOAD DATA INFILE',27,'Syntax\n------ \nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE\n\'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number LINES]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n \nDescription\n----------- \nReads rows from a text file into the designated table on the\ndatabase at a very high speed. The file name must be given\nas a literal string. \n \nFiles are written to disk using the SELECT INTO OUTFILE\nstatement. You can then read the files back into a table\nusing the LOAD DATA INFILE statement. The FIELDS and LINES\nclauses are the same in both statements. These clauses are\noptional, but if both are specified then the FIELDS clause\nmust precede LINES.\n \nIn releases after MariaDB 5.5, LOAD DATA INFILE is unsafe\nfor statement-based replication.\n \nExecuting this statement activates INSERT triggers.\n \nREPLACE and IGNORE\n \nIn cases where you load data from a file into a table that\nalready contains data and has a Primary Key, you may\nencounter issues where the statement attempts to insert a\nrow with a Primary Key that already exists. When this\nhappens, the statement fails with Error 1064, protecting the\ndata already on the table. In cases where you want MariaDB\nto overwrite duplicates, use the REPLACE keyword.\n \nThe REPLACE keyword works like the REPLACE statement. Here,\nthe statement attempts to load the data from the file. If\nthe row does not exist, it adds it to the table. If the row\ncontains an existing Primary Key, it replaces the table\ndata. That is, in the event of a conflict, it assumes the\nfile contains the desired row. \n \nThis operation can cause a degradation in load speed by a\nfactor of 20 or more if the part that has already been\nloaded is larger than the capacity of the InnoDB Buffer\nPool. This happens because it causes a lot of turnaround in\nthe Buffer Pool.\n \nUse the IGNORE keyword when you want to skip any rows that\ncontain a conflicting Primary Key. Here, the statement\nattempts to load the data from the file. If the row does not\nexist, it adds it to the table. If the row contains an\nexisting Primary Key, it ignores the addition request and\nmoves on to the next. That is, in the event of a conflict,\nit assumes the table contains the desired row.\n \nLOCAL\n \nWhen you issue this statement, the Server attempts to read\nfiles from the host file system. Using the LOCAL keyword,\nthe statement instead attempts to read files from the\nclient. This allows you to insert files from the client\'s\nlocal file system into the database.\n \nIn the event that you don\'t want the server to permit this\noperation, (such as for security reasons), you can disable\nsupport using local_infile. When this system variable is set\nto 0, MariaDB rejects LOAD DATA LOCAL INFILE statements,\nfailing with an error message.\n \nCharacter-sets\n \nWhen the statement opens the file, it attempts to read the\ncontents using the default character-set, as defined by the\ncharacter_set_database system variable. \n \nIn the cases where the file was written using a\ncharacter-set other than the default, you can specify the\ncharacter-set to use with the CHARACTER SET clause in the\nstatement. It ignores character-sets specified by the SET\nNAMES statement and by the character_set_client system\nvariable. Setting the CHARACTER SET clause to a value of\nbinary indicates \"no conversion.\"\n \nThe statement interprets all fields in the file as having\nthe same character-set, regardless of the column data type.\nTo properly interpret file contents, you must ensure that it\nwas written with the correct character-set. If you write a\ndata file with mysqldump -T or with the SELECT INTO OUTFILE\nstatement with the mysql client, be sure to use the\n--default-character-set option, so that the output is\nwritten with the desired character-set.\n \nWhen using mixed character sets, use the CHARACTER SET\nclause in both SELECT INTO OUTFILE and LOAD DATA INFILE to\nensure that MariaDB correctly interprets the escape\nsequences.\n \nThe character_set_filesystem system variable controls the\ninterpretation of the filename.\n \nIt is currently not possible to load data files that use the\nucs2 character set.\n \nPriority and Concurrency\n \nIn loading data from a file, there\'s a risk that the\nstatement will attempt insertions concurrent with reads from\nanother client, which can result in the read serving a\nresult-set that contains only part of the update from the\nLOAD DATA INFILE statement.\n \nUsing the LOW_PRIORITY keyword, MariaDB delays insertions\nuntil no other clients are reading from the table.\nAlternatively, you can use the CONCURRENT keyword to perform\nconcurrent insertion.\n \nThe LOW_PRIORITY and CONCURRENT keywords are mutually\nexclusive. They cannot be used in the same statement.\n \nProgress Reporting\n \nSince MariaDB 5.3, the LOAD DATA INFILE statement supports\nprogress reporting. You may find this useful when dealing\nwith long-running operations. Using another client you can\nissue a SHOW PROCESSLIST query to check the progress of the\ndata load.\n \nUsing mysqlimport\n \nMariaDB ships with a separate utility for loading data from\nfiles: mysqlimport. It operates by sending LOAD DATA INFILE\nstatements to the server.\n \nUsing mysqlimport you can compress the file using the\n--compress option, to get better performance over slow\nnetworks, providing both the client and server support the\ncompressed protocol. Use the --local option to load from the\nlocal file system.\n \nIndexing\n \nIn cases where the storage engine supports ALTER TABLE...\nDISABLE KEYS statements, the LOAD DATA INFILE statement\nautomatically disables indexes during the execution.\n \n\n\nURL: https://mariadb.com/kb/en/load-data-infile/','','https://mariadb.com/kb/en/load-data-infile/'),(431,'Non-Recursive Common Table Expressions Overview',27,'Common Table Expressions (CTEs) are a standard SQL feature,\nand are essentially temporary named result sets. There are\ntwo kinds of CTEs: Non-Recursive, which this article covers;\nand Recursive.\n \nCommon table expressions were introduced in MariaDB 10.2.1.\n \nNon-Recursive CTEs\n \nThe WITH keyword signifies a CTE. It is given a name,\nfollowed by a body (the main query) as follows:\n \nCTEs are similar to derived tables. For example\n \nWITH engineers AS \n ( SELECT * FROM employees\n WHERE dept = \'Engineering\' )\n \nSELECT * FROM engineers\nWHERE ...\n \nSELECT * FROM\n ( SELECT * FROM employees\n WHERE dept = \'Engineering\' ) AS engineers\nWHERE\n...\n \nA non-recursive CTE is basically a query-local VIEW. There\nare several advantages and caveats to them. The syntax is\nmore readable than nested FROM (SELECT ...).\nA CTE can refer to another and it can be referenced from\nmultiple places.\n \nA CTE referencing Another CTE\n \nUsing this format makes for a more readable SQL than a\nnested FROM(SELECT ...) clause. Below is an example of this:\n \nWITH engineers AS (\nSELECT * FROM employees\nWHERE dept IN(\'Development\',\'Support\') ),\neu_engineers AS ( SELECT * FROM engineers WHERE country\nIN(\'NL\',...) )\nSELECT\n...\nFROM eu_engineers;\n \nMultiple Uses of a CTE\n \nThis can be an \'anti-self join\', for example:\n \nWITH engineers AS (\nSELECT * FROM employees\nWHERE dept IN(\'Development\',\'Support\') )\n \nSELECT * FROM engineers E1\nWHERE NOT EXISTS\n (SELECT 1 FROM engineers E2\n WHERE E2.country=E1.country\n AND E2.name E1.name );\n \nOr, for year-over-year comparisons, for example:\n \nWITH sales_product_year AS (\nSELECT product, YEAR(ship_date) AS year,\nSUM(price) AS total_amt\nFROM item_sales\nGROUP BY product, year )\n \nSELECT *\nFROM sales_product_year CUR,\nsales_product_year PREV,\nWHERE CUR.product=PREV.product \nAND CUR.year=PREV.year + 1 \nAND CUR.total_amt > PREV.total_amt\n \nAnother use is to compare individuals against their group.\nBelow is an example of how this might be executed:\n \nWITH sales_product_year AS (\nSELECT product,\nYEAR(ship_date) AS year,\nSUM(price) AS total_amt\nFROM item_sales\nGROUP BY product, year\n)\n \nSELECT * \nFROM sales_product_year S1\nWHERE\ntotal_amt > \n (SELECT 0.1 * SUM(total_amt)\n FROM sales_product_year S2\n WHERE S2.year = S1.year)\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/non-recursive-common-table-expressions-overview/','','https://mariadb.com/kb/en/non-recursive-common-table-expressions-overview/'),(432,'ORDER BY',27,'Description\n----------- \nUse the ORDER BY clause to order a resultset, such as that\nare returned from a SELECT\nstatement. You can specify just a column or use any\nexpression with functions. If you are\nusing the GROUP BY clause, you can use grouping functions in\nORDER BY.\nOrdering is done after grouping.\n \nYou can use multiple ordering expressions, separated by\ncommas. Rows will be sorted by\nthe first expression, then by the second expression if they\nhave the same value for the\nfirst, and so on.\n \nYou can use the keywords ASC and DESC after each ordering\nexpression to\nforce that ordering to be ascending or descending,\nrespectively. Ordering is ascending\nby default.\n \nYou can also use a single integer as the ordering\nexpression. If you use an integer n,\nthe results will be ordered by the nth column in the select\nexpression.\n \nWhen string values are compared, they are compared as if by\nthe STRCMP\nfunction. STRCMP ignores trailing whitespace and may\nnormalize\ncharacters and ignore case, depending on the collation in\nuse.\n \nStarting from MariaDB 5.5.35 duplicated entries in the ORDER\nBY clause are removed. MySQL 5.6 also removes duplicated\nfields.\n \nORDER BY can also be used to order the activities of a\nDELETE or UPDATE statement (usually with the LIMIT clause). \n \nUntil MariaDB 10.3.1, it was not possible to use ORDER BY\n(or LIMIT) in a multi-table UPDATE statement. This\nrestriction was lifted in MariaDB 10.3.2.\n \nExamples\n-------- \nCREATE TABLE seq (i INT, x VARCHAR(1));\nINSERT INTO seq VALUES (1,\'a\'), (2,\'b\'), (3,\'b\'),\n(4,\'f\'), (5,\'e\');\n \nSELECT * FROM seq ORDER BY i;\n \n+------+------+\n| i | x |\n+------+------+\n| 1 | a |\n| 2 | b |\n| 3 | b |\n| 4 | f |\n| 5 | e |\n+------+------+\n \nSELECT * FROM seq ORDER BY i DESC;\n \n+------+------+\n| i | x |\n+------+------+\n| 5 | e |\n| 4 | f |\n| 3 | b |\n| 2 | b |\n| 1 | a |\n+------+------+\n \nSELECT * FROM seq ORDER BY x,i;\n \n+------+------+\n| i | x |\n+------+------+\n| 1 | a |\n| 2 | b |\n| 3 | b |\n| 5 | e |\n| 4 | f |\n+------+------+\n \nORDER BY in an UPDATE statement, in conjunction with LIMIT:\n \nUPDATE seq SET x=\'z\' WHERE x=\'b\' ORDER BY i DESC LIMIT\n1;\n \nSELECT * FROM seq;\n \n+------+------+\n| i | x |\n+------+------+\n| 1 | a |\n| 2 | b |\n| 3 | z |\n| 4 | f |\n| 5 | e |\n+------+------+\n \nFrom MariaDB 10.3.2, ORDER BY can be used in a multi-table\nupdate:\n \nCREATE TABLE warehouse (product_id INT, qty INT);\nINSERT INTO warehouse VALUES\n(1,100),(2,100),(3,100),(4,100);\n \nCREATE TABLE store (product_id INT, qty INT);\nINSERT INTO store VALUES (1,5),(2,5),(3,5),(4,5);\n \nUPDATE warehouse,store SET warehouse.qty = warehouse.qty-2,\nstore.qty = store.qty+2 \n WHERE (warehouse.product_id = store.product_id AND\nstore.product_id >= 1) \n ORDER BY store.product_id DESC LIMIT 2;\n \nSELECT * FROM warehouse;\n \n+------------+------+\n| product_id | qty |\n+------------+------+\n| 1 | 100 |\n| 2 | 100 |\n| 3 | 98 |\n| 4 | 98 |\n+------------+------+\n \nSELECT * FROM store;\n \n+------------+------+\n| product_id | qty |\n+------------+------+\n| 1 | 5 |\n| 2 | 5 |\n| 3 | 7 |\n| 4 | 7 |\n+------------+------+\n \n\n\nURL: https://mariadb.com/kb/en/order-by/','','https://mariadb.com/kb/en/order-by/'),(434,'Recursive Common Table Expressions Overview',27,'Recursive Common Table Expressions have been supported since\nMariaDB 10.2.2.\n \nCommon Table Expressions (CTEs) are a standard SQL feature,\nand are essentially temporary named result sets. CTEs first\nappeared in the SQL standard in 1999, and the first\nimplementations began appearing in 2007.\n \nThere are two kinds of CTEs:\nNon-recursive\nRecursive, which this article covers.\n \nSQL is generally poor at recursive structures.\n \nCTEs permit a query to reference itself. A recursive CTE\nwill repeatedly execute subsets of the data until it obtains\nthe complete result set. This makes it particularly useful\nfor handing hierarchical or tree-structured data.\n \nSyntax example\n \nWITH RECURSIVE signifies a recursive CTE. It is given a\nname, followed by a body (the main query) as follows:\n \n\nComputation\n \nGiven the following structure:\n \nFirst execute the anchor part of the query:\n \nNext, execute the recursive part of the query:\n \n\n \n\nSummary so far\n \nwith recursive R as (\n select anchor_data\n union [all]\n select recursive_part\n from R, ...\n)\nselect ...\nCompute anchor_data\nCompute recursive_part to get the new data\nif (new data is non-empty) goto 2;\n \nCAST to avoid truncating data\n \nAs currently implemented by MariaDB and by the SQL Standard,\ndata may be truncated if not correctly cast. It is necessary\nto CAST the column to the correct width if the CTE\'s\nrecursive part produces wider values for a column than the\nCTE\'s nonrecursive part. Some other DBMS give an error in\nthis situation, and MariaDB\'s behavior may change in future\n- see MDEV-12325. See the examples below.\n \nExamples\n-------- \nTransitive closure - determining bus destinations\n \nSample data:\n \nCREATE TABLE bus_routes (origin varchar(50), dst\nvarchar(50));\nINSERT INTO bus_routes VALUES \n (\'New York\', \'Boston\'), \n (\'Boston\', \'New York\'), \n (\'New York\', \'Washington\'), \n (\'Washington\', \'Boston\'), \n (\'Washington\', \'Raleigh\');\n \nNow, we want to return the bus destinations with New York as\nthe origin:\n \nWITH RECURSIVE bus_dst as ( \n SELECT origin as dst FROM bus_routes WHERE origin=\'New\nYork\' \n UNION\n SELECT bus_routes.dst FROM bus_routes, bus_dst WHERE\nbus_dst.dst= bus_routes.origin \n) \nSELECT * FROM bus_dst;\n \n+------------+\n| dst |\n+------------+\n| New York |\n| Boston |\n| Washington |\n| Raleigh |\n+------------+\n \nThe above example is computed as follows:\n \nFirst, the anchor data is calculated:\nStarting from New York\nBoston and Washington are added\n \nNext, the recursive part:\nStarting from Boston and then Washington\nRaleigh is added\nUNION excludes nodes that are already present.\n \nComputing paths - determining bus routes\n \nThis time, we are trying to get bus routes such as “New\nYork -> Washington -> Raleigh”.\n \nUsing the same sample data as the previous example:\n \nWITH RECURSIVE paths (cur_path, cur_dest) AS (\n SELECT origin, origin FROM bus_routes WHERE origin=\'New\nYork\' \n UNION\n SELECT CONCAT(paths.cur_path, \',\', bus_routes.dst),\nbus_routes.dst \n FROM paths, bus_routes \n WHERE paths.cur_dest = bus_routes.origin AND \n LOCATE(bus_routes.dst, paths.cur_path)=0 \n) \nSELECT * FROM paths;\n \n+-----------------------------+------------+\n| cur_path | cur_dest |\n+-----------------------------+------------+\n| New York | New York |\n| New York,Boston | Boston |\n| New York,Washington | Washington |\n| New York,Washington,Boston | Boston |\n| New York,Washington,Raleigh | Raleigh |\n+-----------------------------+------------+\n \nCAST to avoid data truncation\n \nIn the following example, data is truncated because the\nresults are not specifically cast to a wide enough type:\n \nWITH RECURSIVE tbl AS (\n SELECT NULL AS col\n UNION\n SELECT \"THIS NEVER SHOWS UP\" AS col FROM tbl\n)\n+------+\n| col |\n+------+\n| NULL |\n| |\n+------+\n \nExplicitly use CAST to overcome this:\n \nWITH RECURSIVE tbl AS (\n SELECT CAST(NULL AS CHAR(50)) AS col\n UNION SELECT \"THIS NEVER SHOWS UP\" AS col FROM tbl\n) \nSELECT * FROM tbl;\n \n+---------------------+\n| col |\n+---------------------+\n| NULL |\n| THIS NEVER SHOWS UP |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/recursive-common-table-expressions-overview/','','https://mariadb.com/kb/en/recursive-common-table-expressions-overview/'),(435,'REPLACE',27,'Syntax\n------ \nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n \nOr:\n \nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [PARTITION (partition_list)]\n SET col={expr | DEFAULT}, ...\n \nOr:\n \nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [PARTITION (partition_list)] [(col,...)]\n SELECT ...\n \nDescription\n----------- \n REPLACE works exactly like\n INSERT, except that if an old row in the table\n has the same value as a new row for a PRIMARY KEY or a\n UNIQUE index, the old row is deleted before the new row is\n inserted. If the table has more than one UNIQUE keys, it is\npossible that the new row conflicts with more than one row.\nIn this case, all conflicting rows will be deleted.\n \nThe table name can be specified in the form db_name.tbl_name\nor, if a default database is selected, in the form tbl_name\n(see Identifier Qualifiers). This allows to use REPLACE ...\nSELECT to copy rows between different databases.\n \nBasically it works like this:\n \nBEGIN;\nSELECT 1 FROM t1 WHERE key=# FOR UPDATE;\nIF found-row\n DELETE FROM t1 WHERE key=# ;\n INSERT INTO t1 VALUES (...);\nENDIF\nEND;\n \nThe above can be replaced with:\n \nREPLACE INTO t1 VALUES (...)\n \n REPLACE is a MariaDB/MySQL extension to the SQL standard.\nIt\n either inserts, or deletes and inserts. For other\nMariaDB/MySQL extensions to\n standard SQL --- that also handle duplicate values --- see\nIGNORE and INSERT ON DUPLICATE KEY UPDATE.\n \nNote that unless the table has a PRIMARY KEY or\n UNIQUE index, using a REPLACE statement\nmakes no sense. It becomes equivalent to INSERT, because\nthere is no index to be used to determine whether a new row\nduplicates another.\n \nValues for all columns are taken from the values specified\nin the\n REPLACE statement. Any missing columns are set to their\ndefault values, just as happens for INSERT. You cannot refer\nto values from the current row and use them in the new row.\nIf you use an\nassignment such as \'SET col = col + 1\', the\nreference to the column name on the right hand side is\ntreated as\n DEFAULT(col), so the assignment is equivalent to\n \'SET col = DEFAULT(col) + 1\'.\n \nTo use REPLACE, you must have both the\n INSERT and DELETE privileges\nfor the table.\n \nThere are some gotchas you should be aware of, before using\nREPLACE:\nIf there is an AUTO_INCREMENT field, a new value will be\ngenerated.\nIf there are foreign keys, ON DELETE action will be\nactivated by REPLACE.\nTriggers on DELETE and INSERT will be activated by REPLACE.\n \nTo avoid some of these behaviors, you can use INSERT ... ON\nDUPLICATE KEY UPDATE.\n \nThe PARTITION clause was introduced in MariaDB 10.0. See\nPartition Pruning and Selection for details.\n \nThis statement activates INSERT and DELETE triggers. See\nTrigger Overview for details.\n \n\n\nURL: https://mariadb.com/kb/en/replace/','','https://mariadb.com/kb/en/replace/'),(436,'SELECT',27,'Syntax\n------ \nSELECT\n [ALL | DISTINCT | DISTINCTROW]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [ FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position} [ASC | DESC], ...\n[WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position} [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n procedure|[PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\' [CHARACTER SET charset_name]\n[export_options]\n \nINTO DUMPFILE \'file_name\' | INTO var_name [, var_name] ] |\n\n \n [[FOR UPDATE | LOCK IN SHARE MODE] [WAIT n | NOWAIT] ] ]\n \nexport_options:\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n \nDescription\n----------- \nSELECT is used to retrieve rows selected from one or more\ntables, and can include UNION statements and subqueries.\nEach select_expr expression indicates a column or data that\nyou want to retrieve. You\nmust have at least one select expression. See Select\nExpressions below.\n \nThe FROM clause indicates the table or tables from which to\nretrieve rows.\nUse either a single table name or a JOIN expression. See\nJOIN\nfor details. If no table is involved, FROM DUAL can be\nspecified.\n \nThe PARTITION clause was introduced in MariaDB 10.0. See\nPartition Pruning and Selection for details.\nEach table can also be specified as db_name.tabl_name. Each\ncolumn can also be specified as tbl_name.col_name or even\ndb_name.tbl_name.col_name. This allows to write queries\nwhich involve multiple databases. See Identifier Qualifiers\nfor syntax details.\n \nThe WHERE clause, if given, indicates the condition or\n conditions that rows must satisfy to be selected.\n where_condition is an expression that evaluates to true for\n each row to be selected. The statement selects all rows if\nthere is no WHERE\n clause.\nIn the WHERE clause, you can use any of the functions and\n operators that MariaDB supports, except for aggregate\n(summary) functions. See Functions and Operators and\nFunctions and Modifiers for use with GROUP BY (aggregate).\n \nUse the ORDER BY clause to order the results.\n \nUse the LIMIT clause allows you to restrict the results to\nonly\na certain number of rows, optionally with an offset.\n \nUse the GROUP BY and HAVING clauses to group\nrows together when they have columns or computed values in\ncommon.\n \nSELECT can also be used to retrieve rows computed without\nreference to\nany table.\n \nSelect Expressions\n \nA SELECT statement must contain one or more select\nexpressions, separated\nby commas. Each select expression can be one of the\nfollowing:\nThe name of a column.\nAny expression using functions and operators.\n* to select all columns from all tables in the FROM clause.\ntbl_name.* to select all columns from just the table\ntbl_name.\n \nWhen specifying a column, you can either use just the column\nname or qualify the column\nname with the name of the table using tbl_name.col_name. The\nqualified form is\nuseful if you are joining multiple tables in the FROM\nclause. If you do not qualify the\ncolumn names when selecting from multiple tables, MariaDB\nwill try to find the column in\neach table. It is an error if that column name exists in\nmultiple tables.\n \nYou can quote column names using backticks. If you are\nqualifying column names\nwith table names, quote each part separately as\n`tbl_name`.`col_name`.\n \nIf you use any grouping functions\nin any of the select expressions, all rows in your results\nwill be implicitly grouped, as if\nyou had used GROUP BY NULL.\n \nDISTINCT\n \nA query may produce some identical rows. By default, all\nrows are retrieved, even when their values are the same. To\nexplicitly specify that you want to retrieve identical rows,\nuse the ALL option. If you want duplicates to be removed\nfrom the resultset, use the DISTINCT option. DISTINCTROW is\na synonym for DISTINCT. See also COUNT DISTINCT and SELECT\nUNIQUE in Oracle mode.\n \nINTO\n \nThe INTO clause is used to specify that the query results\nshould be written to a file or variable.\nSELECT INTO OUTFILE - formatting and writing the result to\nan external file.\nSELECT INTO DUMPFILE - binary-safe writing of the\nunformatted results to an external file.\nSELECT INTO Variable - selecting and setting variables.\n \nThe reverse of SELECT INTO OUTFILE is LOAD DATA.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nPROCEDURE\n \nPasses the whole result set to a C Procedure. See PROCEDURE\nand PROCEDURE ANALYSE (the only built-in procedure not\nrequiring the server to be recompiled).\n \n\nmax_statement_time clause\n \nBy using max_statement_time in conjunction with SET\nSTATEMENT, it is possible to limit the execution time of\nindividual queries. For example:\n \nSET STATEMENT max_statement_time=100 FOR \n SELECT field1 FROM table_name ORDER BY field1;\n \n\n\nURL: https://mariadb.com/kb/en/select/','','https://mariadb.com/kb/en/select/'),(437,'SELECT INTO DUMPFILE',27,'Syntax\n------ \nSELECT ... INTO DUMPFILE \'file_path\'\n \nDescription\n----------- \nSELECT ... INTO DUMPFILE is a SELECT clause which writes the\nresultset into a single unformatted row, without any\nseparators, in a file. The results will not be returned to\nthe client.\n \nfile_path can be an absolute path, or a relative path\nstarting from the data directory. It can only be specified\nas a string literal, not as a variable. However, the\nstatement can be dynamically composed and executed as a\nprepared statement to work around this limitation.\n \nThis statement is binary-safe and so is particularly useful\nfor writing BLOB values to file. It can be used, for\nexample, to copy an image or an audio document from the\ndatabase to a file. SELECT ... INTO FILE can be used to save\na text file.\n \nThe file must not exist. It cannot be overwritten. A user\nneeds the FILE privilege to run this statement. Also,\nMariaDB needs permission to write files in the specified\nlocation. If the secure_file_priv system variable is set to\na non-empty directory name, the file can only be written to\nthat directory.\n \nSince MariaDB 5.1, the character_set_filesystem system\nvariable has controlled interpretation of file names that\nare given as literal strings.\n \nExample\n \nSELECT _utf8\'Hello world!\' INTO DUMPFILE \'/tmp/world\';\n \nSELECT LOAD_FILE(\'/tmp/world\') AS world;\n \n+--------------+\n| world |\n+--------------+\n| Hello world! |\n+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/select-into-dumpfile/','','https://mariadb.com/kb/en/select-into-dumpfile/'),(438,'SELECT INTO OUTFILE',27,'Syntax\n------ \nSELECT ... INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n [export_options]\n \nexport_options:\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n \nDescription\n----------- \nSELECT INTO OUTFILE writes the resulting rows to a file, and\nallows the use of column and row terminators to specify a\nparticular output format. The default is to terminate fields\nwith tabs (\\t) and lines with newlines (\\n).\n \nThe file must not exist. It cannot be overwritten. A user\nneeds the FILE privilege to run this statement. Also,\nMariaDB needs permission to write files in the specified\nlocation. If the secure_file_priv system variable is set to\na non-empty directory name, the file can only be written to\nthat directory.\n \nThe LOAD DATA INFILE statement complements SELECT INTO\nOUTFILE.\n \nCharacter-sets\n \nThe CHARACTER SET clause specifies the character set in\nwhich the results are to be written. Without the clause, no\nconversion takes place (the binary character set). In this\ncase, if there are multiple character sets, the output will\ncontain these too, and may not easily be able to be\nreloaded.\n \nIn cases where you have two servers using different\ncharacter-sets, using SELECT INTO OUTFILE to transfer data\nfrom one to the other can have unexpected results. To ensure\nthat MariaDB correctly interprets the escape sequences, use\nthe CHARACTER SET clause on both the SELECT INTO OUTFILE\nstatement and the subsequent LOAD DATA INFILE statement.\n \nExample\n \nThe following example produces a file in the CSV format:\n \nSELECT customer_id, firstname, surname INTO OUTFILE\n\'/exportdata/customers.txt\'\n FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'\"\'\n LINES TERMINATED BY \'\\n\'\n FROM customers;\n \n\n\nURL: https://mariadb.com/kb/en/select-into-outfile/','','https://mariadb.com/kb/en/select-into-outfile/'),(442,'WITH',27,'The WITH keyword signifies a Common Table Expression (CTE).\nIt allows you to refer to a subquery expression many times\nin a query, as if having a temporary table that only exists\nfor the duration of a query.\n \nThere are two kinds of CTEs:\nNon-Recursive\nRecursive\n \nCommon Table Expression WITH was introduced in MariaDB\n10.2.1.\n \nRecursive WITH has been supported since MariaDB 10.2.2.\n \nSyntax\n------ \nWITH [RECURSIVE] table_reference as (SELECT ...)\n SELECT ...\n \nYou can use table_reference as any normal table in the\nexternal SELECT part. You can also use WITH in sub queries.\nWITH can also be used with EXPLAIN and SELECT.\n \nBelow is an example with the WITH at the top level:\n \nWITH t AS (SELECT a FROM t1 WHERE b >= \'c\') \n SELECT * FROM t2, t WHERE t2.c = t.a;\n \nThe example below uses WITH in a subquery:\n \nSELECT t1.a, t1.b FROM t1, t2\n WHERE t1.a > t2.c \n AND t2.c IN(WITH t AS (SELECT * FROM t1 WHERE t1.a \n\nURL: https://mariadb.com/kb/en/with/','','https://mariadb.com/kb/en/with/'),(443,'DESCRIBE',28,'Syntax\n------ \n{DESCRIBE | DESC} tbl_name [col_name | wild]\n \nDescription\n----------- \nDESCRIBE provides information about the columns in a table.\nIt is a shortcut for SHOW COLUMNS FROM.\nThese statements also display information for views.\n \ncol_name can be a column name, or a string containing the\nSQL \"%\" and \"_\" wildcard characters to\nobtain output only for the columns with names matching the\nstring. There is no\nneed to enclose the string within quotes unless it contains\nspaces or other\nspecial characters.\n \nDESCRIBE city;\n \n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | YES | | NULL | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | YES | | NULL | |\n+------------+----------+------+-----+---------+----------------+\n \nThe description for SHOW COLUMNS provides\nmore information about the output columns.\n \n\n\nURL: https://mariadb.com/kb/en/describe/','','https://mariadb.com/kb/en/describe/'),(439,'SELECT WITH ROLLUP',27,'Syntax\n------ \nSee SELECT for the full syntax.\n \nDescription\n----------- \nThe WITH ROLLUP modifier adds extra rows to the resultset\nthat represent super-aggregate summaries. The\nsuper-aggregated column is represented by a NULL value.\nMultiple aggregates over different columns will be added if\nthere are multiple GROUP BY columns.\n \nThe LIMIT clause can be used at the same time, and is\napplied after the WITH ROLLUP rows have been added.\n \nWITH ROLLUP cannot be used with ORDER BY. Some sorting is\nstill possible by using ASC or DESC clauses with the GROUP\nBY column, although the super-aggregate rows will always be\nadded last.\n \nExamples\n-------- \nThese examples use the following sample table\n \nCREATE TABLE booksales ( \n country VARCHAR(35), genre\nENUM(\'fiction\',\'non-fiction\'), year YEAR, sales INT);\n \nINSERT INTO booksales VALUES\n (\'Senegal\',\'fiction\',2014,12234),\n(\'Senegal\',\'fiction\',2015,15647),\n (\'Senegal\',\'non-fiction\',2014,64980),\n(\'Senegal\',\'non-fiction\',2015,78901),\n (\'Paraguay\',\'fiction\',2014,87970),\n(\'Paraguay\',\'fiction\',2015,76940),\n (\'Paraguay\',\'non-fiction\',2014,8760),\n(\'Paraguay\',\'non-fiction\',2015,9030);\n \nThe addition of the WITH ROLLUP modifier in this example\nadds an extra row that aggregates both years:\n \nSELECT year, SUM(sales) FROM booksales GROUP BY year;\n \n+------+------------+\n| year | SUM(sales) |\n+------+------------+\n| 2014 | 173944 |\n| 2015 | 180518 |\n+------+------------+\n2 rows in set (0.08 sec)\n \nSELECT year, SUM(sales) FROM booksales GROUP BY year WITH\nROLLUP;\n \n+------+------------+\n| year | SUM(sales) |\n+------+------------+\n| 2014 | 173944 |\n| 2015 | 180518 |\n| NULL | 354462 |\n+------+------------+\n \nIn the following example, each time the genre, the year or\nthe country change, another super-aggregate row is added:\n \nSELECT country, year, genre, SUM(sales) \n FROM booksales GROUP BY country, year, genre;\n \n+----------+------+-------------+------------+\n| country | year | genre | SUM(sales) |\n+----------+------+-------------+------------+\n| Paraguay | 2014 | fiction | 87970 |\n| Paraguay | 2014 | non-fiction | 8760 |\n| Paraguay | 2015 | fiction | 76940 |\n| Paraguay | 2015 | non-fiction | 9030 |\n| Senegal | 2014 | fiction | 12234 |\n| Senegal | 2014 | non-fiction | 64980 |\n| Senegal | 2015 | fiction | 15647 |\n| Senegal | 2015 | non-fiction | 78901 |\n+----------+------+-------------+------------+\n \nSELECT country, year, genre, SUM(sales) \n FROM booksales GROUP BY country, year, genre WITH ROLLUP;\n \n+----------+------+-------------+------------+\n| country | year | genre | SUM(sales) |\n+----------+------+-------------+------------+\n| Paraguay | 2014 | fiction | 87970 |\n| Paraguay | 2014 | non-fiction | 8760 |\n| Paraguay | 2014 | NULL | 96730 |\n| Paraguay | 2015 | fiction | 76940 |\n| Paraguay | 2015 | non-fiction | 9030 |\n| Paraguay | 2015 | NULL | 85970 |\n| Paraguay | NULL | NULL | 182700 |\n| Senegal | 2014 | fiction | 12234 |\n| Senegal | 2014 | non-fiction | 64980 |\n| Senegal | 2014 | NULL | 77214 |\n| Senegal | 2015 | fiction | 15647 |\n| Senegal | 2015 | non-fiction | 78901 |\n| Senegal | 2015 | NULL | 94548 |\n| Senegal | NULL | NULL | 171762 |\n| NULL | NULL | NULL | 354462 |\n+----------+------+-------------+------------+\n \nThe LIMIT clause, applied after WITH ROLLUP:\n \nSELECT country, year, genre, SUM(sales) \n FROM booksales GROUP BY country, year, genre WITH ROLLUP\nLIMIT 4;\n \n+----------+------+-------------+------------+\n| country | year | genre | SUM(sales) |\n+----------+------+-------------+------------+\n| Paraguay | 2014 | fiction | 87970 |\n| Paraguay | 2014 | non-fiction | 8760 |\n| Paraguay | 2014 | NULL | 96730 |\n| Paraguay | 2015 | fiction | 76940 |\n+----------+------+-------------+------------+\n \nSorting by year descending:\n \nSELECT country, year, genre, SUM(sales) \n FROM booksales GROUP BY country, year DESC, genre WITH\nROLLUP;\n \n+----------+------+-------------+------------+\n| country | year | genre | SUM(sales) |\n+----------+------+-------------+------------+\n| Paraguay | 2015 | fiction | 76940 |\n| Paraguay | 2015 | non-fiction | 9030 |\n| Paraguay | 2015 | NULL | 85970 |\n| Paraguay | 2014 | fiction | 87970 |\n| Paraguay | 2014 | non-fiction | 8760 |\n| Paraguay | 2014 | NULL | 96730 |\n| Paraguay | NULL | NULL | 182700 |\n| Senegal | 2015 | fiction | 15647 |\n| Senegal | 2015 | non-fiction | 78901 |\n| Senegal | 2015 | NULL | 94548 |\n| Senegal | 2014 | fiction | 12234 |\n| Senegal | 2014 | non-fiction | 64980 |\n| Senegal | 2014 | NULL | 77214 |\n| Senegal | NULL | NULL | 171762 |\n| NULL | NULL | NULL | 354462 |\n+----------+------+-------------+------------+\n \n\n\nURL: https://mariadb.com/kb/en/select-with-rollup/','','https://mariadb.com/kb/en/select-with-rollup/'); +INSERT INTO `help_topic` VALUES (447,'ANALYZE FORMAT=JSON',28,'ANALYZE FORMAT=JSON is a mix of the EXPLAIN FORMAT=JSON and\nANALYZE statement features. ANALYZE FORMAT=JSON $statement\nwill execute $statement, and then print the output of\nEXPLAIN FORMAT=JSON, amended with the data from query\nexecution.\n \nBasic Execution Data\n \nYou can get the following also from tabular ANALYZE\nstatement form:\nr_rows is provided for any node that reads rows. It shows\nhow many rows were read, on average \nr_filtered is provided whenever there is a condition that is\nchecked. It shows the percentage of rows left after checking\nthe condition.\n \nAdvanced Execution Data\n \nThe most important data that is not available in tabula\nANALYZE statement are:\nr_loops field. This shows how many times the node was\nexecuted. Most query plan elements have this field.\nr_total_time_ms field. It shows how much time in total was\nspent executing this node. If the node has subnodes, their\nexecution time is included.\nr_buffer_size field. Query plan nodes that make use of\nbuffers report the size of buffer that was was used.\n \nData About Individual Query Plan Nodes\n \nfilesort node reports whether sorting was done with LIMIT n\nparameter, and how many rows were in the sort result. \nblock-nl-join node has r_loops field, which allows to tell\nwhether Using join buffer was efficient \nrange-checked-for-each-record reports counters that show the\nresult of the check. \nexpression-cache is used for subqueries, and it reports how\nmany times the cache was used, and what cache hit ratio was.\nunion_result node has r_rows so one can see how many rows\nwere produced after UNION operation\nand so forth\n \nUse Cases\n \nSee Examples of ANALYZE FORMAT=JSON.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/analyze-format-json/','','https://mariadb.com/kb/en/analyze-format-json/'),(440,'UNION',27,'UNION is used to combine the results from multiple SELECT\nstatements into a single result set.\n \nSyntax\n------ \nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n[ORDER BY [column [, column ...]]]\n[LIMIT {[offset,] row_count | row_count OFFSET offset}]\n \nDescription\n----------- \nUNION is used to combine the results from multiple SELECT\nstatements into a single result set.\n \nThe column names from the first SELECT statement are used as\nthe column names for the results returned. Selected columns\nlisted in corresponding positions of each SELECT statement\nshould have the same data type. (For example, the first\ncolumn selected by the first statement should have the same\ntype as the first column selected by the other statements.)\n \nIf they don\'t, the type and length of the columns in the\nresult take into account the values returned by all of the\nSELECTs, so there is no need for explicit casting. Note that\ncurrently this is not the case for recursive CTEs - see\nMDEV-12325.\n \nTable names can be specified as db_name.tbl_name. This\npermits writing UNIONs which involve multiple databases. See\nIdentifier Qualifiers for syntax details.\n \nUNION queries cannot be used with aggregate functions.\n \nALL/DISTINCT\n \nThe ALL keyword causes duplicate rows to be preserved. The\nDISTINCT keyword (the default if the keyword is omitted)\ncauses duplicate rows to be removed by the results.\n \nUNION ALL and UNION DISTINCT can both be present in a query.\nIn this case, UNION DISTINCT will override any UNION ALLs to\nits left.\n \nUntil MariaDB 10.1.1, all UNION ALL statements required the\nserver to create a temporary table. Since MariaDB 10.1.1,\nthe server can in most cases execute UNION ALL without\ncreating a temporary table, improving performance (see\nMDEV-334).\n \nORDER BY and LIMIT\n \nIndividual SELECTs can contain their own ORDER BY and LIMIT\nclauses. In this case, the individual queries need to be\nwrapped between parentheses. However, this does not affect\nthe order of the UNION, so they only are useful to limit the\nrecord read by one SELECT.\n \nThe UNION can have global ORDER BY and LIMIT clauses, which\naffect the whole resultset. If the columns retrieved by\nindividual SELECT statements have an alias (AS), the ORDER\nBY must use that alias, not the real column names.\n \nHIGH_PRIORITY\n \nSpecifying a query as HIGH_PRIORITY will not work inside a\nUNION. If applied to the first SELECT, it will be ignored.\nApplying to a later SELECT results in a syntax error:\n \nERROR 1234 (42000): Incorrect usage/placement of\n\'HIGH_PRIORITY\'\n \nSELECT ... INTO ...\n \nIndividual SELECTs cannot be written INTO DUMPFILE or INTO\nOUTFILE. If the last SELECT statement specifies INTO\nDUMPFILE or INTO OUTFILE, the entire result of the UNION\nwill be written. Placing the clause after any other SELECT\nwill result in a syntax error.\n \nIf the result is a single row, SELECT ... INTO @var_name can\nalso be used.\n \n\nParentheses\n \nFrom MariaDB 10.4.0, parentheses can be used to specify\nprecedence. Before this, a syntax error would be returned.\n \nExamples\n-------- \nUNION between tables having different column names:\n \n(SELECT e_name AS name, email FROM employees)\nUNION\n(SELECT c_name AS name, email FROM customers);\n \nSpecifying the UNION\'s global order and limiting total\nrows:\n \n(SELECT name, email FROM employees)\nUNION\n(SELECT name, email FROM customers)\nORDER BY name LIMIT 10;\n \nAdding a constant row:\n \n(SELECT \'John Doe\' AS name, \'john.doe@example.net\' AS\nemail)\nUNION\n(SELECT name, email FROM customers);\n \nDiffering types:\n \nSELECT CAST(\'x\' AS CHAR(1)) UNION SELECT REPEAT(\'y\',4);\n+----------------------+\n| CAST(\'x\' AS CHAR(1)) |\n+----------------------+\n| x |\n| yyyy |\n+----------------------+\n \nReturning the results in order of each individual SELECT by\nuse of a sort column:\n \n(SELECT 1 AS sort_column, e_name AS name, email FROM\nemployees)\nUNION\n(SELECT 2, c_name AS name, email FROM customers) ORDER BY\nsort_column;\n \nDifference between UNION, EXCEPT and INTERSECT:\n \nCREATE TABLE seqs (i INT);\nINSERT INTO seqs VALUES (1),(2),(3),(4),(5),(6);\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 5 |\n| 6 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 1 |\n| 2 |\n+------+\n \nSELECT i FROM seqs WHERE i =3;\n \n+------+\n| i |\n+------+\n| 3 |\n+------+\n \nParentheses for specifying precedence, from MariaDB 10.4.0\n \nCREATE OR REPLACE TABLE t1 (a INT);\nCREATE OR REPLACE TABLE t2 (b INT);\nCREATE OR REPLACE TABLE t3 (c INT);\n \nINSERT INTO t1 VALUES (1),(2),(3),(4);\nINSERT INTO t2 VALUES (5),(6);\nINSERT INTO t3 VALUES (1),(6);\n \n((SELECT a FROM t1) UNION (SELECT b FROM t2)) INTERSECT\n(SELECT c FROM t3);\n+------+\n| a |\n+------+\n| 1 |\n| 6 |\n+------+\n \n(SELECT a FROM t1) UNION ((SELECT b FROM t2) INTERSECT\n(SELECT c FROM t3));\n+------+\n| a |\n+------+\n| 1 |\n| 2 |\n| 3 |\n| 4 |\n| 6 |\n+------+\n \n\n\nURL: https://mariadb.com/kb/en/union/','','https://mariadb.com/kb/en/union/'),(441,'UPDATE',27,'Syntax\n------ \nSingle-table syntax:\n \nUPDATE [LOW_PRIORITY] [IGNORE] table_reference \n [PARTITION (partition_list)]\n SET col1={expr1|DEFAULT} [,col2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n \nMultiple-table syntax:\n \nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col1={expr1|DEFAULT} [, col2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n \nDescription\n----------- \nFor the single-table syntax, the UPDATE statement updates\ncolumns of existing rows in the named table with new values.\nThe\nSET clause indicates which columns to modify and the values\nthey should be given. Each value can be given as an\nexpression, or the keyword\nDEFAULT to set a column explicitly to its default value. The\nWHERE clause, if given, specifies the conditions that\nidentify\nwhich rows to update. With no WHERE clause, all rows are\nupdated. If the ORDER BY clause is specified, the rows are\nupdated in the order that is specified. The LIMIT clause\nplaces a limit on the number of rows that can be updated.\n \nThe PARTITION clause was introduced in MariaDB 10.0. See\nPartition Pruning and Selection for details.\n \nUntil MariaDB 10.3.2, for the multiple-table syntax, UPDATE\nupdates rows in each\ntable named in table_references that satisfy the conditions.\nIn this case,\nORDER BY and LIMIT cannot be used. This restriction was\nlifted in MariaDB 10.3.2 and both clauses can be used with\nmultiple-table updates. An UPDATE can also reference tables\nwhich are located in different databases; see Identifier\nQualifiers for the syntax.\n \nwhere_condition is an expression that evaluates to true for\neach row to be updated.\n \ntable_references and where_condition are as\nspecified as described in SELECT.\n \nAssignments are evaluated in left-to-right order, unless the\nSIMULTANEOUS_ASSIGNMENT sql_mode (available from MariaDB\n10.3.5) is set, in which case the UPDATE statement evaluates\nall assignments simultaneously. \n \nYou need the UPDATE privilege only for columns referenced in\nan UPDATE that are actually updated. You need only the\nSELECT privilege for any columns that are read but\nnot modified. See GRANT.\n \nThe UPDATE statement supports the following modifiers:\nIf you use the LOW_PRIORITY keyword, execution of\n the UPDATE is delayed until no other clients are reading\nfrom\n the table. This affects only storage engines that use only\ntable-level\n locking (MyISAM, MEMORY, MERGE). See HIGH_PRIORITY and\nLOW_PRIORITY clauses for details.\nIf you use the IGNORE keyword, the update statement does \n not abort even if errors occur during the update. Rows for\nwhich\n duplicate-key conflicts occur are not updated. Rows for\nwhich columns are\n updated to values that would cause data conversion errors\nare updated to the\n closest valid values instead.\n \nUPDATE Statements With the Same Source and Target\n \nFrom MariaDB 10.3.2, UPDATE statements may have the same\nsource and target.\n \nFor example, given the following table:\n \nDROP TABLE t1;\n \nCREATE TABLE t1 (c1 INT, c2 INT);\nINSERT INTO t1 VALUES (10,10), (20,20);\n \nUntil MariaDB 10.3.1, the following UPDATE statement would\nnot work:\n \nUPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1);\nERROR 1093 (HY000): Table \'t1\' is specified twice, \n both as a target for \'UPDATE\' and as a separate source\nfor data\n \nFrom MariaDB 10.3.2, the statement executes successfully:\n \nUPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1);\n \nSELECT * FROM t1;\n \n+------+------+\n| c1 | c2 |\n+------+------+\n| 10 | 10 |\n| 21 | 20 |\n+------+------+\n \nExample\n \nSingle-table syntax:\n \nUPDATE table_name SET column1 = value1, column2 = value2\nWHERE id=100;\n \nMultiple-table syntax:\n \nUPDATE tab1, tab2 SET tab1.column1 = value1, tab1.column2 =\nvalue2 WHERE tab1.id = tab2.id;\n \n\n\nURL: https://mariadb.com/kb/en/update/','','https://mariadb.com/kb/en/update/'),(448,'ANALYZE FORMAT=JSON Examples',28,'Example #1\n \nCustomers who have ordered more than 1M goods.\n \nANALYZE FORMAT=JSON\nSELECT CONT(*)\nFROM customer\nWHERE\n (SELECT SUM(o_totalprice) FROM orders WHERE\no_custkey=c_custkey) > 1000*1000;\n \nThe query takes 40 seconds over cold cache\n \nEXPLAIN: {\n \"query_block\": {\n \"select_id\": 1,\n \"r_loops\": 1,\n \"r_total_time_ms\": 39872,\n \"table\": {\n \"table_name\": \"customer\",\n \"access_type\": \"index\",\n \"key\": \"i_c_nationkey\",\n \"key_length\": \"5\",\n \"used_key_parts\": [\"c_nationkey\"],\n \"r_loops\": 1,\n \"rows\": 150303,\n \"r_rows\": 150000,\n \"r_total_time_ms\": 270.3,\n \"filtered\": 100,\n \"r_filtered\": 60.691,\n \"attached_condition\": \"((subquery#2) > ((1000 *\n1000)))\",\n \"using_index\": true\n },\n \"subqueries\": [\n {\n \"query_block\": {\n \"select_id\": 2,\n \"r_loops\": 150000,\n \"r_total_time_ms\": 39531,\n \"table\": {\n \"table_name\": \"orders\",\n \"access_type\": \"ref\",\n \"possible_keys\": [\"i_o_custkey\"],\n \"key\": \"i_o_custkey\",\n \"key_length\": \"5\",\n \"used_key_parts\": [\"o_custkey\"],\n \"ref\": [\"dbt3sf1.customer.c_custkey\"],\n \"r_loops\": 150000,\n \"rows\": 7,\n \"r_rows\": 10,\n \"r_total_time_ms\": 39208,\n \"filtered\": 100,\n \"r_filtered\": 100\n }\n }\n }\n ]\n }\n}\nANALYZE shows that 39.2 seconds were spent in the subquery,\nwhich was executed 150K times (for every row of outer\ntable).\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/analyze-formatjson-examples/','','https://mariadb.com/kb/en/analyze-formatjson-examples/'),(444,'ANALYZE Statement',28,'The ANALYZE statement was introduced in MariaDB 10.1.0.\n \nDescription\n----------- \nThe ANALYZE statement is similar to the EXPLAIN statement.\nANALYZE statement will invoke the optimizer, execute the\nstatement, and then produce EXPLAIN output instead of the\nresult set. The EXPLAIN output will be annotated with\nstatistics from statement execution.\n \nThis lets one check how close the optimizer\'s estimates\nabout the query plan are to the reality. ANALYZE produces an\noverview, while the\nANALYZE FORMAT=JSON command provides a more detailed view of\nthe query plan and the query execution.\n \nThe syntax is \n \nANALYZE explainable_statement;\n \nwhere the statement is any statement for which one can run\nEXPLAIN.\n \nCommand Output\n \nConsider an example:\n \nANALYZE SELECT * FROM tbl1 \nWHERE key1 \n BETWEEN 10 AND 200 AND \n col1 LIKE \'foo%\'\\G\n \n*************************** 1. row\n***************************\n id: 1\n select_type: SIMPLE\n table: tbl1\n type: range\npossible_keys: key1\n key: key1\n key_len: 5\n ref: NULL\n rows: 181\n r_rows: 181\n filtered: 100.00\n r_filtered: 10.50\n Extra: Using index condition; Using where\n \nCompared to EXPLAIN, ANALYZE produces two extra columns:\nr_rows is an observation-based counterpart of the rows\ncolumn. It shows how many rows were actually read from the\ntable. \nr_filtered is an observation-based counterpart of the\nfiltered column. It shows which fraction of rows was left\nafter applying the WHERE condition.\n \nInterpreting the Output\n \nJoins\n \nLet\'s consider a more complicated example.\n \nANALYZE SELECT *\nFROM orders, customer \nWHERE\n customer.c_custkey=orders.o_custkey AND\n customer.c_acctbal 200*1000\n \n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | r_rows | filtered | r_filtered |\nExtra |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| 1 | SIMPLE | customer | ALL | PRIMARY,... | NULL | NULL |\nNULL | 149095 | 150000 | 18.08 | 9.13 | Using where |\n| 1 | SIMPLE | orders | ref | i_o_custkey | i_o_custkey | 5\n| customer.c_custkey | 7 | 10 | 100.00 | 30.03 | Using where\n|\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n \nHere, one can see that\nFor table customer, customer.rows=149095,\ncustomer.r_rows=150000. The estimate for number of rows we\nwill read was fairly precise\ncustomer.filtered=18.08, customer.r_filtered=9.13. The\noptimizer somewhat overestimated the number of records that\nwill match selectivity of condition attached to `customer`\ntable (in general, when you have a full scan and r_filtered\nis less than 15%, it\'s time to consider adding an\nappropriate index).\nFor table orders, orders.rows=7, orders.r_rows=10. This\nmeans that on average, there are 7 orders for a given\nc_custkey, but in our case there were 10, which is close to\nthe expectation (when this number is consistently far from\nthe expectation, it may be time to run ANALYZE TABLE, or\neven edit the table statistics manually to get better query\nplans).\norders.filtered=100, orders.r_filtered=30.03. The optimizer\ndidn\'t have any way to estimate which fraction of records\nwill be left after it checks the condition that is attached\nto table orders (it\'s orders.o_totalprice > 200*1000). So,\nit used 100%. In reality, it is 30%. 30% is typically not\nselective enough to warrant adding new indexes. For joins\nwith many tables, it might be worth to collect and use\ncolumn statistics for columns in question, this may help the\noptimizer to pick a better query plan.\n \nMeaning of NULL in r_rows and r_filtered\n \nLet\'s modify the previous example slightly\n \nANALYZE SELECT * \nFROM orders, customer \nWHERE\n customer.c_custkey=orders.o_custkey AND\n customer.c_acctbal 200*1000;\n \n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| id | select_type | table | type | possible_keys | key |\nkey_len | ref | rows | r_rows | filtered | r_filtered |\nExtra |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| 1 | SIMPLE | customer | ALL | PRIMARY,... | NULL | NULL |\nNULL | 149095 | 150000 | 18.08 | 0.00 | Using where |\n| 1 | SIMPLE | orders | ref | i_o_custkey | i_o_custkey | 5\n| customer.c_custkey | 7 | NULL | 100.00 | NULL | Using\nwhere |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n \nHere, one can see that orders.r_rows=NULL and\norders.r_filtered=NULL. This means that table orders was not\nscanned even once. \nIndeed, we can also see customer.r_filtered=0.00. This shows\nthat a part of WHERE attached to table `customer` was never\nsatisfied (or, satisfied in less than 0.01% of cases).\n \nANALYZE FORMAT=JSON\n \nANALYZE FORMAT=JSON produces JSON output. It produces much\nmore information than tabular ANALYZE.\n \nNotes\n \nANALYZE UPDATE or ANALYZE DELETE will actually make\nupdates/deletes (ANALYZE SELECT will perform the select\noperation and then discard the resultset).\nPostgreSQL has a similar command, EXPLAIN ANALYZE.\nThe EXPLAIN in the slow query log feature allows MariaDB to\nhave ANALYZE output of slow queries printed into the slow\nquery log (see MDEV-6388).\n \n\n\nURL: https://mariadb.com/kb/en/analyze-statement/','','https://mariadb.com/kb/en/analyze-statement/'),(449,'EXPLAIN FORMAT=JSON',28,'Starting from version 10.1.2, MariaDB supports the EXPLAIN\nFORMAT=JSON syntax.\n \nSynopsis\n \nEXPLAIN FORMAT=JSON is a variant of EXPLAIN command that\nproduces output in JSON form. The output always has one row\nwhich has only one column titled \"JSON\". The contents are\na JSON representation of the query plan, formatted for\nreadability:\n \nEXPLAIN FORMAT=JSON SELECT * FROM t1 WHERE col1=1\\G\n \n*************************** 1. row\n***************************\nEXPLAIN: {\n \"query_block\": {\n \"select_id\": 1,\n \"table\": {\n \"table_name\": \"t1\",\n \"access_type\": \"ALL\",\n \"rows\": 1000,\n \"filtered\": 100,\n \"attached_condition\": \"(t1.col1 = 1)\"\n }\n }\n}\n \nOutput is different from MySQL\n \nThe output of MariaDB\'s EXPLAIN FORMAT=JSON is different\nfrom EXPLAIN FORMAT=JSON in MySQL.The reasons for that are:\nMySQL\'s output has deficiencies. Some are listed here:\nEXPLAIN FORMAT=JSON in MySQL)\nThe output of MySQL\'s EXPLAIN FORMAT=JSON is not defined.\nEven MySQL Workbench has trouble parsing it (see this blog\npost).\nMariaDB has query optimizations that MySQL does not have.\nErgo, MariaDB generates query plans that MySQL does not\ngenerate.\n \nA (as yet incomplete) list of how MariaDB\'s output is\ndifferent from MySQL can be found here: EXPLAIN FORMAT=JSON\ndifferences from MySQL. \n \nOutput format\n \nTODO: MariaDB\'s output format description.\n \n\n\nURL: https://mariadb.com/kb/en/explain-format-json/','','https://mariadb.com/kb/en/explain-format-json/'),(456,'ST_CONTAINS',30,'Syntax\n------ \nST_CONTAINS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether a geometry g1 completely\ncontains geometry g2.\n \nST_CONTAINS() uses object shapes, while CONTAINS(), based on\nthe original MySQL implementation, uses object bounding\nrectangles.\n \nST_CONTAINS tests the opposite relationship to ST_WITHIN().\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POLYGON((175 150, 20 40, 50 60,\n125 100, 175 150))\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'POINT(174 149)\');\n \nSELECT ST_CONTAINS(@g1,@g2);\n+----------------------+\n| ST_CONTAINS(@g1,@g2) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSET @g2 = ST_GEOMFROMTEXT(\'POINT(175 151)\');\n \nSELECT ST_CONTAINS(@g1,@g2);\n+----------------------+\n| ST_CONTAINS(@g1,@g2) |\n+----------------------+\n| 0 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-contains/','','https://mariadb.com/kb/en/st-contains/'),(457,'ST_CROSSES',30,'Syntax\n------ \nST_CROSSES(g1,g2)\n \nDescription\n----------- \nReturns 1 if geometry g1 spatially crosses geometry g2.\nReturns NULL if g1 is a Polygon or a MultiPolygon, or if g2\nis a\nPoint or a MultiPoint. Otherwise, returns 0.\n \nThe term spatially crosses denotes a spatial relation\nbetween two\ngiven geometries that has the following properties:\nThe two geometries intersect\nTheir intersection results in a geometry that has a\ndimension that is one\n less than the maximum dimension of the two given geometries\nTheir intersection is not equal to either of the two given\ngeometries\n \nST_CROSSES() uses object shapes, while CROSSES(), based on\nthe original MySQL implementation, uses object bounding\nrectangles.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'LINESTRING(174 149, 176 151)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'POLYGON((175 150, 20 40, 50 60,\n125 100, 175 150))\');\n \nSELECT ST_CROSSES(@g1,@g2);\n+---------------------+\n| ST_CROSSES(@g1,@g2) |\n+---------------------+\n| 1 |\n+---------------------+\n \nSET @g1 = ST_GEOMFROMTEXT(\'LINESTRING(176 149, 176 151)\');\n \nSELECT ST_CROSSES(@g1,@g2);\n+---------------------+\n| ST_CROSSES(@g1,@g2) |\n+---------------------+\n| 0 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-crosses/','','https://mariadb.com/kb/en/st-crosses/'),(459,'ST_DISJOINT',30,'Syntax\n------ \nST_DISJOINT(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 is spatially\ndisjoint from\n(does not intersect with) geometry g2.\n \nST_DISJOINT() uses object shapes, while DISJOINT(), based on\nthe original MySQL implementation, uses object bounding\nrectangles.\n \nST_DISJOINT() tests the opposite relationship to\nST_INTERSECTS().\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(0 0)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(2 0, 0 2)\');\n \nSELECT ST_DISJOINT(@g1,@g2);\n+----------------------+\n| ST_DISJOINT(@g1,@g2) |\n+----------------------+\n| 1 |\n+----------------------+\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(0 0, 0 2)\');\n \nSELECT ST_DISJOINT(@g1,@g2);\n+----------------------+\n| ST_DISJOINT(@g1,@g2) |\n+----------------------+\n| 0 |\n+----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_disjoint/','','https://mariadb.com/kb/en/st_disjoint/'),(461,'ST_EQUALS',30,'Syntax\n------ \nST_EQUALS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 is spatially\nequal to geometry g2.\n \nST_EQUALS() uses object shapes, while EQUALS(), based on the\noriginal MySQL implementation, uses object bounding\nrectangles.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'LINESTRING(174 149, 176 151)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(176 151, 174 149)\');\n \nSELECT ST_EQUALS(@g1,@g2);\n+--------------------+\n| ST_EQUALS(@g1,@g2) |\n+--------------------+\n| 1 |\n+--------------------+\n \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(0 2)\');\n \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(2 0)\');\n \nSELECT ST_EQUALS(@g1,@g2);\n+--------------------+\n| ST_EQUALS(@g1,@g2) |\n+--------------------+\n| 0 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-equals/','','https://mariadb.com/kb/en/st-equals/'),(462,'ST_INTERSECTS',30,'Syntax\n------ \nST_INTERSECTS(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 spatially\nintersects geometry g2.\n \nST_INTERSECTS() uses object shapes, while INTERSECTS(),\nbased on the original MySQL implementation, uses object\nbounding rectangles.\n \nST_INTERSECTS() tests the opposite relationship to\nST_DISJOINT().\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(0 0)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(0 0, 0 2)\');\n \nSELECT ST_INTERSECTS(@g1,@g2);\n+------------------------+\n| ST_INTERSECTS(@g1,@g2) |\n+------------------------+\n| 1 |\n+------------------------+\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(2 0, 0 2)\');\n \nSELECT ST_INTERSECTS(@g1,@g2);\n+------------------------+\n| ST_INTERSECTS(@g1,@g2) |\n+------------------------+\n| 0 |\n+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-intersects/','','https://mariadb.com/kb/en/st-intersects/'),(465,'ST_TOUCHES',30,'Syntax\n------ \nST_TOUCHES(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 spatially\ntouches geometry g2. Two geometries spatially touch if the\ninteriors of the geometries do not intersect,\nbut the boundary of one of the geometries intersects either\nthe boundary or the\ninterior of the other.\n \nST_TOUCHES() uses object shapes, while TOUCHES(), based on\nthe original MySQL implementation, uses object bounding\nrectangles.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(2 0)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'LINESTRING(2 0, 0 2)\');\n \nSELECT ST_TOUCHES(@g1,@g2);\n+---------------------+\n| ST_TOUCHES(@g1,@g2) |\n+---------------------+\n| 1 |\n+---------------------+\n \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(2 1)\');\n \nSELECT ST_TOUCHES(@g1,@g2);\n+---------------------+\n| ST_TOUCHES(@g1,@g2) |\n+---------------------+\n| 0 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-touches/','','https://mariadb.com/kb/en/st-touches/'),(466,'ST_WITHIN',30,'Syntax\n------ \nST_WITHIN(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether geometry g1 is spatially\nwithin geometry g2.\n \nThis tests the opposite relationship as ST_CONTAINS().\n \nST_WITHIN() uses object shapes, while WITHIN(), based on the\noriginal MySQL implementation, uses object bounding\nrectangles.\n \nExamples\n-------- \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(174 149)\');\n \nSET @g2 = ST_GEOMFROMTEXT(\'POLYGON((175 150, 20 40, 50 60,\n125 100, 175 150))\');\n \nSELECT ST_WITHIN(@g1,@g2);\n+--------------------+\n| ST_WITHIN(@g1,@g2) |\n+--------------------+\n| 1 |\n+--------------------+\n \nSET @g1 = ST_GEOMFROMTEXT(\'POINT(176 151)\');\n \nSELECT ST_WITHIN(@g1,@g2);\n+--------------------+\n| ST_WITHIN(@g1,@g2) |\n+--------------------+\n| 0 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st-within/','','https://mariadb.com/kb/en/st-within/'),(468,'WITHIN',30,'Syntax\n------ \nWithin(g1,g2)\n \nDescription\n----------- \nReturns 1 or 0 to indicate whether g1 is spatially within\ng2.\nThis tests the opposite relationship as Contains().\n \nWITHIN() is based on the original MySQL implementation, and\nuses object bounding rectangles, while ST_WITHIN() uses\nobject shapes.\n \nExamples\n-------- \nSET @g1 = GEOMFROMTEXT(\'POINT(174 149)\');\nSET @g2 = GEOMFROMTEXT(\'POINT(176 151)\');\nSET @g3 = GEOMFROMTEXT(\'POLYGON((175 150, 20 40, 50 60, 125\n100, 175 150))\');\n \nSELECT within(@g1,@g3);\n+-----------------+\n| within(@g1,@g3) |\n+-----------------+\n| 1 |\n+-----------------+\n \nSELECT within(@g2,@g3);\n+-----------------+\n| within(@g2,@g3) |\n+-----------------+\n| 0 |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/within/','','https://mariadb.com/kb/en/within/'),(469,'ADDDATE',31,'Syntax\n------ \nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n \nDescription\n----------- \nWhen invoked with the INTERVAL form of the second argument,\nADDDATE()\nis a synonym for DATE_ADD(). The related function\nSUBDATE() is a synonym for DATE_SUB(). For\ninformation on the INTERVAL unit argument, see the\ndiscussion for\nDATE_ADD().\n \nWhen invoked with the days form of the second argument,\nMariaDB treats it as an\ninteger number of days to be added to expr.\n \nExamples\n-------- \nSELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n+-----------------------------------------+\n| DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY) |\n+-----------------------------------------+\n| 2008-02-02 |\n+-----------------------------------------+\n \nSELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n+----------------------------------------+\n| ADDDATE(\'2008-01-02\', INTERVAL 31 DAY) |\n+----------------------------------------+\n| 2008-02-02 |\n+----------------------------------------+\n \nSELECT ADDDATE(\'2008-01-02\', 31);\n+---------------------------+\n| ADDDATE(\'2008-01-02\', 31) |\n+---------------------------+\n| 2008-02-02 |\n+---------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d, ADDDATE(d, 10) from t1;\n \n+---------------------+---------------------+\n| d | ADDDATE(d, 10) |\n+---------------------+---------------------+\n| 2007-01-30 21:31:07 | 2007-02-09 21:31:07 |\n| 1983-10-15 06:42:51 | 1983-10-25 06:42:51 |\n| 2011-04-21 12:34:56 | 2011-05-01 12:34:56 |\n| 2011-10-30 06:31:41 | 2011-11-09 06:31:41 |\n| 2011-01-30 14:03:25 | 2011-02-09 14:03:25 |\n| 2004-10-07 11:19:34 | 2004-10-17 11:19:34 |\n+---------------------+---------------------+\n \nSELECT d, ADDDATE(d, INTERVAL 10 HOUR) from t1;\n \n+---------------------+------------------------------+\n| d | ADDDATE(d, INTERVAL 10 HOUR) |\n+---------------------+------------------------------+\n| 2007-01-30 21:31:07 | 2007-01-31 07:31:07 |\n| 1983-10-15 06:42:51 | 1983-10-15 16:42:51 |\n| 2011-04-21 12:34:56 | 2011-04-21 22:34:56 |\n| 2011-10-30 06:31:41 | 2011-10-30 16:31:41 |\n| 2011-01-30 14:03:25 | 2011-01-31 00:03:25 |\n| 2004-10-07 11:19:34 | 2004-10-07 21:19:34 |\n+---------------------+------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/adddate/','','https://mariadb.com/kb/en/adddate/'),(470,'ADDTIME',31,'Syntax\n------ \nADDTIME(expr1,expr2)\n \nDescription\n----------- \nADDTIME() adds expr2 to expr1 and returns the result. expr1\nis a time\nor datetime expression, and expr2 is a time expression.\n \nExamples\n-------- \nSELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1\n1:1:1.000002\');\n+---------------------------------------------------------+\n| ADDTIME(\'2007-12-31 23:59:59.999999\', \'1\n1:1:1.000002\') |\n+---------------------------------------------------------+\n| 2008-01-02 01:01:01.000001 |\n+---------------------------------------------------------+\n \nSELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n+-----------------------------------------------+\n| ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\') |\n+-----------------------------------------------+\n| 03:00:01.999997 |\n+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/addtime/','','https://mariadb.com/kb/en/addtime/'),(471,'CONVERT_TZ',31,'Syntax\n------ \nCONVERT_TZ(dt,from_tz,to_tz)\n \nDescription\n----------- \nCONVERT_TZ() converts a datetime value dt from the time zone\ngiven by from_tz to the time zone given by to_tz and returns\nthe resulting value.\n \nIn order to use named time zones, such as GMT, MET or\nAfrica/Johannesburg, the time_zone tables must be loaded\n(see mysql_tzinfo_to_sql).\n \nNo conversion will take place if the value falls outside of\nthe supported TIMESTAMP range (\'1970-01-01 00:00:01\' to\n\'2038-01-19 05:14:07\' UTC) when converted from from_tz to\nUTC.\n \nThis function returns NULL if the arguments are invalid (or\nnamed time zones have not been loaded).\n \nSee time zones for more information.\n \nExamples\n-------- \nSELECT CONVERT_TZ(\'2016-01-01\n12:00:00\',\'+00:00\',\'+10:00\');\n+-----------------------------------------------------+\n| CONVERT_TZ(\'2016-01-01 12:00:00\',\'+00:00\',\'+10:00\')\n|\n+-----------------------------------------------------+\n| 2016-01-01 22:00:00 |\n+-----------------------------------------------------+\n \nUsing named time zones (with the time zone tables loaded):\n \nSELECT CONVERT_TZ(\'2016-01-01\n12:00:00\',\'GMT\',\'Africa/Johannesburg\');\n+---------------------------------------------------------------+\n| CONVERT_TZ(\'2016-01-01\n12:00:00\',\'GMT\',\'Africa/Johannesburg\') |\n+---------------------------------------------------------------+\n| 2016-01-01 14:00:00 |\n+---------------------------------------------------------------+\n \nThe value is out of the TIMESTAMP range, so no conversion\ntakes place:\n \nSELECT CONVERT_TZ(\'1969-12-31\n22:00:00\',\'+00:00\',\'+10:00\');\n+-----------------------------------------------------+\n| CONVERT_TZ(\'1969-12-31 22:00:00\',\'+00:00\',\'+10:00\')\n|\n+-----------------------------------------------------+\n| 1969-12-31 22:00:00 |\n+-----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/convert_tz/','','https://mariadb.com/kb/en/convert_tz/'),(478,'DATEDIFF',31,'Syntax\n------ \nDATEDIFF(expr1,expr2)\n \nDescription\n----------- \nDATEDIFF() returns (expr1 – expr2) expressed\nas a value in days from one date to the other. expr1 and\nexpr2 are date\nor date-and-time expressions. Only the date parts of the\nvalues are used in the\ncalculation.\n \nExamples\n-------- \nSELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n+----------------------------------------------+\n| DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\') |\n+----------------------------------------------+\n| 1 |\n+----------------------------------------------+\n \nSELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n+----------------------------------------------+\n| DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\') |\n+----------------------------------------------+\n| -31 |\n+----------------------------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT NOW();\n+---------------------+\n| NOW() |\n+---------------------+\n| 2011-05-23 10:56:05 |\n+---------------------+\n \nSELECT d, DATEDIFF(NOW(),d) FROM t1;\n \n+---------------------+-------------------+\n| d | DATEDIFF(NOW(),d) |\n+---------------------+-------------------+\n| 2007-01-30 21:31:07 | 1574 |\n| 1983-10-15 06:42:51 | 10082 |\n| 2011-04-21 12:34:56 | 32 |\n| 2011-10-30 06:31:41 | -160 |\n| 2011-01-30 14:03:25 | 113 |\n| 2004-10-07 11:19:34 | 2419 |\n+---------------------+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/datediff/','','https://mariadb.com/kb/en/datediff/'),(479,'DATE_ADD',31,'Syntax\n------ \nDATE_ADD(date,INTERVAL expr unit)\n \nDescription\n----------- \nPerforms date arithmetic. The date argument specifies the\nstarting date or datetime value. expr is an expression\nspecifying the\ninterval value to be added or subtracted from the starting\ndate. expr is a\nstring; it may start with a \"-\" for negative intervals.\nunit is a\nkeyword indicating the units in which the expression should\nbe interpreted. See Date and Time Units for a complete list\nof permitted units. \n \nSee also DATE_SUB().\n \nExamples\n-------- \nSELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n \n+-------------------------------------------+\n| \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND |\n+-------------------------------------------+\n| 2009-01-01 00:00:00 |\n+-------------------------------------------+\n \nSELECT INTERVAL 1 DAY + \'2008-12-31\';\n \n+-------------------------------+\n| INTERVAL 1 DAY + \'2008-12-31\' |\n+-------------------------------+\n| 2009-01-01 |\n+-------------------------------+\n \nSELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n \n+----------------------------------+\n| \'2005-01-01\' - INTERVAL 1 SECOND |\n+----------------------------------+\n| 2004-12-31 23:59:59 |\n+----------------------------------+\n \nSELECT DATE_ADD(\'2000-12-31 23:59:59\', INTERVAL 1 SECOND);\n+----------------------------------------------------+\n| DATE_ADD(\'2000-12-31 23:59:59\', INTERVAL 1 SECOND) |\n+----------------------------------------------------+\n| 2001-01-01 00:00:00 |\n+----------------------------------------------------+\n \nSELECT DATE_ADD(\'2010-12-31 23:59:59\', INTERVAL 1 DAY);\n+-------------------------------------------------+\n| DATE_ADD(\'2010-12-31 23:59:59\', INTERVAL 1 DAY) |\n+-------------------------------------------------+\n| 2011-01-01 23:59:59 |\n+-------------------------------------------------+\n \nSELECT DATE_ADD(\'2100-12-31 23:59:59\', INTERVAL \'1:1\'\nMINUTE_SECOND);\n+---------------------------------------------------------------+\n| DATE_ADD(\'2100-12-31 23:59:59\', INTERVAL \'1:1\'\nMINUTE_SECOND) |\n+---------------------------------------------------------------+\n| 2101-01-01 00:01:00 |\n+---------------------------------------------------------------+\n \nSELECT DATE_ADD(\'1900-01-01 00:00:00\', INTERVAL \'-1 10\'\nDAY_HOUR);\n+------------------------------------------------------------+\n| DATE_ADD(\'1900-01-01 00:00:00\', INTERVAL \'-1 10\'\nDAY_HOUR) |\n+------------------------------------------------------------+\n| 1899-12-30 14:00:00 |\n+------------------------------------------------------------+\n \nSELECT DATE_ADD(\'1992-12-31 23:59:59.000002\', INTERVAL\n\'1.999999\' SECOND_MICROSECOND);\n+--------------------------------------------------------------------------------+\n| DATE_ADD(\'1992-12-31 23:59:59.000002\', INTERVAL\n\'1.999999\' SECOND_MICROSECOND) |\n+--------------------------------------------------------------------------------+\n| 1993-01-01 00:00:01.000001 |\n+--------------------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/date_add/','','https://mariadb.com/kb/en/date_add/'),(480,'DATE_FORMAT',31,'Syntax\n------ \nDATE_FORMAT(date, format[, locale])\n \nDescription\n----------- \nFormats the date value according to the format string. \n \nThe language used for the names is controlled by the value\nof the lc_time_names system variable. See server locale for\nmore on the supported locales.\n \nThe options that can be used by DATE_FORMAT(), as well as\nits inverse STR_TO_DATE() and the FROM_UNIXTIME() function,\nare:\n \nOption | Description | \n \n%a | Short weekday name in current locale (Variable\nlc_time_names). | \n \n%b | Short form month name in current locale. For locale\nen_US this is one of:\nJan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov or Dec. | \n \n%c | Month with 1 or 2 digits. | \n \n%D | Day with English suffix \'th\', \'nd\', \'st\' or\n\'rd\'\'. (1st, 2nd, 3rd...). | \n \n%d | Day with 2 digits. | \n \n%e | Day with 1 or 2 digits. | \n \n%f | Sub seconds 6 digits. | \n \n%H | Hour with 2 digits between 00-23. | \n \n%h | Hour with 2 digits between 01-12. | \n \n%I | Hour with 2 digits between 01-12. | \n \n%i | Minute with 2 digits. | \n \n%j | Day of the year (001-366) | \n \n%k | Hour with 1 digits between 0-23. | \n \n%l | Hour with 1 digits between 1-12. | \n \n%M | Full month name in current locale (Variable\nlc_time_names). | \n \n%m | Month with 2 digits. | \n \n%p | AM/PM according to current locale (Variable\nlc_time_names). | \n \n%r | Time in 12 hour format, followed by AM/PM. Short for\n\'%I:%i:%S %p\'. | \n \n%S | Seconds with 2 digits. | \n \n%s | Seconds with 2 digits. | \n \n%T | Time in 24 hour format. Short for \'%H:%i:%S\'. | \n \n%U | Week number (00-53), when first day of the week is\nSunday. | \n \n%u | Week number (00-53), when first day of the week is\nMonday. | \n \n%V | Week number (01-53), when first day of the week is\nSunday. Used with %X. | \n \n%v | Week number (01-53), when first day of the week is\nMonday. Used with %x. | \n \n%W | Full weekday name in current locale (Variable\nlc_time_names). | \n \n%w | Day of the week. 0 = Sunday, 6 = Saturday. | \n \n%X | Year with 4 digits when first day of the week is\nSunday. Used with %V. | \n \n%x | Year with 4 digits when first day of the week is\nMonday. Used with %v. | \n \n%Y | Year with 4 digits. | \n \n%y | Year with 2 digits. | \n \n%# | For str_to_date(), skip all numbers. | \n \n%. | For str_to_date(), skip all punctation characters. | \n \n%@ | For str_to_date(), skip all alpha characters. | \n \n%% | A literal % character. | \n \nTo get a date in one of the standard formats, GET_FORMAT()\ncan be used.\n \nExamples\n-------- \nSELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n+------------------------------------------------+\n| DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\') |\n+------------------------------------------------+\n| Sunday October 2009 |\n+------------------------------------------------+\n \nSELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n+------------------------------------------------+\n| DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\') |\n+------------------------------------------------+\n| 22:23:00 |\n+------------------------------------------------+\n \nSELECT DATE_FORMAT(\'1900-10-04 22:23:00\', \'%D %y %a %d %m\n%b %j\');\n+------------------------------------------------------------+\n| DATE_FORMAT(\'1900-10-04 22:23:00\', \'%D %y %a %d %m %b\n%j\') |\n+------------------------------------------------------------+\n| 4th 00 Thu 04 10 Oct 277 |\n+------------------------------------------------------------+\n \nSELECT DATE_FORMAT(\'1997-10-04 22:23:00\', \'%H %k %I %r %T\n%S %w\');\n+------------------------------------------------------------+\n| DATE_FORMAT(\'1997-10-04 22:23:00\', \'%H %k %I %r %T %S\n%w\') |\n+------------------------------------------------------------+\n| 22 22 10 10:23:00 PM 22:23:00 00 6 |\n+------------------------------------------------------------+\n \nSELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n+------------------------------------+\n| DATE_FORMAT(\'1999-01-01\', \'%X %V\') |\n+------------------------------------+\n| 1998 52 |\n+------------------------------------+\n \nSELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n+---------------------------------+\n| DATE_FORMAT(\'2006-06-00\', \'%d\') |\n+---------------------------------+\n| 00 |\n+---------------------------------+\n \nOptionally, the locale can be explicitly specified as the\nthird DATE_FORMAT() argument. Doing so makes the function\nindependent from the session settings, and the three\nargument version of DATE_FORMAT() can be used in virtual\nindexed and persistent generated-columns:\n \nSELECT DATE_FORMAT(\'2006-01-01\', \'%W\', \'el_GR\');\n+------------------------------------------+\n| DATE_FORMAT(\'2006-01-01\', \'%W\', \'el_GR\') |\n+------------------------------------------+\n| Κυριακή |\n+------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/date_format/','','https://mariadb.com/kb/en/date_format/'),(481,'DATE_SUB',31,'Syntax\n------ \nDATE_SUB(date,INTERVAL expr unit)\n \nDescription\n----------- \nPerforms date arithmetic. The date argument specifies the\nstarting date or datetime value. expr is an expression\nspecifying the\ninterval value to be added or subtracted from the starting\ndate. expr is a\nstring; it may start with a \"-\" for negative intervals.\nunit is a\nkeyword indicating the units in which the expression should\nbe interpreted. See Date and Time Units for a complete list\nof permitted units. \n \nSee also DATE_ADD().\n \nExamples\n-------- \nSELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n+-----------------------------------------+\n| DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY) |\n+-----------------------------------------+\n| 1997-12-02 |\n+-----------------------------------------+\n \nSELECT DATE_SUB(\'2005-01-01 00:00:00\', INTERVAL \'1\n1:1:1\' DAY_SECOND);\n+----------------------------------------------------------------+\n| DATE_SUB(\'2005-01-01 00:00:00\', INTERVAL \'1 1:1:1\'\nDAY_SECOND) |\n+----------------------------------------------------------------+\n| 2004-12-30 22:58:59 |\n+----------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/date_sub/','','https://mariadb.com/kb/en/date_sub/'),(483,'DAYNAME',31,'Syntax\n------ \nDAYNAME(date)\n \nDescription\n----------- \nReturns the name of the weekday for date. The language used\nfor the name is controlled by the value\nof the lc_time_names system variable. See server locale for\nmore on the supported locales.\n \nExamples\n-------- \nSELECT DAYNAME(\'2007-02-03\');\n+-----------------------+\n| DAYNAME(\'2007-02-03\') |\n+-----------------------+\n| Saturday |\n+-----------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d, DAYNAME(d) FROM t1;\n \n+---------------------+------------+\n| d | DAYNAME(d) |\n+---------------------+------------+\n| 2007-01-30 21:31:07 | Tuesday |\n| 1983-10-15 06:42:51 | Saturday |\n| 2011-04-21 12:34:56 | Thursday |\n| 2011-10-30 06:31:41 | Sunday |\n| 2011-01-30 14:03:25 | Sunday |\n| 2004-10-07 11:19:34 | Thursday |\n+---------------------+------------+\n \nChanging the locale:\n \nSET lc_time_names = \'fr_CA\';\n \nSELECT DAYNAME(\'2013-04-01\');\n+-----------------------+\n| DAYNAME(\'2013-04-01\') |\n+-----------------------+\n| lundi |\n+-----------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/dayname/','','https://mariadb.com/kb/en/dayname/'),(484,'DAYOFMONTH',31,'Syntax\n------ \nDAYOFMONTH(date)\n \nDescription\n----------- \nReturns the day of the month for date, in the range 1 to 31,\nor 0\nfor dates such as \'0000-00-00\' or \'2008-00-00\' which\nhave a zero day\npart.\n \nDAY() is a synonym.\n \nExamples\n-------- \nSELECT DAYOFMONTH(\'2007-02-03\');\n+--------------------------+\n| DAYOFMONTH(\'2007-02-03\') |\n+--------------------------+\n| 3 |\n+--------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d FROM t1 where DAYOFMONTH(d) = 30;\n \n+---------------------+\n| d |\n+---------------------+\n| 2007-01-30 21:31:07 |\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/dayofmonth/','','https://mariadb.com/kb/en/dayofmonth/'),(485,'DAYOFWEEK',31,'Syntax\n------ \nDAYOFWEEK(date)\n \nDescription\n----------- \nReturns the day of the week index for the date (1 = Sunday,\n2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC\nstandard.\n \nThis contrasts with WEEKDAY() which follows a different\nindex numbering\n(0 = Monday, 1 = Tuesday, ... 6 = Sunday).\n \nExamples\n-------- \nSELECT DAYOFWEEK(\'2007-02-03\');\n+-------------------------+\n| DAYOFWEEK(\'2007-02-03\') |\n+-------------------------+\n| 7 |\n+-------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d, DAYNAME(d), DAYOFWEEK(d), WEEKDAY(d) from t1;\n \n+---------------------+------------+--------------+------------+\n| d | DAYNAME(d) | DAYOFWEEK(d) | WEEKDAY(d) |\n+---------------------+------------+--------------+------------+\n| 2007-01-30 21:31:07 | Tuesday | 3 | 1 |\n| 1983-10-15 06:42:51 | Saturday | 7 | 5 |\n| 2011-04-21 12:34:56 | Thursday | 5 | 3 |\n| 2011-10-30 06:31:41 | Sunday | 1 | 6 |\n| 2011-01-30 14:03:25 | Sunday | 1 | 6 |\n| 2004-10-07 11:19:34 | Thursday | 5 | 3 |\n+---------------------+------------+--------------+------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/dayofweek/','','https://mariadb.com/kb/en/dayofweek/'),(487,'EXTRACT',31,'Syntax\n------ \nEXTRACT(unit FROM date)\n \nDescription\n----------- \nThe EXTRACT() function extracts the required unit from the\ndate. See Date and Time Units for a complete list of\npermitted units.\n \nIn MariaDB 10.0.7 and MariaDB 5.5.35, EXTRACT (HOUR FROM\n...) was changed to return a value from 0 to 23, adhering to\nthe SQL standard. Until MariaDB 10.0.6 and MariaDB 5.5.34,\nand in all versions of MySQL at least as of MySQL 5.7, it\ncould return a value > 23. HOUR() is not a standard\nfunction, so continues to adhere to the old behaviour\ninherited from MySQL.\n \nExamples\n-------- \nSELECT EXTRACT(YEAR FROM \'2009-07-02\');\n+---------------------------------+\n| EXTRACT(YEAR FROM \'2009-07-02\') |\n+---------------------------------+\n| 2009 |\n+---------------------------------+\n \nSELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n+------------------------------------------------+\n| EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\') |\n+------------------------------------------------+\n| 200907 |\n+------------------------------------------------+\n \nSELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n+------------------------------------------------+\n| EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\') |\n+------------------------------------------------+\n| 20102 |\n+------------------------------------------------+\n \nSELECT EXTRACT(MICROSECOND FROM \'2003-01-02\n10:30:00.000123\');\n+--------------------------------------------------------+\n| EXTRACT(MICROSECOND FROM \'2003-01-02 10:30:00.000123\') |\n+--------------------------------------------------------+\n| 123 |\n+--------------------------------------------------------+\n \nFrom MariaDB 10.0.7 and MariaDB 5.5.35, EXTRACT (HOUR\nFROM...) returns a value from 0 to 23, as per the SQL\nstandard. HOUR is not a standard function, so continues to\nadhere to the old behaviour inherited from MySQL.\n \nSELECT EXTRACT(HOUR FROM \'26:30:00\'), HOUR(\'26:30:00\');\n+-------------------------------+------------------+\n| EXTRACT(HOUR FROM \'26:30:00\') | HOUR(\'26:30:00\') |\n+-------------------------------+------------------+\n| 2 | 26 |\n+-------------------------------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/extract/','','https://mariadb.com/kb/en/extract/'),(489,'FROM_UNIXTIME',31,'Syntax\n------ \nFROM_UNIXTIME(unix_timestamp),\nFROM_UNIXTIME(unix_timestamp,format)\n \nDescription\n----------- \nReturns a representation of the unix_timestamp argument as a\nvalue in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format,\ndepending on\nwhether the function is used in a string or numeric context.\nThe value\nis expressed in the current time zone. unix_timestamp is an\ninternal\ntimestamp value such as is produced by the UNIX_TIMESTAMP()\nfunction.\n \nIf format is given, the result is formatted according to the\nformat\nstring, which is used the same way as listed in the entry\nfor the\nDATE_FORMAT() function.\n \nTimestamps in MariaDB have a maximum value of 2147483647,\nequivalent to 2038-01-19 05:14:07. This is due to the\nunderlying 32-bit limitation. Using the function on a\ntimestamp beyond this will result in NULL being returned.\nUse DATETIME as a storage type if you require dates beyond\nthis.\n \nThe options that can be used by FROM_UNIXTIME(), as well as\nDATE_FORMAT() and STR_TO_DATE(), are:\n \nOption | Description | \n \n%a | Short weekday name in current locale (Variable\nlc_time_names). | \n \n%b | Short form month name in current locale. For locale\nen_US this is one of:\nJan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov or Dec. | \n \n%c | Month with 1 or 2 digits. | \n \n%D | Day with English suffix \'th\', \'nd\', \'st\' or\n\'rd\'\'. (1st, 2nd, 3rd...). | \n \n%d | Day with 2 digits. | \n \n%e | Day with 1 or 2 digits. | \n \n%f | Sub seconds 6 digits. | \n \n%H | Hour with 2 digits between 00-23. | \n \n%h | Hour with 2 digits between 01-12. | \n \n%I | Hour with 2 digits between 01-12. | \n \n%i | Minute with 2 digits. | \n \n%j | Day of the year (001-366) | \n \n%k | Hour with 1 digits between 0-23. | \n \n%l | Hour with 1 digits between 1-12. | \n \n%M | Full month name in current locale (Variable\nlc_time_names). | \n \n%m | Month with 2 digits. | \n \n%p | AM/PM according to current locale (Variable\nlc_time_names). | \n \n%r | Time in 12 hour format, followed by AM/PM. Short for\n\'%I:%i:%S %p\'. | \n \n%S | Seconds with 2 digits. | \n \n%s | Seconds with 2 digits. | \n \n%T | Time in 24 hour format. Short for \'%H:%i:%S\'. | \n \n%U | Week number (00-53), when first day of the week is\nSunday. | \n \n%u | Week number (00-53), when first day of the week is\nMonday. | \n \n%V | Week number (01-53), when first day of the week is\nSunday. Used with %X. | \n \n%v | Week number (01-53), when first day of the week is\nMonday. Used with %x. | \n \n%W | Full weekday name in current locale (Variable\nlc_time_names). | \n \n%w | Day of the week. 0 = Sunday, 1 = Saturday. | \n \n%X | Year with 4 digits when first day of the week is\nSunday. Used with %V. | \n \n%x | Year with 4 digits when first day of the week is\nSunday. Used with %v. | \n \n%Y | Year with 4 digits. | \n \n%y | Year with 2 digits. | \n \n%# | For str_to_date(), skip all numbers. | \n \n%. | For str_to_date(), skip all punctation characters. | \n \n%@ | For str_to_date(), skip all alpha characters. | \n \n%% | A literal % character. | \n \nPerformance Considerations\n \nIf your session time zone is set to SYSTEM (the default),\nFROM_UNIXTIME() will call the OS function to convert the\ndata using the system time zone. At least on Linux, the\ncorresponding function (localtime_r) uses a global mutex\ninside glibc that can cause contention under high concurrent\nload.\n \nSet your time zone to a named time zone to avoid this issue.\nSee mysql time zone tables for details on how to do this.\n \nExamples\n-------- \nSELECT FROM_UNIXTIME(1196440219);\n+---------------------------+\n| FROM_UNIXTIME(1196440219) |\n+---------------------------+\n| 2007-11-30 11:30:19 |\n+---------------------------+\n \nSELECT FROM_UNIXTIME(1196440219) + 0;\n \n+-------------------------------+\n| FROM_UNIXTIME(1196440219) + 0 |\n+-------------------------------+\n| 20071130113019.000000 |\n+-------------------------------+\n \nSELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), \'%Y %D %M %h:%i:%s\n%x\');\n+---------------------------------------------------------+\n| FROM_UNIXTIME(UNIX_TIMESTAMP(), \'%Y %D %M %h:%i:%s %x\')\n|\n+---------------------------------------------------------+\n| 2010 27th March 01:03:47 2010 |\n+---------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/from_unixtime/','','https://mariadb.com/kb/en/from_unixtime/'),(490,'GET_FORMAT',31,'Syntax\n------ \nGET_FORMAT({DATE|DATETIME|TIME},\n{\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n \nDescription\n----------- \nReturns a format string. This function is useful in\ncombination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n \nPossible result formats are:\n \nFunction Call | Result Format | \n \nGET_FORMAT(DATE,\'EUR\') | \'%d.%m.%Y\' | \n \nGET_FORMAT(DATE,\'USA\') | \'%m.%d.%Y\' | \n \nGET_FORMAT(DATE,\'JIS\') | \'%Y-%m-%d\' | \n \nGET_FORMAT(DATE,\'ISO\') | \'%Y-%m-%d\' | \n \nGET_FORMAT(DATE,\'INTERNAL\') | \'%Y%m%d\' | \n \nGET_FORMAT(DATETIME,\'EUR\') | \'%Y-%m-%d %H.%i.%s\' | \n \nGET_FORMAT(DATETIME,\'USA\') | \'%Y-%m-%d %H.%i.%s\' | \n \nGET_FORMAT(DATETIME,\'JIS\') | \'%Y-%m-%d %H:%i:%s\' | \n \nGET_FORMAT(DATETIME,\'ISO\') | \'%Y-%m-%d %H:%i:%s\' | \n \nGET_FORMAT(DATETIME,\'INTERNAL\') | \'%Y%m%d%H%i%s\' | \n \nGET_FORMAT(TIME,\'EUR\') | \'%H.%i.%s\' | \n \nGET_FORMAT(TIME,\'USA\') | \'%h:%i:%s %p\' | \n \nGET_FORMAT(TIME,\'JIS\') | \'%H:%i:%s\' | \n \nGET_FORMAT(TIME,\'ISO\') | \'%H:%i:%s\' | \n \nGET_FORMAT(TIME,\'INTERNAL\') | \'%H%i%s\' | \n \nExamples\n-------- \nObtaining the string matching to the standard European date\nformat:\n \nSELECT GET_FORMAT(DATE, \'EUR\');\n+-------------------------+\n| GET_FORMAT(DATE, \'EUR\') |\n+-------------------------+\n| %d.%m.%Y |\n+-------------------------+\n \nUsing the same string to format a date:\n \nSELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n+--------------------------------------------------+\n| DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\')) |\n+--------------------------------------------------+\n| 03.10.2003 |\n+--------------------------------------------------+\n \nSELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n+--------------------------------------------------+\n| STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\')) |\n+--------------------------------------------------+\n| 2003-10-31 |\n+--------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/get_format/','','https://mariadb.com/kb/en/get_format/'),(491,'HOUR',31,'Syntax\n------ \nHOUR(time)\n \nDescription\n----------- \nReturns the hour for time. The range of the return value is\n0 to 23\nfor time-of-day values. However, the range of TIME values\nactually is\nmuch larger, so HOUR can return values greater than 23.\n \nThe return value is always positive, even if a negative TIME\nvalue is provided.\n \nExamples\n-------- \nSELECT HOUR(\'10:05:03\');\n+------------------+\n| HOUR(\'10:05:03\') |\n+------------------+\n| 10 |\n+------------------+\n \nSELECT HOUR(\'272:59:59\');\n+-------------------+\n| HOUR(\'272:59:59\') |\n+-------------------+\n| 272 |\n+-------------------+\n \nDifference between EXTRACT (HOUR FROM ...) (>= MariaDB\n10.0.7 and MariaDB 5.5.35) and HOUR:\n \nSELECT EXTRACT(HOUR FROM \'26:30:00\'), HOUR(\'26:30:00\');\n+-------------------------------+------------------+\n| EXTRACT(HOUR FROM \'26:30:00\') | HOUR(\'26:30:00\') |\n+-------------------------------+------------------+\n| 2 | 26 |\n+-------------------------------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/hour/','','https://mariadb.com/kb/en/hour/'),(492,'LAST_DAY',31,'Syntax\n------ \nLAST_DAY(date)\n \nDescription\n----------- \nTakes a date or datetime value and returns the corresponding\nvalue for\nthe last day of the month. Returns NULL if the argument is\ninvalid.\n \nExamples\n-------- \nSELECT LAST_DAY(\'2003-02-05\');\n+------------------------+\n| LAST_DAY(\'2003-02-05\') |\n+------------------------+\n| 2003-02-28 |\n+------------------------+\n \nSELECT LAST_DAY(\'2004-02-05\');\n+------------------------+\n| LAST_DAY(\'2004-02-05\') |\n+------------------------+\n| 2004-02-29 |\n+------------------------+\n \nSELECT LAST_DAY(\'2004-01-01 01:01:01\');\n+---------------------------------+\n| LAST_DAY(\'2004-01-01 01:01:01\') |\n+---------------------------------+\n| 2004-01-31 |\n+---------------------------------+\n \nSELECT LAST_DAY(\'2003-03-32\');\n+------------------------+\n| LAST_DAY(\'2003-03-32\') |\n+------------------------+\n| NULL |\n+------------------------+\n1 row in set, 1 warning (0.00 sec)\n \nWarning (Code 1292): Incorrect datetime value:\n\'2003-03-32\'\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/last_day/','','https://mariadb.com/kb/en/last_day/'),(495,'MAKEDATE',31,'Syntax\n------ \nMAKEDATE(year,dayofyear)\n \nDescription\n----------- \nReturns a date, given year and day-of-year values. dayofyear\nmust be\ngreater than 0 or the result is NULL.\n \nExamples\n-------- \nSELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n+-------------------+-------------------+\n| MAKEDATE(2011,31) | MAKEDATE(2011,32) |\n+-------------------+-------------------+\n| 2011-01-31 | 2011-02-01 |\n+-------------------+-------------------+\n \nSELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n+--------------------+--------------------+\n| MAKEDATE(2011,365) | MAKEDATE(2014,365) |\n+--------------------+--------------------+\n| 2011-12-31 | 2014-12-31 |\n+--------------------+--------------------+\n \nSELECT MAKEDATE(2011,0);\n+------------------+\n| MAKEDATE(2011,0) |\n+------------------+\n| NULL |\n+------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/makedate/','','https://mariadb.com/kb/en/makedate/'),(496,'MAKETIME',31,'Syntax\n------ \nMAKETIME(hour,minute,second)\n \nDescription\n----------- \nReturns a time value calculated from the hour, minute, and\nsecond arguments.\n \nIf minute or second are out of the range 0 to 60, NULL is\nreturned. The hour can be in the range -838 to 838, outside\nof which the value is truncated with a warning.\n \nExamples\n-------- \nSELECT MAKETIME(13,57,33);\n+--------------------+\n| MAKETIME(13,57,33) |\n+--------------------+\n| 13:57:33 |\n+--------------------+\n \nSELECT MAKETIME(-13,57,33);\n+---------------------+\n| MAKETIME(-13,57,33) |\n+---------------------+\n| -13:57:33 |\n+---------------------+\n \nSELECT MAKETIME(13,67,33);\n+--------------------+\n| MAKETIME(13,67,33) |\n+--------------------+\n| NULL |\n+--------------------+\n \nSELECT MAKETIME(-1000,57,33);\n+-----------------------+\n| MAKETIME(-1000,57,33) |\n+-----------------------+\n| -838:59:59 |\n+-----------------------+\n1 row in set, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+-----------------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------------+\n| Warning | 1292 | Truncated incorrect time value:\n\'-1000:57:33\' |\n+---------+------+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/maketime/','','https://mariadb.com/kb/en/maketime/'),(497,'MICROSECOND',31,'Syntax\n------ \nMICROSECOND(expr)\n \nDescription\n----------- \nReturns the microseconds from the time or datetime\nexpression expr as a number in the range from 0 to 999999.\n \nIf expr is a time with no microseconds, zero is returned,\nwhile if expr is a date with no time, zero with a warning is\nreturned.\n \nExamples\n-------- \nSELECT MICROSECOND(\'12:00:00.123456\');\n+--------------------------------+\n| MICROSECOND(\'12:00:00.123456\') |\n+--------------------------------+\n| 123456 |\n+--------------------------------+\n \nSELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n+-------------------------------------------+\n| MICROSECOND(\'2009-12-31 23:59:59.000010\') |\n+-------------------------------------------+\n| 10 |\n+-------------------------------------------+\n \nSELECT MICROSECOND(\'2013-08-07 12:13:14\');\n+------------------------------------+\n| MICROSECOND(\'2013-08-07 12:13:14\') |\n+------------------------------------+\n| 0 |\n+------------------------------------+\n \nSELECT MICROSECOND(\'2013-08-07\');\n+---------------------------+\n| MICROSECOND(\'2013-08-07\') |\n+---------------------------+\n| 0 |\n+---------------------------+\n1 row in set, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+----------------------------------------------+\n| Level | Code | Message |\n+---------+------+----------------------------------------------+\n| Warning | 1292 | Truncated incorrect time value:\n\'2013-08-07\' |\n+---------+------+----------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/microsecond/','','https://mariadb.com/kb/en/microsecond/'),(501,'NOW',31,'Syntax\n------ \nNOW([precision])\nCURRENT_TIMESTAMP\nCURRENT_TIMESTAMP([precision])\nLOCALTIME, LOCALTIME([precision])\nLOCALTIMESTAMP\nLOCALTIMESTAMP([precision])\n \nDescription\n----------- \nReturns the current date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is\nused in a string or numeric context. The value is expressed\nin the\ncurrent time zone.\n \nThe optional precision determines the microsecond precision.\nSee Microseconds in MariaDB.\n \nNOW() (or its synonyms) can be used as the default value for\nTIMESTAMP columns as well as, since MariaDB 10.0.1, DATETIME\ncolumns. Before MariaDB 10.0.1, it was only possible for a\nsingle TIMESTAMP column per table to contain the\nCURRENT_TIMESTAMP as its default.\n \nWhen displayed in the INFORMATION_SCHEMA.COLUMNS table, a\ndefault CURRENT TIMESTAMP is displayed as CURRENT_TIMESTAMP\nup until MariaDB 10.2.2, and as current_timestamp() from\nMariaDB 10.2.3, due to to MariaDB 10.2 accepting expressions\nin the DEFAULT clause.\n \nExamples\n-------- \nSELECT NOW();\n+---------------------+\n| NOW() |\n+---------------------+\n| 2010-03-27 13:13:25 |\n+---------------------+\n \nSELECT NOW() + 0;\n \n+-----------------------+\n| NOW() + 0 |\n+-----------------------+\n| 20100327131329.000000 |\n+-----------------------+\n \nWith precision:\n \nSELECT CURRENT_TIMESTAMP(2);\n+------------------------+\n| CURRENT_TIMESTAMP(2) |\n+------------------------+\n| 2018-07-10 09:47:26.24 |\n+------------------------+\n \nUsed as a default TIMESTAMP:\n \nCREATE TABLE t (createdTS TIMESTAMP NOT NULL DEFAULT\nCURRENT_TIMESTAMP);\n \nFrom MariaDB 10.2.2:\n \nSELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE\nTABLE_SCHEMA=\'test\'\n AND COLUMN_NAME LIKE \'%ts%\'\\G\n*************************** 1. row\n***************************\n TABLE_CATALOG: def\n TABLE_SCHEMA: test\n TABLE_NAME: t\n COLUMN_NAME: ts\n ORDINAL_POSITION: 1\n COLUMN_DEFAULT: current_timestamp()\n...\n \n\n\nURL: https://mariadb.com/kb/en/now/','','https://mariadb.com/kb/en/now/'),(502,'PERIOD_ADD',31,'Syntax\n------ \nPERIOD_ADD(P,N)\n \nDescription\n----------- \nAdds N months to period P. P is in the format YYMM or\nYYYYMM, and is not a date value. If P contains a two-digit\nyear, values from 00 to 69 are converted to from 2000 to\n2069, while values from 70 are converted to 1970 upwards.\n \nReturns a value in the format YYYYMM.\n \nExamples\n-------- \nSELECT PERIOD_ADD(200801,2);\n+----------------------+\n| PERIOD_ADD(200801,2) |\n+----------------------+\n| 200803 |\n+----------------------+\n \nSELECT PERIOD_ADD(6910,2);\n+--------------------+\n| PERIOD_ADD(6910,2) |\n+--------------------+\n| 206912 |\n+--------------------+\n \nSELECT PERIOD_ADD(7010,2);\n+--------------------+\n| PERIOD_ADD(7010,2) |\n+--------------------+\n| 197012 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/period_add/','','https://mariadb.com/kb/en/period_add/'),(503,'PERIOD_DIFF',31,'Syntax\n------ \nPERIOD_DIFF(P1,P2)\n \nDescription\n----------- \nReturns the number of months between periods P1 and P2. P1\nand P2 \ncan be in the format YYMM or YYYYMM, and are not date\nvalues.\n \nIf P1 or P2 contains a two-digit year, values from 00 to 69\nare converted to from 2000 to 2069, while values from 70 are\nconverted to 1970 upwards.\n \nExamples\n-------- \nSELECT PERIOD_DIFF(200802,200703);\n+----------------------------+\n| PERIOD_DIFF(200802,200703) |\n+----------------------------+\n| 11 |\n+----------------------------+\n \nSELECT PERIOD_DIFF(6902,6803);\n+------------------------+\n| PERIOD_DIFF(6902,6803) |\n+------------------------+\n| 11 |\n+------------------------+\n \nSELECT PERIOD_DIFF(7002,6803);\n+------------------------+\n| PERIOD_DIFF(7002,6803) |\n+------------------------+\n| -1177 |\n+------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/period_diff/','','https://mariadb.com/kb/en/period_diff/'),(506,'SEC_TO_TIME',31,'Syntax\n------ \nSEC_TO_TIME(seconds)\n \nDescription\n----------- \nReturns the seconds argument, converted to hours, minutes,\nand\nseconds, as a TIME value. The range of the result is\nconstrained to\nthat of the TIME data type. A warning occurs if the argument\ncorresponds to a value outside that range.\n \nThe time will be returned in the format hh:mm:ss, or hhmmss\nif used in a numeric calculation.\n \nExamples\n-------- \nSELECT SEC_TO_TIME(12414);\n+--------------------+\n| SEC_TO_TIME(12414) |\n+--------------------+\n| 03:26:54 |\n+--------------------+\n \nSELECT SEC_TO_TIME(12414)+0;\n \n+----------------------+\n| SEC_TO_TIME(12414)+0 |\n+----------------------+\n| 32654 |\n+----------------------+\n \nSELECT SEC_TO_TIME(9999999);\n+----------------------+\n| SEC_TO_TIME(9999999) |\n+----------------------+\n| 838:59:59 |\n+----------------------+\n1 row in set, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+-------------------------------------------+\n| Level | Code | Message |\n+---------+------+-------------------------------------------+\n| Warning | 1292 | Truncated incorrect time value:\n\'9999999\' |\n+---------+------+-------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/sec_to_time/','','https://mariadb.com/kb/en/sec_to_time/'),(507,'STR_TO_DATE',31,'Syntax\n------ \nSTR_TO_DATE(str,format)\n \nDescription\n----------- \nThis is the inverse of the DATE_FORMAT() function. It takes\na string str and a format string format. STR_TO_DATE()\nreturns a\nDATETIME value if the format string contains both date and\ntime parts, or a\nDATE or TIME value if the string contains only date or time\nparts.\n \nThe date, time, or datetime values contained in str should\nbe given in the format indicated by format. If str contains\nan illegal date, time, or datetime value, STR_TO_DATE()\nreturns NULL. An illegal value also produces a warning.\n \nThe options that can be used by STR_TO_DATE(), as well as\nits inverse DATE_FORMAT() and the FROM_UNIXTIME() function,\nare:\n \nOption | Description | \n \n%a | Short weekday name in current locale (Variable\nlc_time_names). | \n \n%b | Short form month name in current locale. For locale\nen_US this is one of:\nJan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov or Dec. | \n \n%c | Month with 1 or 2 digits. | \n \n%D | Day with English suffix \'th\', \'nd\', \'st\' or\n\'rd\'\'. (1st, 2nd, 3rd...). | \n \n%d | Day with 2 digits. | \n \n%e | Day with 1 or 2 digits. | \n \n%f | Sub seconds 6 digits. | \n \n%H | Hour with 2 digits between 00-23. | \n \n%h | Hour with 2 digits between 01-12. | \n \n%I | Hour with 2 digits between 01-12. | \n \n%i | Minute with 2 digits. | \n \n%j | Day of the year (001-366) | \n \n%k | Hour with 1 digits between 0-23. | \n \n%l | Hour with 1 digits between 1-12. | \n \n%M | Full month name in current locale (Variable\nlc_time_names). | \n \n%m | Month with 2 digits. | \n \n%p | AM/PM according to current locale (Variable\nlc_time_names). | \n \n%r | Time in 12 hour format, followed by AM/PM. Short for\n\'%I:%i:%S %p\'. | \n \n%S | Seconds with 2 digits. | \n \n%s | Seconds with 2 digits. | \n \n%T | Time in 24 hour format. Short for \'%H:%i:%S\'. | \n \n%U | Week number (00-53), when first day of the week is\nSunday. | \n \n%u | Week number (00-53), when first day of the week is\nMonday. | \n \n%V | Week number (01-53), when first day of the week is\nSunday. Used with %X. | \n \n%v | Week number (01-53), when first day of the week is\nMonday. Used with %x. | \n \n%W | Full weekday name in current locale (Variable\nlc_time_names). | \n \n%w | Day of the week. 0 = Sunday, 6 = Saturday. | \n \n%X | Year with 4 digits when first day of the week is\nSunday. Used with %V. | \n \n%x | Year with 4 digits when first day of the week is\nMonday. Used with %v. | \n \n%Y | Year with 4 digits. | \n \n%y | Year with 2 digits. | \n \n%# | For str_to_date(), skip all numbers. | \n \n%. | For str_to_date(), skip all punctation characters. | \n \n%@ | For str_to_date(), skip all alpha characters. | \n \n%% | A literal % character. | \n \nExamples\n-------- \nSELECT STR_TO_DATE(\'Wednesday, June 2, 2014\', \'%W, %M %e,\n%Y\');\n+---------------------------------------------------------+\n| STR_TO_DATE(\'Wednesday, June 2, 2014\', \'%W, %M %e,\n%Y\') |\n+---------------------------------------------------------+\n| 2014-06-02 |\n+---------------------------------------------------------+\n \nSELECT STR_TO_DATE(\'Wednesday23423, June 2, 2014\', \'%W,\n%M %e, %Y\');\n+--------------------------------------------------------------+\n| STR_TO_DATE(\'Wednesday23423, June 2, 2014\', \'%W, %M %e,\n%Y\') |\n+--------------------------------------------------------------+\n| NULL |\n+--------------------------------------------------------------+\n1 row in set, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+---------+------+-----------------------------------------------------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------------------------------------------------+\n| Warning | 1411 | Incorrect datetime value:\n\'Wednesday23423, June 2, 2014\' for function str_to_date |\n+---------+------+-----------------------------------------------------------------------------------+\n \nSELECT STR_TO_DATE(\'Wednesday23423, June 2, 2014\', \'%W%#,\n%M %e, %Y\');\n+----------------------------------------------------------------+\n| STR_TO_DATE(\'Wednesday23423, June 2, 2014\', \'%W%#, %M\n%e, %Y\') |\n+----------------------------------------------------------------+\n| 2014-06-02 |\n+----------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/str_to_date/','','https://mariadb.com/kb/en/str_to_date/'),(508,'SUBDATE',31,'Syntax\n------ \nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n \nDescription\n----------- \nWhen invoked with the INTERVAL form of the second argument,\nSUBDATE()\nis a synonym for DATE_SUB(). See Date and Time Units for a\ncomplete list of permitted units. \n \nThe second form allows the use of an integer value for days.\nIn such\ncases, it is interpreted as the number of days to be\nsubtracted from\nthe date or datetime expression expr.\n \nExamples\n-------- \nSELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n+-----------------------------------------+\n| DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY) |\n+-----------------------------------------+\n| 2007-12-02 |\n+-----------------------------------------+\n \nSELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n+----------------------------------------+\n| SUBDATE(\'2008-01-02\', INTERVAL 31 DAY) |\n+----------------------------------------+\n| 2007-12-02 |\n+----------------------------------------+\n \nSELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n+------------------------------------+\n| SUBDATE(\'2008-01-02 12:00:00\', 31) |\n+------------------------------------+\n| 2007-12-02 12:00:00 |\n+------------------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d, SUBDATE(d, 10) from t1;\n \n+---------------------+---------------------+\n| d | SUBDATE(d, 10) |\n+---------------------+---------------------+\n| 2007-01-30 21:31:07 | 2007-01-20 21:31:07 |\n| 1983-10-15 06:42:51 | 1983-10-05 06:42:51 |\n| 2011-04-21 12:34:56 | 2011-04-11 12:34:56 |\n| 2011-10-30 06:31:41 | 2011-10-20 06:31:41 |\n| 2011-01-30 14:03:25 | 2011-01-20 14:03:25 |\n| 2004-10-07 11:19:34 | 2004-09-27 11:19:34 |\n+---------------------+---------------------+\n \nSELECT d, SUBDATE(d, INTERVAL 10 MINUTE) from t1;\n \n+---------------------+--------------------------------+\n| d | SUBDATE(d, INTERVAL 10 MINUTE) |\n+---------------------+--------------------------------+\n| 2007-01-30 21:31:07 | 2007-01-30 21:21:07 |\n| 1983-10-15 06:42:51 | 1983-10-15 06:32:51 |\n| 2011-04-21 12:34:56 | 2011-04-21 12:24:56 |\n| 2011-10-30 06:31:41 | 2011-10-30 06:21:41 |\n| 2011-01-30 14:03:25 | 2011-01-30 13:53:25 |\n| 2004-10-07 11:19:34 | 2004-10-07 11:09:34 |\n+---------------------+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/subdate/','','https://mariadb.com/kb/en/subdate/'),(509,'SUBTIME',31,'Syntax\n------ \nSUBTIME(expr1,expr2)\n \nDescription\n----------- \nSUBTIME() returns expr1 - expr2 expressed as a value in the\nsame\nformat as expr1. expr1 is a time or datetime expression, and\nexpr2 is\na time expression.\n \nExamples\n-------- \nSELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1\n1:1:1.000002\');\n+--------------------------------------------------------+\n| SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\')\n|\n+--------------------------------------------------------+\n| 2007-12-30 22:58:58.999997 |\n+--------------------------------------------------------+\n \nSELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n+-----------------------------------------------+\n| SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\') |\n+-----------------------------------------------+\n| -00:59:59.999999 |\n+-----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/subtime/','','https://mariadb.com/kb/en/subtime/'),(510,'SYSDATE',31,'Syntax\n------ \nSYSDATE([precision])\n \nDescription\n----------- \nReturns the current date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is\nused in a string or numeric context.\n \nThe optional precision determines the microsecond precision.\nSee Microseconds in MariaDB.\n \nSYSDATE() returns the time at which it executes. This\ndiffers from the\nbehavior for NOW(), which returns a constant time that\nindicates the\ntime at which the statement began to execute. (Within a\nstored routine\nor trigger, NOW() returns the time at which the routine or\ntriggering\nstatement began to execute.)\n \nIn addition, changing the timestamp system variable with a\nSET timestamp statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp\nsettings in the\nbinary log have no effect on invocations of SYSDATE().\n \nBecause SYSDATE() can return different values even within\nthe same\nstatement, and is not affected by SET TIMESTAMP, it is\nnon-deterministic and therefore unsafe for replication if\nstatement-based binary logging is used. If that is a\nproblem, you can\nuse row-based logging, or start the server with the mysqld\noption --sysdate-is-now to cause SYSDATE() to be an alias\nfor NOW(). The non-deterministic nature of SYSDATE() also\nmeans that indexes cannot be used for evaluating expressions\nthat refer to it, and that statements using the SYSDATE()\nfunction are unsafe for statement-based replication.\n \nExamples\n-------- \nDifference between NOW() and SYSDATE():\n \nSELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2010-03-27 13:23:40 | 0 | 2010-03-27 13:23:40 |\n+---------------------+----------+---------------------+\n \nSELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2010-03-27 13:23:52 | 0 | 2010-03-27 13:23:54 |\n+---------------------+----------+---------------------+\n \nWith precision:\n \nSELECT SYSDATE(4);\n+--------------------------+\n| SYSDATE(4) |\n+--------------------------+\n| 2018-07-10 10:17:13.1689 |\n+--------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/sysdate/','','https://mariadb.com/kb/en/sysdate/'),(512,'TIMEDIFF',31,'Syntax\n------ \nTIMEDIFF(expr1,expr2)\n \nDescription\n----------- \nTIMEDIFF() returns expr1 - expr2 expressed as a time value.\nexpr1 and\nexpr2 are time or date-and-time expressions, but both must\nbe of the\nsame type.\n \nExamples\n-------- \nSELECT TIMEDIFF(\'2000:01:01 00:00:00\', \'2000:01:01\n00:00:00.000001\');\n+---------------------------------------------------------------+\n| TIMEDIFF(\'2000:01:01 00:00:00\', \'2000:01:01\n00:00:00.000001\') |\n+---------------------------------------------------------------+\n| -00:00:00.000001 |\n+---------------------------------------------------------------+\n \nSELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\', \'2008-12-30\n01:01:01.000002\');\n+----------------------------------------------------------------------+\n| TIMEDIFF(\'2008-12-31 23:59:59.000001\', \'2008-12-30\n01:01:01.000002\') |\n+----------------------------------------------------------------------+\n| 46:58:57.999999 |\n+----------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/timediff/','','https://mariadb.com/kb/en/timediff/'),(513,'TIMESTAMP FUNCTION',31,'Syntax\n------ \nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n \nDescription\n----------- \nWith a single argument, this function returns the date or\ndatetime\nexpression expr as a datetime value. With two arguments, it\nadds the\ntime expression expr2 to the date or datetime expression\nexpr1 and\nreturns the result as a datetime value.\n \nExamples\n-------- \nSELECT TIMESTAMP(\'2003-12-31\');\n+-------------------------+\n| TIMESTAMP(\'2003-12-31\') |\n+-------------------------+\n| 2003-12-31 00:00:00 |\n+-------------------------+\n \nSELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'6:30:00\');\n+--------------------------------------------+\n| TIMESTAMP(\'2003-12-31 12:00:00\',\'6:30:00\') |\n+--------------------------------------------+\n| 2003-12-31 18:30:00 |\n+--------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/timestamp-function/','','https://mariadb.com/kb/en/timestamp-function/'),(514,'TIMESTAMPADD',31,'Syntax\n------ \nTIMESTAMPADD(unit,interval,datetime_expr)\n \nDescription\n----------- \nAdds the integer expression interval to the date or datetime\nexpression datetime_expr. The unit for interval is given by\nthe unit\nargument, which should be one of the following values:\nMICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH,\nQUARTER, or YEAR.\n \nThe unit value may be specified using one of keywords as\nshown, or\nwith a prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY\nboth are\nlegal.\n \nBefore MariaDB 5.5, FRAC_SECOND was permitted as a synonym\nfor MICROSECOND.\n \nExamples\n-------- \nSELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n+-------------------------------------+\n| TIMESTAMPADD(MINUTE,1,\'2003-01-02\') |\n+-------------------------------------+\n| 2003-01-02 00:01:00 |\n+-------------------------------------+\n \nSELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n+-----------------------------------+\n| TIMESTAMPADD(WEEK,1,\'2003-01-02\') |\n+-----------------------------------+\n| 2003-01-09 |\n+-----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/timestampadd/','','https://mariadb.com/kb/en/timestampadd/'),(515,'TIMESTAMPDIFF',31,'Syntax\n------ \nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n \nDescription\n----------- \nReturns datetime_expr2 - datetime_expr1, where\ndatetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One\nexpression may be\na date and the other a datetime; a date value is treated as\na datetime\nhaving the time part \'00:00:00\' where necessary. The unit\nfor the\nresult (an integer) is given by the unit argument. The legal\nvalues\nfor unit are the same as those listed in the description of\nthe\nTIMESTAMPADD() function, i.e MICROSECOND, SECOND, MINUTE,\nHOUR, DAY, WEEK, MONTH, QUARTER, or YEAR.\n \nTIMESTAMPDIFF can also be used to calculate age.\n \nExamples\n-------- \nSELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n+------------------------------------------------+\n| TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\') |\n+------------------------------------------------+\n| 3 |\n+------------------------------------------------+\n \nSELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n+-----------------------------------------------+\n| TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\') |\n+-----------------------------------------------+\n| -1 |\n+-----------------------------------------------+\n \nSELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01\n12:05:55\');\n+----------------------------------------------------------+\n| TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01\n12:05:55\') |\n+----------------------------------------------------------+\n| 128885 |\n+----------------------------------------------------------+\n \nCalculating age:\n \nSELECT CURDATE();\n+------------+\n| CURDATE() |\n+------------+\n| 2019-05-27 |\n+------------+\n \nSELECT TIMESTAMPDIFF(YEAR, \'1971-06-06\', CURDATE()) AS\nage;\n \n+------+\n| age |\n+------+\n| 47 |\n+------+\n \nSELECT TIMESTAMPDIFF(YEAR, \'1971-05-06\', CURDATE()) AS\nage;\n \n+------+\n| age |\n+------+\n| 48 |\n+------+\n \nAge as of 2014-08-02:\n \nSELECT name, date_of_birth,\nTIMESTAMPDIFF(YEAR,date_of_birth,\'2014-08-02\') AS age \n FROM student_details;\n \n+---------+---------------+------+\n| name | date_of_birth | age |\n+---------+---------------+------+\n| Chun | 1993-12-31 | 20 |\n| Esben | 1946-01-01 | 68 |\n| Kaolin | 1996-07-16 | 18 |\n| Tatiana | 1988-04-13 | 26 |\n+---------+---------------+------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/timestampdiff/','','https://mariadb.com/kb/en/timestampdiff/'),(518,'TO_DAYS',31,'Syntax\n------ \nTO_DAYS(date)\n \nDescription\n----------- \nGiven a date date, returns the number of days since the\nstart of the current calendar (0000-00-00).\n \nThe function is not designed for use with dates before the\nadvent of the Gregorian calendar in October 1582. Results\nwill not be reliable since it doesn\'t account for the lost\ndays when the calendar changed from the Julian calendar.\n \nThis is the converse of the FROM_DAYS() function.\n \nExamples\n-------- \nSELECT TO_DAYS(\'2007-10-07\');\n+-----------------------+\n| TO_DAYS(\'2007-10-07\') |\n+-----------------------+\n| 733321 |\n+-----------------------+\n \nSELECT TO_DAYS(\'0000-01-01\');\n+-----------------------+\n| TO_DAYS(\'0000-01-01\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nSELECT TO_DAYS(950501);\n+-----------------+\n| TO_DAYS(950501) |\n+-----------------+\n| 728779 |\n+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/to_days/','','https://mariadb.com/kb/en/to_days/'),(519,'TO_SECONDS',31,'Syntax\n------ \nTO_SECONDS(expr)\n \nDescription\n----------- \nReturns the number of seconds from year 0 till expr, or NULL\nif expr is not a valid date or datetime.\n \nExamples\n-------- \nSELECT TO_SECONDS(\'2013-06-13\');\n+--------------------------+\n| TO_SECONDS(\'2013-06-13\') |\n+--------------------------+\n| 63538300800 |\n+--------------------------+\n \nSELECT TO_SECONDS(\'2013-06-13 21:45:13\');\n+-----------------------------------+\n| TO_SECONDS(\'2013-06-13 21:45:13\') |\n+-----------------------------------+\n| 63538379113 |\n+-----------------------------------+\n \nSELECT TO_SECONDS(NOW());\n+-------------------+\n| TO_SECONDS(NOW()) |\n+-------------------+\n| 63543530875 |\n+-------------------+\n \nSELECT TO_SECONDS(20130513);\n+----------------------+\n| TO_SECONDS(20130513) |\n+----------------------+\n| 63535622400 |\n+----------------------+\n1 row in set (0.00 sec)\n \nSELECT TO_SECONDS(130513);\n+--------------------+\n| TO_SECONDS(130513) |\n+--------------------+\n| 63535622400 |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/to_seconds/','','https://mariadb.com/kb/en/to_seconds/'),(520,'UNIX_TIMESTAMP',31,'Syntax\n------ \nUNIX_TIMESTAMP()\nUNIX_TIMESTAMP(date)\n \nDescription\n----------- \nIf called with no argument, returns a Unix timestamp\n(seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If\nUNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the\nargument as seconds\nsince \'1970-01-01 00:00:00\' UTC. date may be a DATE\nstring, a\nDATETIME string, a TIMESTAMP, or a number in\nthe format YYMMDD or YYYYMMDD. The server interprets date as\na value in the\ncurrent time zone and converts it to an internal value in\nUTC. Clients can set\ntheir time zone as described in time zones.\n \nThe inverse function of UNIX_TIMESTAMP() is FROM_UNIXTIME()\n \nUNIX_TIMESTAMP() supports microseconds.\n \nTimestamps in MariaDB have a maximum value of 2147483647,\nequivalent to 2038-01-19 05:14:07. This is due to the\nunderlying 32-bit limitation. Using the function on a date\nbeyond this will result in NULL being returned. Use DATETIME\nas a storage type if you require dates beyond this.\n \nError Handling\n \nReturns NULL for wrong arguments to UNIX_TIMESTAMP(). In\nMySQL and MariaDB before 5.3 wrong arguments to\nUNIX_TIMESTAMP() returned 0. \n \nCompatibility\n \nAs you can see in the examples above,\nUNIX_TIMESTAMP(constant-date-string) returns a timestamp\nwith 6 decimals while MariaDB 5.2 and before returns it\nwithout decimals. This can cause a problem if you are using\nUNIX_TIMESTAMP() as a partitioning function. You can fix\nthis by using FLOOR(UNIX_TIMESTAMP(..)) or changing the date\nstring to a date number, like 20080101000000. \n \nExamples\n-------- \nSELECT UNIX_TIMESTAMP();\n+------------------+\n| UNIX_TIMESTAMP() |\n+------------------+\n| 1269711082 |\n+------------------+\n \nSELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n+---------------------------------------+\n| UNIX_TIMESTAMP(\'2007-11-30 10:30:19\') |\n+---------------------------------------+\n| 1196436619.000000 |\n+---------------------------------------+\n \nSELECT UNIX_TIMESTAMP(\"2007-11-30 10:30:19.123456\");\n+----------------------------------------------+\n| unix_timestamp(\"2007-11-30 10:30:19.123456\") |\n+----------------------------------------------+\n| 1196411419.123456 |\n+----------------------------------------------+\n \nSELECT FROM_UNIXTIME(UNIX_TIMESTAMP(\'2007-11-30\n10:30:19\'));\n+------------------------------------------------------+\n| FROM_UNIXTIME(UNIX_TIMESTAMP(\'2007-11-30 10:30:19\')) |\n+------------------------------------------------------+\n| 2007-11-30 10:30:19.000000 |\n+------------------------------------------------------+\n \nSELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(\'2007-11-30\n10:30:19\')));\n+-------------------------------------------------------------+\n| FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(\'2007-11-30\n10:30:19\'))) |\n+-------------------------------------------------------------+\n| 2007-11-30 10:30:19 |\n+-------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/unix_timestamp/','','https://mariadb.com/kb/en/unix_timestamp/'),(523,'UTC_TIMESTAMP',31,'Syntax\n------ \nUTC_TIMESTAMP\nUTC_TIMESTAMP([precision])\n \nDescription\n----------- \nReturns the current UTC date and time as a value in\n\'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the\nfunction is used in a string or numeric context.\n \nThe optional precision determines the microsecond precision.\nSee Microseconds in MariaDB.\n \nExamples\n-------- \nSELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n \n+---------------------+-----------------------+\n| UTC_TIMESTAMP() | UTC_TIMESTAMP() + 0 |\n+---------------------+-----------------------+\n| 2010-03-27 17:33:16 | 20100327173316.000000 |\n+---------------------+-----------------------+\n \nWith precision:\n \nSELECT UTC_TIMESTAMP(4);\n+--------------------------+\n| UTC_TIMESTAMP(4) |\n+--------------------------+\n| 2018-07-10 07:51:09.1019 |\n+--------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/utc_timestamp/','','https://mariadb.com/kb/en/utc_timestamp/'),(524,'WEEK',31,'Syntax\n------ \nWEEK(date[,mode])\n \nDescription\n----------- \nThis function returns the week number for date. The\ntwo-argument form of\nWEEK() allows you to specify whether the week starts on\nSunday or Monday\nand whether the return value should be in the range from 0\nto 53 or from 1 to\n53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used.\n \nModes\n \nMode | 1st day of week | Range | Week 1 is the 1st week with\n| \n \n0 | Sunday | 0-53 | a Sunday in this year | \n \n1 | Monday | 0-53 | more than 3 days this year | \n \n2 | Sunday | 1-53 | a Sunday in this year | \n \n3 | Monday | 1-53 | more than 3 days this year | \n \n4 | Sunday | 0-53 | more than 3 days this year | \n \n5 | Monday | 0-53 | a Monday in this year | \n \n6 | Sunday | 1-53 | more than 3 days this year | \n \n7 | Monday | 1-53 | a Monday in this year | \n \nExamples\n-------- \nSELECT WEEK(\'2008-02-20\');\n+--------------------+\n| WEEK(\'2008-02-20\') |\n+--------------------+\n| 7 |\n+--------------------+\n \nSELECT WEEK(\'2008-02-20\',0);\n+----------------------+\n| WEEK(\'2008-02-20\',0) |\n+----------------------+\n| 7 |\n+----------------------+\n \nSELECT WEEK(\'2008-02-20\',1);\n+----------------------+\n| WEEK(\'2008-02-20\',1) |\n+----------------------+\n| 8 |\n+----------------------+\n \nSELECT WEEK(\'2008-12-31\',0);\n+----------------------+\n| WEEK(\'2008-12-31\',0) |\n+----------------------+\n| 52 |\n+----------------------+\n \nSELECT WEEK(\'2008-12-31\',1);\n+----------------------+\n| WEEK(\'2008-12-31\',1) |\n+----------------------+\n| 53 |\n+----------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d, WEEK(d,0), WEEK(d,1) from t1;\n \n+---------------------+-----------+-----------+\n| d | WEEK(d,0) | WEEK(d,1) |\n+---------------------+-----------+-----------+\n| 2007-01-30 21:31:07 | 4 | 5 |\n| 1983-10-15 06:42:51 | 41 | 41 |\n| 2011-04-21 12:34:56 | 16 | 16 |\n| 2011-10-30 06:31:41 | 44 | 43 |\n| 2011-01-30 14:03:25 | 5 | 4 |\n| 2004-10-07 11:19:34 | 40 | 41 |\n+---------------------+-----------+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/week/','','https://mariadb.com/kb/en/week/'),(525,'WEEKDAY',31,'Syntax\n------ \nWEEKDAY(date)\n \nDescription\n----------- \nReturns the weekday index for date \n(0 = Monday, 1 = Tuesday, ... 6 = Sunday).\n \nThis contrasts with DAYOFWEEK() which follows the ODBC\nstandard\n(1 = Sunday, 2 = Monday, ..., 7 = Saturday).\n \nExamples\n-------- \nSELECT WEEKDAY(\'2008-02-03 22:23:00\');\n+--------------------------------+\n| WEEKDAY(\'2008-02-03 22:23:00\') |\n+--------------------------------+\n| 6 |\n+--------------------------------+\n \nSELECT WEEKDAY(\'2007-11-06\');\n+-----------------------+\n| WEEKDAY(\'2007-11-06\') |\n+-----------------------+\n| 1 |\n+-----------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT d FROM t1 where WEEKDAY(d) = 6;\n \n+---------------------+\n| d |\n+---------------------+\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n+---------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/weekday/','','https://mariadb.com/kb/en/weekday/'),(526,'WEEKOFYEAR',31,'Syntax\n------ \nWEEKOFYEAR(date)\n \nDescription\n----------- \nReturns the calendar week of the date as a number in the\nrange from 1\nto 53. WEEKOFYEAR() is a compatibility function that is\nequivalent to\nWEEK(date,3).\n \nExamples\n-------- \nSELECT WEEKOFYEAR(\'2008-02-20\');\n+--------------------------+\n| WEEKOFYEAR(\'2008-02-20\') |\n+--------------------------+\n| 8 |\n+--------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \n select * from t1;\n \n+---------------------+\n| d |\n+---------------------+\n| 2007-01-30 21:31:07 |\n| 1983-10-15 06:42:51 |\n| 2011-04-21 12:34:56 |\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n| 2004-10-07 11:19:34 |\n+---------------------+\n \nSELECT d, WEEKOFYEAR(d), WEEK(d,3) from t1;\n \n+---------------------+---------------+-----------+\n| d | WEEKOFYEAR(d) | WEEK(d,3) |\n+---------------------+---------------+-----------+\n| 2007-01-30 21:31:07 | 5 | 5 |\n| 1983-10-15 06:42:51 | 41 | 41 |\n| 2011-04-21 12:34:56 | 16 | 16 |\n| 2011-10-30 06:31:41 | 43 | 43 |\n| 2011-01-30 14:03:25 | 4 | 4 |\n| 2004-10-07 11:19:34 | 41 | 41 |\n+---------------------+---------------+-----------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/weekofyear/','','https://mariadb.com/kb/en/weekofyear/'),(527,'YEAR',31,'Syntax\n------ \nYEAR(date)\n \nDescription\n----------- \nReturns the year for the given date, in the range 1000 to\n9999, or 0 for the\n\"zero\" date.\n \nExamples\n-------- \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT * FROM t1;\n \n+---------------------+\n| d |\n+---------------------+\n| 2007-01-30 21:31:07 |\n| 1983-10-15 06:42:51 |\n| 2011-04-21 12:34:56 |\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n| 2004-10-07 11:19:34 |\n+---------------------+\n \nSELECT * FROM t1 WHERE YEAR(d) = 2011;\n \n+---------------------+\n| d |\n+---------------------+\n| 2011-04-21 12:34:56 |\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n+---------------------+\n \nSELECT YEAR(\'1987-01-01\');\n+--------------------+\n| YEAR(\'1987-01-01\') |\n+--------------------+\n| 1987 |\n+--------------------+\n \n\n\nURL: https://mariadb.com/kb/en/year/','','https://mariadb.com/kb/en/year/'),(528,'YEARWEEK',31,'Syntax\n------ \nYEARWEEK(date), YEARWEEK(date,mode)\n \nDescription\n----------- \nReturns year and week for a date. The mode argument works\nexactly like the mode\nargument to WEEK(). The year in the result may be different\nfrom the\nyear in the date argument for the first and the last week of\nthe year.\n \nExamples\n-------- \nSELECT YEARWEEK(\'1987-01-01\');\n+------------------------+\n| YEARWEEK(\'1987-01-01\') |\n+------------------------+\n| 198652 |\n+------------------------+\n \nCREATE TABLE t1 (d DATETIME);\nINSERT INTO t1 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\n \nSELECT * FROM t1;\n \n+---------------------+\n| d |\n+---------------------+\n| 2007-01-30 21:31:07 |\n| 1983-10-15 06:42:51 |\n| 2011-04-21 12:34:56 |\n| 2011-10-30 06:31:41 |\n| 2011-01-30 14:03:25 |\n| 2004-10-07 11:19:34 |\n+---------------------+\n6 rows in set (0.02 sec)\n \nSELECT YEARWEEK(d) FROM t1 WHERE YEAR(d) = 2011;\n \n+-------------+\n| YEARWEEK(d) |\n+-------------+\n| 201116 |\n| 201144 |\n| 201105 |\n+-------------+\n3 rows in set (0.03 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/yearweek/','','https://mariadb.com/kb/en/yearweek/'),(529,'Well-Known Binary (WKB) Format',32,'WKB stands for Well-Known Binary, a format for representing\ngeographical and geometrical data.\n \nWKB uses 1-byte unsigned integers, 4-byte unsigned integers,\nand 8-byte double-precision numbers.\nThe first byte indicates the byte order. 00 for big endian,\nor 01 for little endian.\nThe next 4 bytes indicate the geometry type. Values from 1\nto 7 indicate whether the type is Point, LineString,\nPolygon, MultiPoint, MultiLineString, MultiPolygon, or\nGeometryCollection respectively. \nThe 8-byte floats represent the co-ordinates.\n \nTake the following example, a sequence of 21 bytes each\nrepresented by two hex digits:\n \n000000000140000000000000004010000000000000\nIt\'s big endian\n000000000140000000000000004010000000000000\n \nIt\'s a POINT\n000000000140000000000000004010000000000000\n \nThe X co-ordinate is 2.0\n000000000140000000000000004010000000000000\n \nThe Y-co-ordinate is 4.0\n000000000140000000000000004010000000000000\n \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/well-known-binary-wkb-format/','','https://mariadb.com/kb/en/well-known-binary-wkb-format/'),(534,'MPolyFromWKB',32,'Syntax\n------ \nMPolyFromWKB(wkb[,srid])\nMultiPolygonFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a MULTIPOLYGON value using its WKB representation\nand SRID.\n \nMPolyFromWKB() and MultiPolygonFromWKB() are synonyms.\n \nExamples\n-------- \nSET @g = ST_AsBinary(MPointFromText(\'MULTIPOLYGON(((28\n26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52\n18)),((59 18,67 18,67 13,59 13,59 18)))\'));\n \nSELECT ST_AsText(MPolyFromWKB(@g));\n+---------------------------------------------------------------------------------------------------------------+\n| ST_AsText(MPolyFromWKB(@g)) |\n+---------------------------------------------------------------------------------------------------------------+\n| MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66\n23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) |\n+---------------------------------------------------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/mpolyfromwkb/','','https://mariadb.com/kb/en/mpolyfromwkb/'),(549,'ST_GeomCollFromWKB',32,'Syntax\n------ \nST_GeomCollFromWKB(wkb[,srid])\nST_GeometryCollectionFromWKB(wkb[,srid])\nGeomCollFromWKB(wkb[,srid])\nGeometryCollectionFromWKB(wkb[,srid])\n \nDescription\n----------- \nConstructs a GEOMETRYCOLLECTION value using its WKB\nrepresentation and SRID.\n \nST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB(),\nGeomCollFromWKB() and GeometryCollectionFromWKB() are\nsynonyms.\n \nExamples\n-------- \nSET @g =\nST_AsBinary(ST_GeomFromText(\'GEOMETRYCOLLECTION(POLYGON((5\n5,10 5,10 10,5 5)),POINT(10 10))\'));\n \nSELECT ST_AsText(ST_GeomCollFromWKB(@g));\n+----------------------------------------------------------------+\n| ST_AsText(ST_GeomCollFromWKB(@g)) |\n+----------------------------------------------------------------+\n| GEOMETRYCOLLECTION(POLYGON((5 5,10 5,10 10,5 5)),POINT(10\n10)) |\n+----------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_geomcollfromwkb/','','https://mariadb.com/kb/en/st_geomcollfromwkb/'),(569,'ST_BOUNDARY',36,'The ST_BOUNDARY function was introduced in MariaDB 10.1.2\n \nSyntax\n------ \nST_BOUNDARY(g)\nBOUNDARY(g)\n \nDescription\n----------- \nReturns a geometry that is the closure of the combinatorial\nboundary of the geometry value g.\n \nBOUNDARY() is a synonym.\n \nExamples\n-------- \nSELECT ST_AsText(ST_Boundary(ST_GeomFromText(\'LINESTRING(3\n3,0 0, -3 3)\')));\n+----------------------------------------------------------------------+\n| ST_AsText(ST_Boundary(ST_GeomFromText(\'LINESTRING(3 3,0\n0, -3 3)\'))) |\n+----------------------------------------------------------------------+\n| MULTIPOINT(3 3,-3 3) |\n+----------------------------------------------------------------------+\n \nSELECT ST_AsText(ST_Boundary(ST_GeomFromText(\'POLYGON((3\n3,0 0, -3 3, 3 3))\')));\n+--------------------------------------------------------------------------+\n| ST_AsText(ST_Boundary(ST_GeomFromText(\'POLYGON((3 3,0 0,\n-3 3, 3 3))\'))) |\n+--------------------------------------------------------------------------+\n| LINESTRING(3 3,0 0,-3 3,3 3) |\n+--------------------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_boundary/','','https://mariadb.com/kb/en/st_boundary/'),(571,'ST_ENVELOPE',36,'Syntax\n------ \nST_ENVELOPE(g)\nENVELOPE(g)\n \nDescription\n----------- \nReturns the Minimum Bounding Rectangle (MBR) for the\ngeometry value g. The result is returned as a Polygon value.\n \nThe polygon is defined by the corner points of the bounding\nbox:\n \nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX\nMINY))\n \nST_ENVELOPE() and ENVELOPE() are synonyms.\n \nExamples\n-------- \nSELECT AsText(ST_ENVELOPE(GeomFromText(\'LineString(1 1,4\n4)\')));\n+----------------------------------------------------------+\n| AsText(ST_ENVELOPE(GeomFromText(\'LineString(1 1,4 4)\')))\n|\n+----------------------------------------------------------+\n| POLYGON((1 1,4 1,4 4,1 4,1 1)) |\n+----------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_envelope/','','https://mariadb.com/kb/en/st_envelope/'),(574,'ST_ISCLOSED',36,'Syntax\n------ \nST_IsClosed(g)\nIsClosed(g)\n \nDescription\n----------- \nReturns 1 if a given LINESTRING\'s start and end points are\nthe same, or 0 if they are not the same. Before MariaDB\n10.1.5, returns NULL if not given a LINESTRING. After\nMariaDB 10.1.5, returns -1.\n \nST_IsClosed() and IsClosed() are synonyms.\n \nExamples\n-------- \nSET @ls = \'LineString(0 0, 0 4, 4 4, 0 0)\';\n \nSELECT ST_ISCLOSED(GEOMFROMTEXT(@ls));\n+--------------------------------+\n| ST_ISCLOSED(GEOMFROMTEXT(@ls)) |\n+--------------------------------+\n| 1 |\n+--------------------------------+\n \nSET @ls = \'LineString(0 0, 0 4, 4 4, 0 1)\';\n \nSELECT ST_ISCLOSED(GEOMFROMTEXT(@ls));\n+--------------------------------+\n| ST_ISCLOSED(GEOMFROMTEXT(@ls)) |\n+--------------------------------+\n| 0 |\n+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/st_isclosed/','','https://mariadb.com/kb/en/st_isclosed/'),(583,'BINARY Operator',37,'Syntax\n------ \nBINARY\n \nDescription\n----------- \nThe BINARY operator casts the string following it to a\nbinary string. This is an easy way to force a column\ncomparison to be done byte by byte rather than character by\ncharacter. This causes the comparison to be case sensitive\neven if the column isn\'t defined as BINARY or BLOB. \n \nBINARY also causes trailing spaces to be significant.\n \nExamples\n-------- \nSELECT \'a\' = \'A\';\n \n+-----------+\n| \'a\' = \'A\' |\n+-----------+\n| 1 |\n+-----------+\n \nSELECT BINARY \'a\' = \'A\';\n \n+------------------+\n| BINARY \'a\' = \'A\' |\n+------------------+\n| 0 |\n+------------------+\n \nSELECT \'a\' = \'a \';\n \n+------------+\n| \'a\' = \'a \' |\n+------------+\n| 1 |\n+------------+\n \nSELECT BINARY \'a\' = \'a \';\n \n+-------------------+\n| BINARY \'a\' = \'a \' |\n+-------------------+\n| 0 |\n+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/binary-operator/','','https://mariadb.com/kb/en/binary-operator/'),(585,'CAST',37,'Syntax\n------ \nCAST(expr AS type)\n \nDescription\n----------- \nThe CAST() function takes a value of one type and produces a\nvalue of another type, similar to the CONVERT() function.\nFor more information, see the description of CONVERT(). \n \nThe main difference between the CAST() and CONVERT() is that\nCONVERT(expr,type) is ODBC syntax while CAST(expr as type)\nand CONVERT(... USING ...) are SQL92 syntax.\n \nIn MariaDB 10.4 and later, you can use the CAST() function\nwith the INTERVAL keyword.\n \nUntil MariaDB 5.5.31, X\'HHHH\', the standard SQL syntax for\nbinary string literals, erroneously worked in the same way\nas 0xHHHH. In 5.5.31 it was intentionally changed to behave\nas a string in all contexts (and never as a number).\n \nThis introduces an incompatibility with previous versions of\nMariaDB, and all versions of MySQL (see the example below). \n \nExamples\n-------- \nSimple casts:\n \nSELECT CAST(\"abc\" AS BINARY);\nSELECT CAST(\"1\" AS UNSIGNED INTEGER);\nSELECT CAST(123 AS CHAR CHARACTER SET utf8)\n \nNote that when one casts to CHAR without specifying the\ncharacter set, the collation_connection character set\ncollation will be used. When used with CHAR CHARACTER SET,\nthe default collation for that character set will be used.\n \nSELECT COLLATION(CAST(123 AS CHAR));\n+------------------------------+\n| COLLATION(CAST(123 AS CHAR)) |\n+------------------------------+\n| latin1_swedish_ci |\n+------------------------------+\n \nSELECT COLLATION(CAST(123 AS CHAR CHARACTER SET utf8));\n+-------------------------------------------------+\n| COLLATION(CAST(123 AS CHAR CHARACTER SET utf8)) |\n+-------------------------------------------------+\n| utf8_general_ci |\n+-------------------------------------------------+\n \nIf you also want to change the collation, you have to use\nthe COLLATE operator:\n \nSELECT COLLATION(CAST(123 AS CHAR CHARACTER SET utf8) \n COLLATE utf8_unicode_ci);\n+-------------------------------------------------------------------------+\n| COLLATION(CAST(123 AS CHAR CHARACTER SET utf8) COLLATE\nutf8_unicode_ci) |\n+-------------------------------------------------------------------------+\n| utf8_unicode_ci |\n+-------------------------------------------------------------------------+\n \nUsing CAST() to order an ENUM field as a CHAR rather than\nthe internal numerical value:\n \nCREATE TABLE enum_list (enum_field enum(\'c\',\'a\',\'b\'));\n \nINSERT INTO enum_list (enum_field) \nVALUES(\'c\'),(\'a\'),(\'c\'),(\'b\');\n \nSELECT * FROM enum_list \nORDER BY enum_field;\n \n+------------+\n| enum_field |\n+------------+\n| c |\n| c |\n| a |\n| b |\n+------------+\n \nSELECT * FROM enum_list \nORDER BY CAST(enum_field AS CHAR);\n+------------+\n| enum_field |\n+------------+\n| a |\n| b |\n| c |\n| c |\n+------------+\n \nFrom MariaDB 5.5.31, the following will trigger warnings,\nsince x\'aa\' and \'X\'aa\' no longer behave as a number.\nPreviously, and in all versions of MySQL, no warnings are\ntriggered since they did erroneously behave as a number:\n \nSELECT CAST(0xAA AS UNSIGNED), CAST(x\'aa\' AS UNSIGNED),\nCAST(X\'aa\' AS UNSIGNED);\n+------------------------+-------------------------+-------------------------+\n| CAST(0xAA AS UNSIGNED) | CAST(x\'aa\' AS UNSIGNED) |\nCAST(X\'aa\' AS UNSIGNED) |\n+------------------------+-------------------------+-------------------------+\n| 170 | 0 | 0 |\n+------------------------+-------------------------+-------------------------+\n1 row in set, 2 warnings (0.00 sec)\n \nWarning (Code 1292): Truncated incorrect INTEGER value:\n\'\\xAA\'\nWarning (Code 1292): Truncated incorrect INTEGER value:\n\'\\xAA\'\n \nCasting to intervals:\n \nSELECT CAST(2019-01-04 INTERVAL AS DAY_SECOND(2)) AS\n\"Cast\";\n \n+-------------+\n| Cast |\n+-------------+\n| 00:20:17.00 |\n+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/cast/','','https://mariadb.com/kb/en/cast/'),(586,'CHAR Function',37,'Syntax\n------ \nCHAR(N,... [USING charset_name])\n \nDescription\n----------- \nCHAR() interprets each argument as an INT and returns a\nstring consisting of the characters given by the code values\nof those integers. NULL values are skipped. By default,\nCHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n \nSELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n \nIf USING is given and the result string is illegal for the\ngiven character set, a warning is issued. Also, if strict\nSQL mode is enabled, the result from CHAR() becomes NULL.\n \nExamples\n-------- \nSELECT CHAR(77,97,114,\'105\',97,\'68\',66);\n+----------------------------------+\n| CHAR(77,97,114,\'105\',97,\'68\',66) |\n+----------------------------------+\n| MariaDB |\n+----------------------------------+\n \nSELECT CHAR(77,77.3,\'77.3\');\n+----------------------+\n| CHAR(77,77.3,\'77.3\') |\n+----------------------+\n| MMM |\n+----------------------+\n1 row in set, 1 warning (0.00 sec)\n \nWarning (Code 1292): Truncated incorrect INTEGER value:\n\'77.3\'\n \n\n\nURL: https://mariadb.com/kb/en/char-function/','','https://mariadb.com/kb/en/char-function/'),(588,'CHAR_LENGTH',37,'Syntax\n------ \nCHAR_LENGTH(str)\n \nDescription\n----------- \nReturns the length of the given string argument, measured in\ncharacters. A multi-byte character counts as a single\ncharacter. This means that for a string containing five\ntwo-byte characters, LENGTH() (or OCTET_LENGTH() in Oracle\nmode) returns 10, whereas CHAR_LENGTH() returns 5. If the\nargument is NULL, it returns NULL. \n \nIf the argument is not a string value, it is converted into\na string.\n \nIt is synonymous with the CHARACTER_LENGTH() function.\n \nUntil MariaDB 10.3.1, returns MYSQL_TYPE_LONGLONG, or\nbigint(10), in all cases. From MariaDB 10.3.1, returns\nMYSQL_TYPE_LONG, or int(10), when the result would fit\nwithin 32-bits.\n \nExamples\n-------- \nSELECT CHAR_LENGTH(\'MariaDB\');\n+------------------------+\n| CHAR_LENGTH(\'MariaDB\') |\n+------------------------+\n| 7 |\n+------------------------+\n \nSELECT CHAR_LENGTH(\'π\');\n+-------------------+\n| CHAR_LENGTH(\'π\') |\n+-------------------+\n| 1 |\n+-------------------+\n \n\n\nURL: https://mariadb.com/kb/en/char_length/','','https://mariadb.com/kb/en/char_length/'),(589,'CHR',37,'The CHR() function was introduced in MariaDB 10.3.1 to\nprovide Oracle compatibility\n \nSyntax\n------ \nCHR(N)\n \nDescription\n----------- \nCHR() interprets each argument N as an integer and returns a\nVARCHAR(1) string consisting of the character given by the\ncode values of the integer. The character set and collation\nof the string are set according to the values of the\ncharacter_set_database and collation_database system\nvariables.\n \nCHR() is similar to the CHAR() function, but only accepts a\nsingle argument.\n \nCHR() is available in all sql_modes.\n \nExamples\n-------- \nSELECT CHR(67);\n+---------+\n| CHR(67) |\n+---------+\n| C |\n+---------+\n \nSELECT CHR(\'67\');\n+-----------+\n| CHR(\'67\') |\n+-----------+\n| C |\n+-----------+\n \nSELECT CHR(\'C\');\n+----------+\n| CHR(\'C\') |\n+----------+\n| |\n+----------+\n1 row in set, 1 warning (0.000 sec)\n \nSHOW WARNINGS;\n \n+---------+------+----------------------------------------+\n| Level | Code | Message |\n+---------+------+----------------------------------------+\n| Warning | 1292 | Truncated incorrect INTEGER value: \'C\'\n|\n+---------+------+----------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/chr/','','https://mariadb.com/kb/en/chr/'),(590,'CONCAT',37,'Syntax\n------ \nCONCAT(str1,str2,...)\n \nDescription\n----------- \nReturns the string that results from concatenating the\narguments. May have one or more arguments. If all arguments\nare non-binary strings, the result is a non-binary string.\nIf the arguments include any binary strings, the result is a\nbinary string. A numeric argument is converted to its\nequivalent binary string form; if you want to avoid that,\nyou can use an explicit type cast, as in this example:\n \nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n \nCONCAT() returns NULL if any argument is NULL.\n \nA NULL parameter hides all information contained in other\nparameters from the result. Sometimes this is not desirable;\nto avoid this, you can:\nUse the CONCAT_WS() function with an empty separator,\nbecause that function is NULL-safe.\nUse IFNULL() to turn NULLs into empty strings.\n \nOracle Mode\n \nIn Oracle mode from MariaDB 10.3, CONCAT ignores NULL.\n \nExamples\n-------- \nSELECT CONCAT(\'Ma\', \'ria\', \'DB\');\n+---------------------------+\n| CONCAT(\'Ma\', \'ria\', \'DB\') |\n+---------------------------+\n| MariaDB |\n+---------------------------+\n \nSELECT CONCAT(\'Ma\', \'ria\', NULL, \'DB\');\n+---------------------------------+\n| CONCAT(\'Ma\', \'ria\', NULL, \'DB\') |\n+---------------------------------+\n| NULL |\n+---------------------------------+\n \nSELECT CONCAT(42.0);\n+--------------+\n| CONCAT(42.0) |\n+--------------+\n| 42.0 |\n+--------------+\n \nUsing IFNULL() to handle NULLs:\n \nSELECT CONCAT(\'The value of @v is: \', IFNULL(@v, \'\'));\n+------------------------------------------------+\n| CONCAT(\'The value of @v is: \', IFNULL(@v, \'\')) |\n+------------------------------------------------+\n| The value of @v is: |\n+------------------------------------------------+\n \nIn Oracle mode, from MariaDB 10.3:\n \nSELECT CONCAT(\'Ma\', \'ria\', NULL, \'DB\');\n+---------------------------------+\n| CONCAT(\'Ma\', \'ria\', NULL, \'DB\') |\n+---------------------------------+\n| MariaDB |\n+---------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/concat/','','https://mariadb.com/kb/en/concat/'),(591,'CONCAT_WS',37,'Syntax\n------ \nCONCAT_WS(separator,str1,str2,...)\n \nDescription\n----------- \nCONCAT_WS() stands for Concatenate With Separator and is a\nspecial form of CONCAT(). The first argument is the\nseparator for the rest of the arguments. The separator is\nadded between the strings to be concatenated. The separator\ncan be a string, as can the rest of the arguments.\n \nIf the separator is NULL, the result is NULL; all other NULL\nvalues are skipped. This makes CONCAT_WS() suitable when you\nwant to concatenate some values and avoid losing all\ninformation if one of them is NULL.\n \nExamples\n-------- \nSELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last\nName\');\n+-------------------------------------------------------+\n| CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last\nName\') |\n+-------------------------------------------------------+\n| First name,Second name,Last Name |\n+-------------------------------------------------------+\n \nSELECT CONCAT_WS(\'-\',\'Floor\',NULL,\'Room\');\n+------------------------------------+\n| CONCAT_WS(\'-\',\'Floor\',NULL,\'Room\') |\n+------------------------------------+\n| Floor-Room |\n+------------------------------------+\n \nIn some cases, remember to include a space in the separator\nstring:\n \nSET @a = \'gnu\', @b = \'penguin\', @c = \'sea lion\';\n \nQuery OK, 0 rows affected (0.00 sec)\n \nSELECT CONCAT_WS(\', \', @a, @b, @c);\n+-----------------------------+\n| CONCAT_WS(\', \', @a, @b, @c) |\n+-----------------------------+\n| gnu, penguin, sea lion |\n+-----------------------------+\n \nUsing CONCAT_WS() to handle NULLs:\n \nSET @a = \'a\', @b = NULL, @c = \'c\';\n \nSELECT CONCAT_WS(\'\', @a, @b, @c);\n+---------------------------+\n| CONCAT_WS(\'\', @a, @b, @c) |\n+---------------------------+\n| ac |\n+---------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/concat_ws/','','https://mariadb.com/kb/en/concat_ws/'),(592,'CONVERT',37,'Syntax\n------ \nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n \nDescription\n----------- \nThe CONVERT() and CAST() functions take a value of one type\nand produce a value of another type.\n \nThe type can be one of the following values:\nBINARY\nCHAR\nDATE\nDATETIME \nDECIMAL[(M[,D])]\nDOUBLE \nFLOAT — From MariaDB 10.4.5\nINTEGER \nShort for SIGNED INTEGER\n \nSIGNED [INTEGER]\nTIME \nUNSIGNED [INTEGER]\n \nNote that in MariaDB, INT and INTEGER are the same thing.\n \nBINARY produces a string with the BINARY data type. If the\noptional length is given, BINARY(N) causes the cast to use\nno more than N bytes of the argument. Values shorter than\nthe given number in bytes are padded with 0x00 bytes to make\nthem equal the length value.\n \nCHAR(N) causes the cast to use no more than the number of\ncharacters given in the argument.\n \nThe main difference between the CAST() and CONVERT() is that\nCONVERT(expr,type) is ODBC syntax while CAST(expr as type)\nand CONVERT(... USING ...) are SQL92 syntax.\n \nCONVERT() with USING is used to convert data between\ndifferent character sets. In MariaDB, transcoding names are\nthe same as the\ncorresponding character set names. For example, this\nstatement\nconverts the string \'abc\' in the default character set to\nthe\ncorresponding string in the utf8 character set:\n \nSELECT CONVERT(\'abc\' USING utf8);\n \nExamples\n-------- \nSELECT enum_col FROM tbl_name \nORDER BY CAST(enum_col AS CHAR);\n \nConverting a BINARY to string to permit the LOWER function\nto work:\n \nSET @x = \'AardVark\';\n \nSET @x = BINARY \'AardVark\';\n \nSELECT LOWER(@x), LOWER(CONVERT (@x USING latin1));\n+-----------+----------------------------------+\n| LOWER(@x) | LOWER(CONVERT (@x USING latin1)) |\n+-----------+----------------------------------+\n| AardVark | aardvark |\n+-----------+----------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/convert/','','https://mariadb.com/kb/en/convert/'),(593,'ELT',37,'Syntax\n------ \nELT(N, str1[, str2, str3,...])\n \nDescription\n----------- \nTakes a numeric argument and a series of string arguments.\nReturns the string that corresponds to the given numeric\nposition. For instance, it returns str1 if N is 1, str2 if N\nis 2, and so on. If the numeric argument is a FLOAT, MariaDB\nrounds it to the nearest INTEGER. If the numeric argument is\nless than 1, greater than the total number of arguments, or\nnot a number, ELT() returns NULL. It must have at least two\narguments.\n \nIt is complementary to the FIELD() function.\n \nExamples\n-------- \nSELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n+------------------------------------+\n| ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\') |\n+------------------------------------+\n| ej |\n+------------------------------------+\n \nSELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n+------------------------------------+\n| ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\') |\n+------------------------------------+\n| foo |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/elt/','','https://mariadb.com/kb/en/elt/'),(594,'EXPORT_SET',37,'Syntax\n------ \nEXPORT_SET(bits, on, off[, separator[, number_of_bits]])\n \nDescription\n----------- \nTakes a minimum of three arguments. Returns a string where\neach bit in the given bits argument is returned, with the\nstring values given for on and off. \n \nBits are examined from right to left, (from low-order to\nhigh-order bits). Strings are added to the result from left\nto right, separated by a separator string (defaults as\n\',\'). You can optionally limit the number of bits the\nEXPORT_SET() function examines using the number_of_bits\noption. \n \nIf any of the arguments are set as NULL, the function\nreturns NULL.\n \nExamples\n-------- \nSELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n+-----------------------------+\n| EXPORT_SET(5,\'Y\',\'N\',\',\',4) |\n+-----------------------------+\n| Y,N,Y,N |\n+-----------------------------+\n \nSELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n+------------------------------+\n| EXPORT_SET(6,\'1\',\'0\',\',\',10) |\n+------------------------------+\n| 0,1,1,0,0,0,0,0,0,0 |\n+------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/export_set/','','https://mariadb.com/kb/en/export_set/'),(596,'FIELD',37,'Syntax\n------ \nFIELD(pattern, str1[,str2,...])\n \nDescription\n----------- \nReturns the index position of the string or number matching\nthe given pattern. Returns 0 in the event that none of the\narguments match the pattern. Raises an Error 1582 if not\ngiven at least two arguments.\n \nWhen all arguments given to the FIELD() function are\nstrings, they are treated as case-insensitive. When all the\narguments are numbers, they are treated as numbers.\nOtherwise, they are treated as doubles. \n \nIf the given pattern occurs more than once, the FIELD()\nfunction only returns the index of the first instance. If\nthe given pattern is NULL, the function returns 0, as a NULL\npattern always fails to match.\n \nThis function is complementary to the ELT() function.\n \nExamples\n-------- \nSELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\',\n\'foo\') \n AS \'Field Results\';\n \n+---------------+\n| Field Results | \n+---------------+\n| 2 |\n+---------------+\n \nSELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\',\n\'foo\')\n AS \'Field Results\';\n \n+---------------+\n| Field Results | \n+---------------+\n| 0 |\n+---------------+\n \nSELECT FIELD(1, 2, 3, 4, 5, 1) AS \'Field Results\';\n \n+---------------+\n| Field Results |\n+---------------+\n| 5 |\n+---------------+\n \nSELECT FIELD(NULL, 2, 3) AS \'Field Results\';\n \n+---------------+\n| Field Results |\n+---------------+\n| 0 |\n+---------------+\n \nSELECT FIELD(\'fail\') AS \'Field Results\';\n \nError 1582 (42000): Incorrect parameter count in call\nto native function \'field\'\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/field/','','https://mariadb.com/kb/en/field/'),(595,'EXTRACTVALUE',37,'Syntax\n------ \nEXTRACTVALUE(xml_frag, xpath_expr)\n \nDescription\n----------- \nThe EXTRACTVALUE() function takes two string arguments: a\nfragment of XML markup and an XPath expression, (also known\nas a locator). It returns the text (That is, CDDATA), of the\nfirst text node which is a child of the element or elements\nmatching the XPath expression. \n \nIn cases where a valid XPath expression does not match any\ntext nodes in a valid XML fragment, (including the implicit\n/text() expression), the EXTRACTVALUE() function returns an\nempty string.\n \nInvalid Arguments\n \nWhen either the XML fragment or the XPath expression is\nNULL, the EXTRACTVALUE() function returns NULL. When the XML\nfragment is invalid, it raises a warning Code 1525:\n \nWarning (Code 1525): Incorrect XML value: \'parse error at\nline 1 pos 11: unexpected END-OF-INPUT\'\n \nWhen the XPath value is invalid, it generates an Error 1105:\n \nERROR 1105 (HY000): XPATH syntax error: \')\'\n \nExplicit text() Expressions\n \nThis function is the equivalent of performing a match using\nthe XPath expression after appending /text(). In other\nwords:\n \nSELECT\n EXTRACTVALUE(\'example\', \'/cases/case\') AS \'Base\nExample\',\n EXTRACTVALUE(\'example\', \'/cases/case/text()\') AS\n\'text() Example\';\n \n+--------------+----------------+\n| Base Example | text() Example |\n+--------------+----------------+\n| example | example |\n+--------------+----------------+\n \nCount Matches\n \nWhen EXTRACTVALUE() returns multiple matches, it returns the\ncontent of the first child text node of each matching\nelement, in the matched order, as a single, space-delimited\nstring.\n \nBy design, the EXTRACTVALUE() function makes no distinction\nbetween a match on an empty element and no match at all. If\nyou need to determine whether no matching element was found\nin the XML fragment or if an element was found that\ncontained no child text nodes, use the XPath count()\nfunction. \n \nFor instance, when looking for a value that exists, but\ncontains no child text nodes, you would get a count of the\nnumber of matching instances:\n \nSELECT\n EXTRACTVALUE(\'\', \'/cases/case\') AS \'Empty Example\',\n EXTRACTVALUE(\'\', \'/cases/case/count()\') AS \'count()\nExample\';\n \n+---------------+-----------------+\n| Empty Example | count() Example |\n+---------------+-----------------+\n| | 1 |\n+---------------+-----------------+\n \nAlternatively, when looking for a value that doesn\'t exist,\ncount() returns 0.\n \nSELECT\n EXTRACTVALUE(\'\', \'/cases/person\') AS \'No Match\nExample\',\n EXTRACTVALUE(\'\', \'/cases/person/count()\') AS \'count()\nExample\';\n \n+------------------+-----------------+\n| No Match Example | count() Example |\n+------------------+-----------------+\n| | 0|\n+------------------+-----------------+\n \nMatches\n \nImportant: The EXTRACTVALUE() function only returns CDDATA.\nIt does not return tags that the element might contain or\nthe text that these child elements contain.\n \nSELECT EXTRACTVALUE(\'Personx@example.com\', \'/cases\') AS\nCase;\n \n+--------+\n| Case |\n+--------+\n| Person |\n+--------+\n \nNote, in the above example, while the XPath expression\nmatches to the parent instance, it does not return the\ncontained tag or its content.\n \nExamples\n-------- \nSELECT\n ExtractValue(\'cccddd\', \'/a\') AS val1,\n ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n ExtractValue(\'cccddd\', \'//b\') AS val3,\n ExtractValue(\'cccddd\', \'/b\') AS val4,\n ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n \n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/extractvalue/','','https://mariadb.com/kb/en/extractvalue/'),(597,'FIND_IN_SET',37,'Syntax\n------ \nFIND_IN_SET(pattern, strlist)\n \nDescription\n----------- \nReturns the index position where the given pattern occurs in\na string list. The first argument is the pattern you want to\nsearch for. The second argument is a string containing\ncomma-separated variables. If the second argument is of the\nSET data-type, the function is optimized to use bit\narithmetic.\n \nIf the pattern does not occur in the string list or if the\nstring list is an empty string, the function returns 0. If\neither argument is NULL, the function returns NULL. The\nfunction does not return the correct result if the pattern\ncontains a comma (\",\") character.\n \nExamples\n-------- \nSELECT FIND_IN_SET(\'b\',\'a,b,c,d\') AS \"Found Results\";\n \n+---------------+\n| Found Results |\n+---------------+\n| 2 |\n+---------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/find_in_set/','','https://mariadb.com/kb/en/find_in_set/'),(598,'FORMAT',37,'Syntax\n------ \nFORMAT(num, decimal_position[, locale])\n \nDescription\n----------- \nFormats the given number for display as a string, adding\nseparators to appropriate position and rounding the results\nto the given decimal position. For instance, it would format\n15233.345 to 15,233.35.\n \nIf the given decimal position is 0, it rounds to return no\ndecimal point or fractional part. You can optionally specify\na locale value to format numbers to the pattern appropriate\nfor the given region.\n \nExamples\n-------- \nSELECT FORMAT(1234567890.09876543210, 4) AS \'Format\';\n \n+--------------------+\n| Format |\n+--------------------+\n| 1,234,567,890.0988 |\n+--------------------+\n \nSELECT FORMAT(1234567.89, 4) AS \'Format\';\n \n+----------------+\n| Format |\n+----------------+\n| 1,234,567.8900 |\n+----------------+\n \nSELECT FORMAT(1234567.89, 0) AS \'Format\';\n \n+-----------+\n| Format |\n+-----------+\n| 1,234,568 |\n+-----------+\n \nSELECT FORMAT(123456789,2,\'rm_CH\') AS \'Format\';\n \n+----------------+\n| Format |\n+----------------+\n| 123\'456\'789,00 |\n+----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/format/','','https://mariadb.com/kb/en/format/'),(599,'FROM_BASE64',37,'The FROM_BASE64() function was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nFROM_BASE64(str)\n \nDescription\n----------- \nDecodes the given base-64 encode string, returning the\nresult as a binary string. Returns NULL if the given string\nis NULL or if it\'s invalid.\n \nIt is the reverse of the TO_BASE64 function.\n \nThere are numerous methods to base-64 encode a string.\nMariaDB uses the following:\nIt encodes alphabet value 64 as \'+\'.\nIt encodes alphabet value 63 as \'/\'.\nIt codes output in groups of four printable characters. Each\nthree byte of data encoded uses four characters. If the\nfinal group is incomplete, it pads the difference with the\n\'=\' character.\nIt divides long output, adding a new line very 76\ncharacters.\nIn decoding, it recognizes and ignores newlines, carriage\nreturns, tabs and space whitespace characters.\n \nSELECT TO_BASE64(\'Maria\') AS \'Input\';\n \n+-----------+\n| Input |\n+-----------+\n| TWFyaWE= |\n+-----------+\n \nSELECT FROM_BASE64(\'TWFyaWE=\') AS \'Output\';\n \n+--------+\n| Output |\n+--------+\n| Maria |\n+--------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/from_base64/','','https://mariadb.com/kb/en/from_base64/'),(600,'HEX',37,'Syntax\n------ \nHEX(N_or_S)\n \nDescription\n----------- \nIf N_or_S is a number, returns a string representation of\nthe hexadecimal\nvalue of N, where N is a longlong (BIGINT) number. This is\nequivalent to CONV(N,10,16).\n \nIf N_or_S is a string, returns a hexadecimal string\nrepresentation of\nN_or_S where each byte of each character in N_or_S is\nconverted to two hexadecimal\ndigits. If N_or_S is NULL, returns NULL. The inverse of this\noperation is performed by the UNHEX()\nfunction.\n \nExamples\n-------- \nSELECT HEX(255);\n+----------+\n| HEX(255) |\n+----------+\n| FF |\n+----------+\n \nSELECT 0x4D617269614442;\n \n+------------------+\n| 0x4D617269614442 |\n+------------------+\n| MariaDB |\n+------------------+\n \nSELECT HEX(\'MariaDB\');\n+----------------+\n| HEX(\'MariaDB\') |\n+----------------+\n| 4D617269614442 |\n+----------------+\n \n\n\nURL: https://mariadb.com/kb/en/hex/','','https://mariadb.com/kb/en/hex/'),(601,'INSERT Function',37,'Syntax\n------ \nINSERT(str,pos,len,newstr)\n \nDescription\n----------- \nReturns the string str, with the substring beginning at\nposition pos\nand len characters long replaced by the string newstr.\nReturns the\noriginal string if pos is not within the length of the\nstring.\nReplaces the rest of the string from position pos if len is\nnot within\nthe length of the rest of the string. Returns NULL if any\nargument is\nNULL.\n \nExamples\n-------- \nSELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n+-----------------------------------+\n| INSERT(\'Quadratic\', 3, 4, \'What\') |\n+-----------------------------------+\n| QuWhattic |\n+-----------------------------------+\n \nSELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n+------------------------------------+\n| INSERT(\'Quadratic\', -1, 4, \'What\') |\n+------------------------------------+\n| Quadratic |\n+------------------------------------+\n \nSELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n+-------------------------------------+\n| INSERT(\'Quadratic\', 3, 100, \'What\') |\n+-------------------------------------+\n| QuWhat |\n+-------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/insert-function/','','https://mariadb.com/kb/en/insert-function/'),(605,'LENGTH',37,'Syntax\n------ \nLENGTH(str)\n \nDescription\n----------- \nReturns the length of the string str, measured in bytes. A\nmulti-byte\ncharacter counts as multiple bytes. This means that for a\nstring\ncontaining five two-byte characters, LENGTH() returns 10,\nwhereas\nCHAR_LENGTH() returns 5. \n \nIf str is not a string value, it is converted into a string.\nIf str is NULL, the function returns NULL.\n \nUntil MariaDB 10.3.1, returns MYSQL_TYPE_LONGLONG, or\nbigint(10), in all cases. From MariaDB 10.3.1, returns\nMYSQL_TYPE_LONG, or int(10), when the result would fit\nwithin 32-bits.\n \nOracle Mode\n \nWhen running Oracle mode from MariaDB 10.3, LENGTH() is a\nsynonym for CHAR_LENGTH().\n \nExamples\n-------- \nSELECT LENGTH(\'MariaDB\');\n+-------------------+\n| LENGTH(\'MariaDB\') |\n+-------------------+\n| 7 |\n+-------------------+\n \nSELECT LENGTH(\'π\');\n+--------------+\n| LENGTH(\'π\') |\n+--------------+\n| 2 |\n+--------------+\n \nIn Oracle mode from MariaDB 10.3:\n \nSELECT LENGTH(\'π\');\n+--------------+\n| LENGTH(\'π\') |\n+--------------+\n| 1 |\n+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/length/','','https://mariadb.com/kb/en/length/'),(608,'LOAD_FILE',37,'Syntax\n------ \nLOAD_FILE(file_name)\n \nDescription\n----------- \nReads the file and returns the file contents as a string. To\nuse this function, the file must be located on the server\nhost, you must specify the full path name to the file, and\nyou must have the FILE privilege. The file must be readable\nby all and it must be less than the size, in bytes, of the\nmax_allowed_packet system variable. If the secure_file_priv\nsystem variable is set to a non-empty directory name, the\nfile to be loaded must be located in that directory.\n \nIf the file does not exist or cannot be read because one of\nthe preceding conditions is not satisfied, the function\nreturns NULL.\n \nSince MariaDB 5.1, the character_set_filesystem system\nvariable has controlled interpretation of file names that\nare given as literal strings.\n \nStatements using the LOAD_FILE() function are not safe for\nstatement based replication. This is because the slave will\nexecute the LOAD_FILE() command itself. If the file doesn\'t\nexist on the slave, the function will return NULL.\n \nExamples\n-------- \nUPDATE t SET blob_col=LOAD_FILE(\'/tmp/picture\') WHERE\nid=1;\n \n\n\nURL: https://mariadb.com/kb/en/load_file/','','https://mariadb.com/kb/en/load_file/'),(607,'LIKE',37,'Syntax\n------ \nexpr LIKE pat [ESCAPE \'escape_char\']\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n \nDescription\n----------- \nTests whether expr matches the pattern pat. Returns either 1\n(TRUE) or 0 (FALSE).\nBoth expr and pat may be any valid expression and are\nevaluated to strings.\nPatterns may use the following wildcard characters:\n% matches any number of characters, including zero.\n_ matches any single character.\n \nUse NOT LIKE to test if a string does not match a pattern.\nThis is equivalent to using\nthe NOT operator on the entire LIKE expression.\n \nIf either the expression or the pattern is NULL, the result\nis NULL.\n \nLIKE performs case-insensitive substring matches if the\ncollation for the\nexpression and pattern is case-insensitive. For\ncase-sensitive matches, declare either argument\nto use a binary collation using COLLATE, or coerce either of\nthem to a BINARY\nstring using CAST. Use SHOW COLLATION to get a list of\navailable collations. Collations ending in _bin are\ncase-sensitive.\n \nNumeric arguments are coerced to binary strings.\n \nThe _ wildcard matches a single character, not byte. It will\nonly match a multi-byte character\nif it is valid in the expression\'s character set. For\nexample, _ will match _utf8\"€\", but it\nwill not match _latin1\"€\" because the Euro sign is not a\nvalid latin1 character. If necessary,\nuse CONVERT to use the expression in a different character\nset.\n \nIf you need to match the characters _ or %, you must escape\nthem. By default,\nyou can prefix the wildcard characters the backslash\ncharacter \\ to escape them.\nThe backslash is used both to encode special characters like\nnewlines when a string is\nparsed as well as to escape wildcards in a pattern after\nparsing. Thus, to match an\nactual backslash, you sometimes need to double-escape it as\n\"\\\\\\\\\".\n \nTo avoid difficulties with the backslash character, you can\nchange the wildcard escape\ncharacter using ESCAPE in a LIKE expression. The argument to\nESCAPE\nmust be a single-character string.\n \nExamples\n-------- \nSelect the days that begin with \"T\":\n \nCREATE TABLE t1 (d VARCHAR(16));\nINSERT INTO t1 VALUES (\"Monday\"), (\"Tuesday\"),\n(\"Wednesday\"), (\"Thursday\"), (\"Friday\"),\n(\"Saturday\"), (\"Sunday\");\nSELECT * FROM t1 WHERE d LIKE \"T%\";\n \nSELECT * FROM t1 WHERE d LIKE \"T%\";\n+----------+\n| d |\n+----------+\n| Tuesday |\n| Thursday |\n+----------+\n \nSelect the days that contain the substring \"es\":\n \nSELECT * FROM t1 WHERE d LIKE \"%es%\";\n \nSELECT * FROM t1 WHERE d LIKE \"%es%\";\n+-----------+\n| d |\n+-----------+\n| Tuesday |\n| Wednesday |\n+-----------+\n \nSelect the six-character day names:\n \nSELECT * FROM t1 WHERE d like \"___day\";\n \nSELECT * FROM t1 WHERE d like \"___day\";\n+---------+\n| d |\n+---------+\n| Monday |\n| Friday |\n| Sunday |\n+---------+\n \nWith the default collations, LIKE is case-insensitive:\n \nSELECT * FROM t1 where d like \"t%\";\n \nSELECT * FROM t1 where d like \"t%\";\n+----------+\n| d |\n+----------+\n| Tuesday |\n| Thursday |\n+----------+\n \nUse COLLATE to specify a binary collation, forcing\ncase-sensitive matches:\n \nSELECT * FROM t1 WHERE d like \"t%\" COLLATE latin1_bin;\n \nSELECT * FROM t1 WHERE d like \"t%\" COLLATE latin1_bin;\nEmpty set (0.00 sec)\n \nYou can include functions and operators in the expression to\nmatch. Select dates\nbased on their day name:\n \nCREATE TABLE t2 (d DATETIME);\nINSERT INTO t2 VALUES\n (\"2007-01-30 21:31:07\"),\n (\"1983-10-15 06:42:51\"),\n (\"2011-04-21 12:34:56\"),\n (\"2011-10-30 06:31:41\"),\n (\"2011-01-30 14:03:25\"),\n (\"2004-10-07 11:19:34\");\nSELECT * FROM t2 WHERE DAYNAME(d) LIKE \"T%\";\n \nSELECT * FROM t2 WHERE DAYNAME(d) LIKE \"T%\";\n+------------------+\n| d |\n+------------------+\n| 2007-01-30 21:31 |\n| 2011-04-21 12:34 |\n| 2004-10-07 11:19 |\n+------------------+\n3 rows in set, 7 warnings (0.00 sec)\n \nOptimizing LIKE\n \nMariaDB can use indexes for LIKE on string columns in the\ncase where the LIKE doesn\'t start with % or _.\nStarting from MariaDB 10.0, one can set the\noptimizer_use_condition_selectivity variable to 5. If this\nis done, then the optimizer will read\noptimizer_selectivity_sampling_limit rows to calculate the\nselectivity of the LIKE expression before starting to\ncalculate the query plan. This can help speed up some LIKE\nqueries by providing the optimizer with more information\nabout your data.\n \n\n\nURL: https://mariadb.com/kb/en/like/','','https://mariadb.com/kb/en/like/'),(609,'LOCATE',37,'Syntax\n------ \nLOCATE(substr,str), LOCATE(substr,str,pos)\n \nDescription\n----------- \nThe first syntax returns the position of the first\noccurrence of\nsubstring substr in string str. The second syntax returns\nthe position\nof the first occurrence of substring substr in string str,\nstarting at\nposition pos. Returns 0 if substr is not in str.\n \nLOCATE() performs a case-insensitive search.\n \nIf any argument is NULL, returns NULL.\n \nINSTR() is a synonym of LOCATE() without the third argument.\n \nExamples\n-------- \nSELECT LOCATE(\'bar\', \'foobarbar\');\n+----------------------------+\n| LOCATE(\'bar\', \'foobarbar\') |\n+----------------------------+\n| 4 |\n+----------------------------+\n \nSELECT LOCATE(\'My\', \'Maria\');\n+-----------------------+\n| LOCATE(\'My\', \'Maria\') |\n+-----------------------+\n| 0 |\n+-----------------------+\n \nSELECT LOCATE(\'bar\', \'foobarbar\', 5);\n+-------------------------------+\n| LOCATE(\'bar\', \'foobarbar\', 5) |\n+-------------------------------+\n| 7 |\n+-------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/locate/','','https://mariadb.com/kb/en/locate/'),(610,'LOWER',37,'Syntax\n------ \nLOWER(str)\n \nDescription\n----------- \nReturns the string str with all characters changed to\nlowercase\naccording to the current character set mapping. The default\nis latin1\n(cp1252 West European).\n \nExamples\n-------- \n SELECT LOWER(\'QUADRATICALLY\');\n+------------------------+\n| LOWER(\'QUADRATICALLY\') |\n+------------------------+\n| quadratically |\n+------------------------+\n \nLOWER() (and UPPER()) are ineffective when applied to binary\nstrings (BINARY, VARBINARY, BLOB). \nTo perform lettercase conversion, CONVERT the string to a\nnon-binary string:\n \nSET @str = BINARY \'North Carolina\';\n \nSELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+----------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+----------------+-----------------------------------+\n| North Carolina | north carolina |\n+----------------+-----------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/lower/','','https://mariadb.com/kb/en/lower/'),(611,'LPAD',37,'Syntax\n------ \nLPAD(str, len [,padstr])\n \nDescription\n----------- \nReturns the string str, left-padded with the string padstr\nto a length\nof len characters. If str is longer than len, the return\nvalue is\nshortened to len characters. If padstr is omitted, the LPAD\nfunction pads spaces.\n \nPrior to MariaDB 10.3.1, the padstr parameter was mandatory.\n \nReturns NULL if given a NULL argument. If the result is\nempty (zero length), returns either an empty string or, from\nMariaDB 10.3.6 with SQL_MODE=Oracle, NULL.\n \nThe Oracle mode version of the function can be accessed\noutside of Oracle mode by using LPAD_ORACLE as the function\nname.\n \nExamples\n-------- \nSELECT LPAD(\'hello\',10,\'.\');\n+----------------------+\n| LPAD(\'hello\',10,\'.\') |\n+----------------------+\n| .....hello |\n+----------------------+\n \nSELECT LPAD(\'hello\',2,\'.\');\n+---------------------+\n| LPAD(\'hello\',2,\'.\') |\n+---------------------+\n| he |\n+---------------------+\n \nFrom MariaDB 10.3.1, with the pad string defaulting to\nspace.\n \nSELECT LPAD(\'hello\',10);\n+------------------+\n| LPAD(\'hello\',10) |\n+------------------+\n| hello |\n+------------------+\n \nOracle mode version from MariaDB 10.3.6:\n \nSELECT LPAD(\'\',0),LPAD_ORACLE(\'\',0);\n+------------+-------------------+\n| LPAD(\'\',0) | LPAD_ORACLE(\'\',0) |\n+------------+-------------------+\n| | NULL |\n+------------+-------------------+\n \n\n\nURL: https://mariadb.com/kb/en/lpad/','','https://mariadb.com/kb/en/lpad/'),(612,'LTRIM',37,'Syntax\n------ \nLTRIM(str)\n \nDescription\n----------- \nReturns the string str with leading space characters\nremoved.\n \nReturns NULL if given a NULL argument. If the result is\nempty, returns either an empty string, or, from MariaDB\n10.3.6 with SQL_MODE=Oracle, NULL.\n \nThe Oracle mode version of the function can be accessed\noutside of Oracle mode by using LTRIM_ORACLE as the function\nname.\n \nExamples\n-------- \nSELECT QUOTE(LTRIM(\' MariaDB \'));\n+-------------------------------+\n| QUOTE(LTRIM(\' MariaDB \')) |\n+-------------------------------+\n| \'MariaDB \' |\n+-------------------------------+\n \nOracle mode version from MariaDB 10.3.6:\n \nSELECT LTRIM(\'\'),LTRIM_ORACLE(\'\');\n+-----------+------------------+\n| LTRIM(\'\') | LTRIM_ORACLE(\'\') |\n+-----------+------------------+\n| | NULL |\n+-----------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/ltrim/','','https://mariadb.com/kb/en/ltrim/'),(613,'MAKE_SET',37,'Syntax\n------ \nMAKE_SET(bits,str1,str2,...)\n \nDescription\n----------- \nReturns a set value (a string containing substrings\nseparated by \",\"\ncharacters) consisting of the strings that have the\ncorresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and\nso on. NULL\nvalues in str1, str2, ... are not appended to the result.\n \nExamples\n-------- \nSELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n+-------------------------+\n| MAKE_SET(1,\'a\',\'b\',\'c\') |\n+-------------------------+\n| a |\n+-------------------------+\n \nSELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n+----------------------------------------+\n| MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\') |\n+----------------------------------------+\n| hello,world |\n+----------------------------------------+\n \nSELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n+---------------------------------------------+\n| MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\') |\n+---------------------------------------------+\n| hello |\n+---------------------------------------------+\n \nSELECT QUOTE(MAKE_SET(0,\'a\',\'b\',\'c\'));\n+--------------------------------+\n| QUOTE(MAKE_SET(0,\'a\',\'b\',\'c\')) |\n+--------------------------------+\n| \'\' |\n+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/make_set/','','https://mariadb.com/kb/en/make_set/'),(614,'MATCH AGAINST',37,'Syntax\n------ \nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n \nDescription\n----------- \nA special construct used to perform a fulltext search on a\nfulltext index.\n \nSee Fulltext Index Overview for a full description, and\nFull-text Indexes for more articles on the topic.\n \nExamples\n-------- \nCREATE TABLE ft_myisam(copy TEXT,FULLTEXT(copy))\nENGINE=MyISAM;\n \nINSERT INTO ft_myisam(copy) VALUES (\'Once upon a time\'),\n(\'There was a wicked witch\'), \n (\'Who ate everybody up\');\n \nSELECT * FROM ft_myisam WHERE MATCH(copy)\nAGAINST(\'wicked\');\n+--------------------------+\n| copy |\n+--------------------------+\n| There was a wicked witch |\n+--------------------------+\n \nSELECT id, body, MATCH (title,body) AGAINST\n (\'Security implications of running MySQL as root\'\n IN NATURAL LANGUAGE MODE) AS score\n FROM articles WHERE MATCH (title,body) AGAINST\n (\'Security implications of running MySQL as root\'\n IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014\n|\n| 6 | When configured properly, MySQL ... | 1.3114095926285\n|\n+----+-------------------------------------+-----------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/match-against/','','https://mariadb.com/kb/en/match-against/'),(622,'REGEXP_INSTR',37,'REGEXP_INSTR was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nREGEXP_INSTR(subject, pattern)\n \nReturns the position of the first occurrence of the regular\nexpression pattern in the string subject, or 0 if pattern\nwas not found.\n \nThe positions start with 1 and are measured in characters\n(i.e. not in bytes), which is important for multi-byte\ncharacter sets. You can cast a multi-byte character set to\nBINARY to get offsets in bytes.\n \nThe function follows the case sensitivity rules of the\neffective collation. Matching is performed case\ninsensitively for case insensitive collations, and case\nsensitively for case sensitive collations and for binary\ndata.\n \nThe collation case sensitivity can be overwritten using the\n(?i) and (?-i) PCRE flags.\n \nMariaDB 10.0.5 switched to the PCRE regular expression\nlibrary for enhanced regular expression performance, and\nREGEXP_INSTR was introduced as part of this enhancement.\n \nExamples\n-------- \nSELECT REGEXP_INSTR(\'abc\',\'b\');\n-> 2\n \nSELECT REGEXP_INSTR(\'abc\',\'x\');\n-> 0\n \nSELECT REGEXP_INSTR(\'BJÖRN\',\'N\');\n-> 5\n \nCasting a multi-byte character set as BINARY to get offsets\nin bytes:\n \nSELECT REGEXP_INSTR(BINARY \'BJÖRN\',\'N\') AS\ncast_utf8_to_binary;\n-> 6\n \nCase sensitivity:\n \nSELECT REGEXP_INSTR(\'ABC\',\'b\');\n-> 2\n \nSELECT REGEXP_INSTR(\'ABC\' COLLATE utf8_bin,\'b\');\n-> 0\n \nSELECT REGEXP_INSTR(BINARY\'ABC\',\'b\');\n-> 0\n \nSELECT REGEXP_INSTR(\'ABC\',\'(?-i)b\');\n-> 0\n \nSELECT REGEXP_INSTR(\'ABC\' COLLATE utf8_bin,\'(?i)b\');\n-> 2\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/regexp_instr/','','https://mariadb.com/kb/en/regexp_instr/'),(623,'REGEXP_REPLACE',37,'REGEXP_REPLACE was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nREGEXP_REPLACE(subject, pattern, replace)\n \nDescription\n----------- \nREGEXP_REPLACE returns the string subject with all\noccurrences of the regular expression pattern replaced by\nthe string replace. If no occurrences are found, then\nsubject is returned as is.\n \nThe replace string can have backreferences to the\nsubexpressions in the form \\N, where N is a number from 1\nto 9.\n \nThe function follows the case sensitivity rules of the\neffective collation. Matching is performed case\ninsensitively for case insensitive collations, and case\nsensitively for case sensitive collations and for binary\ndata.\n \nThe collation case sensitivity can be overwritten using the\n(?i) and (?-i) PCRE flags.\n \nMariaDB 10.0.5 switched to the PCRE regular expression\nlibrary for enhanced regular expression performance, and\nREGEXP_REPLACE was introduced as part of this enhancement.\n \nMariaDB 10.0.11 introduced the default_regex_flags variable\nto address the remaining compatibilities between PCRE and\nthe old regex library. \n \nExamples\n-------- \nSELECT REGEXP_REPLACE(\'ab12cd\',\'[0-9]\',\'\') AS\nremove_digits;\n-> abcd\n \nSELECT REGEXP_REPLACE(\'titlebody\', \'\',\' \')\nAS strip_html;\n-> title body\n \nBackreferences to the subexpressions in the form \\N, where\nN is a number from 1 to 9:\n \nSELECT REGEXP_REPLACE(\'James Bond\',\'^(.*)\n(.*)$\',\'\\\\2, \\\\1\') AS reorder_name;\n-> Bond, James\n \nCase insensitive and case sensitive matches:\n \nSELECT REGEXP_REPLACE(\'ABC\',\'b\',\'-\') AS\ncase_insensitive;\n-> A-C\n \nSELECT REGEXP_REPLACE(\'ABC\' COLLATE utf8_bin,\'b\',\'-\')\nAS case_sensitive;\n-> ABC\n \nSELECT REGEXP_REPLACE(BINARY \'ABC\',\'b\',\'-\') AS\nbinary_data;\n-> ABC\n \nOverwriting the collation case sensitivity using the (?i)\nand (?-i) PCRE flags.\n \nSELECT REGEXP_REPLACE(\'ABC\',\'(?-i)b\',\'-\') AS\nforce_case_sensitive;\n-> ABC\n \nSELECT REGEXP_REPLACE(BINARY \'ABC\',\'(?i)b\',\'-\') AS\nforce_case_insensitive;\n-> A-C\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/regexp_replace/','','https://mariadb.com/kb/en/regexp_replace/'),(624,'REGEXP_SUBSTR',37,'REGEXP_SUBSTR was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nREGEXP_SUBSTR(subject,pattern)\n \nDescription\n----------- \nReturns the part of the string subject that matches the\nregular expression pattern, or an empty string if pattern\nwas not found.\n \nThe function follows the case sensitivity rules of the\neffective collation. Matching is performed case\ninsensitively for case insensitive collations, and case\nsensitively for case sensitive collations and for binary\ndata.\n \nThe collation case sensitivity can be overwritten using the\n(?i) and (?-i) PCRE flags.\n \nMariaDB 10.0.5 switched to the PCRE regular expression\nlibrary for enhanced regular expression performance, and\nREGEXP_SUBSTR was introduced as part of this enhancement.\n \nMariaDB 10.0.11 introduced the default_regex_flags variable\nto address the remaining compatibilities between PCRE and\nthe old regex library. \n \nExamples\n-------- \nSELECT REGEXP_SUBSTR(\'ab12cd\',\'[0-9]+\');\n-> 12\n \nSELECT REGEXP_SUBSTR(\n \'See https://mariadb.org/en/foundation/ for details\',\n \'https?://[^/]*\');\n-> https://mariadb.org\n \nSELECT REGEXP_SUBSTR(\'ABC\',\'b\');\n-> B\n \nSELECT REGEXP_SUBSTR(\'ABC\' COLLATE utf8_bin,\'b\');\n->\n \nSELECT REGEXP_SUBSTR(BINARY\'ABC\',\'b\');\n->\n \nSELECT REGEXP_SUBSTR(\'ABC\',\'(?i)b\');\n-> B\n \nSELECT REGEXP_SUBSTR(\'ABC\' COLLATE utf8_bin,\'(?+i)b\');\n-> B\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/regexp_substr/','','https://mariadb.com/kb/en/regexp_substr/'),(629,'RPAD',37,'Syntax\n------ \nRPAD(str, len [, padstr])\n \nDescription\n----------- \nReturns the string str, right-padded with the string padstr\nto a\nlength of len characters. If str is longer than len, the\nreturn value\nis shortened to len characters. If padstr is omitted, the\nRPAD function pads spaces.\n \nPrior to MariaDB 10.3.1, the padstr parameter was mandatory.\n \nReturns NULL if given a NULL argument. If the result is\nempty (a length of zero), returns either an empty string,\nor, from MariaDB 10.3.6 with SQL_MODE=Oracle, NULL.\n \nThe Oracle mode version of the function can be accessed\noutside of Oracle mode by using RPAD_ORACLE as the function\nname.\n \nExamples\n-------- \nSELECT RPAD(\'hello\',10,\'.\');\n+----------------------+\n| RPAD(\'hello\',10,\'.\') |\n+----------------------+\n| hello..... |\n+----------------------+\n \nSELECT RPAD(\'hello\',2,\'.\');\n+---------------------+\n| RPAD(\'hello\',2,\'.\') |\n+---------------------+\n| he |\n+---------------------+\n \nFrom MariaDB 10.3.1, with the pad string defaulting to\nspace.\n \nSELECT RPAD(\'hello\',30);\n+--------------------------------+\n| RPAD(\'hello\',30) |\n+--------------------------------+\n| hello |\n+--------------------------------+\n \nOracle mode version from MariaDB 10.3.6:\n \nSELECT RPAD(\'\',0),RPAD_ORACLE(\'\',0);\n+------------+-------------------+\n| RPAD(\'\',0) | RPAD_ORACLE(\'\',0) |\n+------------+-------------------+\n| | NULL |\n+------------+-------------------+\n \n\n\nURL: https://mariadb.com/kb/en/rpad/','','https://mariadb.com/kb/en/rpad/'),(630,'RTRIM',37,'Syntax\n------ \nRTRIM(str)\n \nDescription\n----------- \nReturns the string str with trailing space characters\nremoved.\n \nReturns NULL if given a NULL argument. If the result is\nempty, returns either an empty string, or, from MariaDB\n10.3.6 with SQL_MODE=Oracle, NULL.\n \nThe Oracle mode version of the function can be accessed\noutside of Oracle mode by using RTRIM_ORACLE as the function\nname.\n \nExamples\n-------- \nSELECT QUOTE(RTRIM(\'MariaDB \'));\n+-----------------------------+\n| QUOTE(RTRIM(\'MariaDB \')) |\n+-----------------------------+\n| \'MariaDB\' |\n+-----------------------------+\n \nOracle mode version from MariaDB 10.3.6:\n \nSELECT RTRIM(\'\'),RTRIM_ORACLE(\'\');\n+-----------+------------------+\n| RTRIM(\'\') | RTRIM_ORACLE(\'\') |\n+-----------+------------------+\n| | NULL |\n+-----------+------------------+\n \n\n\nURL: https://mariadb.com/kb/en/rtrim/','','https://mariadb.com/kb/en/rtrim/'),(631,'SOUNDEX',37,'Syntax\n------ \nSOUNDEX(str)\n \nDescription\n----------- \nReturns a soundex string from str. Two strings that sound\nalmost the\nsame should have identical soundex strings. A standard\nsoundex string is four\ncharacters long, but the SOUNDEX() function returns an\narbitrarily long\nstring. You can use SUBSTRING() on the result to get a\nstandard soundex\nstring. All non-alphabetic characters in str are ignored.\nAll\ninternational alphabetic characters outside the A-Z range\nare treated as\nvowels.\n \nImportant: When using SOUNDEX(), you should be aware of the\nfollowing limitations:\nThis function, as currently implemented, is intended to work\nwell with\n strings that are in the English language only. Strings in\nother languages may\n not produce reliable results.\n \nExamples\n-------- \nSOUNDEX(\'Hello\');\n+------------------+\n| SOUNDEX(\'Hello\') |\n+------------------+\n| H400 |\n+------------------+\n \nSELECT SOUNDEX(\'MariaDB\');\n+--------------------+\n| SOUNDEX(\'MariaDB\') |\n+--------------------+\n| M631 |\n+--------------------+\n \nSELECT SOUNDEX(\'Knowledgebase\');\n+--------------------------+\n| SOUNDEX(\'Knowledgebase\') |\n+--------------------------+\n| K543212 |\n+--------------------------+\n \nSELECT givenname, surname FROM users WHERE\nSOUNDEX(givenname) = SOUNDEX(\"robert\");\n+-----------+---------+\n| givenname | surname |\n+-----------+---------+\n| Roberto | Castro |\n+-----------+---------+\n \n\n\nURL: https://mariadb.com/kb/en/soundex/','','https://mariadb.com/kb/en/soundex/'),(636,'SUBSTRING',37,'Syntax\n------ \nSUBSTRING(str,pos), \nSUBSTRING(str FROM pos), \nSUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n \nSUBSTR(str,pos), \nSUBSTR(str FROM pos), \nSUBSTR(str,pos,len),\nSUBSTR(str FROM pos FOR len)\n \nDescription\n----------- \nThe forms without a len argument return a substring from\nstring str starting at position pos.\n \nThe forms with a len argument return a substring len\ncharacters long from string str, starting at position pos.\n \nThe forms that use FROM are standard SQL syntax.\n \nIt is also possible to use a negative value for pos. In this\ncase, the beginning of the substring is pos characters from\nthe end of the string, rather than the beginning. A negative\nvalue may be used for pos in any of the forms of this\nfunction.\n \nBy default, the position of the first character in the\nstring from which the substring is to be extracted is\nreckoned as 1. For Oracle-compatibility, from MariaDB\n10.3.3, when sql_mode is set to \'oracle\', position zero is\ntreated as position 1 (although the first character is still\nreckoned as 1).\n \nIf any argument is NULL, returns NULL.\n \nExamples\n-------- \nSELECT SUBSTRING(\'Knowledgebase\',5);\n+------------------------------+\n| SUBSTRING(\'Knowledgebase\',5) |\n+------------------------------+\n| ledgebase |\n+------------------------------+\n \nSELECT SUBSTRING(\'MariaDB\' FROM 6);\n+-----------------------------+\n| SUBSTRING(\'MariaDB\' FROM 6) |\n+-----------------------------+\n| DB |\n+-----------------------------+\n \nSELECT SUBSTRING(\'Knowledgebase\',3,7);\n+--------------------------------+\n| SUBSTRING(\'Knowledgebase\',3,7) |\n+--------------------------------+\n| owledge |\n+--------------------------------+\n \nSELECT SUBSTRING(\'Knowledgebase\', -4);\n+--------------------------------+\n| SUBSTRING(\'Knowledgebase\', -4) |\n+--------------------------------+\n| base |\n+--------------------------------+\n \nSELECT SUBSTRING(\'Knowledgebase\', -8, 4);\n+-----------------------------------+\n| SUBSTRING(\'Knowledgebase\', -8, 4) |\n+-----------------------------------+\n| edge |\n+-----------------------------------+\n \nSELECT SUBSTRING(\'Knowledgebase\' FROM -8 FOR 4);\n+------------------------------------------+\n| SUBSTRING(\'Knowledgebase\' FROM -8 FOR 4) |\n+------------------------------------------+\n| edge |\n+------------------------------------------+\n \nOracle mode from MariaDB 10.3.3:\n \nSELECT SUBSTR(\'abc\',0,3);\n+-------------------+\n| SUBSTR(\'abc\',0,3) |\n+-------------------+\n| |\n+-------------------+\n \nSELECT SUBSTR(\'abc\',1,2);\n+-------------------+\n| SUBSTR(\'abc\',1,2) |\n+-------------------+\n| ab |\n+-------------------+\n \nSET sql_mode=\'oracle\';\n \nSELECT SUBSTR(\'abc\',0,3);\n+-------------------+\n| SUBSTR(\'abc\',0,3) |\n+-------------------+\n| abc |\n+-------------------+\n \nSELECT SUBSTR(\'abc\',1,2);\n+-------------------+\n| SUBSTR(\'abc\',1,2) |\n+-------------------+\n| ab |\n+-------------------+\n \n\n\nURL: https://mariadb.com/kb/en/substring/','','https://mariadb.com/kb/en/substring/'),(637,'SUBSTRING_INDEX',37,'Syntax\n------ \nSUBSTRING_INDEX(str,delim,count)\n \nDescription\n----------- \nReturns the substring from string str before count\noccurrences of the\ndelimiter delim. If count is positive, everything to the\nleft\nof the final delimiter (counting from the left) is returned.\nIf count\nis negative, everything to the right of the final delimiter\n(counting from the\nright) is returned. SUBSTRING_INDEX() performs a\ncase-sensitive match when\nsearching for delim.\n \nIf any argument is NULL, returns NULL.\n \nExamples\n-------- \nSELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2);\n+--------------------------------------------+\n| SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', 2) |\n+--------------------------------------------+\n| www.mariadb |\n+--------------------------------------------+\n \nSELECT SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2);\n+---------------------------------------------+\n| SUBSTRING_INDEX(\'www.mariadb.org\', \'.\', -2) |\n+---------------------------------------------+\n| mariadb.org |\n+---------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/substring_index/','','https://mariadb.com/kb/en/substring_index/'),(638,'TO_BASE64',37,'The TO_BASE64() function was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nTO_BASE64(str)\n \nDescription\n----------- \nConverts the string argument str to its base-64 encoded\nform, returning the result as a character string in the\nconnection character set and collation.\n \nThe argument str will be converted to string first if it is\nnot a string. A NULL argument will return a NULL result.\n \nThe reverse function, FROM_BASE64(), decodes an encoded\nbase-64 string.\n \nThere are a numerous different methods to base-64 encode a\nstring. The following are used by MariaDB and MySQL:\nAlphabet value 64 is encoded as \'+\'.\nAlphabet value 63 is encoded as \'/\'.\nEncoding output is made up of groups of four printable\ncharacters, with each three bytes of data encoded using four\ncharacters. If the final group is not complete, it is padded\nwith \'=\' characters to make up a length of four.\nTo divide long output, a newline is added after every 76\ncharacters.\nDecoding will recognize and ignore newlines, carriage\nreturns, tabs, and spaces. \n \nExamples\n-------- \nSELECT TO_BASE64(\'Maria\');\n+--------------------+\n| TO_BASE64(\'Maria\') |\n+--------------------+\n| TWFyaWE= |\n+--------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/to_base64/','','https://mariadb.com/kb/en/to_base64/'),(639,'TRIM',37,'Syntax\n------ \nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str),\nTRIM([remstr FROM] str)\n \nDescription\n----------- \nReturns the string str with all remstr prefixes or suffixes\nremoved. If none of the specifiers BOTH, LEADING, or\nTRAILING is given, BOTH is assumed. remstr is optional and,\nif not specified, spaces are removed.\n \nReturns NULL if given a NULL argument. If the result is\nempty, returns either an empty string, or, from MariaDB\n10.3.6 with SQL_MODE=Oracle, NULL.\n \nThe Oracle mode version of the function can be accessed\noutside of Oracle mode by using TRIM_ORACLE as the function\nname.\n \nExamples\n-------- \nSELECT TRIM(\' bar \')\\G\n*************************** 1. row\n***************************\nTRIM(\' bar \'): bar\n \nSELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\')\\G\n*************************** 1. row\n***************************\nTRIM(LEADING \'x\' FROM \'xxxbarxxx\'): barxxx\n \nSELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\')\\G\n*************************** 1. row\n***************************\nTRIM(BOTH \'x\' FROM \'xxxbarxxx\'): bar\n \nSELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\')\\G\n*************************** 1. row\n***************************\nTRIM(TRAILING \'xyz\' FROM \'barxxyz\'): barx\n \nOracle mode version from MariaDB 10.3.6:\n \nSELECT TRIM(\'\'),TRIM_ORACLE(\'\');\n+----------+-----------------+\n| TRIM(\'\') | TRIM_ORACLE(\'\') |\n+----------+-----------------+\n| | NULL |\n+----------+-----------------+\n \n\n\nURL: https://mariadb.com/kb/en/trim/','','https://mariadb.com/kb/en/trim/'),(641,'UNHEX',37,'Syntax\n------ \nUNHEX(str)\n \nDescription\n----------- \nPerforms the inverse operation of HEX(str). That is, it\ninterprets\neach pair of hexadecimal digits in the argument as a number\nand\nconverts it to the character represented by the number. The\nresulting\ncharacters are returned as a binary string.\n \nIf str is NULL, UNHEX() returns NULL.\n \nExamples\n-------- \nSELECT HEX(\'MariaDB\');\n+----------------+\n| HEX(\'MariaDB\') |\n+----------------+\n| 4D617269614442 |\n+----------------+\n \nSELECT UNHEX(\'4D617269614442\');\n+-------------------------+\n| UNHEX(\'4D617269614442\') |\n+-------------------------+\n| MariaDB |\n+-------------------------+\n \nSELECT 0x4D617269614442;\n \n+------------------+\n| 0x4D617269614442 |\n+------------------+\n| MariaDB |\n+------------------+\n \nSELECT UNHEX(HEX(\'string\'));\n+----------------------+\n| UNHEX(HEX(\'string\')) |\n+----------------------+\n| string |\n+----------------------+\n \nSELECT HEX(UNHEX(\'1267\'));\n+--------------------+\n| HEX(UNHEX(\'1267\')) |\n+--------------------+\n| 1267 |\n+--------------------+\n \n\n\nURL: https://mariadb.com/kb/en/unhex/','','https://mariadb.com/kb/en/unhex/'),(642,'UPDATEXML',37,'Syntax\n------ \nUpdateXML(xml_target, xpath_expr, new_xml)\n \nDescription\n----------- \nThis function replaces a single portion of a given fragment\nof XML markup\nxml_target with a new XML fragment new_xml, and then returns\nthe\nchanged XML. The portion of xml_target that is replaced\nmatches an XPath\nexpression xpath_expr supplied by the user. If no expression\nmatching\nxpath_expr is found, or if multiple matches are found, the\nfunction returns\nthe original xml_target XML fragment. All three arguments\nshould be\nstrings.\n \nExamples\n-------- \nSELECT\n UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n \\G\n*************************** 1. row\n***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n1 row in set (0.00 sec)\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/updatexml/','','https://mariadb.com/kb/en/updatexml/'),(644,'WEIGHT_STRING',37,'The WEIGHT_STRING function was introduced in MariaDB 10.0.5.\n \nSyntax\n------ \nWEIGHT_STRING(str [AS {CHAR|BINARY}(N)] [LEVEL levels]\n[flags])\n levels: N [ASC|DESC|REVERSE] [, N [ASC|DESC|REVERSE]] ... \n \nDescription\n----------- \nReturns a binary string representing the string\'s sorting\nand comparison value. A string with a lower result means\nthat for sorting purposes the string appears before a string\nwith a higher result.\n \nWEIGHT_STRING() is particularly useful when adding new\ncollations, for testing purposes.\n \nIf str is a non-binary string (CHAR, VARCHAR or TEXT),\nWEIGHT_STRING returns the string\'s collation weight. If str\nis a binary string (BINARY, VARBINARY or BLOB), the return\nvalue is simply the input value, since the weight for each\nbyte in a binary string is the byte value.\n \nWEIGHT_STRING() returns NULL if given a NULL input. \n \nThe optional AS clause permits casting the input string to a\nbinary or non-binary string, as well as to a particular\nlength.\n \nAS BINARY(N) measures the length in bytes rather than\ncharacters, and right pads with 0x00 bytes to the desired\nlength. \n \nAS CHAR(N) measures the length in characters, and right pads\nwith spaces to the desired length.\n \nN has a minimum value of 1, and if it is less than the\nlength of the input string, the string is truncated without\nwarning.\n \nThe optional LEVEL clause specifies that the return value\nshould contain weights for specific collation levels. The\nlevels specifier can either be a single integer, a\ncomma-separated list of integers, or a range of integers\nseparated by a dash (whitespace is ignored). Integers can\nrange from 1 to a maximum of 6, dependent on the collation,\nand need to be listed in ascending order.\n \nIf the LEVEL clause is no provided, a default of 1 to the\nmaximum for the collation is assumed.\n \nIf the LEVEL is specified without using a range, an optional\nmodifier is permitted.\n \nASC, the default, returns the weights without any\nmodification.\n \nDESC returns bitwise-inverted weights.\n \nREVERSE returns the weights in reverse order.\n \nExamples\n-------- \nThe examples below use the HEX() function to represent\nnon-printable results in hexadecimal format.\n \nSELECT HEX(WEIGHT_STRING(\'x\'));\n+-------------------------+\n| HEX(WEIGHT_STRING(\'x\')) |\n+-------------------------+\n| 0058 |\n+-------------------------+\n \nSELECT HEX(WEIGHT_STRING(\'x\' AS BINARY(4)));\n+--------------------------------------+\n| HEX(WEIGHT_STRING(\'x\' AS BINARY(4))) |\n+--------------------------------------+\n| 78000000 |\n+--------------------------------------+\n \nSELECT HEX(WEIGHT_STRING(\'x\' AS CHAR(4)));\n+------------------------------------+\n| HEX(WEIGHT_STRING(\'x\' AS CHAR(4))) |\n+------------------------------------+\n| 0058002000200020 |\n+------------------------------------+\n \nSELECT HEX(WEIGHT_STRING(0xaa22ee LEVEL 1));\n+--------------------------------------+\n| HEX(WEIGHT_STRING(0xaa22ee LEVEL 1)) |\n+--------------------------------------+\n| AA22EE |\n+--------------------------------------+\n \nSELECT HEX(WEIGHT_STRING(0xaa22ee LEVEL 1 DESC));\n+-------------------------------------------+\n| HEX(WEIGHT_STRING(0xaa22ee LEVEL 1 DESC)) |\n+-------------------------------------------+\n| 55DD11 |\n+-------------------------------------------+\n \nSELECT HEX(WEIGHT_STRING(0xaa22ee LEVEL 1 REVERSE));\n+----------------------------------------------+\n| HEX(WEIGHT_STRING(0xaa22ee LEVEL 1 REVERSE)) |\n+----------------------------------------------+\n| EE22AA |\n+----------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/weight_string/','','https://mariadb.com/kb/en/weight_string/'),(645,'ALTER DATABASE',39,'Modifies a database, changing its overall characteristics.\n \nSyntax\n------ \nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n \nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n \nDescription\n----------- \nALTER DATABASE enables you to change the overall\ncharacteristics of a\ndatabase. These characteristics are stored in the db.opt\nfile in the\ndatabase directory. To use ALTER DATABASE, you need the\nALTER\nprivilege on the database. ALTER SCHEMA is a synonym for\nALTER\nDATABASE.\n \nThe CHARACTER SET clause changes the default database\ncharacter set.\nThe COLLATE clause changes the default database collation.\nSee Character Sets and Collations for more.\n \nYou can see what character sets and collations are available\nusing,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION\nstatements.\n \nChanging the default character set/collation of a database\ndoes not change the character set/collation of any stored\nprocedures or stored functions that were previously created,\nand relied on the defaults. These need to be dropped and\nrecreated in order to apply the character set/collation\nchanges.\n \nThe database name can be omitted from the first syntax, in\nwhich case\nthe statement applies to the default database.\n \nThe syntax that includes the UPGRADE DATA DIRECTORY NAME\nclause was\nadded in MySQL 5.1.23. It updates the name of the directory\nassociated\nwith the database to use the encoding implemented in MySQL\n5.1 for\nmapping database names to database directory names (see\nIdentifier to File Name Mapping). This\nclause is for use under these conditions:\nIt is intended when upgrading MySQL to 5.1 or later from\nolder versions.\nIt is intended to update a database directory name to the\ncurrent encoding format if the name contains special\ncharacters that need encoding.\nThe statement is used by mysqlcheck (as invoked by\nmysql_upgrade).\n \nFor example,if a database in MySQL 5.0 has a name of a-b-c,\nthe name\ncontains instance of the `-\' character. In 5.0, the\ndatabase directory\nis also named a-b-c, which is not necessarily safe for all\nfile\nsystems. In MySQL 5.1 and up, the same database name is\nencoded as\na@002db@002dc to produce a file system-neutral directory\nname.\n \nWhen a MySQL installation is upgraded to MySQL 5.1 or later\nfrom an\nolder version,the server displays a name such as a-b-c\n(which is in\nthe old format) as #mysql50#a-b-c, and you must refer to the\nname\nusing the #mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME\nin this\ncase to explicitly tell the server to re-encode the database\ndirectory\nname to the current encoding format:\n \nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n \nAfter executing this statement, you can refer to the\ndatabase as a-b-c\nwithout the special #mysql50# prefix.\n \nExamples\n-------- \nALTER DATABASE test CHARACTER SET = \'utf8\' COLLATE =\n\'utf8_bin\';\n \n\n\nURL: https://mariadb.com/kb/en/alter-database/','','https://mariadb.com/kb/en/alter-database/'),(646,'ALTER EVENT',39,'Modifies one or more characteristics of an existing event.\n \nSyntax\n------ \nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO sql_statement]\n \nDescription\n----------- \nThe ALTER EVENT statement is used to change one or more of\nthe\ncharacteristics of an existing event without the need to\ndrop and recreate it.\nThe syntax for each of the DEFINER, ON SCHEDULE, ON\nCOMPLETION,\nCOMMENT, ENABLE / DISABLE, and DO clauses is exactly the\nsame as when used with CREATE EVENT.\n \nThis statement requires the EVENT privilege.\nWhen a user executes a successful ALTER EVENT statement,\nthat user becomes\nthe definer for the affected event.\n \n(In MySQL 5.1.11 and earlier, an event could be altered only\nby its definer, or\nby a user having the SUPER privilege.)\n \nALTER EVENT works only with an existing event:\n \nALTER EVENT no_such_event ON SCHEDULE EVERY \'2:3\'\nDAY_HOUR;\nERROR 1539 (HY000): Unknown event \'no_such_event\'\n \nExamples\n-------- \nALTER EVENT myevent \n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 HOUR \n DO \n UPDATE myschema.mytable SET mycol = mycol + 1;\n \n\n\nURL: https://mariadb.com/kb/en/alter-event/','','https://mariadb.com/kb/en/alter-event/'),(647,'ALTER FUNCTION',39,'Syntax\n------ \nALTER FUNCTION func_name [characteristic ...]\n \ncharacteristic:\n { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL\nDATA }\n | SQL SECURITY { DEFINER | INVOKER }\n | COMMENT \'string\'\n \nDescription\n----------- \nThis statement can be used to change the characteristics of\na stored\nfunction. More than one change may be specified in an ALTER\nFUNCTION\nstatement. However, you cannot change the parameters or body\nof a\nstored function using this statement; to make such changes,\nyou must\ndrop and re-create the function using DROP FUNCTION and\nCREATE FUNCTION.\n \nYou must have the ALTER ROUTINE privilege for the function.\n(That\nprivilege is granted automatically to the function creator.)\nIf binary\nlogging is enabled, the ALTER FUNCTION statement might also\nrequire\nthe SUPER privilege, as described in Binary Logging of\nStored Routines.\n \nExample\n \nALTER FUNCTION hello SQL SECURITY INVOKER;\n \n\n\nURL: https://mariadb.com/kb/en/alter-function/','','https://mariadb.com/kb/en/alter-function/'),(649,'ALTER PROCEDURE',39,'Syntax\n------ \nALTER PROCEDURE proc_name [characteristic ...]\n \ncharacteristic:\n { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL\nDATA }\n | SQL SECURITY { DEFINER | INVOKER }\n | COMMENT \'string\'\n \nDescription\n----------- \nThis statement can be used to change the characteristics of\na stored\nprocedure. More than one change may be specified in an ALTER\nPROCEDURE\nstatement. However, you cannot change the parameters or body\nof a\nstored procedure using this statement. To make such changes,\nyou must\ndrop and re-create the procedure using either CREATE OR\nREPLACE PROCEDURE (since MariaDB 10.1.3) or DROP PROCEDURE\nand CREATE PROCEDURE (MariaDB 10.1.2 and before).\n \nYou must have the ALTER ROUTINE privilege for the procedure.\nBy default, that privilege is granted automatically to the\nprocedure creator. See Stored Routine Privileges.\n \nExample\n \nALTER PROCEDURE simpleproc SQL SECURITY INVOKER;\n \n\n\nURL: https://mariadb.com/kb/en/alter-procedure/','','https://mariadb.com/kb/en/alter-procedure/'),(654,'ALTER VIEW',39,'Syntax\n------ \nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n \nDescription\n----------- \nThis statement changes the definition of a view, which must\nexist. The\nsyntax is similar to that for CREATE VIEW and the effect is\nthe same\nas for CREATE OR REPLACE VIEW if the view exists. This\nstatement\nrequires the CREATE VIEW and DROP privileges for the view,\nand some\nprivilege for each column referred to in the SELECT\nstatement. As of\nMariaDB 5.1.23, ALTER VIEW is allowed only to the definer or\nusers with\nthe SUPER privilege.\n \nExample\n \nALTER VIEW v AS SELECT a, a*3 AS a2 FROM t;\n \n\n\nURL: https://mariadb.com/kb/en/alter-view/','','https://mariadb.com/kb/en/alter-view/'),(656,'CREATE DATABASE',39,'Syntax\n------ \nCREATE [OR REPLACE] {DATABASE | SCHEMA} [IF NOT EXISTS]\ndb_name\n [create_specification] ...\n \ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n \nDescription\n----------- \nCREATE DATABASE creates a database with the given name. To\nuse this statement, you need the CREATE privilege for the\ndatabase. CREATE SCHEMA is a synonym for CREATE DATABASE.\n \nFor valid identifiers to use as database names, see\nIdentifier Names.\n \nOR REPLACE\n \nThe OR REPLACE clause was added in MariaDB 10.1.3\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP DATABASE IF EXISTS db_name;\n \nCREATE DATABASE db_name ...;\n \nIF NOT EXISTS\n \nWhen the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the specified database\nalready exists.\n \nExamples\n-------- \nCREATE DATABASE db1;\n \nQuery OK, 1 row affected (0.18 sec)\n \nCREATE DATABASE db1;\n \nERROR 1007 (HY000): Can\'t create database \'db1\'; database\nexists\n \nCREATE OR REPLACE DATABASE db1;\nQuery OK, 2 rows affected (0.00 sec)\n \nCREATE DATABASE IF NOT EXISTS db1;\nQuery OK, 1 row affected, 1 warning (0.01 sec)\n \nSHOW WARNINGS;\n+-------+------+----------------------------------------------+\n| Level | Code | Message |\n+-------+------+----------------------------------------------+\n| Note | 1007 | Can\'t create database \'db1\';\n database exists |\n+-------+------+----------------------------------------------+\n \nSetting the character sets and collation. See Setting\nCharacter Sets and Collations for more details.\n \nCREATE DATABASE czech_slovak_names \n CHARACTER SET = \'keybcs2\'\n COLLATE = \'keybcs2_bin\';\n \n\n\nURL: https://mariadb.com/kb/en/create-database/','','https://mariadb.com/kb/en/create-database/'),(650,'ALTER SEQUENCE',39,'ALTER SEQUENCE was introduced in MariaDB 10.3.\n \nSyntax\n------ \nALTER SEQUENCE [IF EXISTS] sequence_name\n[ INCREMENT [ BY | = ] increment ]\n[ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]\n[ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]\n[ START [ WITH | = ] start ] [ CACHE [=] cache ] [ [ NO ]\nCYCLE ]\n[ RESTART [[WITH | =] restart]\n \nALTER SEQUENCE allows one to change any values for a\nSEQUENCE created with CREATE SEQUENCE.\n \nThe options for ALTER SEQUENCE can be given in any order.\n \nDescription\n----------- \nALTER SEQUENCE changes the parameters of an existing\nsequence generator. Any parameters not specifically set in\nthe ALTER SEQUENCE command retain their prior settings.\n \nALTER SEQUENCE requires the ALTER privilege.\n \nArguments to ALTER SEQUENCE\n \nThe following options may be used:\n \nOption | Default value | Description | \n \nINCREMENT | 1 | Increment to use for values. May be\nnegative. | \n \nMINVALUE | 1 if INCREMENT > 0 and -9223372036854775807 if\nINCREMENT < 0 | Minimum value for the sequence. | \n \nMAXVALUE | 9223372036854775806 if INCREMENT > 0 and -1 if\nINCREMENT < 0 | Max value for sequence. | \n \nSTART | MINVALUE if INCREMENT > 0 and MAX_VALUE if\nINCREMENT< 0 | First value that the sequence will generate.\n| \n \nCACHE | 1000 | Number of values that should be cached. 0 if\nno CACHE. The underlying table will be updated first time a\nnew sequence number is generated and each time the cache\nruns out. | \n \nCYCLE | 0 (= NO CYCLE) | 1 if the sequence should start\nagain from MINVALUE# after it has run out of values. | \n \nRESTART | START if restart value not is given |  If RESTART\noption is used, NEXT VALUE will return the restart value. | \n \nThe optional clause RESTART [ WITH restart ] sets the next\nvalue for the sequence. This is equivalent to calling the\nSETVAL() function with the is_used argument as 0. The\nspecified value will be returned by the next call of\nnextval. Using RESTART with no restart value is\nequivalent to supplying the start value that was recorded by\nCREATE SEQUENCE or last set by ALTER SEQUENCE START WITH.\n \nALTER SEQUENCE will not allow you to change the sequence so\nthat it\'s inconsistent. For example:\n \nCREATE SEQUENCE s1;\nALTER SEQUENCE s1 MINVALUE 10;\nERROR 4061 (HY000): Sequence \'test.t1\' values are\nconflicting\n \nALTER SEQUENCE s1 MINVALUE 10 RESTART 10;\nERROR 4061 (HY000): Sequence \'test.t1\' values are\nconflicting\n \nALTER SEQUENCE s1 MINVALUE 10 START 10 RESTART 10;\n \nINSERT\n \nTo allow SEQUENCE objects to be backed up by old tools, like\nmysqldump, one can use SELECT to read the current state of a\nSEQUENCE object and use an INSERT to update the SEQUENCE\nobject. INSERT is only allowed if all fields are specified:\n \nCREATE SEQUENCE s1;\nINSERT INTO s1 VALUES(1000,10,2000,1005,1,1000,0,0);\nSELECT * FROM s1;\n \n+------------+-----------+-----------+-------+-----------+-------+-------+-------+\n| next_value | min_value | max_value | start | increment |\ncache | cycle | round |\n+------------+-----------+-----------+-------+-----------+-------+-------+-------+\n| 1000 | 10 | 2000 | 1005 | 1 | 1000 | 0 | 0 |\n+------------+-----------+-----------+-------+-----------+-------+-------+-------+\n \nSHOW CREATE SEQUENCE s1;\n+-------+--------------------------------------------------------------------------------------------------------------+\n| Table | Create Table |\n+-------+--------------------------------------------------------------------------------------------------------------+\n| s1 | CREATE SEQUENCE `s1` start with 1005 minvalue 10\nmaxvalue 2000 increment by 1 cache 1000 nocycle ENGINE=Aria\n|\n+-------+--------------------------------------------------------------------------------------------------------------+\n \nNotes\n \nALTER SEQUENCE will instantly affect all future SEQUENCE\noperations. This is in contrast to some other databases\nwhere the changes requested by ALTER SEQUENCE will not be\nseen until the sequence cache has run out.\n \nALTER SEQUENCE will take a full table lock of the sequence\nobject during\nits (brief) operation. This ensures that ALTER SEQUENCE is\nreplicated\ncorrectly. If you only want to set the next sequence value\nto a\nhigher value than current, then you should use SETVAL()\ninstead, as this is not blocking.\n \nIf you want to change storage engine, sequence comment or\nrename the sequence, you can use ALTER TABLE for this.\n \n\n\nURL: https://mariadb.com/kb/en/alter-sequence/','','https://mariadb.com/kb/en/alter-sequence/'),(660,'CREATE PACKAGE',39,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nCREATE\n [ OR REPLACE]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n PACKAGE [ IF NOT EXISTS ]\n [ db_name . ] package_name\n [ package_characteristic ... ]\n{ AS | IS }\n [ package_specification_element ... ]\nEND [ package_name ]\n \npackage_characteristic:\n COMMENT \'string\'\n | SQL SECURITY { DEFINER | INVOKER }\n \npackage_specification_element:\n FUNCTION_SYM package_specification_function ;\n | PROCEDURE_SYM package_specification_procedure ;\n \npackage_specification_function:\n func_name [ ( func_param [, func_param]... ) ]\n RETURNS func_return_type\n [ package_routine_characteristic... ]\n \npackage_specification_procedure:\n proc_name [ ( proc_param [, proc_param]... ) ]\n [ package_routine_characteristic... ]\n \nfunc_return_type:\n type\n \nfunc_param:\n param_name type\n \nproc_param:\n param_name { IN | OUT | INOUT | IN OUT } type\n \ntype:\n Any valid MariaDB explicit or anchored data type\n \npackage_routine_characteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL\nDATA }\n | SQL SECURITY { DEFINER | INVOKER }\n \nDescription\n----------- \nThe CREATE PACKAGE statement can be used when Oracle\nSQL_MODE is set.\n \nThe CREATE PACKAGE creates the specification for a stored\npackage (a collection of logically related stored objects).\nA stored package specification declares public routines\n(procedures and functions) of the package, but does not\nimplement these routines.\n \nA package whose specification was created by the CREATE\nPACKAGE statement, should later be implemented using the\nCREATE PACKAGE BODY statement.\n \nExamples\n-------- \nSET sql_mode=ORACLE;\nDELIMITER $$\nCREATE OR REPLACE PACKAGE employee_tools AS\n FUNCTION getSalary(eid INT) RETURN DECIMAL(10,2);\n PROCEDURE raiseSalary(eid INT, amount DECIMAL(10,2));\n PROCEDURE raiseSalaryStd(eid INT);\n PROCEDURE hire(ename TEXT, esalary DECIMAL(10,2));\nEND;\n$$\nDELIMITER ;\n \n\n\nURL: https://mariadb.com/kb/en/create-package/','','https://mariadb.com/kb/en/create-package/'),(655,'CONSTRAINT',39,'MariaDB supports the implementation of constraints at the\ntable-level using either CREATE TABLE or ALTER TABLE\nstatements. A table constraint restricts the data you can\nadd to the table. If you attempt to insert invalid data on a\ncolumn, MariaDB throws an error. \n \nSyntax\n------ \n[CONSTRAINT [symbol]] constraint_expression\n \nconstraint_expression:\n | PRIMARY KEY [index_type] (index_col_name, ...)\n[index_option] ...\n | FOREIGN KEY [index_name] (index_col_name, ...) \n REFERENCES tbl_name (index_col_name, ...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n | UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name, ...) [index_option] ...\n | CHECK (check_constraints)\n \nindex_type:\n USING {BTREE | HASH | RTREE}\n \nindex_col_name:\n col_name [(length)] [ASC | DESC]\n \nindex_option:\n | KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n | CLUSTERING={YES|NO}\n \nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT\n \nDescription\n----------- \nConstraints provide restrictions on the data you can add to\na table. This allows you to enforce data integrity from\nMariaDB, rather than through application logic. When a\nstatement violates a constraint, MariaDB throws an error.\n \nThere are four types of table constraints:\n \nConstraint | Description | \n \nPRIMARY KEY | Sets the column for referencing rows. Values\nmust be unique and not null. | \n \nFOREIGN KEY | Sets the column to reference the primary key\non another table. | \n \nUNIQUE | Requires values in column or columns only occur\nonce in the table. | \n \nCHECK | Checks whether the data meets the given condition. |\n\n \nFOREIGN KEY Constraints\n \nInnoDB supports foreign key constraints. The syntax for a\nforeign key\nconstraint definition in InnoDB looks like this:\n \n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n \nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n \nCHECK Constraints\n \nFrom MariaDB 10.2.1, constraints are enforced. Before\nMariaDB 10.2.1 constraint expressions were accepted in the\nsyntax but ignored.\n \nIn MariaDB 10.2.1 you can define constraints in 2 different\nways:\nCHECK(expression) given as part of a column definition.\nCONSTRAINT [constraint_name] CHECK (expression)\n \nBefore a row is inserted or updated, all constraints are\nevaluated in the order they are defined. If any constraint\nexpression returns false, then the row will not be inserted\nor updated.\nOne can use most deterministic functions in a constraint,\nincluding UDFs.\n \nCREATE TABLE t1 (a INT CHECK (a>2), b INT CHECK (b>2),\nCONSTRAINT a_greater CHECK (a>b));\n \nIf you use the second format and you don\'t give a name to\nthe constraint, then the constraint will get an\nautomatically generated name. This is done so that you can\nlater delete the constraint with ALTER TABLE DROP\nconstraint_name.\n \nOne can disable all constraint expression checks by setting\nthe check_constraint_checks variable to OFF. This is useful\nfor example when loading a table that violates some\nconstraints that you want to later find and fix in SQL.\n \nReplication\n \nIn row-based replication, only the master checks\nconstraints, and failed statements will not be replicated.\nIn statement-based replication, the slaves will also check\nconstraints. Constraints should therefore be identical, as\nwell as deterministic, in a replication environment.\n \nAuto_increment\n \nFrom MariaDB 10.2.6, auto_increment columns are no longer\npermitted in check constraints. Previously they were\npermitted, but would not work correctly. See MDEV-11117.\n \nExamples\n-------- \nCREATE TABLE product (category INT NOT NULL, id INT NOT\nNULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\n \nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\n \nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n \nThe following examples will work from MariaDB 10.2.1\nonwards.\n \nNumeric constraints and comparisons:\n \nCREATE TABLE t1 (a INT CHECK (a>2), b INT CHECK (b>2),\nCONSTRAINT a_greater CHECK (a>b));\n \nINSERT INTO t1(a) VALUES (1);\nERROR 4022 (23000): CONSTRAINT `a` failed for `test`.`t1`\n \nINSERT INTO t1(a,b) VALUES (3,4);\nERROR 4022 (23000): CONSTRAINT `a_greater` failed for\n`test`.`t1`\n \nINSERT INTO t1(a,b) VALUES (4,3);\nQuery OK, 1 row affected (0.04 sec)\n \nDropping a constraint:\n \nALTER TABLE t1 DROP CONSTRAINT a_greater;\n \nAdding a constraint:\n \nALTER TABLE t1 ADD CONSTRAINT a_greater CHECK (a>b);\n \nDate comparisons and character length:\n \nCREATE TABLE t2 (name VARCHAR(30) CHECK\n(CHAR_LENGTH(name)>2), start_date DATE, \n end_date DATE CHECK (start_date IS NULL OR end_date IS NULL\nOR start_date2)), start_date DATE, \n end_date DATE CHECK (start_date IS NULL OR end_date IS NULL\nOR start_date2 is very different to CHAR_LENGTH(name>2) as\nthe latter mistakenly performs a numeric comparison on the\nname field, leading to unexpected results.\n \n\n\nURL: https://mariadb.com/kb/en/constraint/','','https://mariadb.com/kb/en/constraint/'),(657,'CREATE EVENT',39,'Syntax\n------ \nCREATE [OR REPLACE]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n EVENT \n [IF NOT EXISTS]\n event_name \n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO sql_statement;\n \nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval \n [STARTS timestamp [+ INTERVAL interval] ...] \n [ENDS timestamp [+ INTERVAL interval] ...]\n \ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n \nDescription\n----------- \nThis statement creates and schedules a new event. It\nrequires the\nEVENT privilege for the schema in which the event is to be\ncreated.\n \nThe minimum requirements for a valid CREATE EVENT statement\nare as\nfollows:\nThe keywords CREATE EVENT plus an event name, which uniquely\nidentifies\n the event in the current schema. (Prior to MySQL 5.1.12,\nthe event name\n needed to be unique only among events created by the same\nuser on a given\n database.)\nAn ON SCHEDULE clause, which determines when and how often\nthe event\n executes.\nA DO clause, which contains the SQL statement to be executed\nby an\n event.\n \nHere is an example of a minimal CREATE EVENT statement:\n \nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n \nThe previous statement creates an event named myevent. This\nevent executes once\n— one hour following its creation\n— by running an SQL statement that increments the\nvalue of the myschema.mytable table\'s mycol column by 1.\n \nThe event_name must be a valid MariaDB identifier with a\nmaximum length\nof 64 characters. It may be delimited using back ticks, and\nmay be\nqualified with the name of a database schema. An event is\nassociated\nwith both a MariaDB user (the definer) and a schema, and its\nname must\nbe unique among names of events within that schema. In\ngeneral, the\nrules governing event names are the same as those for names\nof stored\nroutines. See Identifier Names.\n \nIf no schema is indicated as part of event_name, the default\n(current)\nschema is assumed.\n \nFor valid identifiers to use as event names, see Identifier\nNames.\n \nOR REPLACE\n \nThe OR REPLACE clause was included in MariaDB 10.1.4. If\nused and the event already exists, instead of an error being\nreturned, the existing event will be dropped and replaced by\nthe newly defined event.\n \nIF NOT EXISTS\n \nIf the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the event already exists.\nCannot be used together with OR REPLACE.\n \nON SCHEDULE\n \nThe ON SCHEDULE clause can be used to specify when the event\nmust be triggered.\n \nAT\n \nIf you want to execute the event only once (one time event),\nyou can use the AT keyword, followed by a timestamp. If you\nuse CURRENT_TIMESTAMP, the event acts as soon as it is\ncreated. As a convenience, you can add one or more intervals\nto that timestamp. You can also specify a timestamp in the\npast, so that the event is stored but not triggered, until\nyou modify it via ALTER EVENT.\n \nThe following example shows how to create an event that will\nbe triggered tomorrow at a certain time:\n \nCREATE EVENT example\nON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY + INTERVAL\n3 HOUR\nDO something;\n \nYou can also specify that an event must be triggered at a\nregular interval (recurring event). In such cases, use the\nEVERY clause followed by the interval.\n \nIf an event is recurring, you can specify when the first\nexecution must happen via the STARTS clause and a maximum\ntime for the last execution via the ENDS clause. STARTS and\nENDS clauses are followed by a timestamp and, optionally,\none or more intervals. The ENDS clause can specify a\ntimestamp in the past, so that the event is stored but not\nexecuted until you modify it via ALTER EVENT.\n \nIn the following example, next month a recurring event will\nbe triggered hourly for a week:\n \nCREATE EVENT example\nON SCHEDULE EVERY 1 HOUR\nSTARTS CURRENT_TIMESTAMP + INTERVAL 1 MONTH\nENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH + INTERVAL 1 WEEK\nDO some_task;\n \nIntervals consist of a quantity and a time unit. The time\nunits are the same used for other staments and time\nfunctions, except that you can\'t use microseconds for\nevents. For simple time units, like HOUR or MINUTE, the\nquantity is an integer number, for example \'10 MINUTE\'.\nFor composite time units, like HOUR_MINUTE or HOUR_SECOND,\nthe quantity must be a string with all involved simple\nvalues and their separators, for example \'2:30\' or\n\'2:30:30\'.\n \nON COMPLETION [NOT] PRESERVE\n \nThe ON COMPLETION clause can be used to specify if the event\nmust be deleted after its last execution (that is, after its\nAT or ENDS timestamp is past). By default, events are\ndropped when they are expired. To explicitly state that this\nis the desired behaviour, you can use ON COMPLETION NOT\nPRESERVE. Instead, if you want the event to be preserved,\nyou can use ON COMPLETION PRESERVE.\n \nIn you specify ON COMPLETION NOT PRESERVE, and you specify a\ntimestamp in the past for AT or ENDS clause, the event will\nbe immediatly dropped. In such cases, you will get a Note\n1558: \"Event execution time is in the past and ON\nCOMPLETION NOT PRESERVE is set. The event was dropped\nimmediately after creation\".\n \nENABLE/DISABLE/DISABLE ON SLAVE\n \nEvents are ENABLEd by default. If you want to stop MariaDB\nfrom executing\nan event, you may specify DISABLE. When it is ready to be\nactivated, you\nmay enable it using ALTER EVENT. Another option is\nDISABLE ON SLAVE, which indicates that an event was created\non a master and has been replicated to the slave, which is\nprevented from executing the event. If DISABLE ON SLAVE is\nspecifically set, the event will not be executed.\n \nCOMMENT\n \nThe COMMENT clause may be used to set a comment for the\nevent. Maximum\nlength for comments is 64 characters. The comment is a\nstring, so it must be\nquoted. To see events comments, you can query the\nINFORMATION_SCHEMA.EVENTS table (the column is named\nEVENT_COMMENT).\n \nExamples\n-------- \nMinimal CREATE EVENT statement:\n \nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n \nAn event that will be triggered tomorrow at a certain time:\n \nCREATE EVENT example\nON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY + INTERVAL\n3 HOUR\nDO something;\n \nNext month a recurring event will be triggered hourly for a\nweek:\n \nCREATE EVENT example\nON SCHEDULE EVERY 1 HOUR\nSTARTS CURRENT_TIMESTAMP + INTERVAL 1 MONTH\nENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH + INTERVAL 1 WEEK\nDO some_task;\n \nOR REPLACE and IF NOT EXISTS:\n \nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n \nERROR 1537 (HY000): Event \'myevent\' already exists\n \nCREATE OR REPLACE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;;\nQuery OK, 0 rows affected (0.00 sec)\n \nCREATE EVENT IF NOT EXISTS myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \n SHOW WARNINGS;\n \n+-------+------+--------------------------------+\n| Level | Code | Message |\n+-------+------+--------------------------------+\n| Note | 1537 | Event \'myevent\' already exists |\n+-------+------+--------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-event/','','https://mariadb.com/kb/en/create-event/'),(659,'CREATE INDEX',39,'Syntax\n------ \nCREATE [OR REPLACE] [UNIQUE|FULLTEXT|SPATIAL] INDEX \n [IF NOT EXISTS] index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [WAIT n | NOWAIT]\n [index_option]\n [algorithm_option | lock_option] ...\n \nindex_col_name:\n col_name [(length)] [ASC | DESC]\n \nindex_type:\n USING {BTREE | HASH | RTREE}\n \nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n \nalgorithm_option:\n ALGORITHM [=] {DEFAULT|INPLACE|COPY|NOCOPY|INSTANT}\n \nlock_option:\n LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n \nDescription\n----------- \nCREATE INDEX is mapped to an ALTER TABLE statement to create\nindexes.\nSee ALTER TABLE. CREATE INDEX cannot be used to create a\nPRIMARY KEY; use ALTER TABLE instead.\n \nIf another connection is using the table, a metadata lock is\nactive, and this statement will wait until the lock is\nreleased. This is also true for non-transactional tables.\n \nAnother shortcut, DROP INDEX, allows the removal of an\nindex.\n \nFor valid identifiers to use as index names, see Identifier\nNames.\n \nNote that KEY_BLOCK_SIZE is currently ignored in CREATE\nINDEX, although it is included in the output of SHOW CREATE\nTABLE.\n \nPrivileges\n \nExecuting the CREATE INDEX statement requires the INDEX\nprivilege for the table or the database.\n \nOnline DDL\n \nIn MariaDB 10.0 and later, online DDL is supported with the\nALGORITHM and LOCK clauses.\n \nSee InnoDB Online DDL Overview for more information on\nonline DDL with InnoDB.\n \nCREATE OR REPLACE INDEX ...\n \nThe OR REPLACE clause was added in MariaDB 10.1.4.\n \nIf the OR REPLACE clause is used and if the index already\nexists, then instead of returning an error, the server will\ndrop the existing index and replace it with the newly\ndefined index.\n \nCREATE INDEX IF NOT EXISTS ...\n \nIf the IF NOT EXISTS clause is used, then the index will\nonly be created if an index with the same name does not\nalready exist. If the index already exists, then a warning\nwill be triggered by default.\n \nIndex Definitions\n \nSee CREATE TABLE: Index Definitions for information about\nindex definitions.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nALGORITHM\n \nSee ALTER TABLE: ALGORITHM for more information.\n \nLOCK\n \nSee ALTER TABLE: LOCK for more information.\n \nProgress Reporting\n \nMariaDB provides progress reporting for CREATE INDEX\nstatement for clients\nthat support the new progress reporting protocol. For\nexample, if you were using the mysql client, then the\nprogress report might look like this::\n \nCREATE INDEX ON tab (num);;\nStage: 1 of 2 \'copy to tmp table\' 46% of stage\n \nThe progress report is also shown in the output of the SHOW\nPROCESSLIST statement and in the contents of the\ninformation_schema.PROCESSLIST table.\n \nSee Progress Reporting for more information.\n \nExamples\n-------- \nCreating a unique index:\n \nCREATE UNIQUE INDEX HomePhone ON Employees(Home_Phone);\n \nOR REPLACE and IF NOT EXISTS:\n \nCREATE INDEX xi ON xx5 (x);\nQuery OK, 0 rows affected (0.03 sec)\n \nCREATE INDEX xi ON xx5 (x);\nERROR 1061 (42000): Duplicate key name \'xi\'\n \nCREATE OR REPLACE INDEX xi ON xx5 (x);\nQuery OK, 0 rows affected (0.03 sec)\n \nCREATE INDEX IF NOT EXISTS xi ON xx5 (x);\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+-------------------------+\n| Level | Code | Message |\n+-------+------+-------------------------+\n| Note | 1061 | Duplicate key name \'xi\' |\n+-------+------+-------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-index/','','https://mariadb.com/kb/en/create-index/'),(663,'CREATE SEQUENCE',39,'CREATE SEQUENCE was introduced in MariaDB 10.3.\n \nSyntax\n------ \nCREATE [OR REPLACE] [TEMPORARY] SEQUENCE [IF NOT EXISTS]\nsequence_name\n[ INCREMENT [ BY | = ] increment ]\n[ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]\n[ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]\n[ START [ WITH | = ] start ] \n[ CACHE [=] cache | NOCACHE ] [ CYCLE | NOCYCLE] \n[table_options]\n \nThe options for CREATE SEQUENCE can be given in any order,\noptionally followed by table_options.\n \ntable_options can be any of the normal table options in\nCREATE TABLE but the most usable ones are ENGINE=... and\nCOMMENT=.\n \nNOMAXVALUE and NOMINVALUE are there to allow one to create\nSEQUENCEs using the Oracle syntax.\n \nDescription\n----------- \nCREATE SEQUENCE will create a sequence that generates new\nvalues when called with NEXT VALUE FOR sequence_name. It\'s\nan alternative to AUTO INCREMENT when one wants to have more\ncontrol of how the numbers are generated. As the SEQUENCE\ncaches values (up to CACHE) it can in some cases be much\nfaster than AUTO INCREMENT. Another benefit is that one can\naccess the last value generated by all used sequences, which\nsolves one of the limitations with LAST_INSERT_ID().\n \nCREATE SEQUENCE requires the CREATE privilege.\n \nDROP SEQUENCE can be used to drop a sequence, and ALTER\nSEQUENCE to change it.\n \nArguments to Create\n \nThe following options may be used:\n \nOption | Default value |  Description | \n \nINCREMENT |  1 | Increment to use for values. May be\nnegative. Setting an increment of 0 causes the sequence to\nuse the value of the auto_increment_increment system\nvariable at the time of creation, which is always a positive\nnumber. (see MDEV-16035). | \n \nMINVALUE | 1 if INCREMENT > 0 and -9223372036854775807 if\nINCREMENT < 0 | Minimum value for the sequence | \n \nMAXVALUE | 9223372036854775806 if INCREMENT > 0 and -1 if\nINCREMENT < 0 | Max value for sequence | \n \nSTART | MINVALUE if INCREMENT > 0 and MAX_VALUE if\nINCREMENT< 0 | First value that the sequence will generate |\n\n \nCACHE | 1000 |  Number of values that should be cached. 0\nif no CACHE. The underlying table will be updated first time\na new sequence number is generated and each time the cache\nruns out. | \n \nIf CYCLE is used then the sequence should start again from\nMINVALUE after it has run out of values. Default value is\nNOCYCLE.\n \nConstraints on Create Arguments\n \nTo be able to create a legal sequence, the following must\nhold:\nMAXVALUE >= start\nMAXVALUE > MINVALUE\nSTART >= MINVALUE\nMAXVALUE = -9223372036854775807 (LONGLONG_MIN+1)\n \nNote that sequences can\'t generate the maximum/minimum 64\nbit number because of the constraint of\nMINVALUE and MAXVALUE. \n \nExamples\n-------- \nCREATE SEQUENCE s START WITH 100 INCREMENT BY 10;\n \nCREATE SEQUENCE s2 START WITH -100 INCREMENT BY -10;\n \nThe following statement fails, as the increment conflicts\nwith the defaults\n \nCREATE SEQUENCE s3 START WITH -100 INCREMENT BY 10;\n \nERROR 4082 (HY000): Sequence \'test.s3\' values are\nconflicting\n \nThe sequence can be created by specifying workable minimum\nand maximum values:\n \nCREATE SEQUENCE s3 START WITH -100 INCREMENT BY 10\nMINVALUE=-100 MAXVALUE=1000;\n \n\n\nURL: https://mariadb.com/kb/en/create-sequence/','','https://mariadb.com/kb/en/create-sequence/'),(661,'CREATE PACKAGE BODY',39,'Oracle-style packages were introduced in MariaDB 10.3.5.\n \nSyntax\n------ \nCREATE [ OR REPLACE ]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n PACKAGE BODY\n [ IF NOT EXISTS ]\n [ db_name . ] package_name\n [ package_characteristic... ]\n{ AS | IS }\n package_implementation_declare_section\n package_implementation_executable_section\nEND [ package_name]\n \npackage_implementation_declare_section:\n package_implementation_item_declaration\n [ package_implementation_item_declaration... ]\n [ package_implementation_routine_definition... ]\n | package_implementation_routine_definition\n [ package_implementation_routine_definition...]\n \npackage_implementation_item_declaration:\n variable_declaration ;\n \nvariable_declaration:\n variable_name[,...] type [:= expr ]\n \npackage_implementation_routine_definition:\n FUNCTION package_specification_function\n [ package_implementation_function_body ] ;\n | PROCEDURE package_specification_procedure\n [ package_implementation_procedure_body ] ;\n \npackage_implementation_function_body:\n { AS | IS } package_routine_body [func_name]\n \npackage_implementation_procedure_body:\n { AS | IS } package_routine_body [proc_name]\n \npackage_routine_body:\n [ package_routine_declarations ]\n BEGIN\n statements [ EXCEPTION exception_handlers ]\n END\n \npackage_routine_declarations:\n package_routine_declaration \';\'\n[package_routine_declaration \';\']...\n \npackage_routine_declaration:\n variable_declaration\n | condition_name CONDITION FOR condition_value\n | user_exception_name EXCEPTION\n | CURSOR_SYM cursor_name\n [ ( cursor_formal_parameters ) ]\n IS select_statement\n ;\n \npackage_implementation_executable_section:\n END\n | BEGIN\n statement ; [statement ; ]...\n [EXCEPTION exception_handlers]\n END\n \nexception_handlers:\n exception_handler [exception_handler...]\n \nexception_handler:\n WHEN_SYM condition_value [, condition_value]...\n THEN_SYM statement ; [statement ;]...\n \ncondition_value:\n condition_name\n | user_exception_name\n | SQLWARNING\n | SQLEXCEPTION\n | NOT FOUND\n | OTHERS_SYM\n | SQLSTATE [VALUE] sqlstate_value\n | mariadb_error_code\n \n\nDescription\n----------- \nThe CREATE PACKAGE BODY statement can be used when Oracle\nSQL_MODE is set.\n \nThe CREATE PACKAGE BODY statement creates the package body\nfor a stored package. The package specification must be\npreviously created using the CREATE PACKAGE statement.\n \nA package body provides implementations of the package\npublic routines and can optionally have:\npackage-wide private variables\npackage private routines\nforward declarations for private routines\nan executable initialization section\n \nExamples\n-------- \nSET sql_mode=ORACLE;\nDELIMITER $$\nCREATE OR REPLACE PACKAGE employee_tools AS\n FUNCTION getSalary(eid INT) RETURN DECIMAL(10,2);\n PROCEDURE raiseSalary(eid INT, amount DECIMAL(10,2));\n PROCEDURE raiseSalaryStd(eid INT);\n PROCEDURE hire(ename TEXT, esalary DECIMAL(10,2));\nEND;\n$$\nCREATE PACKAGE BODY employee_tools AS\n -- package body variables\n stdRaiseAmount DECIMAL(10,2):=500;\n \n -- private routines\n PROCEDURE log (eid INT, ecmnt TEXT) AS\n BEGIN\n INSERT INTO employee_log (id, cmnt) VALUES (eid, ecmnt);\n END;\n \n -- public routines\n PROCEDURE hire(ename TEXT, esalary DECIMAL(10,2)) AS\n eid INT;\n BEGIN\n INSERT INTO employee (name, salary) VALUES (ename,\nesalary);\n eid:= last_insert_id();\n log(eid, \'hire \' || ename);\n END;\n \n FUNCTION getSalary(eid INT) RETURN DECIMAL(10,2) AS\n nSalary DECIMAL(10,2);\n BEGIN\n SELECT salary INTO nSalary FROM employee WHERE id=eid;\n log(eid, \'getSalary id=\' || eid || \' salary=\' ||\nnSalary);\n RETURN nSalary;\n END;\n \n PROCEDURE raiseSalary(eid INT, amount DECIMAL(10,2)) AS\n BEGIN\n UPDATE employee SET salary=salary+amount WHERE id=eid;\n log(eid, \'raiseSalary id=\' || eid || \' amount=\' ||\namount);\n END;\n \n PROCEDURE raiseSalaryStd(eid INT) AS\n BEGIN\n raiseSalary(eid, stdRaiseAmount);\n log(eid, \'raiseSalaryStd id=\' || eid);\n END;\n \nBEGIN\n -- This code is executed when the current session\n -- accesses any of the package routines for the first time\n log(0, \'Session \' || connection_id() || \' \' ||\ncurrent_user || \' started\');\nEND;\n$$\n \nDELIMITER ;\n \n\n\nURL: https://mariadb.com/kb/en/create-package-body/','','https://mariadb.com/kb/en/create-package-body/'),(669,'DROP DATABASE',39,'Syntax\n------ \nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n \nDescription\n----------- \nDROP DATABASE drops all tables in the database and deletes\nthe database. Be very careful with this statement! To use\nDROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is\na synonym for DROP DATABASE.\n \nImportant: When a database is dropped, user privileges on\nthe database are not automatically dropped. See GRANT.\n \nIF EXISTS\n \nUse IF EXISTS to prevent an error from occurring for\ndatabases that do not exist. A NOTE is generated for each\nnon-existent database when using IF EXISTS. See SHOW\nWARNINGS.\n \nExamples\n-------- \nDROP DATABASE bufg;\n \nQuery OK, 0 rows affected (0.39 sec)\n \nDROP DATABASE bufg;\n \nERROR 1008 (HY000): Can\'t drop database \'bufg\'; database\ndoesn\'t exist\n \n \\W\nShow warnings enabled.\n \nDROP DATABASE IF EXISTS bufg;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\nNote (Code 1008): Can\'t drop database \'bufg\'; database\ndoesn\'t exist\n \n\n\nURL: https://mariadb.com/kb/en/drop-database/','','https://mariadb.com/kb/en/drop-database/'),(664,'CREATE SERVER',39,'Syntax\n------ \nCREATE [OR REPLACE] SERVER [IF NOT EXISTS] server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n \noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n \nDescription\n----------- \nThis statement creates the definition of a server for use\nwith the Spider,\nFEDERATED or FederatedX storage\nengine. The CREATE SERVER statement creates a new row within\nthe\nservers table within the mysql database. This statement\nrequires the SUPER privilege.\n \nThe server_name should be a unique reference to the server.\nServer definitions\nare global within the scope of the server, it is not\npossible to qualify the\nserver definition to a specific database. server_name has a\nmaximum length of\n64 characters (names longer than 64 characters are silently\ntruncated), and is\ncase insensitive. You may specify the name as a quoted\nstring.\n \nThe wrapper_name should be mysql, and may be quoted with\nsingle quotes.\nOther values for wrapper_name are not currently supported.\n \nFor each option you must specify either a character literal\nor numeric literal.\nCharacter literals are UTF-8, support a maximum length of 64\ncharacters and\ndefault to a blank (empty) string. String literals are\nsilently truncated to 64\ncharacters. Numeric literals must be a number between 0 and\n9999, default value\nis 0.\n \nNote: The OWNER option is currently not applied, and has no\neffect on\nthe ownership or operation of the server connection that is\ncreated.\n \nThe CREATE SERVER statement creates an entry in the\nmysql.servers table that can later be used with the\nCREATE TABLE statement when creating a Spider, FederatedX or\nFEDERATED table. The options that you specify will\nbe used to populate the columns in the mysql.servers table.\nThe table columns\nare Server_name, Host, Db, Username, Password, Port and\nSocket.\n \n DROP SERVER removes a previously created server definition.\n\n \nCREATE SERVER is not written to the binary log, irrespective\nof\nthe binary log format being used.\n \nFor valid identifiers to use as server names, see Identifier\nNames.\n \nOR REPLACE\n \nIf the optional OR REPLACE clause is used, it acts as a\nshortcut for:\n \nDROP SERVER IF EXISTS name;\n \nCREATE SERVER server_name ...;\n \nIF NOT EXISTS\n \nIf the IF NOT EXISTS clause is used, MariaDB will return a\nwarning instead of an error if the server already exists.\nCannot be used together with OR REPLACE.\n \nExamples\n-------- \nCREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE\n\'test\');\n \nOR REPLACE and IF NOT EXISTS:\n \nCREATE SERVER s \nFOREIGN DATA WRAPPER mysql \nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE\n\'test\');\nERROR 1476 (HY000): The foreign server, s, you are trying to\ncreate already exists\n \nCREATE OR REPLACE SERVER s \nFOREIGN DATA WRAPPER mysql \nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE\n\'test\');\nQuery OK, 0 rows affected (0.00 sec)\n \nCREATE SERVER IF NOT EXISTS s \nFOREIGN DATA WRAPPER mysql \nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE\n\'test\');\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+----------------------------------------------------------------+\n| Level | Code | Message |\n+-------+------+----------------------------------------------------------------+\n| Note | 1476 | The foreign server, s, you are trying to\ncreate already exists |\n+-------+------+----------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/create-server/','','https://mariadb.com/kb/en/create-server/'),(670,'DROP EVENT',39,'Syntax\n------ \nDROP EVENT [IF EXISTS] event_name\n \nDescription\n----------- \nThis statement drops the event named event_name. The event\nimmediately\nceases being active, and is deleted completely from the\nserver.\n \nIf the event does not exist, the error\nERROR 1517 (HY000): Unknown event \'event_name\'\nresults. You can override this and cause the\nstatement to generate a NOTE for non-existent events instead\nby using\nIF EXISTS. See SHOW WARNINGS.\n \nThis statement requires the EVENT privilege. In MySQL 5.1.11\nand earlier, an event could be dropped only\nby its definer, or by a user having the SUPER privilege.\n \nExamples\n-------- \nDROP EVENT myevent3;\n \nUsing the IF EXISTS clause:\n \nDROP EVENT IF EXISTS myevent3;\n \nQuery OK, 0 rows affected, 1 warning (0.01 sec)\n \nSHOW WARNINGS;\n \n+-------+------+-------------------------------+\n| Level | Code | Message |\n+-------+------+-------------------------------+\n| Note | 1305 | Event myevent3 does not exist |\n+-------+------+-------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-event/','','https://mariadb.com/kb/en/drop-event/'),(671,'DROP FUNCTION',39,'Syntax\n------ \nDROP FUNCTION [IF EXISTS] f_name\n \nDescription\n----------- \nThe DROP FUNCTION statement is used to drop a stored\nfunction or a user-defined function (UDF). That is, the\nspecified routine is removed from the server, along with all\nprivileges specific to the function. You must have the ALTER\nROUTINE privilege for the routine in order to drop it. If\nthe automatic_sp_privileges server system variable is set,\nboth the ALTER ROUTINE and EXECUTE privileges are granted\nautomatically to the routine creator - see Stored Routine\nPrivileges.\n \nIF EXISTS\n \nThe IF EXISTS clause is a MySQL/MariaDB extension. It\nprevents an error from occurring if the function does not\nexist. A\nNOTE is produced that can be viewed with SHOW WARNINGS.\n \nFor dropping a user-defined functions (UDF), see DROP\nFUNCTION UDF.\n \nExamples\n-------- \nDROP FUNCTION hello;\n \nQuery OK, 0 rows affected (0.042 sec)\n \nDROP FUNCTION hello;\n \nERROR 1305 (42000): FUNCTION test.hello does not exist\n \nDROP FUNCTION IF EXISTS hello;\n \nQuery OK, 0 rows affected, 1 warning (0.000 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------------------+\n| Level | Code | Message |\n+-------+------+------------------------------------+\n| Note | 1305 | FUNCTION test.hello does not exist |\n+-------+------+------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-function/','','https://mariadb.com/kb/en/drop-function/'),(667,'CREATE TRIGGER',39,'Syntax\n------ \nCREATE [OR REPLACE]\n [DEFINER = { user | CURRENT_USER | role | CURRENT_ROLE }]\n TRIGGER [IF NOT EXISTS] trigger_name trigger_time\ntrigger_event\n ON tbl_name FOR EACH ROW\n [{ FOLLOWS | PRECEDES } other_trigger_name ]\n trigger_stmt\n \nDescription\n----------- \nThis statement creates a new trigger. A trigger is a named\ndatabase\nobject that is associated with a table, and that activates\nwhen a\nparticular event occurs for the table. The trigger becomes\nassociated\nwith the table named tbl_name, which must refer to a\npermanent table.\nYou cannot associate a trigger with a TEMPORARY table or a\nview.\n \nCREATE TRIGGER requires the TRIGGER privilege for the table\nassociated\nwith the trigger. (Before MySQL 5.1.6, this statement\nrequires the\nSUPER privilege.)\n \nYou can have multiple triggers for the same trigger_time and\ntrigger_event.\n \nFor valid identifiers to use as trigger names, see\nIdentifier Names.\n \nOR REPLACE\n \nIf used and the trigger already exists, instead of an error\nbeing returned, the existing trigger will be dropped and\nreplaced by the newly defined trigger.\n \nDEFINER\n \nThe DEFINER clause determines the security context to be\nused when\nchecking access privileges at trigger activation time.\n \nIF NOT EXISTS\n \nIf the IF NOT EXISTS clause is used, the trigger will only\nbe created if a trigger of the same name does not exist. If\nthe trigger already exists, by default a warning will be\nreturned.\n \ntrigger_time\n \ntrigger_time is the trigger action time. It can be BEFORE or\nAFTER to\nindicate that the trigger activates before or after each row\nto be\nmodified.\n \ntrigger_event\n \ntrigger_event indicates the kind of statement that activates\nthe\ntrigger. The trigger_event can be one of the following:\nINSERT: The trigger is activated whenever a new row is\ninserted into the table; for example, through INSERT, LOAD\nDATA, and REPLACE statements.\nUPDATE: The trigger is activated whenever a row is modified;\nfor example, through UPDATE statements.\nDELETE: The trigger is activated whenever a row is deleted\nfrom the table; for example, through DELETE and REPLACE\nstatements. However, DROP TABLE and TRUNCATE statements on\nthe table do not activate this trigger, because they do not\nuse DELETE. Dropping a partition does not activate DELETE\ntriggers, either.\n \nFOLLOWS/PRECEDES other_trigger_name\n \nThe FOLLOWS other_trigger_name and PRECEDES\nother_trigger_name options were added in MariaDB 10.2.3 as\npart of supporting multiple triggers per action time.\nThis is the same syntax used by MySQL 5.7, although MySQL\n5.7 does not have multi-trigger support.\n \nFOLLOWS adds the new trigger after another trigger while\nPRECEDES adds the new trigger before another trigger. If\nneither option is used, the new trigger is added last for\nthe given action and time.\n \nFOLLOWS and PRECEDES are not stored in the trigger\ndefinition. However the trigger order is guaranteed to not\nchange over time. mysqldump and other backup methods will\nnot change trigger order.\nYou can verify the trigger order from the ACTION_ORDER\ncolumn in INFORMATION_SCHEMA.TRIGGERS table.\n \nSELECT trigger_name, action_order FROM\ninformation_schema.triggers \n WHERE event_object_table=\'t1\';\n \nExamples\n-------- \nCREATE DEFINER=`root`@`localhost` TRIGGER increment_animal\n AFTER INSERT ON animals FOR EACH ROW \n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n \nOR REPLACE and IF NOT EXISTS\n \nCREATE DEFINER=`root`@`localhost` TRIGGER increment_animal\n AFTER INSERT ON animals FOR EACH ROW\n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n \nERROR 1359 (HY000): Trigger already exists\n \nCREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER\nincrement_animal\n AFTER INSERT ON animals FOR EACH ROW\n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n \nQuery OK, 0 rows affected (0.12 sec)\n \nCREATE DEFINER=`root`@`localhost` TRIGGER IF NOT EXISTS\nincrement_animal\n AFTER INSERT ON animals FOR EACH ROW\n UPDATE animal_count SET animal_count.animals =\nanimal_count.animals+1;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------+\n| Level | Code | Message |\n+-------+------+------------------------+\n| Note | 1359 | Trigger already exists |\n+-------+------+------------------------+\n1 row in set (0.00 sec)\n \n\n\nURL: https://mariadb.com/kb/en/create-trigger/','','https://mariadb.com/kb/en/create-trigger/'),(672,'DROP INDEX',39,'Syntax\n------ \nDROP INDEX [IF EXISTS] index_name ON tbl_name \n [WAIT n |NOWAIT]\n [algorithm_option | lock_option] ...\n \nalgorithm_option:\n ALGORITHM [=] {DEFAULT|INPLACE|COPY|NOCOPY|INSTANT}\n \nlock_option:\n LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n \nDescription\n----------- \nDROP INDEX drops the index named index_name from the table\ntbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop\nthe\nindex.\n \nIf another connection is using the table, a metadata lock is\nactive, and this statement will wait until the lock is\nreleased. This is also true for non-transactional tables.\n \nSee ALTER TABLE.\n \nAnother shortcut, CREATE INDEX, allows the creation of an\nindex.\n \nTo remove the primary key, `PRIMARY` must be specified as\nindex_name. Note that the quotes are necessary, because\nPRIMARY is a keyword.\n \nPrivileges\n \nExecuting the DROP INDEX statement requires the INDEX\nprivilege for the table or the database.\n \nOnline DDL\n \nIn MariaDB 10.0 and later, online DDL is supported with the\nALGORITHM and LOCK clauses.\n \nSee InnoDB Online DDL Overview for more information on\nonline DDL with InnoDB.\n \nDROP INDEX IF EXISTS ...\n \nThe IF EXISTS clause was added in MariaDB 10.1.4.\n \nIf the IF EXISTS clause is used, then MariaDB will return a\nwarning instead of an error if the index does not exist.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nALGORITHM\n \nSee ALTER TABLE: ALGORITHM for more information.\n \nLOCK\n \nSee ALTER TABLE: LOCK for more information.\n \nProgress Reporting\n \nMariaDB provides progress reporting for DROP INDEX statement\nfor clients\nthat support the new progress reporting protocol. For\nexample, if you were using the mysql client, then the\nprogress report might look like this::\n \n\n\nURL: https://mariadb.com/kb/en/drop-index/','','https://mariadb.com/kb/en/drop-index/'),(675,'DROP PROCEDURE',39,'Syntax\n------ \nDROP PROCEDURE [IF EXISTS] sp_name\n \nDescription\n----------- \nThis statement is used to drop a stored procedure. That is,\nthe\nspecified routine is removed from the server along with all\nprivileges specific to the procedure. You must have the\nALTER ROUTINE privilege for the routine. If the\nautomatic_sp_privileges server system variable is set, that\nprivilege and EXECUTE are granted automatically to the\nroutine creator - see Stored Routine Privileges.\n \nThe IF EXISTS clause is a MySQL/MariaDB extension. It\nprevents an error from occurring if the procedure or\nfunction does not exist. A\nNOTE is produced that can be viewed with SHOW WARNINGS.\n \nWhile this statement takes effect immediately, threads which\nare executing a procedure can continue execution.\n \nExamples\n-------- \nDROP PROCEDURE simpleproc;\n \nIF EXISTS:\n \nDROP PROCEDURE simpleproc;\n \nERROR 1305 (42000): PROCEDURE test.simpleproc does not exist\n \nDROP PROCEDURE IF EXISTS simpleproc;\n \nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------------------------+\n| Level | Code | Message |\n+-------+------+------------------------------------------+\n| Note | 1305 | PROCEDURE test.simpleproc does not exist |\n+-------+------+------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-procedure/','','https://mariadb.com/kb/en/drop-procedure/'),(676,'DROP SEQUENCE',39,'DROP SEQUENCE was introduced in MariaDB 10.3.\n \nSyntax\n------ \nDROP [TEMPORARY] SEQUENCE [IF EXISTS] [/*COMMENT TO SAVE*/]\n sequence_name [, sequence_name] ...\n \nDescription\n----------- \nDROP SEQUENCE removes one or more sequences created with\nCREATE SEQUENCE. You must have the DROP privilege for each\nsequence. MariaDB returns an error indicating by name which\nnon-existing tables it was unable to drop, but it also drops\nall of the tables in the list that do exist.\n \nImportant: When a table is dropped, user privileges on the\ntable are not automatically dropped. See GRANT.\n \nIf another connection is using the sequence, a metadata lock\nis active, and this statement will wait until the lock is\nreleased. This is also true for non-transactional tables.\n \nFor each referenced sequence, DROP SEQUENCE drops a\ntemporary sequence with that name, if it exists. If it does\nnot exist, and the TEMPORARY keyword is not used, it drops a\nnon-temporary sequence with the same name, if it exists. The\nTEMPORARY keyword ensures that a non-temporary sequence will\nnot accidentally be dropped.\n \nUse IF EXISTS to prevent an error from occurring for\nsequences that do not exist. A NOTE is generated for each\nnon-existent sequence when using IF EXISTS. See SHOW\nWARNINGS.\n \nDROP SEQUENCE requires the DROP privilege.\n \nNotes\n \nDROP SEQUENCE only removes sequences, not tables. However,\nDROP TABLE can remove both sequences and tables.\n \n\n\nURL: https://mariadb.com/kb/en/drop-sequence/','','https://mariadb.com/kb/en/drop-sequence/'),(677,'DROP SERVER',39,'Syntax\n------ \nDROP SERVER [ IF EXISTS ] server_name\n \nDescription\n----------- \nDrops the server definition for the server named\nserver_name. The\ncorresponding row within the mysql.servers table will be\ndeleted. This\nstatement requires the SUPER privilege. \n \nDropping a server for a table does not affect any\nFederatedX, FEDERATED or Spider tables that used this\nconnection information when they were created. \n \nIF EXISTS\n \nIf the IF EXISTS clause is used, MariaDB will not return an\nerror if the server does not exist. Unlike all other\nstatements, DROP SERVER IF EXISTS does not issue a note if\nthe server does not exist. See MDEV-9400.\n \nExamples\n-------- \nDROP SERVER s;\n \nIF EXISTS:\n \nDROP SERVER s;\n \nERROR 1477 (HY000): The foreign server name you are trying\nto reference \n does not exist. Data source error: s\n \nDROP SERVER IF EXISTS s;\n \nQuery OK, 0 rows affected (0.00 sec)\n \n\n\nURL: https://mariadb.com/kb/en/drop-server/','','https://mariadb.com/kb/en/drop-server/'),(680,'DROP TRIGGER',39,'Syntax\n------ \nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n \nDescription\n----------- \nThis statement drops a trigger. The schema (database) name\nis optional. If the\nschema is omitted, the trigger is dropped from the default\nschema.\nIts use requires the TRIGGER privilege for the table\nassociated with the trigger.\n \nUse IF EXISTS to prevent an error from occurring for a\ntrigger that does not exist. A NOTE is generated for a\nnon-existent trigger\nwhen using IF EXISTS. See SHOW WARNINGS.\n \nNote: Triggers for a table are also dropped if you drop the\ntable.\n \nExamples\n-------- \nDROP TRIGGER test.example_trigger;\n \nUsing the IF EXISTS clause:\n \nDROP TRIGGER IF EXISTS test.example_trigger;\n \nQuery OK, 0 rows affected, 1 warning (0.01 sec)\n \nSHOW WARNINGS;\n \n+-------+------+------------------------+\n| Level | Code | Message |\n+-------+------+------------------------+\n| Note | 1360 | Trigger does not exist |\n+-------+------+------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-trigger/','','https://mariadb.com/kb/en/drop-trigger/'),(678,'DROP TABLE',39,'Syntax\n------ \nDROP [TEMPORARY] TABLE [IF EXISTS] [/*COMMENT TO SAVE*/]\n tbl_name [, tbl_name] ...\n [WAIT n|NOWAIT]\n [RESTRICT | CASCADE]\n \nDescription\n----------- \nDROP TABLE removes one or more tables. You must have the\nDROP privilege\nfor each table. All table data and the table definition are\nremoved, as well as triggers associated to the table, so be\ncareful with this statement! If any of the tables named in\nthe argument list do\nnot exist, MariaDB returns an error indicating by name which\nnon-existing tables\nit was unable to drop, but it also drops all of the tables\nin the list that do\nexist.\n \nImportant: When a table is dropped, user privileges on the\ntable are not\nautomatically dropped. See GRANT.\n \nIf another connection is using the table, a metadata lock is\nactive, and this statement will wait until the lock is\nreleased. This is also true for non-transactional tables.\n \nNote that for a partitioned table, DROP TABLE permanently\nremoves the table\ndefinition, all of its partitions, and all of the data which\nwas stored in\nthose partitions. It also removes the partitioning\ndefinition (.par) file\nassociated with the dropped table.\n \nFor each referenced table, DROP TABLE drops a temporary\ntable with that name, if it exists. If it does not exist,\nand the TEMPORARY keyword is not used, it drops a\nnon-temporary table with the same name, if it exists. The\nTEMPORARY keyword ensures that a non-temporary table will\nnot accidentally be dropped.\n \nUse IF EXISTS to prevent an error from occurring for tables\nthat do not\nexist. A NOTE is generated for each non-existent table when\nusing\nIF EXISTS. See SHOW WARNINGS.\n \nIf a foreign key references this table, the table cannot be\ndropped. In this case, it is necessary to drop the foreign\nkey first.\n \nRESTRICT and CASCADE are allowed to make porting from other\ndatabase systems easier. In MariaDB, they do nothing.\n \nSince MariaDB 5.5.27, the comment before the tablenames\n(that /*COMMENT TO SAVE*/) is stored in the binary log. That\nfeature can be used by replication tools to send their\ninternal messages.\n \nIt is possible to specify table names as db_name.tab_name.\nThis is useful to delete tables from multiple databases with\none statement. See Identifier Qualifiers for details.\n \nThe DROP privilege is required to use DROP TABLE on\nnon-temporary tables. For temporary tables, no privilege is\nrequired, because such tables are only visible for the\ncurrent session.\n \nNote: DROP TABLE automatically commits the current active\ntransaction,\nunless you use the TEMPORARY keyword.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nDROP TABLE in replication\n \nDROP TABLE has the following characteristics in replication:\nDROP TABLE IF EXISTS are always logged.\nDROP TABLE without IF EXISTS for tables that don\'t exist\nare not written to the binary log.\nDropping of TEMPORARY tables are prefixed in the log with\nTEMPORARY. These drops are only logged when running\nstatement or mixed mode replication.\nOne DROP TABLE statement can be logged with up to 3\ndifferent DROP statements:\nDROP TEMPORARY TABLE\nlist_of_non_transactional_temporary_tables\nDROP TEMPORARY TABLE list_of_transactional_temporary_tables\nDROP TABLE list_of_normal_tables\n \nStarting from MariaDB 10.0.8, DROP TABLE on the master is\ntreated on the slave as DROP TABLE IF EXISTS. You can change\nthat by setting slave-ddl-exec-mode to STRICT.\n \nDropping an Internal #sql-... Table\n \nIf the mysqld process is killed during an ALTER TABLE you\nmay find a table named #sql-... in your data directory. In\nMariaDB 10.3, InnoDB tables with this prefix will de deleted\nautomatically during startup.\nIn MariaDB 10.4 we will ensure that these temporary tables\nwill always be deleted automatically.\n \nIf you want to delete one of these tables explicitly you can\ndo so by using the following syntax:\n \nDROP TABLE `#mysql50##sql-...`;\n \nWhen running an ALTER TABLE…ALGORITHM=INPLACE that\nrebuilds the table, InnoDB will create an internal #sql-ib\ntable. For these tables, the .frm file will be called\nsomething else. In order to drop such a table after a server\ncrash, you must rename the #sql*.frm file to match the\n#sql-ib*.ibd file.\n \nDropping All Tables in a Database\n \nThe best way to drop all tables in a database is by\nexecuting DROP DATABASE, which will drop the database\nitself, and all tables in it.\n \nHowever, if you want to drop all tables in the database, but\nyou also want to keep the database itself and any other\nnon-table objects in it, then you would need to execute DROP\nTABLE to drop each individual table. You can construct these\nDROP TABLE commands by querying the TABLES table in the\ninformation_schema database. For example:\n \nSELECT CONCAT(\'DROP TABLE IF EXISTS `\', TABLE_SCHEMA,\n\'`.`\', TABLE_NAME, \'`;\')\nFROM information_schema.TABLES\nWHERE TABLE_SCHEMA = \'mydb\';\n \nExamples\n-------- \nDROP TABLE Employees, Customers;\n \nNotes\n \nBeware that DROP TABLE can drop both tables and sequences.\nThis is mainly done to allow old tools like mysqldump to\nwork with sequences.\n \n\n\nURL: https://mariadb.com/kb/en/drop-table/','','https://mariadb.com/kb/en/drop-table/'),(681,'DROP VIEW',39,'Syntax\n------ \nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n \nDescription\n----------- \nDROP VIEW removes one or more views. You must have the DROP\nprivilege for\neach view. If any of the views named in the argument list do\nnot exist, MariaDB\nreturns an error indicating by name which non-existing views\nit was unable to\ndrop, but it also drops all of the views in the list that do\nexist.\n \nThe IF EXISTS clause prevents an error from occurring for\nviews that don\'t\nexist. When this clause is given, a NOTE is generated for\neach non-existent\nview. See SHOW WARNINGS.\n \nRESTRICT and CASCADE, if given, are parsed and ignored.\n \nIt is possible to specify view names as db_name.view_name.\nThis is useful to delete views from multiple databases with\none statement. See Identifier Qualifiers for details.\n \nThe DROP privilege is required to use DROP TABLE on\nnon-temporary tables. For temporary tables, no privilege is\nrequired, because such tables are only visible for the\ncurrent session.\n \nIf a view references another view, it will be possible to\ndrop the referenced view. However, the other view will\nreference a view which does not exist any more. Thus,\nquerying it will produce an error similar to the following:\n \nERROR 1356 (HY000): View \'db_name.view_name\' references\ninvalid table(s) or \ncolumn(s) or function(s) or definer/invoker of view lack\nrights to use them\n \nThis problem is reported in the output of CHECK TABLE.\n \nNote that it is not necessary to use DROP VIEW to replace an\nexisting view, because CREATE VIEW has an OR REPLACE clause.\n \nExamples\n-------- \nDROP VIEW v,v2;\n \nGiven views v and v2, but no view v3\n \nDROP VIEW v,v2,v3;\nERROR 1051 (42S02): Unknown table \'v3\'\n \nDROP VIEW IF EXISTS v,v2,v3;\nQuery OK, 0 rows affected, 1 warning (0.01 sec)\n \nSHOW WARNINGS;\n+-------+------+-------------------------+\n| Level | Code | Message |\n+-------+------+-------------------------+\n| Note | 1051 | Unknown table \'test.v3\' |\n+-------+------+-------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/drop-view/','','https://mariadb.com/kb/en/drop-view/'),(682,'Invisible Columns',39,'Invisible columns (sometimes also called hidden columns)\nfirst appeared in MariaDB 10.3.3.\n \nColumns can be given an INVISIBLE attribute in a CREATE\nTABLE or ALTER TABLE statement. These columns will then not\nbe listed in the results of a SELECT * statement, nor do\nthey need to be assigned a value in an INSERT statement,\nunless INSERT explicitly mentions them by name.\n \nSince SELECT * does not return the invisible columns, new\ntables or views created in this manner will have no trace of\nthe invisible columns. If specifically referenced in the\nSELECT statement, the columns will be brought into the\nview/new table, but the INVISIBLE attribute will not.\n \nInvisible columns can be declared as NOT NULL, but then\nrequire a DEFAULT value.\n \nIt is not possible for all columns in a table to be\ninvisible.\n \nExamples\n-------- \nCREATE TABLE t (x INT, y INT INVISIBLE, z INT INVISIBLE NOT\nNULL);\nERROR 4106 (HY000): Invisible column `z` must have a default\nvalue\n \nCREATE TABLE t (x INT, y INT INVISIBLE, z INT INVISIBLE NOT\nNULL DEFAULT 4);\n \nINSERT INTO t VALUES (1),(2);\n \nINSERT INTO t (x,y) VALUES (3,33);\n \nSELECT * FROM t;\n \n+------+\n| x |\n+------+\n| 1 |\n| 2 |\n| 3 |\n+------+\n \nSELECT x,y,z FROM t;\n \n+------+------+---+\n| x | y | z |\n+------+------+---+\n| 1 | NULL | 4 |\n| 2 | NULL | 4 |\n| 3 | 33 | 4 |\n+------+------+---+\n \nDESC t;\n \n+-------+---------+------+-----+---------+-----------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+---------+------+-----+---------+-----------+\n| x | int(11) | YES | | NULL | |\n| y | int(11) | YES | | NULL | INVISIBLE |\n| z | int(11) | NO | | 4 | INVISIBLE |\n+-------+---------+------+-----+---------+-----------+\n \nALTER TABLE t MODIFY x INT INVISIBLE, MODIFY y INT, MODIFY z\nINT NOT NULL DEFAULT 4;\n \nDESC t;\n \n+-------+---------+------+-----+---------+-----------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+---------+------+-----+---------+-----------+\n| x | int(11) | YES | | NULL | INVISIBLE |\n| y | int(11) | YES | | NULL | |\n| z | int(11) | NO | | 4 | |\n+-------+---------+------+-----+---------+-----------+\n \nCreating a view from a table with hidden columns:\n \nCREATE VIEW v1 AS SELECT * FROM t;\n \nDESC v1;\n \n+-------+---------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+---------+------+-----+---------+-------+\n| x | int(11) | YES | | NULL | |\n+-------+---------+------+-----+---------+-------+\n \nCREATE VIEW v2 AS SELECT x,y,z FROM t;\n \nDESC v2;\n \n+-------+---------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+---------+------+-----+---------+-------+\n| x | int(11) | YES | | NULL | |\n| y | int(11) | YES | | NULL | |\n| z | int(11) | NO | | 4 | |\n+-------+---------+------+-----+---------+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/invisible-columns/','','https://mariadb.com/kb/en/invisible-columns/'),(683,'MERGE',39,'Description\n----------- \nThe MERGE storage engine, also known as the MRG_MyISAM\nengine, is a\ncollection of identical MyISAM tables that can be used as\none.\n\"Identical\" means that all tables have identical column\nand index\ninformation. You cannot merge MyISAM tables in which the\ncolumns are\nlisted in a different order, do not have exactly the same\ncolumns, or\nhave the indexes in different order. However, any or all of\nthe MyISAM\ntables can be compressed with myisampack. Columns names and\nindexes names can be different, as long as data types and\nNULL/NOT NULL clauses are the same. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS\ndo not\nmatter.\n \nEach index in a MERGE table must match an index in\nunderlying MyISAM tables, but the opposite is not true.\nAlso, a MERGE table cannot have a PRIMARY KEY or UNIQUE\nindexes, because it cannot enforce uniqueness over all\nunderlying tables.\n \nThe following options are meaningful for MERGE tables:\nUNION. This option specifies the list of the underlying\nMyISAM tables. The list is enclosed between parentheses and\nseparated with commas.\nINSERT_METHOD. This options specifies whether, and how,\nINSERTs are allowed for the table. Allowed values are: NO\n(INSERTs are not allowed), FIRST (new rows will be written\ninto the first table specified in the UNION list), LAST (new\nrows will be written into the last table specified in the\nUNION list). The default value is NO.\n \nIf you define a MERGE table with a definition which is\ndifferent from the underlying MyISAM tables, or one of the\nunderlying tables is not MyISAM, the CREATE TABLE statement\nwill not return any error. But any statement which involves\nthe table will produce an error like the following:\n \nERROR 1168 (HY000): Unable to open underlying table which is\ndifferently defined \n or of non-MyISAM type or doesn\'t exist\n \nA CHECK TABLE will show more information about the problem.\n \nThe error is also produced if the table is properly define,\nbut an underlying table\'s definition changes at some point\nin time.\n \nIf you try to insert a new row into a MERGE table with\nINSERT_METHOD=NO, you will get an error like the following:\n \nERROR 1036 (HY000): Table \'tbl_name\' is read only\n \nIt is possible to build a MERGE table on MyISAM tables which\nhave one or more virtual columns. MERGE itself does not\nsupport virtual columns, thus such columns will be seen as\nregular columns. The data types and sizes will still need to\nbe identical, and they cannot be NOT NULL.\n \nExamples\n-------- \nCREATE TABLE t1 (\n a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n message CHAR(20)) ENGINE=MyISAM;\n \nCREATE TABLE t2 (\n a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n message CHAR(20)) ENGINE=MyISAM;\n \nINSERT INTO t1 (message) VALUES\n(\'Testing\'),(\'table\'),(\'t1\');\n \nINSERT INTO t2 (message) VALUES\n(\'Testing\'),(\'table\'),(\'t2\');\n \nCREATE TABLE total (\n a INT NOT NULL AUTO_INCREMENT,\n message CHAR(20), INDEX(a))\n ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n \nSELECT * FROM total;\n \n+---+---------+\n| a | message |\n+---+---------+\n| 1 | Testing |\n| 2 | table |\n| 3 | t1 |\n| 1 | Testing |\n| 2 | table |\n| 3 | t2 |\n+---+---------+\n \nIn the following example, we\'ll create three MyISAM tables,\nand then a MERGE table on them. However, one of them uses a\ndifferent data type for the column b, so a SELECT will\nproduce an error:\n \nCREATE TABLE t1 (\n a INT,\n b INT\n) ENGINE = MyISAM;\n \nCREATE TABLE t2 (\n a INT,\n b INT\n) ENGINE = MyISAM;\n \nCREATE TABLE t3 (\n a INT,\n b TINYINT\n) ENGINE = MyISAM;\n \nCREATE TABLE t_mrg (\n a INT,\n b INT\n) ENGINE = MERGE,UNION=(t1,t2,t3);\n \nSELECT * FROM t_mrg;\n \nERROR 1168 (HY000): Unable to open underlying table which is\ndifferently defined\n or of non-MyISAM type or doesn\'t exist\n \nTo find out what\'s wrong, we\'ll use a CHECK TABLE:\n \nCHECK TABLE t_mrg;\n \n+------------+-------+----------+-----------------------------------------------------------------------------------------------------+\n| Table | Op | Msg_type | Msg_text |\n+------------+-------+----------+-----------------------------------------------------------------------------------------------------+\n| test.t_mrg | check | Error | Table \'test.t3\' is\ndifferently defined or of non-MyISAM type or doesn\'t exist\n|\n| test.t_mrg | check | Error | Unable to open underlying\ntable which is differently defined or of non-MyISAM type or\ndoesn\'t exist |\n| test.t_mrg | check | error | Corrupt |\n+------------+-------+----------+-----------------------------------------------------------------------------------------------------+\n \nNow, we know that the problem is in t3\'s definition.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/merge/','','https://mariadb.com/kb/en/merge/'),(684,'RENAME TABLE',39,'Syntax\n------ \nRENAME TABLE tbl_name \n [WAIT n | NOWAIT]\n TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n \nDescription\n----------- \nThis statement renames one or more tables or views, but not\nthe privileges associated to them.\n \nThe rename operation is done atomically, which means that no\nother session can\naccess any of the tables while the rename is running. For\nexample, if you have\nan existing table old_table, you can create another table\nnew_table that has the same structure but is empty, and then\nreplace the existing table with the empty one as follows\n(assuming that\nbackup_table does not already exist):\n \nCREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO\nold_table;\n \ntbl_name can optionally be specified as db_name.tbl_name.\nSee Identifier Qualifiers. This allows to use RENAME to move\na table from a database to another (as long as they are on\nthe same filesystem):\n \nRENAME TABLE db1.t TO db2.t;\n \nNote that moving a table to another database is not possible\nif it has some triggers. Trying to do so produces the\nfollowing error:\n \nERROR 1435 (HY000): Trigger in wrong schema\n \nAlso, views cannot be moved to another database:\n \nERROR 1450 (HY000): Changing schema from \'old_db\' to\n\'new_db\' is not allowed.\n \nIf a RENAME TABLE renames more than one table and one\nrenaming fails, all renames executed by the same statement\nare rolled back.\n \nRenames are always executed in the specified order. Knowing\nthis, it is also possible to swap two tables\' names:\n \nRENAME TABLE t1 TO tmp_table,\n t2 TO t1,\n tmp_table TO t2;\n \nPrivileges\n \nExecuting the RENAME TABLE statement requires the DROP,\nCREATE and INSERT privileges for the table or the database.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/rename-table/','','https://mariadb.com/kb/en/rename-table/'),(685,'Silent Column Changes',39,'When a CREATE TABLE or ALTER TABLE command is issued,\nMariaDB will silently change a column specification in the\nfollowing cases:\nPRIMARY KEY columns are always NOT NULL.\nAny trailing spaces from SET and ENUM values are discarded.\nTIMESTAMP columns are always NOT NULL, and display sizes are\ndiscarded\nA row-size limit of 65535 bytes applies\nIf strict SQL mode is not enabled, a VARCHAR column longer\nthan 65535 become TEXT, and a VARBINARY columns longer than\n65535 becomes a BLOB. If strict mode is enabled the silent\nchanges will not be made, and an error will occur.\nIf a USING clause specifies an index that\'s not permitted\nby the storage engine, the engine will instead use another\navailable index type that can be applied without affecting\nresults.\nIf the CHARACTER SET binary attribute is specified, the\ncolumn is created as the matching binary data type. A TEXT\nbecomes a BLOB, CHAR a BINARY and VARCHAR a VARBINARY. ENUMs\nand SETs are created as defined.\n \nTo ease imports from other RDBMS\'s, MariaDB will also\nsilently map the following data types:\n \nOther Vendor Type | MariaDB Type | \n \nBOOL | TINYINT | \n \nBOOLEAN | TINYINT | \n \nCHARACTER VARYING(M) | VARCHAR(M) | \n \nFIXED | DECIMAL | \n \nFLOAT4 | FLOAT | \n \nFLOAT8 | DOUBLE | \n \nINT1 | TINYINT | \n \nINT2 | SMALLINT | \n \nINT3 | MEDIUMINT | \n \nINT4 | INT | \n \nINT8 | BIGINT | \n \nLONG VARBINARY | MEDIUMBLOB | \n \nLONG VARCHAR | MEDIUMTEXT | \n \nLONG | MEDIUMTEXT | \n \nMIDDLEINT | MEDIUMINT | \n \nNUMERIC | DECIMAL | \n \nCurrently, all MySQL types are supported in MariaDB.\n \nFor type mapping between Cassandra and MariaDB, see\nCassandra storage engine.\n \nExample\n \nSilent changes in action:\n \nCREATE TABLE SilenceIsGolden\n (\n f1 TEXT CHARACTER SET binary,\n f2 VARCHAR(15) CHARACTER SET binary,\n f3 CHAR CHARACTER SET binary,\n f4 ENUM(\'x\',\'y\',\'z\') CHARACTER SET binary,\n f5 VARCHAR (65536),\n f6 VARBINARY (65536),\n f7 INT1\n );\nQuery OK, 0 rows affected, 2 warnings (0.31 sec)\n \nSHOW WARNINGS;\n \n+-------+------+-----------------------------------------------+\n| Level | Code | Message |\n+-------+------+-----------------------------------------------+\n| Note | 1246 | Converting column \'f5\' from VARCHAR to\nTEXT |\n| Note | 1246 | Converting column \'f6\' from VARBINARY to\nBLOB |\n+-------+------+-----------------------------------------------+\n \nDESCRIBE SilenceIsGolden;\n \n+-------+-------------------+------+-----+---------+-------+\n| Field | Type | Null | Key | Default | Extra |\n+-------+-------------------+------+-----+---------+-------+\n| f1 | blob | YES | | NULL | |\n| f2 | varbinary(15) | YES | | NULL | |\n| f3 | binary(1) | YES | | NULL | |\n| f4 | enum(\'x\',\'y\',\'z\') | YES | | NULL | |\n| f5 | mediumtext | YES | | NULL | |\n| f6 | mediumblob | YES | | NULL | |\n| f7 | tinyint(4) | YES | | NULL | |\n+-------+-------------------+------+-----+---------+-------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/silent-column-changes/','','https://mariadb.com/kb/en/silent-column-changes/'),(689,'NEXT VALUE for sequence_name',40,'SEQUENCEs were introduced in MariaDB 10.3\n \nSyntax\n------ \nNEXT VALUE FOR sequence\n \nor\n \nNEXTVAL(sequence_name)\n \nor in Oracle mode (SQL_MODE=ORACLE)\n \nsequence_name.nextval\n \nNEXT VALUE FOR is ANSI SQL syntax while NEXTVAL() is\nPostgreSQL syntax.\n \nDescription\n----------- \nGenerate next value for a SEQUENCE.\nYou can greatly speed up NEXT VALUE by creating the sequence\nwith the CACHE option. If not, every NEXT VALUE usage will\ncause changes in the stored SEQUENCE table.\nWhen using NEXT VALUE the value will be reserved at once and\nwill not be reused, except if the SEQUENCE was created with\nCYCLE. This means that when you are using SEQUENCEs you have\nto expect gaps in the generated sequence numbers.\nIf one updates the SEQUENCE with SETVAL() or ALTER SEQUENCE\n... RESTART, NEXT VALUE FOR will notice this and start from\nthe next requested value.\nFLUSH TABLES will close the sequence and the next sequence\nnumber generated will be according to what\'s stored in the\nSEQUENCE object. In effect, this will discard the cached\nvalues.\nNEXT VALUE requires the INSERT privilege.\n \nYou can also use NEXT VALUE FOR sequence for column DEFAULT.\n \n\n\nURL: https://mariadb.com/kb/en/next-value-for-sequence_name/','','https://mariadb.com/kb/en/next-value-for-sequence_name/'),(691,'PREVIOUS VALUE FOR sequence_name',40,'SEQUENCEs were introduced in MariaDB 10.3.\n \nSyntax\n------ \nPREVIOUS VALUE FOR sequence_name\n \nor\n \nLASTVAL(sequence_name)\n \nor in Oracle mode (SQL_MODE=ORACLE)\n \nsequence_name.currval\n \nPREVIOUS VALUE FOR is IBM DB2 syntax while LASTVAL() is\nPostgreSQL syntax.\n \nDescription\n----------- \nGet last value in the current connection generated from a\nsequence.\nIf the sequence has not yet been used by the connection,\nPREVIOUS VALUE FOR returns NULL\nIf a SEQUENCE has been dropped and re-created then it\'s\ntreated as a new SEQUENCE and PREVIOUS VALUE FOR will return\nNULL.\nFLUSH TABLES has no effect on PREVIOUS VALUE FOR.\nPrevious values for all used sequences are stored per\nconnection until connection ends.\n \nPREVIOUS VALUE FOR requires the SELECT privilege.\n \nExample\n \nSELECT PREVIOUS VALUE FOR s;\n \n+----------------------+\n| PREVIOUS VALUE FOR s |\n+----------------------+\n| 100 |\n+----------------------+\n \n\n\nURL:\nhttps://mariadb.com/kb/en/previous-value-for-sequence_name/','','https://mariadb.com/kb/en/previous-value-for-sequence_name/'),(686,'TRUNCATE TABLE',39,'Syntax\n------ \nTRUNCATE [TABLE] tbl_name\n [WAIT n | NOWAIT]\n \nDescription\n----------- \nTRUNCATE TABLE empties a table completely. It requires the\nDROP privilege. See GRANT.\n \ntbl_name can also be specified in the form db_name.tbl_name\n(see Identifier Qualifiers).\n \nLogically, TRUNCATE TABLE is equivalent to a DELETE\nstatement that deletes all rows, but there are practical\ndifferences under some circumstances.\n \nTRUNCATE TABLE will fail for an InnoDB table if any FOREIGN\nKEY constraints from other tables reference the table,\nreturning the error:\n \nERROR 1701 (42000): Cannot truncate a table referenced in a\nforeign key constraint\n \nForeign Key constraints between columns in the same table\nare permitted.\n \nFor an InnoDB table, if there are no FOREIGN KEY\nconstraints, InnoDB performs fast truncation by dropping the\noriginal table and creating an empty one with the same\ndefinition, which is much faster than deleting rows one by\none. The AUTO_INCREMENT counter is reset by TRUNCATE TABLE,\nregardless of whether there is a FOREIGN KEY constraint.\n \nThe count of rows affected by TRUNCATE TABLE is accurate\nonly\nwhen it is mapped to a DELETE statement.\n \nFor other storage engines, TRUNCATE TABLE differs from\nDELETE in the following ways:\nTruncate operations drop and re-create the table, which is\nmuch\n faster than deleting rows one by one, particularly for\nlarge tables.\nTruncate operations cause an implicit commit.\nTruncation operations cannot be performed if the session\nholds an\n active table lock.\nTruncation operations do not return a meaningful value for\nthe number\n of deleted rows. The usual result is \"0 rows affected,\"\nwhich should\n be interpreted as \"no information.\"\nAs long as the table format file tbl_name.frm is valid, the\n table can be re-created as an empty table\n with TRUNCATE TABLE, even if the data or index files have\nbecome\n corrupted.\nThe table handler does not remember the last\n used AUTO_INCREMENT value, but starts counting\n from the beginning. This is true even for MyISAM and\nInnoDB, which normally\n do not reuse sequence values.\nWhen used with partitioned tables, TRUNCATE TABLE preserves\n the partitioning; that is, the data and index files are\ndropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\nSince truncation of a table does not make any use of DELETE,\n the TRUNCATE statement does not invoke ON DELETE triggers.\nTRUNCATE TABLE will only reset the values in the Performance\nSchema summary tables to zero or null, and will not remove\nthe rows.\n \nFor the purposes of binary logging and replication, TRUNCATE\nTABLE is treated as DROP TABLE followed by CREATE TABLE (DDL\nrather than DML).\n \nTRUNCATE TABLE does not work on views. Currently, TRUNCATE\nTABLE drops all historical records from a system-versioned\ntable.\n \nWAIT/NOWAIT\n \nSet the lock wait timeout. See WAIT and NOWAIT.\n \nOracle-mode\n \nOracle-mode from MariaDB 10.3 permits the optional keywords\nREUSE STORAGE or DROP STORAGE to be used.\n \nTRUNCATE [TABLE] tbl_name [{DROP | REUSE} STORAGE]\n \nThese have no effect on the operation.\n \nPerformance\n \nTRUNCATE TABLE is faster than DELETE, because it drops and\nre-creates a table.\n \nWith XtraDB/InnoDB, TRUNCATE TABLE is slower if\ninnodb_file_per_table=ON is set (the default since MariaDB\n5.5). This is because TRUNCATE TABLE unlinks the underlying\ntablespace file, which can be an expensive operation. See\nMDEV-8069 for more details.\n \nThe performance issues with innodb_file_per_table=ON can be\nexacerbated in cases where the InnoDB buffer pool is very\nlarge and innodb_adaptive_hash_index=ON is set. In that\ncase, using DROP TABLE followed by CREATE TABLE instead of\nTRUNCATE TABLE may perform better. Setting\ninnodb_adaptive_hash_index=OFF can also help. In MariaDB\n10.2.19 and later, this performance can also be improved by\nsetting innodb_safe_truncate=OFF. See MDEV-9459 for more\ndetails.\n \nSetting innodb_adaptive_hash_index=OFF can also improve\nTRUNCATE TABLE performance in general. See MDEV-16796 for\nmore details.\n \n\n\nURL: https://mariadb.com/kb/en/truncate-table/','','https://mariadb.com/kb/en/truncate-table/'),(694,'Differences between JSON_QUERY and JSON_VALUE',41,'JSON functions were added in MariaDB 10.2.3.\n \nThe primary difference between the two functions is that\nJSON_QUERY returns an object or an array, while JSON_VALUE\nreturns a scalar. \n \nTake the following JSON document as an example\n \nSET @json=\'{ \"x\": [0,1], \"y\": \"[0,1]\", \"z\":\n\"Monty\" }\';\n \nNote that data member \"x\" is an array, and data members\n\"y\" and \"z\" are strings. The following examples\ndemonstrate the differences between the two functions.\n \nSELECT JSON_QUERY(@json,\'$\'), JSON_VALUE(@json,\'$\');\n+--------------------------------------------+-----------------------+\n| JSON_QUERY(@json,\'$\') | JSON_VALUE(@json,\'$\') |\n+--------------------------------------------+-----------------------+\n| { \"x\": [0,1], \"y\": \"[0,1]\", \"z\": \"Monty\" } |\nNULL |\n+--------------------------------------------+-----------------------+\n \nSELECT JSON_QUERY(@json,\'$.x\'), JSON_VALUE(@json,\'$.x\');\n+-------------------------+-------------------------+\n| JSON_QUERY(@json,\'$.x\') | JSON_VALUE(@json,\'$.x\') |\n+-------------------------+-------------------------+\n| [0,1] | NULL |\n+-------------------------+-------------------------+\n \nSELECT JSON_QUERY(@json,\'$.y\'), JSON_VALUE(@json,\'$.y\');\n+-------------------------+-------------------------+\n| JSON_QUERY(@json,\'$.y\') | JSON_VALUE(@json,\'$.y\') |\n+-------------------------+-------------------------+\n| NULL | [0,1] |\n+-------------------------+-------------------------+\n \nSELECT JSON_QUERY(@json,\'$.z\'), JSON_VALUE(@json,\'$.z\');\n+-------------------------+-------------------------+\n| JSON_QUERY(@json,\'$.z\') | JSON_VALUE(@json,\'$.z\') |\n+-------------------------+-------------------------+\n| NULL | Monty |\n+-------------------------+-------------------------+\n \nSELECT JSON_QUERY(@json,\'$.x[0]\'),\nJSON_VALUE(@json,\'$.x[0]\');\n+----------------------------+----------------------------+\n| JSON_QUERY(@json,\'$.x[0]\') |\nJSON_VALUE(@json,\'$.x[0]\') |\n+----------------------------+----------------------------+\n| NULL | 0 |\n+----------------------------+----------------------------+\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/differences-between-json_query-and-json_value/','','https://mariadb.com/kb/en/differences-between-json_query-and-json_value/'),(692,'Sequence Overview',40,'Sequences were introduced in MariaDB 10.3.\n \nIntroduction\n \nA sequence is an object that generates a sequence of numeric\nvalues, as specified by the CREATE SEQUENCE statement. \n \nCREATE SEQUENCE will create a sequence that generates new\nvalues when called with NEXT VALUE FOR sequence_name. It\'s\nan alternative to AUTO INCREMENT when one wants to have more\ncontrol of how the numbers are generated. As the SEQUENCE\ncaches values (up to the CACHE value in the CREATE SEQUENCE\nstatement, by default 1000) it can in some cases be much\nfaster than AUTO INCREMENT. Another benefit is that one can\naccess the last value generated by all used sequences, which\nsolves one of the limitations with LAST_INSERT_ID().\n \nCreating a Sequence\n \nThe CREATE SEQUENCE statement is used to create a sequence.\nHere is an example of a sequence starting at 100,\nincrementing by 10 each time:\n \nCREATE SEQUENCE s START WITH 100 INCREMENT BY 10;\n \nThe CREATE SEQUENCE statement, along with defaults, can be\nviewd with the SHOW CREATE SEQUENCE STATEMENT, for example:\n \nSHOW CREATE SEQUENCE s\\G\n*************************** 1. row\n***************************\n Table: s\nCreate Table: CREATE SEQUENCE `s` start with 100 minvalue 1\nmaxvalue 9223372036854775806 \n increment by 10 cache 1000 nocycle ENGINE=InnoDB\n \nUsing Sequence Objects\n \nTo get the next value from a sequence, use\n \nNEXT VALUE FOR sequence_name\n \nor\n \nNEXTVAL(sequence_name)\n \nor in Oracle mode (SQL_MODE=ORACLE)\n \nsequence_name.nextval\n \nFor retrieving the last value used by the current connection\nfrom a sequence\nuse:\n \nPREVIOUS VALUE FOR sequence_name\n \nor\n \nLASTVAL(sequence_name)\n \nor in Oracle mode (SQL_MODE=ORACLE)\n \nsequence_name.currval\n \nFor example:\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 100 |\n+------------+\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 110 |\n+------------+\n \nSELECT LASTVAL(s);\n+------------+\n| LASTVAL(s) |\n+------------+\n| 110 |\n+------------+\n \nUsing Sequences in DEFAULT\n \nStarting from 10.3.3 you can use Sequences in DEFAULT:\n \ncreate sequence s1;\n \ncreate table t1 (a int primary key default (next value for\ns1), b int);\ninsert into t1 (b) values (1),(2);\nselect * from t1;\n \n+---+------+\n| a | b |\n+---+------+\n| 1 | 1 |\n| 2 | 2 |\n+---+------+\n \nChanging a Sequence\n \nThe ALTER SEQUENCE statement is used for changing sequences.\nFor example, to restart the sequence at another value:\n \nALTER SEQUENCE s RESTART 50;\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 50 |\n+------------+\n \nThe SETVAL function can also be used to set the next value\nto be returned for a SEQUENCE, for example:\n \nSELECT SETVAL(s, 100);\n+----------------+\n| SETVAL(s, 100) |\n+----------------+\n| 100 |\n+----------------+\n \nSETVAL can only be used to increase the sequence value.\nAttempting to set a lower value will fail, returning NULL:\n \nSELECT SETVAL(s, 50);\n+---------------+\n| SETVAL(s, 50) |\n+---------------+\n| NULL |\n+---------------+\n \nDropping a Sequence\n \nThe DROP SEQUENCE statement is used to drop a sequence, for\nexample:\n \nDROP SEQUENCE s;\n \nReplication\n \nIf one wants to use Sequences in a master-master setup or\nwith Galera one\nshould use INCREMENT=0. This will tell the Sequence to use\nauto_increment_increment and auto_increment_offset to\ngenerate unique values for each server.\n \nStandards Compliance\n \nMariaDB 10.3 supports both ANSI SQL and Oracle syntax for\nsequences.\n \nHowever as SEQUENCE is implemented as a special kind of\ntable, it uses the same namespace as tables. The benefits\nare that sequences show up in SHOW TABLES, and one can also\ncreate a sequence with CREATE TABLE and drop it with DROP\nTABLE. One can SELECT from it as from any other table. This\nensures that all old tools that work with tables should work\nwith sequences.\n \nSince sequence objects act as regular tables in many\ncontexts, they will be affected by LOCK TABLES. This is not\nthe case in other DBMS, such as Oracle, where LOCK TABLE\ndoes not affect sequences.\n \nNotes\n \nOne of the goals with the Sequence implementation is that\nall old\ntools, such as mysqldump, should work unchanged, while still\nkeeping the\nnormal usage of sequence standard compatibly.\n \nTo make this possible, sequence is currently implemented as\na table with a few exclusive properties.\n \nThe special properties for sequence tables are:\nA sequence table has always one row.\nWhen one creates a sequence, either with CREATE TABLE or\nCREATE SEQUENCE, one row will be inserted.\nIf one tries to insert into a sequence table, the single row\nwill be updated. This allows mysqldump to work but also\ngives the additional benefit that one can change all\nproperties of a sequence with a single insert. New\napplications should of course also use ALTER SEQUENCE.\nUPDATE or DELETE can\'t be performed on Sequence objects.\nDoing a select on the sequence shows the current state of\nthe sequence, except the values that are reserved in the\ncache. The next_value column shows the next value not\nreserved by the cache.\nFLUSH TABLES will close the sequence and the next sequence\nnumber generated will be according to what\'s stored in the\nSequence object. In effect, this will discard the cached\nvalues.\nA number of normal table operations work on Sequence tables.\nSee next section.\n \nTable Operations that Work with Sequences\n \nSHOW CREATE TABLE sequence_name. This shows the table\nstructure that is behind the SEQUENCE including the field\nnames that can be used with SELECT or even CREATE TABLE.\nCREATE TABLE sequence-structure ... SEQUENCE=1\nALTER TABLE sequence RENAME TO sequence2\nRENAME TABLE sequence_name TO new_sequence_name\nDROP TABLE sequence_name. This is allowed mainly to get old\ntools like mysqldump to work with sequence tables.\nSHOW TABLES\n \nImplementation\n \nInternally, sequence tables are created as a normal table\nwithout\nrollback (the InnoDB, Aria and MySAM engines support this),\nwrapped by a\nsequence engine object. This allowed us to create sequences\nwith\nalmost no performance impact for normal tables. (The cost is\none \'if\'\nper insert if the binary log is enabled).\n \nUnderlying Table Structure\n \nThe following example shows the table structure of sequences\nand how it\ncan be used as a table.\n(Output of results are slightly edited to make them easier\nto read)\n \ncreate sequence t1;\nshow create sequence t1\\G\n***** 1. row *****\n CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue\n9223372036854775806\n increment by 1 cache 1000 nocycle ENGINE=InnoDB\n \nshow create table t1\\G\n***** 1. row *****\nCreate Table: CREATE TABLE `t1` (\n `next_not_cached_value` bigint(21) NOT NULL,\n `minimum_value` bigint(21) NOT NULL,\n `maximum_value` bigint(21) NOT NULL,\n `start_value` bigint(21) NOT NULL COMMENT \'start value\nwhen sequences is created or value if RESTART is used\',\n `increment` bigint(21) NOT NULL COMMENT \'increment\nvalue\',\n `cache_size` bigint(21) unsigned NOT NULL,\n `cycle_option` tinyint(1) unsigned NOT NULL COMMENT \'0 if\nno cycles are allowed, 1 if the sequence should begin a new\ncycle when maximum_value is passed\',\n `cycle_count` bigint(21) NOT NULL COMMENT \'How many cycles\nhave been done\'\n) ENGINE=InnoDB SEQUENCE=1\n \nselect * from t1\\G\nnext_not_cached_value: 1\n minimum_value: 1\n maximum_value: 9223372036854775806\n start_value: 1\n increment: 1\n cache_size: 1000\n cycle_option: 0\n cycle_count: 0\nThe cycle_count column is incremented every time the\nsequence wraps around.\n \nCredits\n \nThanks to Jianwe Zhao from Aliyun for his work on SEQUENCE\nin AliSQL, which gave ideas and inspiration for this work.\nThanks to Peter Gulutzan,who helped test and gave useful\ncomments about the implementation.\n \n\n\nURL: https://mariadb.com/kb/en/sequence-overview/','','https://mariadb.com/kb/en/sequence-overview/'),(693,'SETVAL()',40,'SEQUENCEs were introduced in MariaDB 10.3.\n \nSyntax\n------ \nSETVAL(sequence_name, next_value, [is_used, [round]])\n \nDescription\n----------- \nSet the next value to be returned for a SEQUENCE.\n \nThis function is compatible with PostgreSQL syntax, extended\nwith the round argument.\n \nIf the is_used argument is not given or is 1 or true, then\nthe next used value will\none after the given value. If is_used is 0 or false then the\nnext generated value\nwill be the given value.\n \nIf round is used then it will set the round value (or the\ninternal cycle count, starting at zero) for the sequence.\nIf round is not used, it\'s assumed to be 0.\n \nnext_value must be an integer literal.\n \nFor SEQUENCE tables defined with CYCLE (see CREATE SEQUENCE)\none should use both next_value and round to define the next\nvalue. In this case the\ncurrent sequence value is defined to be round, next_value.\n \nThe result returned by SETVAL() is next_value or NULL if the\ngiven next_value and round is smaller than the current\nvalue.\n \nSETVAL() will not set the SEQUENCE value to a something that\nis less than\nits current value. This is needed to ensure that SETVAL()\nis replication safe. If you want to set the SEQUENCE to a\nsmaller number\nuse ALTER SEQUENCE.\n \nIf CYCLE is used, first round and then next_value are\ncompared\nto see if the value is bigger than the current value.\n \nInternally, in the MariaDB server, SETVAL() is used to\ninform\nslaves that a SEQUENCE has changed value. The slave may get\nSETVAL() statements out of order, but this is ok as only the\nbiggest one will have an effect.\n \nSETVAL requires the INSERT privilege.\n \nExamples\n-------- \nSELECT setval(foo, 42); -- Next nextval will return 43\nSELECT setval(foo, 42, true); -- Same as above\nSELECT setval(foo, 42, false); -- Next nextval will return\n42\n \nSETVAL setting higher and lower values on a sequence with an\nincrement of 10:\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 50 |\n+------------+\n \nSELECT SETVAL(s, 100);\n+----------------+\n| SETVAL(s, 100) |\n+----------------+\n| 100 |\n+----------------+\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 110 |\n+------------+\n \nSELECT SETVAL(s, 50);\n+---------------+\n| SETVAL(s, 50) |\n+---------------+\n| NULL |\n+---------------+\n \nSELECT NEXTVAL(s);\n+------------+\n| NEXTVAL(s) |\n+------------+\n| 120 |\n+------------+\n \nExample demonstrating round:\n \nCREATE OR REPLACE SEQUENCE s1\n START WITH 1\n MINVALUE 1\n MAXVALUE 99\n INCREMENT BY 1 \n CACHE 20 \n CYCLE;\n \nSELECT SETVAL(s1, 99, 1, 0);\n+----------------------+\n| SETVAL(s1, 99, 1, 0) |\n+----------------------+\n| 99 |\n+----------------------+\n \nSELECT NEXTVAL(s1);\n+-------------+\n| NEXTVAL(s1) |\n+-------------+\n| 1 |\n+-------------+\n \nThe following statement returns NULL, as the given\nnext_value and round is smaller than the current value.\n \nSELECT SETVAL(s1, 99, 1, 0);\n+----------------------+\n| SETVAL(s1, 99, 1, 0) |\n+----------------------+\n| NULL |\n+----------------------+\n \nSELECT NEXTVAL(s1);\n+-------------+\n| NEXTVAL(s1) |\n+-------------+\n| 2 |\n+-------------+\n \nIncreasing the round from zero to 1 will allow next_value to\nbe returned.\n \nSELECT SETVAL(s1, 99, 1, 1);\n+----------------------+\n| SETVAL(s1, 99, 1, 1) |\n+----------------------+\n| 99 |\n+----------------------+\n \nSELECT NEXTVAL(s1);\n+-------------+\n| NEXTVAL(s1) |\n+-------------+\n| 1 |\n+-------------+\n \n\n\nURL: https://mariadb.com/kb/en/setval/','','https://mariadb.com/kb/en/setval/'),(696,'JSON_ARRAY_APPEND',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_ARRAY_APPEND(json_doc, path, value[, path, value] ...)\n \nDescription\n----------- \nAppends values to the end of the specified arrays within a\nJSON document, returning the result, or NULL if any of the\narguments are NULL.\n \nEvaluation is performed from left to right, with the\nresulting document from the previous pair becoming the new\nvalue against which the next pair is evaluated.\n \nIf the json_doc is not a valid JSON document, or if any of\nthe paths are not valid, or contain a * or ** wildcard, an\nerror is returned.\n \nExamples\n-------- \nSET @json = \'[1, 2, [3, 4]]\';\n \nSELECT JSON_ARRAY_APPEND(@json, \'$[0]\', 5)\n+-------------------------------------+\n| JSON_ARRAY_APPEND(@json, \'$[0]\', 5) |\n+-------------------------------------+\n| [[1, 5], 2, [3, 4]] |\n+-------------------------------------+\n \nSELECT JSON_ARRAY_APPEND(@json, \'$[1]\', 6);\n+-------------------------------------+\n| JSON_ARRAY_APPEND(@json, \'$[1]\', 6) |\n+-------------------------------------+\n| [1, [2, 6], [3, 4]] |\n+-------------------------------------+\n \nSELECT JSON_ARRAY_APPEND(@json, \'$[1]\', 6, \'$[2]\', 7);\n+------------------------------------------------+\n| JSON_ARRAY_APPEND(@json, \'$[1]\', 6, \'$[2]\', 7) |\n+------------------------------------------------+\n| [1, [2, 6], [3, 4, 7]] |\n+------------------------------------------------+\n \nSELECT JSON_ARRAY_APPEND(@json, \'$\', 5);\n+----------------------------------+\n| JSON_ARRAY_APPEND(@json, \'$\', 5) |\n+----------------------------------+\n| [1, 2, [3, 4], 5] |\n+----------------------------------+\n \nSET @json = \'{\"A\": 1, \"B\": [2], \"C\": [3, 4]}\';\n \nSELECT JSON_ARRAY_APPEND(@json, \'$.B\', 5);\n+------------------------------------+\n| JSON_ARRAY_APPEND(@json, \'$.B\', 5) |\n+------------------------------------+\n| {\"A\": 1, \"B\": [2, 5], \"C\": [3, 4]} |\n+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_array_append/','','https://mariadb.com/kb/en/json_array_append/'),(697,'JSON_ARRAY_INSERT',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_ARRAY_INSERT(json_doc, path, value[, path, value] ...)\n \nDescription\n----------- \nInserts a value into a JSON document, returning the modified\ndocument, or NULL if any of the arguments are NULL.\n \nEvaluation is performed from left to right, with the\nresulting document from the previous pair becoming the new\nvalue against which the next pair is evaluated.\n \nIf the json_doc is not a valid JSON document, or if any of\nthe paths are not valid, or contain a * or ** wildcard, an\nerror is returned.\n \nExamples\n-------- \nSET @json = \'[1, 2, [3, 4]]\';\n \nSELECT JSON_ARRAY_INSERT(@json, \'$[0]\', 5);\n+-------------------------------------+\n| JSON_ARRAY_INSERT(@json, \'$[0]\', 5) |\n+-------------------------------------+\n| [5, 1, 2, [3, 4]] |\n+-------------------------------------+\n \nSELECT JSON_ARRAY_INSERT(@json, \'$[1]\', 6);\n+-------------------------------------+\n| JSON_ARRAY_INSERT(@json, \'$[1]\', 6) |\n+-------------------------------------+\n| [1, 6, 2, [3, 4]] |\n+-------------------------------------+\n \nSELECT JSON_ARRAY_INSERT(@json, \'$[1]\', 6, \'$[2]\', 7);\n+------------------------------------------------+\n| JSON_ARRAY_INSERT(@json, \'$[1]\', 6, \'$[2]\', 7) |\n+------------------------------------------------+\n| [1, 6, 7, 2, [3, 4]] |\n+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_array_insert/','','https://mariadb.com/kb/en/json_array_insert/'),(699,'JSON_CONTAINS',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_CONTAINS(json_doc, val[, path])\n \nDescription\n----------- \nReturns whether or not the specified value is found in the\ngiven JSON document or, optionally, at the specified path\nwithin the document. Returns 1 if it does, 0 if not and NULL\nif any of the arguments are null. An error occurs if the\ndocument or path is not valid, or contains the * or **\nwildcards.\n \nExamples\n-------- \nSET @json = \'{\"A\": 0, \"B\": {\"C\": 1}, \"D\": 2}\';\n \nSELECT JSON_CONTAINS(@json, \'2\', \'$.A\');\n+----------------------------------+\n| JSON_CONTAINS(@json, \'2\', \'$.A\') |\n+----------------------------------+\n| 0 |\n+----------------------------------+\n \nSELECT JSON_CONTAINS(@json, \'2\', \'$.D\');\n+----------------------------------+\n| JSON_CONTAINS(@json, \'2\', \'$.D\') |\n+----------------------------------+\n| 1 |\n+----------------------------------+\n \nSELECT JSON_CONTAINS(@json, \'{\"C\": 1}\', \'$.A\');\n+-----------------------------------------+\n| JSON_CONTAINS(@json, \'{\"C\": 1}\', \'$.A\') |\n+-----------------------------------------+\n| 0 |\n+-----------------------------------------+\n \nSELECT JSON_CONTAINS(@json, \'{\"C\": 1}\', \'$.B\');\n+-----------------------------------------+\n| JSON_CONTAINS(@json, \'{\"C\": 1}\', \'$.B\') |\n+-----------------------------------------+\n| 1 |\n+-----------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_contains/','','https://mariadb.com/kb/en/json_contains/'),(700,'JSON_CONTAINS_PATH',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_CONTAINS_PATH(json_doc, return_arg, path[, path] ...)\n \nDescription\n----------- \nIndicates whether the given JSON document contains data at\nthe specified path or paths. Returns 1 if it does, 0 if not\nand NULL if any of the arguments are null.\n \nThe return_arg can be one or all:\none - Returns 1 if at least one path exists within the JSON\ndocument. \nall - Returns 1 only if all paths exist within the JSON\ndocument.\n \nExamples\n-------- \nSET @json = \'{\"A\": 1, \"B\": [2], \"C\": [3, 4]}\';\n \nSELECT JSON_CONTAINS_PATH(@json, \'one\', \'$.A\', \'$.D\');\n+------------------------------------------------+\n| JSON_CONTAINS_PATH(@json, \'one\', \'$.A\', \'$.D\') |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n1 row in set (0.00 sec)\n \nSELECT JSON_CONTAINS_PATH(@json, \'all\', \'$.A\', \'$.D\');\n+------------------------------------------------+\n| JSON_CONTAINS_PATH(@json, \'all\', \'$.A\', \'$.D\') |\n+------------------------------------------------+\n| 0 |\n+------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_contains_path/','','https://mariadb.com/kb/en/json_contains_path/'),(701,'JSON_DEPTH',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_DEPTH(json_doc)\n \nDescription\n----------- \nReturns the maximum depth of the given JSON document, or\nNULL if the argument is null. An error will occur if the\nargument is an invalid JSON document.\nScalar values or empty arrays or objects have a depth of 1.\nArrays or objects that are not empty but contain only\nelements or member values of depth 1 will have a depth of 2.\nIn other cases, the depth will be greater than 2.\n \nExamples\n-------- \nSELECT JSON_DEPTH(\'[]\'), JSON_DEPTH(\'true\'),\nJSON_DEPTH(\'{}\');\n+------------------+--------------------+------------------+\n| JSON_DEPTH(\'[]\') | JSON_DEPTH(\'true\') |\nJSON_DEPTH(\'{}\') |\n+------------------+--------------------+------------------+\n| 1 | 1 | 1 |\n+------------------+--------------------+------------------+\n \nSELECT JSON_DEPTH(\'[1, 2, 3]\'), JSON_DEPTH(\'[[], {},\n[]]\');\n+-------------------------+----------------------------+\n| JSON_DEPTH(\'[1, 2, 3]\') | JSON_DEPTH(\'[[], {}, []]\') |\n+-------------------------+----------------------------+\n| 2 | 2 |\n+-------------------------+----------------------------+\n \nSELECT JSON_DEPTH(\'[1, 2, [3, 4, 5, 6], 7]\');\n+---------------------------------------+\n| JSON_DEPTH(\'[1, 2, [3, 4, 5, 6], 7]\') |\n+---------------------------------------+\n| 3 |\n+---------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_depth/','','https://mariadb.com/kb/en/json_depth/'),(703,'JSON_EXISTS',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nDescription\n----------- \nDetermines whether a specified JSON value exists in the\ngiven data. Returns 1 if found, 0 if not, or NULL if any of\nthe inputs were NULL.\n \nExamples\n-------- \nSELECT JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2,\n3]}\', \"$.key2\");\n+------------------------------------------------------------+\n| JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2, 3]}\',\n\"$.key2\") |\n+------------------------------------------------------------+\n| 1 |\n+------------------------------------------------------------+\n \nSELECT JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2,\n3]}\', \"$.key3\");\n+------------------------------------------------------------+\n| JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2, 3]}\',\n\"$.key3\") |\n+------------------------------------------------------------+\n| 0 |\n+------------------------------------------------------------+\n \nSELECT JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2,\n3]}\', \"$.key2[1]\");\n+---------------------------------------------------------------+\n| JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2, 3]}\',\n\"$.key2[1]\") |\n+---------------------------------------------------------------+\n| 1 |\n+---------------------------------------------------------------+\n \nSELECT JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2,\n3]}\', \"$.key2[10]\");\n+----------------------------------------------------------------+\n| JSON_EXISTS(\'{\"key1\":\"xxxx\", \"key2\":[1, 2, 3]}\',\n\"$.key2[10]\") |\n+----------------------------------------------------------------+\n| 0 |\n+----------------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_exists/','','https://mariadb.com/kb/en/json_exists/'),(704,'JSON_EXTRACT',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_EXTRACT(json_doc, path[, path] ...)\n \nDescription\n----------- \nExtracts data from a JSON document. The extracted data is\nselected from the parts matching the path arguments. Returns\nall matched values; either as a single matched value, or, if\nthe arguments could return multiple values, a result\nautowrapped as an array in the matching order.\n \nReturns NULL if no paths match or if any of the arguments\nare NULL. \n \nAn error will occur if any path argument is not a valid\npath, or if the json_doc argument is not a valid JSON\ndocument.\n \nExamples\n-------- \nSET @json = \'[1, 2, [3, 4]]\';\n \nSELECT JSON_EXTRACT(@json, \'$[1]\');\n+-----------------------------+\n| JSON_EXTRACT(@json, \'$[1]\') |\n+-----------------------------+\n| 2 |\n+-----------------------------+\n \nSELECT JSON_EXTRACT(@json, \'$[2]\');\n+-----------------------------+\n| JSON_EXTRACT(@json, \'$[2]\') |\n+-----------------------------+\n| [3, 4] |\n+-----------------------------+\n \nSELECT JSON_EXTRACT(@json, \'$[2][1]\');\n+--------------------------------+\n| JSON_EXTRACT(@json, \'$[2][1]\') |\n+--------------------------------+\n| 4 |\n+--------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_extract/','','https://mariadb.com/kb/en/json_extract/'),(705,'JSON_INSERT',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_INSERT(json_doc, path, val[, path, val] ...)\n \nDescription\n----------- \nInserts data into a JSON document, returning the resulting\ndocument or NULL if any argument is null. \n \nAn error will occur if the JSON document is not invalid, or\nif any of the paths are invalid or contain a * or **\nwildcard.\n \nJSON_INSERT can only insert data while JSON_REPLACE can only\nupdate. JSON_SET can update or insert data. \n \nExamples\n-------- \nSET @json = \'{ \"A\": 0, \"B\": [1, 2]}\';\n \nSELECT JSON_INSERT(@json, \'$.C\', \'[3, 4]\');\n+--------------------------------------+\n| JSON_INSERT(@json, \'$.C\', \'[3, 4]\') |\n+--------------------------------------+\n| { \"A\": 0, \"B\": [1, 2], \"C\":\"[3, 4]\"} |\n+--------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_insert/','','https://mariadb.com/kb/en/json_insert/'),(706,'JSON_KEYS',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_KEYS(json_doc[, path])\n \nDescription\n----------- \nReturns the keys as a JSON array from the top-level value of\na JSON object or, if the optional path argument is provided,\nthe top-level keys from the path. \n \nExcludes keys from nested sub-objects in the top level\nvalue. The resulting array will be empty if the selected\nobject is empty.\n \nReturns NULL if any of the arguments are null, a given path\ndoes not locate an object, or if the json_doc argument is\nnot an object.\n \nAn error will occur if JSON document is invalid, the path is\ninvalid or if the path contains a * or ** wildcard.\n \nExamples\n-------- \nSELECT JSON_KEYS(\'{\"A\": 1, \"B\": {\"C\": 2}}\');\n+--------------------------------------+\n| JSON_KEYS(\'{\"A\": 1, \"B\": {\"C\": 2}}\') |\n+--------------------------------------+\n| [\"A\", \"B\"] |\n+--------------------------------------+\n \nSELECT JSON_KEYS(\'{\"A\": 1, \"B\": 2, \"C\": {\"D\":\n3}}\', \'$.C\');\n+-----------------------------------------------------+\n| JSON_KEYS(\'{\"A\": 1, \"B\": 2, \"C\": {\"D\": 3}}\',\n\'$.C\') |\n+-----------------------------------------------------+\n| [\"D\"] |\n+-----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_keys/','','https://mariadb.com/kb/en/json_keys/'),(707,'JSON_LENGTH',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_LENGTH(json_doc[, path])\n \nDescription\n----------- \nReturns the length of a JSON document, or, if the optional\npath argument is given, the length of the value within the\ndocument specified by the path. \n \nReturns NULL if any of the arguments argument are null or\nthe path argument does not identify a value in the document.\n\n \nAn error will occur if the JSON document is invalid, the\npath is invalid or if the path contains a * or ** wildcard.\n \nLength will be determined as follow:\nA scalar\'s length is always 1.\nIf an array, the number of elements in the array.\nIf an object, the number of members in the object.\n \nThe length of nested arrays or objects are not counted.\n \nExamples\n-------- \n\n \n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_length/','','https://mariadb.com/kb/en/json_length/'),(709,'JSON_MERGE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_MERGE(json_doc, json_doc[, json_doc] ...)\n \nDescription\n----------- \nMerges the given JSON documents.\n \nReturns the merged result,or NULL if any argument is NULL.\n \nAn error occurs if any of the arguments are not valid JSON\ndocuments.\n \nJSON_MERGE has been deprecated since MariaDB 10.2.25,\nMariaDB 10.3.16 and MariaDB 10.4.5. JSON_MERGE_PATCH is an\nRFC 7396-compliant replacement, and JSON_MERGE_PRESERVE is a\nsynonym.\n \nExample\n \nSET @json1 = \'[1, 2]\';\n \nSET @json2 = \'[3, 4]\';\n \nSELECT JSON_MERGE(@json1,@json2);\n+---------------------------+\n| JSON_MERGE(@json1,@json2) |\n+---------------------------+\n| [1, 2, 3, 4] |\n+---------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/json_merge/','','https://mariadb.com/kb/en/json_merge/'),(710,'JSON_MERGE_PATCH',41,'JSON_MERGE_PATCH was introduced in MariaDB 10.2.25, MariaDB\n10.3.16 and MariaDB 10.4.5.\n \nSyntax\n------ \nJSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...)\n \nDescription\n----------- \nMerges the given JSON documents, returning the merged\nresult, or NULL if any argument is NULL.\n \nJSON_MERGE_PATCH is an RFC 7396-compliant replacement for\nJSON_MERGE, which has been deprecated.\n \nExample\n \nSET @json1 = \'[1, 2]\';\n \nSET @json2 = \'[2, 3]\';\n \nSELECT\nJSON_MERGE_PATCH(@json1,@json2),JSON_MERGE_PRESERVE(@json1,@json2);\n+---------------------------------+------------------------------------+\n| JSON_MERGE_PATCH(@json1,@json2) |\nJSON_MERGE_PRESERVE(@json1,@json2) |\n+---------------------------------+------------------------------------+\n| [2, 3] | [1, 2, 2, 3] |\n+---------------------------------+------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_merge_patch/','','https://mariadb.com/kb/en/json_merge_patch/'),(711,'JSON_MERGE_PRESERVE',41,'JSON_MERGE_PRESERVE was introduced in MariaDB 10.2.25,\nMariaDB 10.3.16 and MariaDB 10.4.5.\n \nSyntax\n------ \nJSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...)\n \nDescription\n----------- \nMerges the given JSON documents, returning the merged\nresult, or NULL if any argument is NULL.\n \nJSON_MERGE_PRESERVE was introduced in MariaDB 10.2.25,\nMariaDB 10.3.16 and MariaDB 10.4.5 as a synonym for\nJSON_MERGE, which has been deprecated.\n \nExample\n \nSET @json1 = \'[1, 2]\';\n \nSET @json2 = \'[2, 3]\';\n \nSELECT\nJSON_MERGE_PATCH(@json1,@json2),JSON_MERGE_PRESERVE(@json1,@json2);\n+---------------------------------+------------------------------------+\n| JSON_MERGE_PATCH(@json1,@json2) |\nJSON_MERGE_PRESERVE(@json1,@json2) |\n+---------------------------------+------------------------------------+\n| [2, 3] | [1, 2, 2, 3] |\n+---------------------------------+------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/json_merge_preserve/','','https://mariadb.com/kb/en/json_merge_preserve/'),(713,'JSON_QUERY',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_QUERY(json_doc, path)\n \nDescription\n----------- \nGiven a JSON document, returns an object or array specified\nby the path. Returns NULL if not given a valid JSON\ndocument, or if there is no match.\n \nExamples\n-------- \nselect json_query(\'{\"key1\":{\"a\":1, \"b\":[1,2]}}\',\n\'$.key1\');\n+-----------------------------------------------------+\n| json_query(\'{\"key1\":{\"a\":1, \"b\":[1,2]}}\',\n\'$.key1\') |\n+-----------------------------------------------------+\n| {\"a\":1, \"b\":[1,2]} |\n+-----------------------------------------------------+\n \nselect json_query(\'{\"key1\":123, \"key1\": [1,2,3]}\',\n\'$.key1\');\n+-------------------------------------------------------+\n| json_query(\'{\"key1\":123, \"key1\": [1,2,3]}\',\n\'$.key1\') |\n+-------------------------------------------------------+\n| [1,2,3] |\n+-------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_query/','','https://mariadb.com/kb/en/json_query/'),(714,'JSON_QUOTE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_QUOTE(json_value)\n \nDescription\n----------- \nQuotes a string as a JSON value, usually for producing valid\nJSON string literals for inclusion in JSON documents. Wraps\nthe string with double quote characters and escapes interior\nquotes and other special characters, returning a utf8mb4\nstring. \n \nReturns NULL if the argument is NULL.\n \nExamples\n-------- \nSELECT JSON_QUOTE(\'A\'), JSON_QUOTE(\"B\"),\nJSON_QUOTE(\'\"C\"\');\n+-----------------+-----------------+-------------------+\n| JSON_QUOTE(\'A\') | JSON_QUOTE(\"B\") |\nJSON_QUOTE(\'\"C\"\') |\n+-----------------+-----------------+-------------------+\n| \"A\" | \"B\" | \"\\\"C\\\"\" |\n+-----------------+-----------------+-------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_quote/','','https://mariadb.com/kb/en/json_quote/'),(715,'JSON_REMOVE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_REMOVE(json_doc, path[, path] ...)\n \nDescription\n----------- \nRemoves data from a JSON document returning the result, or\nNULL if any of the arguments are null. If the element does\nnot exist in the document, no changes are made.\n \nAn error will occur if JSON document is invalid, the path is\ninvalid or if the path contains a * or ** wildcard.\n \nPath arguments are evaluated from left to right, with the\nresult from the earlier evaluation being used as the value\nfor the next.\n \nExamples\n-------- \nSELECT JSON_REMOVE(\'{\"A\": 1, \"B\": 2, \"C\": {\"D\":\n3}}\', \'$.C\');\n+-------------------------------------------------------+\n| JSON_REMOVE(\'{\"A\": 1, \"B\": 2, \"C\": {\"D\": 3}}\',\n\'$.C\') |\n+-------------------------------------------------------+\n| {\"A\": 1, \"B\": 2} |\n+-------------------------------------------------------+\n \nSELECT JSON_REMOVE(\'[\"A\", \"B\", [\"C\", \"D\"],\n\"E\"]\', \'$[1]\');\n+----------------------------------------------------+\n| JSON_REMOVE(\'[\"A\", \"B\", [\"C\", \"D\"], \"E\"]\',\n\'$[1]\') |\n+----------------------------------------------------+\n| [\"A\", [\"C\", \"D\"], \"E\"] |\n+----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_remove/','','https://mariadb.com/kb/en/json_remove/'),(716,'JSON_REPLACE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_REPLACE(json_doc, path, val[, path, val] ...)\n \nDescription\n----------- \nReplaces existing values in a JSON document, returning the\nresult, or NULL if any of the arguments are NULL. \n \nAn error will occur if the JSON document is invalid, the\npath is invalid or if the path contains a * or ** wildcard.\n \nPaths and values are evaluated from left to right, with the\nresult from the earlier evaluation being used as the value\nfor the next.\n \nJSON_REPLACE can only update data, while JSON_INSERT can\nonly insert. JSON_SET can update or insert data. \n \nExamples\n-------- \nSELECT JSON_REPLACE(\'{ \"A\": 1, \"B\": [2, 3]}\',\n\'$.B[1]\', 4);\n+-----------------------------------------------------+\n| JSON_REPLACE(\'{ \"A\": 1, \"B\": [2, 3]}\', \'$.B[1]\',\n4) |\n+-----------------------------------------------------+\n| { \"A\": 1, \"B\": [2, 4]} |\n+-----------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_replace/','','https://mariadb.com/kb/en/json_replace/'),(717,'JSON_SEARCH',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_SEARCH(json_doc, return_arg, search_str[, escape_char[,\npath] ...])\n \nDescription\n----------- \nReturns the path to the given string within a JSON document,\nor NULL if any of json_doc, search_str or a path argument is\nNULL; if the search string is not found, or if no path\nexists within the document. \n \nA warning will occur if the JSON document is not valid, any\nof the path arguments are not valid, if return_arg is\nneither one nor all, or if the escape character is not a\nconstant. NULL will be returned.\n \nreturn_arg can be one of two values:\n\'one: Terminates after finding the first match, so will\nreturn one path string. If there is more than one match, it\nis undefined which is considered first.\nall: Returns all matching path strings, without duplicates.\nMultiple strings are autowrapped as an array. The order is\nundefined.\n \nExamples\n-------- \nSET @json = \'[\"A\", [{\"B\": \"1\"}], {\"C\":\"AB\"},\n{\"D\":\"BC\"}]\';\n \nSELECT JSON_SEARCH(@json, \'one\', \'AB\');\n+---------------------------------+\n| JSON_SEARCH(@json, \'one\', \'AB\') |\n+---------------------------------+\n| \"$[2].C\" |\n+---------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_search/','','https://mariadb.com/kb/en/json_search/'),(719,'JSON_TYPE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_TYPE(json_val)\n \nDescription\n----------- \nReturns the type of a JSON value, or NULL if the argument is\nnull.\n \nAn error will occur if the argument is an invalid JSON\nvalue.\n \nThe following is a complete list of the possible return\ntypes:\n \nReturn type | Value | \n \nARRAY | JSON array | \n \nBIT | MariaDB BIT scalar | \n \nBLOB | MariaDB binary types (BINARY, VARBINARY or BLOB) | \n \nBOOLEAN | JSON true/false literals | \n \nDATE | MariaDB DATE scalar | \n \nDATETIME | MariaDB DATETIME or TIMESTAMP scalar | \n \nDECIMAL | MariaDB DECIMAL or NUMERIC scalar | \n \nDOUBLE | MariaDB DOUBLE FLOAT scalar | \n \nINTEGER | MariaDB integer types (TINYINT, SMALLINT,\nMEDIUMINT, INT or BIGINT) | \n \nNULL | JSON null literal or NULL argument | \n \nOBJECT | JSON object | \n \nOPAQUE | Any valid JSON value that is not one of the other\ntypes. | \n \nSTRING | MariaDB character types (CHAR, VARCHAR, TEXT, ENUM\nor SET) | \n \nTIME | MariaDB TIME scalar | \n \nExamples\n-------- \nSELECT JSON_TYPE(\'{\"A\": 1, \"B\": 2, \"C\": 3}\');\n+---------------------------------------+\n| JSON_TYPE(\'{\"A\": 1, \"B\": 2, \"C\": 3}\') |\n+---------------------------------------+\n| OBJECT |\n+---------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_type/','','https://mariadb.com/kb/en/json_type/'),(720,'JSON_UNQUOTE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_UNQUOTE(val)\n \nDescription\n----------- \nUnquotes a JSON value, returning a string, or NULL if the\nargument is null. \n \nAn error will occur if the given value begins and ends with\ndouble quotes and is an invalid JSON string literal.\n \nCertain character sequences have special meanings within a\nstring. Usually, a backspace is ignored, but the escape\nsequences in the table below are recognised by MariaDB,\nunless the SQL Mode is set to NO_BACKSLASH_ESCAPES SQL.\n \nEscape sequence | Character | \n \n\\\" | Double quote (\") | \n \n\\b | Backspace | \n \n\\f | Formfeed | \n \n\\n | Newline (linefeed) | \n \n\\r | Carriage return | \n \n\\t | Tab | \n \n\\\\ | Backslash (\\) | \n \n\\uXXXX | UTF-8 bytes for Unicode value XXXX | \n \nExamples\n-------- \nSELECT JSON_UNQUOTE(\'\"Monty\"\');\n+-------------------------+\n| JSON_UNQUOTE(\'\"Monty\"\') |\n+-------------------------+\n| Monty |\n+-------------------------+\n \nWith the default SQL Mode:\n \nSELECT JSON_UNQUOTE(\'Si\\bng\\ting\');\n+-----------------------------+\n| JSON_UNQUOTE(\'Si\\bng\\ting\') |\n+-----------------------------+\n| Sng ing |\n+-----------------------------+\n \nSetting NO_BACKSLASH_ESCAPES:\n \nSET @@sql_mode = \'NO_BACKSLASH_ESCAPES\';\n \nSELECT JSON_UNQUOTE(\'Si\\bng\\ting\');\n+-----------------------------+\n| JSON_UNQUOTE(\'Si\\bng\\ting\') |\n+-----------------------------+\n| Si\\bng\\ting |\n+-----------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_unquote/','','https://mariadb.com/kb/en/json_unquote/'),(721,'JSON_VALID',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_VALID(value)\n \nDescription\n----------- \nIndicates whether the given value is a valid JSON document\nor not. Returns 1 if valid, 0 if not, and NULL if the\nargument is NULL.\n \nFrom MariaDB 10.4.3, the JSON_VALID function is\nautomatically used as a CHECK constraint for the JSON data\ntype alias in order to ensure that a valid json document is\ninserted. \n \nExamples\n-------- \nSELECT JSON_VALID(\'{\"id\": 1, \"name\": \"Monty\"}\');\n+------------------------------------------+\n| JSON_VALID(\'{\"id\": 1, \"name\": \"Monty\"}\') |\n+------------------------------------------+\n| 1 |\n+------------------------------------------+\n \nSELECT JSON_VALID(\'{\"id\": 1, \"name\": \"Monty\",\n\"oddfield\"}\');\n+------------------------------------------------------+\n| JSON_VALID(\'{\"id\": 1, \"name\": \"Monty\",\n\"oddfield\"}\') |\n+------------------------------------------------------+\n| 0 |\n+------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_valid/','','https://mariadb.com/kb/en/json_valid/'),(722,'JSON_VALUE',41,'JSON functions were added in MariaDB 10.2.3.\n \nSyntax\n------ \nJSON_VALUE(json_doc, path)\n \nDescription\n----------- \nGiven a JSON document, returns the scalar specified by the\npath. Returns NULL if not given a valid JSON document, or if\nthere is no match.\n \nExamples\n-------- \nselect json_value(\'{\"key1\":123}\', \'$.key1\');\n+--------------------------------------+\n| json_value(\'{\"key1\":123}\', \'$.key1\') |\n+--------------------------------------+\n| 123 |\n+--------------------------------------+\n \nselect json_value(\'{\"key1\": [1,2,3], \"key1\":123}\',\n\'$.key1\');\n+-------------------------------------------------------+\n| json_value(\'{\"key1\": [1,2,3], \"key1\":123}\',\n\'$.key1\') |\n+-------------------------------------------------------+\n| 123 |\n+-------------------------------------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/json_value/','','https://mariadb.com/kb/en/json_value/'),(727,'DENSE_RANK',42,'The DENSE_RANK() function was first introduced with window\nfunctions in MariaDB 10.2.0.\n \nSyntax\n------ \nDENSE_RANK() OVER (\n [ PARTITION BY partition_expression ]\n [ ORDER BY order_list ]\n) \n \nDescription\n----------- \nDENSE_RANK() is a window function that displays the number\nof a given row, starting at one and following the ORDER BY\nsequence of the window function, with identical values\nreceiving the same result. Unlike the RANK() function, there\nare no skipped values if the preceding results are\nidentical. It is also similar to the ROW_NUMBER() function\nexcept that in that function, identical values will receive\na different row number for each result.\n \nExamples\n-------- \nThe distinction between DENSE_RANK(), RANK() and\nROW_NUMBER():\n \nCREATE TABLE student(course VARCHAR(10), mark int, name\nvarchar(10));\n \nINSERT INTO student VALUES \n (\'Maths\', 60, \'Thulile\'),\n (\'Maths\', 60, \'Pritha\'),\n (\'Maths\', 70, \'Voitto\'),\n (\'Maths\', 55, \'Chun\'),\n (\'Biology\', 60, \'Bilal\'),\n (\'Biology\', 70, \'Roger\');\n \nSELECT \n RANK() OVER (PARTITION BY course ORDER BY mark DESC) AS\nrank, \n DENSE_RANK() OVER (PARTITION BY course ORDER BY mark DESC)\nAS dense_rank, \n ROW_NUMBER() OVER (PARTITION BY course ORDER BY mark DESC)\nAS row_num, \n course, mark, name \nFROM student ORDER BY course, mark DESC;\n \n+------+------------+---------+---------+------+---------+\n| rank | dense_rank | row_num | course | mark | name |\n+------+------------+---------+---------+------+---------+\n| 1 | 1 | 1 | Biology | 70 | Roger |\n| 2 | 2 | 2 | Biology | 60 | Bilal |\n| 1 | 1 | 1 | Maths | 70 | Voitto |\n| 2 | 2 | 2 | Maths | 60 | Thulile |\n| 2 | 2 | 3 | Maths | 60 | Pritha |\n| 4 | 3 | 4 | Maths | 55 | Chun |\n+------+------------+---------+---------+------+---------+\n \n\n\nURL: https://mariadb.com/kb/en/dense_rank/','','https://mariadb.com/kb/en/dense_rank/'),(723,'Window Functions Overview',42,'Window functions were introduced in MariaDB 10.2.\n \nIntroduction\n \nWindow functions allow calculations to be performed across a\nset of rows related to the current row.\n \nSyntax\n------ \nfunction (expression) OVER (\n [ PARTITION BY expression_list ]\n [ ORDER BY order_list [ frame_clause ] ] ) \n \nfunction:\n A valid window function\n \nexpression_list:\n expression | column_name [, expr_list ]\n \norder_list:\n expression | column_name [ ASC | DESC ] \n [, ... ]\n \nframe_clause:\n {ROWS | RANGE} {frame_border | BETWEEN frame_border AND\nframe_border}\n \nframe_border:\n | UNBOUNDED PRECEDING\n | UNBOUNDED FOLLOWING\n | CURRENT ROW\n | expr PRECEDING\n | expr FOLLOWING\n \nDescription\n----------- \nIn some ways, window functions are similar to aggregate\nfunctions in that they perform calculations across a set of\nrows. However, unlike aggregate functions, the output is not\ngrouped into a single row. \n \nNon-aggregate window functions include \nCUME_DIST\nDENSE_RANK\nFIRST_VALUE\nLAG\nLAST_VALUE\nLEAD\nMEDIAN\nNTH_VALUE\nNTILE\nPERCENT_RANK\nPERCENTILE_CONT\nPERCENTILE_DISC\nRANK, ROW_NUMBER\n \nAggregate functions that can also be used as window\nfunctions include \nAVG\nBIT_AND\nBIT_OR\nBIT_XOR\nCOUNT\nMAX\nMIN\nSTD\nSTDDEV\nSTDDEV_POP\nSTDDEV_SAMP\nSUM\nVAR_POP\nVAR_SAMP\nVARIANCE\n \nWindow function queries are characterised by the OVER\nkeyword, following which the set of rows used for the\ncalculation is specified. By default, the set of rows used\nfor the calculation (the \"window) is the entire dataset,\nwhich can be ordered with the ORDER BY clause. The PARTITION\nBY clause is used to reduce the window to a particular group\nwithin the dataset.\n \nFor example, given the following data:\n \nCREATE TABLE student (name CHAR(10), test CHAR(10), score\nTINYINT); \n \nINSERT INTO student VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87), (\'Tatiana\', \'Tuning\', 83);\n \nthe following two queries return the average partitioned by\ntest and by name respectively:\n \nSELECT name, test, score, AVG(score) OVER (PARTITION BY\ntest) \n AS average_by_test FROM student;\n \n+---------+--------+-------+-----------------+\n| name | test | score | average_by_test |\n+---------+--------+-------+-----------------+\n| Chun | SQL | 75 | 65.2500 |\n| Chun | Tuning | 73 | 68.7500 |\n| Esben | SQL | 43 | 65.2500 |\n| Esben | Tuning | 31 | 68.7500 |\n| Kaolin | SQL | 56 | 65.2500 |\n| Kaolin | Tuning | 88 | 68.7500 |\n| Tatiana | SQL | 87 | 65.2500 |\n| Tatiana | Tuning | 83 | 68.7500 |\n+---------+--------+-------+-----------------+\n \nSELECT name, test, score, AVG(score) OVER (PARTITION BY\nname) \n AS average_by_name FROM student;\n \n+---------+--------+-------+-----------------+\n| name | test | score | average_by_name |\n+---------+--------+-------+-----------------+\n| Chun | SQL | 75 | 74.0000 |\n| Chun | Tuning | 73 | 74.0000 |\n| Esben | SQL | 43 | 37.0000 |\n| Esben | Tuning | 31 | 37.0000 |\n| Kaolin | SQL | 56 | 72.0000 |\n| Kaolin | Tuning | 88 | 72.0000 |\n| Tatiana | SQL | 87 | 85.0000 |\n| Tatiana | Tuning | 83 | 85.0000 |\n+---------+--------+-------+-----------------+\n \nIt is also possible to specify which rows to include for the\nwindow function (for example, the current row and all\npreceding rows). See Window Frames for more details.\n \nScope\n \nWindow functions were introduced in SQL:2003, and their\ndefinition was expanded in subsequent versions of the\nstandard. The last expansion was in the latest version of\nthe standard, SQL:2011. \n \nMost database products support a subset of the standard,\nthey implement some functions defined as late as in\nSQL:2011, and at the same time leave some parts of SQL:2008\nunimplemented.\n \nMariaDB:\nSupports ROWS and RANGE-type frames\nAll kinds of frame bounds are supported, including RANGE\nPRECEDING|FOLLOWING n frame bounds (unlike PostgreSQL or MS\nSQL Server)\nDoes not yet support DATE[TIME] datatype and arithmetic for\nRANGE-type frames (MDEV-9727)\n \nDoes not support GROUPS-type frames (it seems that no\npopular database supports it, either)\n \nDoes not support frame exclusion (no other database seems to\nsupport it, either) (MDEV-9724)\nDoes not support explicit NULLS FIRST or NULLS LAST.\nDoes not support nested navigation in window functions (this\nis VALUE_OF(expr AT row_marker [, default_value) syntax)\n \nThe following window functions are supported:\n\"Streamable\" window functions: ROW_NUMBER, RANK,\nDENSE_RANK, \nWindow functions that can be streamed once the number of\nrows in partition is known: PERCENT_RANK, CUME_DIST, NTILE\n \nAggregate functions that are currently supported as window\nfunctions are: COUNT, SUM, AVG, BIT_OR, BIT_AND, BIT_XOR.\nAggregate functions with the DISTINCT specifier (e.g. COUNT(\nDISTINCT x)) are not supported as window functions.\n \nLinks\n \nMDEV-6115 is the main jira task for window functions\ndevelopment. Other tasks are are attached as sub-tasks\nbb-10.2-mdev9543 is the feature tree for window functions.\nDevelopment is ongoing, and this tree has the newest\nchanges.\nTestcases are in mysql-test/t/win*.test\n \nExamples\n-------- \nGiven the following sample data:\n \nCREATE TABLE users (\n email VARCHAR(30), \n first_name VARCHAR(30), \n last_name VARCHAR(30), \n account_type VARCHAR(30)\n);\n \nINSERT INTO users VALUES \n (\'admin@boss.org\', \'Admin\', \'Boss\', \'admin\'), \n (\'bob.carlsen@foo.bar\', \'Bob\', \'Carlsen\',\n\'regular\'),\n (\'eddie.stevens@data.org\', \'Eddie\', \'Stevens\',\n\'regular\'),\n (\'john.smith@xyz.org\', \'John\', \'Smith\', \'regular\'),\n\n (\'root@boss.org\', \'Root\', \'Chief\', \'admin\')\n \nFirst, let\'s order the records by email alphabetically,\ngiving each an ascending rnum value starting with 1. This\nwill make use of the ROW_NUMBER window function:\n \nSELECT row_number() OVER (ORDER BY email) AS rnum,\n email, first_name, last_name, account_type\nFROM users ORDER BY email;\n \n+------+------------------------+------------+-----------+--------------+\n| rnum | email | first_name | last_name | account_type |\n+------+------------------------+------------+-----------+--------------+\n| 1 | admin@boss.org | Admin | Boss | admin |\n| 2 | bob.carlsen@foo.bar | Bob | Carlsen | regular |\n| 3 | eddie.stevens@data.org | Eddie | Stevens | regular |\n| 4 | john.smith@xyz.org | John | Smith | regular |\n| 5 | root@boss.org | Root | Chief | admin |\n+------+------------------------+------------+-----------+--------------\n \nWe can generate separate sequences based on account type,\nusing the PARTITION BY clause:\n \nSELECT row_number() OVER (PARTITION BY account_type ORDER BY\nemail) AS rnum, \n email, first_name, last_name, account_type \nFROM users ORDER BY account_type,email;\n \n+------+------------------------+------------+-----------+--------------+\n| rnum | email | first_name | last_name | account_type |\n+------+------------------------+------------+-----------+--------------+\n| 1 | admin@boss.org | Admin | Boss | admin |\n| 2 | root@boss.org | Root | Chief | admin |\n| 1 | bob.carlsen@foo.bar | Bob | Carlsen | regular |\n| 2 | eddie.stevens@data.org | Eddie | Stevens | regular |\n| 3 | john.smith@xyz.org | John | Smith | regular |\n+------+------------------------+------------+-----------+--------------+\n \nGiven the following structure and data, we want to find the\ntop 5 salaries from each department. \n \nCREATE TABLE employee_salaries (dept VARCHAR(20), name\nVARCHAR(20), salary INT(11));\n \nINSERT INTO employee_salaries VALUES\n(\'Engineering\', \'Dharma\', 3500),\n(\'Engineering\', \'Bình\', 3000),\n(\'Engineering\', \'Adalynn\', 2800),\n(\'Engineering\', \'Samuel\', 2500),\n(\'Engineering\', \'Cveta\', 2200),\n(\'Engineering\', \'Ebele\', 1800),\n(\'Sales\', \'Carbry\', 500),\n(\'Sales\', \'Clytemnestra\', 400),\n(\'Sales\', \'Juraj\', 300),\n(\'Sales\', \'Kalpana\', 300),\n(\'Sales\', \'Svantepolk\', 250),\n(\'Sales\', \'Angelo\', 200);\n \nWe could do this without using window functions, as follows:\n \nselect dept, name, salary\nfrom employee_salaries as t1\nwhere (select count(t2.salary)\n from employee_salaries as t2\n where t1.name != t2.name and\n t1.dept = t2.dept and\n t2.salary > t1.salary) \n\nURL:\nhttps://mariadb.com/kb/en/library/window-functions-overview/','','https://mariadb.com/kb/en/library/window-functions-overview/'),(725,'Window Frames',42,'Window functions were first introduced in MariaDB 10.2.0.\n \nSyntax\n------ \nframe_clause:\n {ROWS | RANGE} {frame_border | BETWEEN frame_border AND\nframe_border}\n \nframe_border:\n | UNBOUNDED PRECEDING\n | UNBOUNDED FOLLOWING\n | CURRENT ROW\n | expr PRECEDING\n | expr FOLLOWING\n \nDescription\n----------- \nA basic overview of window functions is described in Window\nFunctions Overview. Window frames expand this functionality\nby allowing the function to include a specified a number of\nrows around the current row.\n \nThese include:\nAll rows before the current row (UNBOUNDED PRECEDING), for\nexample RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\nAll rows after the current row (UNBOUNDED FOLLOWING), for\nexample RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING\nA set number of rows before the current row (expr PRECEDING)\nfor example RANGE BETWEEN 6 PRECEDING AND CURRENT ROW\nA set number of rows after the current row (expr PRECEDING\nAND expr FOLLOWING) for example RANGE BETWEEN CURRENT ROW\nAND 2 FOLLOWING\nA specified number of rows both before and after the current\nrow, for example RANGE BETWEEN 6 PRECEDING AND 3 FOLLOWING \n \nThe following functions operate on window frames:\nAVG\nBIT_AND\nBIT_OR\nBIT_XOR\nCOUNT\nLEAD\nMAX\nMIN\nNTILE\nSTD\nSTDDEV\nSTDDEV_POP\nSTDDEV_SAMP\nSUM\nVAR_POP\nVAR_SAMP\nVARIANCE\n \nWindow frames are determined by the frame_clause in the\nwindow function request. \n \nTake the following example:\n \nCREATE TABLE `student_test` (\n name char(10),\n test char(10),\n score tinyint(4)\n);\n \nINSERT INTO student_test VALUES \n (\'Chun\', \'SQL\', 75), (\'Chun\', \'Tuning\', 73), \n (\'Esben\', \'SQL\', 43), (\'Esben\', \'Tuning\', 31), \n (\'Kaolin\', \'SQL\', 56), (\'Kaolin\', \'Tuning\', 88), \n (\'Tatiana\', \'SQL\', 87);\n \nSELECT name, test, score, SUM(score) \n OVER () AS total_score \n FROM student_test;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Chun | SQL | 75 | 453 |\n| Chun | Tuning | 73 | 453 |\n| Esben | SQL | 43 | 453 |\n| Esben | Tuning | 31 | 453 |\n| Kaolin | SQL | 56 | 453 |\n| Kaolin | Tuning | 88 | 453 |\n| Tatiana | SQL | 87 | 453 |\n+---------+--------+-------+-------------+\n \nBy not specifying an OVER condition, the SUM function is run\nover the entire dataset. However, if we specify an ORDER BY\ncondition based on score (and order the entire result in the\nsame way for clarity), the following result is returned:\n \nSELECT name, test, score, SUM(score) \n OVER (ORDER BY score) AS total_score \n FROM student_test ORDER BY score;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Esben | Tuning | 31 | 31 |\n| Esben | SQL | 43 | 74 |\n| Kaolin | SQL | 56 | 130 |\n| Chun | Tuning | 73 | 203 |\n| Chun | SQL | 75 | 278 |\n| Tatiana | SQL | 87 | 365 |\n| Kaolin | Tuning | 88 | 453 |\n+---------+--------+-------+-------------+\n \nThe total_score column represents a running total of the\ncurrent row, and all previous rows. The window frame in this\nexample expands as the function proceeds.\n \nThe above query makes use of the default to define the\nwindow frame. It could be written explicitly as follows:\n \nSELECT name, test, score, SUM(score) \n OVER (ORDER BY score RANGE BETWEEN UNBOUNDED PRECEDING AND\nCURRENT ROW) AS total_score \n FROM student_test ORDER BY score;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Esben | Tuning | 31 | 31 |\n| Esben | SQL | 43 | 74 |\n| Kaolin | SQL | 56 | 130 |\n| Chun | Tuning | 73 | 203 |\n| Chun | SQL | 75 | 278 |\n| Tatiana | SQL | 87 | 365 |\n| Kaolin | Tuning | 88 | 453 |\n+---------+--------+-------+-------------+\n \nLet\'s look at some alternatives:\n \nFirstly, applying the window function to the current row and\nall following rows can be done with the use of UNBOUNDED\nFOLLOWING:\n \nSELECT name, test, score, SUM(score) \n OVER (ORDER BY score RANGE BETWEEN CURRENT ROW AND\nUNBOUNDED FOLLOWING) AS total_score \n FROM student_test ORDER BY score;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Esben | Tuning | 31 | 453 |\n| Esben | SQL | 43 | 422 |\n| Kaolin | SQL | 56 | 379 |\n| Chun | Tuning | 73 | 323 |\n| Chun | SQL | 75 | 250 |\n| Tatiana | SQL | 87 | 175 |\n| Kaolin | Tuning | 88 | 88 |\n+---------+--------+-------+-------------+\n \nIt\'s possible to specify a number of rows, rather than the\nentire unbounded following or preceding set. The following\nexample takes the current row, as well as the previous row:\n \nSELECT name, test, score, SUM(score) \n OVER (ORDER BY score ROWS BETWEEN 1 PRECEDING AND CURRENT\nROW) AS total_score \n FROM student_test ORDER BY score;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Esben | Tuning | 31 | 31 |\n| Esben | SQL | 43 | 74 |\n| Kaolin | SQL | 56 | 99 |\n| Chun | Tuning | 73 | 129 |\n| Chun | SQL | 75 | 148 |\n| Tatiana | SQL | 87 | 162 |\n| Kaolin | Tuning | 88 | 175 |\n+---------+--------+-------+-------------+\n \nThe current row and the following row:\n \nSELECT name, test, score, SUM(score) \n OVER (ORDER BY score ROWS BETWEEN 1 PRECEDING AND 1\nFOLLOWING) AS total_score \n FROM student_test ORDER BY score;\n \n+---------+--------+-------+-------------+\n| name | test | score | total_score |\n+---------+--------+-------+-------------+\n| Esben | Tuning | 31 | 74 |\n| Esben | SQL | 43 | 130 |\n| Kaolin | SQL | 56 | 172 |\n| Chun | Tuning | 73 | 204 |\n| Chun | SQL | 75 | 235 |\n| Tatiana | SQL | 87 | 250 |\n| Kaolin | Tuning | 88 | 175 |\n+---------+--------+-------+-------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/library/window-frames/','','https://mariadb.com/kb/en/library/window-frames/'),(728,'FIRST_VALUE',42,'The FIRST_VALUE() function was first introduced with other\nwindow functions in MariaDB 10.2.\n \nSyntax\n------ \nFIRST_VALUE(expr) OVER (\n [ PARTITION BY partition_expression ]\n [ ORDER BY order_list ]\n) \n \nDescription\n----------- \nFIRST_VALUE returns the first result from an ordered set, or\nNULL if no such result exists.\n \nExamples\n-------- \nCREATE TABLE t1 (\n pk int primary key,\n a int,\n b int,\n c char(10),\n d decimal(10, 3),\n e real\n);\n \nINSERT INTO t1 VALUES\n( 1, 0, 1, \'one\', 0.1, 0.001),\n( 2, 0, 2, \'two\', 0.2, 0.002),\n( 3, 0, 3, \'three\', 0.3, 0.003),\n( 4, 1, 2, \'three\', 0.4, 0.004),\n( 5, 1, 1, \'two\', 0.5, 0.005),\n( 6, 1, 1, \'one\', 0.6, 0.006),\n( 7, 2, NULL, \'n_one\', 0.5, 0.007),\n( 8, 2, 1, \'n_two\', NULL, 0.008),\n( 9, 2, 2, NULL, 0.7, 0.009),\n(10, 2, 0, \'n_four\', 0.8, 0.010),\n(11, 2, 10, NULL, 0.9, NULL);\n \nSELECT pk, FIRST_VALUE(pk) OVER (ORDER BY pk) AS first_asc,\n LAST_VALUE(pk) OVER (ORDER BY pk) AS last_asc,\n FIRST_VALUE(pk) OVER (ORDER BY pk DESC) AS first_desc,\n LAST_VALUE(pk) OVER (ORDER BY pk DESC) AS last_desc\nFROM t1\nORDER BY pk DESC;\n \n+----+-----------+----------+------------+-----------+\n| pk | first_asc | last_asc | first_desc | last_desc |\n+----+-----------+----------+------------+-----------+\n| 11 | 1 | 11 | 11 | 11 |\n| 10 | 1 | 10 | 11 | 10 |\n| 9 | 1 | 9 | 11 | 9 |\n| 8 | 1 | 8 | 11 | 8 |\n| 7 | 1 | 7 | 11 | 7 |\n| 6 | 1 | 6 | 11 | 6 |\n| 5 | 1 | 5 | 11 | 5 |\n| 4 | 1 | 4 | 11 | 4 |\n| 3 | 1 | 3 | 11 | 3 |\n| 2 | 1 | 2 | 11 | 2 |\n| 1 | 1 | 1 | 11 | 1 |\n+----+-----------+----------+------------+-----------+\n \nCREATE OR REPLACE TABLE t1 (i int);\nINSERT INTO t1 VALUES\n(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);\n \nSELECT i,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW\nand 1 FOLLOWING) AS f_1f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW and\n1 FOLLOWING) AS l_1f,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 PRECEDING\nAND 1 FOLLOWING) AS f_1p1f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 PRECEDING AND\n1 FOLLOWING) AS f_1p1f,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 2 PRECEDING\nAND 1 PRECEDING) AS f_2p1p,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 2 PRECEDING AND\n1 PRECEDING) AS f_2p1p,\n FIRST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 FOLLOWING\nAND 2 FOLLOWING) AS f_1f2f,\n LAST_VALUE(i) OVER (ORDER BY i ROWS BETWEEN 1 FOLLOWING AND\n2 FOLLOWING) AS f_1f2f\nFROM t1;\n \n+------+------+------+--------+--------+--------+--------+--------+--------+\n| i | f_1f | l_1f | f_1p1f | f_1p1f | f_2p1p | f_2p1p |\nf_1f2f | f_1f2f |\n+------+------+------+--------+--------+--------+--------+--------+--------+\n| 1 | 1 | 2 | 1 | 2 | NULL | NULL | 2 | 3 |\n| 2 | 2 | 3 | 1 | 3 | 1 | 1 | 3 | 4 |\n| 3 | 3 | 4 | 2 | 4 | 1 | 2 | 4 | 5 |\n| 4 | 4 | 5 | 3 | 5 | 2 | 3 | 5 | 6 |\n| 5 | 5 | 6 | 4 | 6 | 3 | 4 | 6 | 7 |\n| 6 | 6 | 7 | 5 | 7 | 4 | 5 | 7 | 8 |\n| 7 | 7 | 8 | 6 | 8 | 5 | 6 | 8 | 9 |\n| 8 | 8 | 9 | 7 | 9 | 6 | 7 | 9 | 10 |\n| 9 | 9 | 10 | 8 | 10 | 7 | 8 | 10 | 10 |\n| 10 | 10 | 10 | 9 | 10 | 8 | 9 | NULL | NULL |\n+------+------+------+--------+--------+--------+--------+--------+--------+\n \n\n\nURL: https://mariadb.com/kb/en/first_value/','','https://mariadb.com/kb/en/first_value/'),(729,'LAG',42,'The LAG() function was first introduced with other window\nfunctions in MariaDB 10.2.\n \nSyntax\n------ \nLAG (expr[, offset]) OVER ( \n [ PARTITION BY partition_expression ] \n < ORDER BY order_list >\n)\n \nDescription\n----------- \nThe LAG function accesses data from a previous row according\nto the ORDER BY clause without the need for a self-join. The\nspecific row is determined by the offset (default 1), which\nspecifies the number of rows behind the current row to use.\nAn offset of 0 is the current row.\n \nExamples\n-------- \nCREATE TABLE t1 (pk int primary key, a int, b int, c\nchar(10), d decimal(10, 3), e real);\n \nINSERT INTO t1 VALUES\n ( 1, 0, 1, \'one\', 0.1, 0.001),\n ( 2, 0, 2, \'two\', 0.2, 0.002),\n ( 3, 0, 3, \'three\', 0.3, 0.003),\n ( 4, 1, 2, \'three\', 0.4, 0.004),\n ( 5, 1, 1, \'two\', 0.5, 0.005),\n ( 6, 1, 1, \'one\', 0.6, 0.006),\n ( 7, 2, NULL, \'n_one\', 0.5, 0.007),\n ( 8, 2, 1, \'n_two\', NULL, 0.008),\n ( 9, 2, 2, NULL, 0.7, 0.009),\n (10, 2, 0, \'n_four\', 0.8, 0.010),\n (11, 2, 10, NULL, 0.9, NULL);\n \nSELECT pk, LAG(pk) OVER (ORDER BY pk) AS l,\n LAG(pk,1) OVER (ORDER BY pk) AS l1,\n LAG(pk,2) OVER (ORDER BY pk) AS l2,\n LAG(pk,0) OVER (ORDER BY pk) AS l0,\n LAG(pk,-1) OVER (ORDER BY pk) AS lm1,\n LAG(pk,-2) OVER (ORDER BY pk) AS lm2 \nFROM t1;\n \n+----+------+------+------+------+------+------+\n| pk | l | l1 | l2 | l0 | lm1 | lm2 |\n+----+------+------+------+------+------+------+\n| 1 | NULL | NULL | NULL | 1 | 2 | 3 |\n| 2 | 1 | 1 | NULL | 2 | 3 | 4 |\n| 3 | 2 | 2 | 1 | 3 | 4 | 5 |\n| 4 | 3 | 3 | 2 | 4 | 5 | 6 |\n| 5 | 4 | 4 | 3 | 5 | 6 | 7 |\n| 6 | 5 | 5 | 4 | 6 | 7 | 8 |\n| 7 | 6 | 6 | 5 | 7 | 8 | 9 |\n| 8 | 7 | 7 | 6 | 8 | 9 | 10 |\n| 9 | 8 | 8 | 7 | 9 | 10 | 11 |\n| 10 | 9 | 9 | 8 | 10 | 11 | NULL |\n| 11 | 10 | 10 | 9 | 11 | NULL | NULL |\n+----+------+------+------+------+------+------+\n \n\n\nURL: https://mariadb.com/kb/en/lag/','','https://mariadb.com/kb/en/lag/'),(730,'LEAD',42,'The LEAD() function was first introduced with other window\nfunctions in MariaDB 10.2.\n \nSyntax\n------ \nLEAD (expr[, offset]) OVER ( \n [ PARTITION BY partition_expression ] \n [ ORDER BY order_list ]\n)\n \nDescription\n----------- \nThe LEAD function accesses data from a following row in the\nsame result set without the need for a self-join. The\nspecific row is determined by the offset (default 1), which\nspecifies the number of rows ahead the current row to use.\nAn offset of 0 is the current row.\n \nExample\n \nCREATE TABLE t1 (pk int primary key, a int, b int, c\nchar(10), d decimal(10, 3), e real);\n \nINSERT INTO t1 VALUES\n ( 1, 0, 1, \'one\', 0.1, 0.001),\n ( 2, 0, 2, \'two\', 0.2, 0.002),\n ( 3, 0, 3, \'three\', 0.3, 0.003),\n ( 4, 1, 2, \'three\', 0.4, 0.004),\n ( 5, 1, 1, \'two\', 0.5, 0.005),\n ( 6, 1, 1, \'one\', 0.6, 0.006),\n ( 7, 2, NULL, \'n_one\', 0.5, 0.007),\n ( 8, 2, 1, \'n_two\', NULL, 0.008),\n ( 9, 2, 2, NULL, 0.7, 0.009),\n (10, 2, 0, \'n_four\', 0.8, 0.010),\n (11, 2, 10, NULL, 0.9, NULL);\n \nSELECT pk, LEAD(pk) OVER (ORDER BY pk) AS l,\n LEAD(pk,1) OVER (ORDER BY pk) AS l1,\n LEAD(pk,2) OVER (ORDER BY pk) AS l2,\n LEAD(pk,0) OVER (ORDER BY pk) AS l0,\n LEAD(pk,-1) OVER (ORDER BY pk) AS lm1,\n LEAD(pk,-2) OVER (ORDER BY pk) AS lm2 \nFROM t1;\n \n+----+------+------+------+------+------+------+\n| pk | l | l1 | l2 | l0 | lm1 | lm2 |\n+----+------+------+------+------+------+------+\n| 1 | 2 | 2 | 3 | 1 | NULL | NULL |\n| 2 | 3 | 3 | 4 | 2 | 1 | NULL |\n| 3 | 4 | 4 | 5 | 3 | 2 | 1 |\n| 4 | 5 | 5 | 6 | 4 | 3 | 2 |\n| 5 | 6 | 6 | 7 | 5 | 4 | 3 |\n| 6 | 7 | 7 | 8 | 6 | 5 | 4 |\n| 7 | 8 | 8 | 9 | 7 | 6 | 5 |\n| 8 | 9 | 9 | 10 | 8 | 7 | 6 |\n| 9 | 10 | 10 | 11 | 9 | 8 | 7 |\n| 10 | 11 | 11 | NULL | 10 | 9 | 8 |\n| 11 | NULL | NULL | NULL | 11 | 10 | 9 |\n+----+------+------+------+------+------+------+\n \n\n\nURL: https://mariadb.com/kb/en/lead/','','https://mariadb.com/kb/en/lead/'),(731,'Median Window Function',42,'The MEDIAN() window function was first introduced with in\nMariaDB 10.3.3.\n \nSyntax\n------ \nMEDIAN(median expression) OVER (\n [ PARTITION BY partition_expression ] \n)\n \nDescription\n----------- \nMEDIAN() is a window function that returns the median value\nof a range of values.\n \nIt is a specific case of PERCENTILE_CONT, with an argument\nof 0.5 and the ORDER BY column the one in MEDIAN\'s\nargument. \n \nMEDIAN() OVER ( [ PARTITION BY partition_expression] )\n \nIs equivalent to:\n \nPERCENTILE_CONT(0.5) WITHIN \n GROUP (ORDER BY ) OVER ( [ PARTITION BY\npartition_expression ])\n \nExamples\n-------- \nCREATE TABLE book_rating (name CHAR(30), star_rating\nTINYINT);\n \nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n5);\nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n3);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 1);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 2);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 5);\n \nSELECT name, median(star_rating) OVER (PARTITION BY name)\nFROM book_rating;\n \n+-----------------------+----------------------------------------------+\n| name | median(star_rating) OVER (PARTITION BY name) |\n+-----------------------+----------------------------------------------+\n| Lord of the Ladybirds | 4.0000000000 |\n| Lord of the Ladybirds | 4.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n+-----------------------+----------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/median/','','https://mariadb.com/kb/en/median/'),(733,'NTILE',42,'The NTILE() function was first introduced with window\nfunctions in MariaDB 10.2.0.\n \nSyntax\n------ \nNTILE (expr) OVER ( \n [ PARTITION BY partition_expression ] \n [ ORDER BY order_list ]\n)\n \nDescription\n----------- \nNTILE() is a window function that returns an integer\nindicating which group a given row falls into. The number of\ngroups is specified in the argument (expr), starting at one.\nOrdered rows in the partition are divided into the specified\nnumber of groups with as equal a size as possible. \n \nExamples\n-------- \ncreate table t1 (\n pk int primary key,\n a int,\n b int\n );\n \ninsert into t1 values\n (11 , 0, 10),\n (12 , 0, 10),\n (13 , 1, 10),\n (14 , 1, 10),\n (18 , 2, 10),\n (15 , 2, 20),\n (16 , 2, 20),\n (17 , 2, 20),\n (19 , 4, 20),\n (20 , 4, 20);\n \nselect pk, a, b,\n ntile(1) over (order by pk)\n from t1;\n \n+----+------+------+-----------------------------+\n| pk | a | b | ntile(1) over (order by pk) |\n+----+------+------+-----------------------------+\n| 11 | 0 | 10 | 1 |\n| 12 | 0 | 10 | 1 |\n| 13 | 1 | 10 | 1 |\n| 14 | 1 | 10 | 1 |\n| 15 | 2 | 20 | 1 |\n| 16 | 2 | 20 | 1 |\n| 17 | 2 | 20 | 1 |\n| 18 | 2 | 10 | 1 |\n| 19 | 4 | 20 | 1 |\n| 20 | 4 | 20 | 1 |\n+----+------+------+-----------------------------+\n \nselect pk, a, b,\n ntile(4) over (order by pk)\n from t1;\n \n+----+------+------+-----------------------------+\n| pk | a | b | ntile(4) over (order by pk) |\n+----+------+------+-----------------------------+\n| 11 | 0 | 10 | 1 |\n| 12 | 0 | 10 | 1 |\n| 13 | 1 | 10 | 1 |\n| 14 | 1 | 10 | 2 |\n| 15 | 2 | 20 | 2 |\n| 16 | 2 | 20 | 2 |\n| 17 | 2 | 20 | 3 |\n| 18 | 2 | 10 | 3 |\n| 19 | 4 | 20 | 4 |\n| 20 | 4 | 20 | 4 |\n+----+------+------+-----------------------------+\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/ntile/','','https://mariadb.com/kb/en/ntile/'),(734,'PERCENT_RANK',42,'The PERCENT_RANK() function was first introduced with window\nfunctions in MariaDB 10.2.0.\n \nSyntax\n------ \nPERCENT_RANK() OVER (\n [ PARTITION BY partition_expression ] \n [ ORDER BY order_list ]\n)\n \nDescription\n----------- \nPERCENT_RANK() is a window function that returns the\nrelative percent rank of a given row. The following formula\nis used to calculate the percent rank:\n \n(rank - 1) / (number of rows in the window or partition - 1)\n \nExamples\n-------- \ncreate table t1 (\n pk int primary key,\n a int,\n b int\n);\n \ninsert into t1 values\n( 1 , 0, 10),\n( 2 , 0, 10),\n( 3 , 1, 10),\n( 4 , 1, 10),\n( 8 , 2, 10),\n( 5 , 2, 20),\n( 6 , 2, 20),\n( 7 , 2, 20),\n( 9 , 4, 20),\n(10 , 4, 20);\n \nselect pk, a, b,\n rank() over (order by a) as rank,\n percent_rank() over (order by a) as pct_rank,\n cume_dist() over (order by a) as cume_dist\nfrom t1;\n \n+----+------+------+------+--------------+--------------+\n| pk | a | b | rank | pct_rank | cume_dist |\n+----+------+------+------+--------------+--------------+\n| 1 | 0 | 10 | 1 | 0.0000000000 | 0.2000000000 |\n| 2 | 0 | 10 | 1 | 0.0000000000 | 0.2000000000 |\n| 3 | 1 | 10 | 3 | 0.2222222222 | 0.4000000000 |\n| 4 | 1 | 10 | 3 | 0.2222222222 | 0.4000000000 |\n| 5 | 2 | 20 | 5 | 0.4444444444 | 0.8000000000 |\n| 6 | 2 | 20 | 5 | 0.4444444444 | 0.8000000000 |\n| 7 | 2 | 20 | 5 | 0.4444444444 | 0.8000000000 |\n| 8 | 2 | 10 | 5 | 0.4444444444 | 0.8000000000 |\n| 9 | 4 | 20 | 9 | 0.8888888889 | 1.0000000000 |\n| 10 | 4 | 20 | 9 | 0.8888888889 | 1.0000000000 |\n+----+------+------+------+--------------+--------------+\n \nselect pk, a, b,\n percent_rank() over (order by pk) as pct_rank,\n cume_dist() over (order by pk) as cume_dist\nfrom t1 order by pk;\n \n+----+------+------+--------------+--------------+\n| pk | a | b | pct_rank | cume_dist |\n+----+------+------+--------------+--------------+\n| 1 | 0 | 10 | 0.0000000000 | 0.1000000000 |\n| 2 | 0 | 10 | 0.1111111111 | 0.2000000000 |\n| 3 | 1 | 10 | 0.2222222222 | 0.3000000000 |\n| 4 | 1 | 10 | 0.3333333333 | 0.4000000000 |\n| 5 | 2 | 20 | 0.4444444444 | 0.5000000000 |\n| 6 | 2 | 20 | 0.5555555556 | 0.6000000000 |\n| 7 | 2 | 20 | 0.6666666667 | 0.7000000000 |\n| 8 | 2 | 10 | 0.7777777778 | 0.8000000000 |\n| 9 | 4 | 20 | 0.8888888889 | 0.9000000000 |\n| 10 | 4 | 20 | 1.0000000000 | 1.0000000000 |\n+----+------+------+--------------+--------------+\n \nselect pk, a, b,\n percent_rank() over (partition by a order by a) as\npct_rank,\n cume_dist() over (partition by a order by a) as cume_dist\nfrom t1;\n \n+----+------+------+--------------+--------------+\n| pk | a | b | pct_rank | cume_dist |\n+----+------+------+--------------+--------------+\n| 1 | 0 | 10 | 0.0000000000 | 1.0000000000 |\n| 2 | 0 | 10 | 0.0000000000 | 1.0000000000 |\n| 3 | 1 | 10 | 0.0000000000 | 1.0000000000 |\n| 4 | 1 | 10 | 0.0000000000 | 1.0000000000 |\n| 5 | 2 | 20 | 0.0000000000 | 1.0000000000 |\n| 6 | 2 | 20 | 0.0000000000 | 1.0000000000 |\n| 7 | 2 | 20 | 0.0000000000 | 1.0000000000 |\n| 8 | 2 | 10 | 0.0000000000 | 1.0000000000 |\n| 9 | 4 | 20 | 0.0000000000 | 1.0000000000 |\n| 10 | 4 | 20 | 0.0000000000 | 1.0000000000 |\n+----+------+------+--------------+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/percent_rank/','','https://mariadb.com/kb/en/percent_rank/'),(736,'PERCENTILE_DISC',42,'The PERCENTILE_DISC() window function was first introduced\nwith in MariaDB 10.3.3.\n \nSyntax\n------ \n\nDescription\n----------- \nPERCENTILE_DISC() (standing for discrete percentile) is a\nwindow function which returns the first value in the set\nwhose ordered position is the same or more than the\nspecified fraction.\n \nEssentially, the following process is followed to find the\nvalue to return:\nGet the number of rows in the partition.\nWalk through the partition, in order, until finding the the\nfirst row with CUME_DIST() > function_argument.\n \nExamples\n-------- \nCREATE TABLE book_rating (name CHAR(30), star_rating\nTINYINT);\n \nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n5);\nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n3);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 1);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 2);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 5);\n \nSELECT name, PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY\nstar_rating)\n OVER (PARTITION BY name) AS pc FROM book_rating;\n \n+-----------------------+------+\n| name | pc |\n+-----------------------+------+\n| Lord of the Ladybirds | 3 |\n| Lord of the Ladybirds | 3 |\n| Lady of the Flies | 2 |\n| Lady of the Flies | 2 |\n| Lady of the Flies | 2 |\n+-----------------------+------+\n5 rows in set (0.000 sec)\n \nSELECT name, PERCENTILE_DISC(0) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc FROM book_rating;\n \n+-----------------------+------+\n| name | pc |\n+-----------------------+------+\n| Lord of the Ladybirds | 3 |\n| Lord of the Ladybirds | 3 |\n| Lady of the Flies | 1 |\n| Lady of the Flies | 1 |\n| Lady of the Flies | 1 |\n+-----------------------+------+\n5 rows in set (0.000 sec)\n \nSELECT name, PERCENTILE_DISC(1) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc FROM book_rating;\n \n+-----------------------+------+\n| name | pc |\n+-----------------------+------+\n| Lord of the Ladybirds | 5 |\n| Lord of the Ladybirds | 5 |\n| Lady of the Flies | 5 |\n| Lady of the Flies | 5 |\n| Lady of the Flies | 5 |\n+-----------------------+------+\n5 rows in set (0.000 sec)\n \nSELECT name, PERCENTILE_DISC(0.6) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc FROM book_rating;\n \n+-----------------------+------+\n| name | pc |\n+-----------------------+------+\n| Lord of the Ladybirds | 5 |\n| Lord of the Ladybirds | 5 |\n| Lady of the Flies | 2 |\n| Lady of the Flies | 2 |\n| Lady of the Flies | 2 |\n+-----------------------+------\n \n\n\nURL: https://mariadb.com/kb/en/percentile_disc/','','https://mariadb.com/kb/en/percentile_disc/'),(735,'PERCENTILE_CONT',42,'The PERCENTILE_CONT() window function was first introduced\nwith in MariaDB 10.3.3.\n \nSyntax\n------ \nDescription\n----------- \nPERCENTILE_CONT() (standing for continuous percentile) is a\nwindow function which returns a value which corresponds to\nthe given fraction in the sort order. If required, it will\ninterpolate between adjacent input items.\n \nEssentially, the following process is followed to find the\nvalue to return:\nGet the number of rows in the partition, denoted by N\nRN = p*(N-1), where p denotes the argument to the\nPERCENTILE_CONT function\ncalculate the FRN(floor row number) and CRN(column row\nnumber for the group( FRN= floor(RN) and CRN = ceil(RN))\nlook up rows FRN and CRN\nIf (CRN = FRN = RN) then the result is (value of expression\nfrom row at RN)\nOtherwise the result is\n(CRN - RN) * (value of expression for row at FRN) +\n(RN - FRN) * (value of expression for row at CRN)\n \nThe MEDIAN function is a specific case of PERCENTILE_CONT,\nequivalent to PERCENTILE_CONT(0.5).\n \nExamples\n-------- \nCREATE TABLE book_rating (name CHAR(30), star_rating\nTINYINT);\n \nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n5);\nINSERT INTO book_rating VALUES (\'Lord of the Ladybirds\',\n3);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 1);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 2);\nINSERT INTO book_rating VALUES (\'Lady of the Flies\', 5);\n \nSELECT name, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc \n FROM book_rating;\n \n+-----------------------+--------------+\n| name | pc |\n+-----------------------+--------------+\n| Lord of the Ladybirds | 4.0000000000 |\n| Lord of the Ladybirds | 4.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n| Lady of the Flies | 2.0000000000 |\n+-----------------------+--------------+\n \nSELECT name, PERCENTILE_CONT(1) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc \n FROM book_rating;\n \n+-----------------------+--------------+\n| name | pc |\n+-----------------------+--------------+\n| Lord of the Ladybirds | 5.0000000000 |\n| Lord of the Ladybirds | 5.0000000000 |\n| Lady of the Flies | 5.0000000000 |\n| Lady of the Flies | 5.0000000000 |\n| Lady of the Flies | 5.0000000000 |\n+-----------------------+--------------+\n \nSELECT name, PERCENTILE_CONT(0) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc \n FROM book_rating;\n \n+-----------------------+--------------+\n| name | pc |\n+-----------------------+--------------+\n| Lord of the Ladybirds | 3.0000000000 |\n| Lord of the Ladybirds | 3.0000000000 |\n| Lady of the Flies | 1.0000000000 |\n| Lady of the Flies | 1.0000000000 |\n| Lady of the Flies | 1.0000000000 |\n+-----------------------+--------------+\n \nSELECT name, PERCENTILE_CONT(0.6) WITHIN GROUP (ORDER BY\nstar_rating) \n OVER (PARTITION BY name) AS pc \n FROM book_rating;\n \n+-----------------------+--------------+\n| name | pc |\n+-----------------------+--------------+\n| Lord of the Ladybirds | 4.2000000000 |\n| Lord of the Ladybirds | 4.2000000000 |\n| Lady of the Flies | 2.6000000000 |\n| Lady of the Flies | 2.6000000000 |\n| Lady of the Flies | 2.6000000000 |\n+-----------------------+--------------+\n \n\n\nURL: https://mariadb.com/kb/en/percentile_cont/','','https://mariadb.com/kb/en/percentile_cont/'),(737,'RANK',42,'The RANK() function was first introduced with window\nfunctions in MariaDB 10.2.0.\n \nSyntax\n------ \nRANK() OVER (\n [ PARTITION BY partition_expression ]\n [ ORDER BY order_list ]\n) \n \nDescription\n----------- \nRANK() is a window function that displays the number of a\ngiven row, starting at one and following the ORDER BY\nsequence of the window function, with identical values\nreceiving the same result. It is similar to the ROW_NUMBER()\nfunction except that in that function, identical values will\nreceive a different row number for each result.\n \nExamples\n-------- \nThe distinction between DENSE_RANK(), RANK() and\nROW_NUMBER():\n \nCREATE TABLE student(course VARCHAR(10), mark int, name\nvarchar(10));\n \nINSERT INTO student VALUES \n (\'Maths\', 60, \'Thulile\'),\n (\'Maths\', 60, \'Pritha\'),\n (\'Maths\', 70, \'Voitto\'),\n (\'Maths\', 55, \'Chun\'),\n (\'Biology\', 60, \'Bilal\'),\n (\'Biology\', 70, \'Roger\');\n \nSELECT \n RANK() OVER (PARTITION BY course ORDER BY mark DESC) AS\nrank, \n DENSE_RANK() OVER (PARTITION BY course ORDER BY mark DESC)\nAS dense_rank, \n ROW_NUMBER() OVER (PARTITION BY course ORDER BY mark DESC)\nAS row_num, \n course, mark, name \nFROM student ORDER BY course, mark DESC;\n \n+------+------------+---------+---------+------+---------+\n| rank | dense_rank | row_num | course | mark | name |\n+------+------------+---------+---------+------+---------+\n| 1 | 1 | 1 | Biology | 70 | Roger |\n| 2 | 2 | 2 | Biology | 60 | Bilal |\n| 1 | 1 | 1 | Maths | 70 | Voitto |\n| 2 | 2 | 2 | Maths | 60 | Thulile |\n| 2 | 2 | 3 | Maths | 60 | Pritha |\n| 4 | 3 | 4 | Maths | 55 | Chun |\n+------+------------+---------+---------+------+---------+\n \n\n\nURL: https://mariadb.com/kb/en/rank/','','https://mariadb.com/kb/en/rank/'),(738,'ROW_NUMBER',42,'ROW_NUMBER() was first introduced with window functions in\nMariaDB 10.2.0.\n \nSyntax\n------ \nROW_NUMBER() OVER (\n [ PARTITION BY partition_expression ]\n [ ORDER BY order_list ]\n) \n \nDescription\n----------- \nROW_NUMBER() is a window function that displays the number\nof a given row, starting at one and following the ORDER BY\nsequence of the window function, with identical values\nreceiving different row numbers. It is similar to the RANK()\nand DENSE_RANK() functions except that in that function,\nidentical values will receive the same rank for each result.\n \nExamples\n-------- \nThe distinction between DENSE_RANK(), RANK() and\nROW_NUMBER():\n \nCREATE TABLE student(course VARCHAR(10), mark int, name\nvarchar(10));\n \nINSERT INTO student VALUES \n (\'Maths\', 60, \'Thulile\'),\n (\'Maths\', 60, \'Pritha\'),\n (\'Maths\', 70, \'Voitto\'),\n (\'Maths\', 55, \'Chun\'),\n (\'Biology\', 60, \'Bilal\'),\n (\'Biology\', 70, \'Roger\');\n \nSELECT \n RANK() OVER (PARTITION BY course ORDER BY mark DESC) AS\nrank, \n DENSE_RANK() OVER (PARTITION BY course ORDER BY mark DESC)\nAS dense_rank, \n ROW_NUMBER() OVER (PARTITION BY course ORDER BY mark DESC)\nAS row_num, \n course, mark, name \nFROM student ORDER BY course, mark DESC;\n \n+------+------------+---------+---------+------+---------+\n| rank | dense_rank | row_num | course | mark | name |\n+------+------------+---------+---------+------+---------+\n| 1 | 1 | 1 | Biology | 70 | Roger |\n| 2 | 2 | 2 | Biology | 60 | Bilal |\n| 1 | 1 | 1 | Maths | 70 | Voitto |\n| 2 | 2 | 2 | Maths | 60 | Thulile |\n| 2 | 2 | 3 | Maths | 60 | Pritha |\n| 4 | 3 | 4 | Maths | 55 | Chun |\n+------+------------+---------+---------+------+---------+\n \n\n\nURL: https://mariadb.com/kb/en/row_number/','','https://mariadb.com/kb/en/row_number/'),(739,'SPIDER_BG_DIRECT_SQL',43,'Syntax\n------ \nSPIDER_BG_DIRECT_SQL(\'sql\', \'tmp_table_list\',\n\'parameters\')\n \nDescription\n----------- \nExecutes the given SQL statement in the background on the\nremote server, as defined in the parameters listing. If the\nquery returns a result-set, it sttores the results in the\ngiven temporary table. When the given SQL statement executes\nsuccessfully, this function returns the number of called\nUDF\'s. It returns 0 when the given SQL statement fails.\n \nThis function is a UDF installed with the Spider storage\nengine.\n \nExamples\n-------- \nSELECT SPIDER_BG_DIRECT_SQL(\'SELECT * FROM example_table\',\n\'\', \n \'srv \"node1\", port \"8607\"\') AS \"Direct Query\";\n+--------------+\n| Direct Query | \n+--------------+\n| 1 |\n+--------------+\n \nParameters\n \nerror_rw_mode\n \nDescription: Returns empty results on network error.\n0 : Return error on getting network error.\n1: Return 0 records on getting network error.\n \nDefault Table Value: 0\nDSN Parameter Name: erwm\n \n\n\nURL: https://mariadb.com/kb/en/spider_bg_direct_sql/','','https://mariadb.com/kb/en/spider_bg_direct_sql/'),(740,'SPIDER_COPY_TABLES',43,'Syntax\n------ \nSPIDER_COPY_TABLES(spider_table_name, \n source_link_id, destination_link_id_list [,parameters])\n \nDescription\n----------- \nA UDF installed with the Spider Storage Engine, this\nfunction copies table data from source_link_id to\ndestination_link_id_list. The service does not need to be\nstopped in order to copy.\n \nIf the Spider table is partitioned, the name must be of the\nformat table_name#P#partition_name. The partition name can\nbe viewed in the mysql.spider_tables table, for example:\n \nSELECT table_name FROM mysql.spider_tables;\n+-------------+\n| table_name |\n+-------------+\n| spt_a#P#pt1 |\n| spt_a#P#pt2 |\n| spt_a#P#pt3 |\n+-------------+\n \nReturns 1 if the data was copied successfully, or 0 if\ncopying the data failed.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/spider_copy_tables/','','https://mariadb.com/kb/en/spider_copy_tables/'),(741,'SPIDER_DIRECT_SQL',43,'Syntax\n------ \nSPIDER_DIRECT_SQL(\'sql\', \'tmp_table_list\',\n\'parameters\')\n \nDescription\n----------- \nA UDF installed with the Spider Storage Engine, this\nfunction is used to execute the SQL string sql on the remote\nserver, as defined in parameters. If any resultsets are\nreturned, they are stored in the tmp_table_list.\n \nThe function returns 1 if the SQL executes successfully, or\n0 if it fails.\n \nExamples\n-------- \nSELECT SPIDER_DIRECT_SQL(\'SELECT * FROM s\', \'\', \'srv\n\"node1\", port \"8607\"\');\n+----------------------------------------------------------------------+\n| SPIDER_DIRECT_SQL(\'SELECT * FROM s\', \'\', \'srv\n\"node1\", port \"8607\"\') |\n+----------------------------------------------------------------------+\n| 1 |\n+----------------------------------------------------------------------+\n \n\n\nURL: https://mariadb.com/kb/en/spider_direct_sql/','','https://mariadb.com/kb/en/spider_direct_sql/'),(743,'COLUMN_ADD',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_ADD(dyncol_blob, column_nr, value [as type],\n[column_nr, value [as type]]...);\nCOLUMN_ADD(dyncol_blob, column_name, value [as type],\n[column_name, value [as type]]...);\n \nDescription\n----------- \nAdds or updates dynamic columns.\ndyncol_blob must be either a valid dynamic columns blob (for\nexample, COLUMN_CREATE returns such blob), or an empty\nstring.\ncolumn_name specifies the name of the column to be added. If\ndyncol_blob already has a column with this name, it will be\noverwritten.\nvalue specifies the new value for the column. Passing a NULL\nvalue will cause the column to be deleted.\nas type is optional. See #datatypes section for a discussion\nabout types.\n \nThe return value is a dynamic column blob after the\nmodifications.\n \nExamples\n-------- \n-- MariaDB 5.3+:\nUPDATE tbl SET dyncol_blob=COLUMN_ADD(dyncol_blob, 1\n/*column id*/, \"value\") WHERE id=1;\n \n-- MariaDB 10.0.1+:\nUPDATE t1 SET dyncol_blob=COLUMN_ADD(dyncol_blob,\n\"column_name\", \"value\") WHERE id=1;\n \nNote: COLUMN_ADD() is a regular function (just like\nCONCAT()), hence, in order to update the value in the table\nyou have to use the UPDATE ... SET\ndynamic_col=COLUMN_ADD(dynamic_col,\n....) pattern.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_add/','','https://mariadb.com/kb/en/column_add/'),(745,'COLUMN_CREATE',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_CREATE(column_nr, value [as type], [column_nr, value\n[as type]]...);\nCOLUMN_CREATE(column_name, value [as type], [column_name,\nvalue [as type]]...);\n \nDescription\n----------- \nReturns a dynamic columns blob that stores the specified\ncolumns with values.\n \nThe return value is suitable for \nstoring in a table\nfurther modification with other dynamic columns functions\n \nThe as type part allows one to specify the value type. In\nmost cases,\nthis is redundant because MariaDB will be able to deduce the\ntype of the\nvalue. Explicit type specification may be needed when the\ntype of the value is\nnot apparent. For example, a literal \'2012-12-01\' has a\nCHAR type by\ndefault, one will need to specify \'2012-12-01\' AS DATE to\nhave it stored as\na date. See Dynamic Columns:Datatypes for further details.\n \nExamples\n-------- \n-- MariaDB 5.3+:\nINSERT INTO tbl SET dyncol_blob=COLUMN_CREATE(1 /*column\nid*/, \"value\");\n-- MariaDB 10.0.1+:\nINSERT INTO tbl SET\ndyncol_blob=COLUMN_CREATE(\"column_name\", \"value\");\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_create/','','https://mariadb.com/kb/en/column_create/'),(748,'COLUMN_GET',44,'The Dynamic columns feature was introduced in MariaDB 5.3.\n \nSyntax\n------ \nCOLUMN_GET(dyncol_blob, column_nr as type);\nCOLUMN_GET(dyncol_blob, column_name as type);\n \nDescription\n----------- \nGets the value of a dynamic column by its name. If no column\nwith the given name exists, NULL will be returned.\n \ncolumn_name as type requires that one specify the datatype\nof the dynamic column they are reading. \n \nThis may seem counter-intuitive: why would one need to\nspecify which datatype they\'re retrieving? Can\'t the\ndynamic columns system figure the datatype from the data\nbeing stored?\n \nThe answer is: SQL is a statically-typed language. The SQL\ninterpreter needs to know the datatypes of all expressions\nbefore the query is run (for example, when one is using\nprepared statements and runs \"select COLUMN_GET(...)\", the\nprepared statement API requires the server to inform the\nclient about the datatype of the column being read before\nthe query is executed and the server can see what datatype\nthe column actually has).\n \nA note about lengths\n \nIf you\'re running queries like:\n \nSELECT COLUMN_GET(blob, \'colname\' as CHAR) ...\n \nwithout specifying a maximum length (i.e. using #as CHAR#,\nnot as CHAR(n)), MariaDB will report the maximum length of\nthe resultset column to be 53,6870,911 for MariaDB\n5.3-10.0.0 and 16,777,216 for MariaDB 10.0.1+. This may\ncause excessive memory usage in some client libraries,\nbecause they try to pre-allocate a buffer of maximum\nresultset width. To avoid this problem, use CHAR(n) whenever\nyou\'re using COLUMN_GET in the select list.\n \nSee Dynamic Columns:Datatypes for more information about\ndatatypes.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_get/','','https://mariadb.com/kb/en/column_get/'),(749,'COLUMN_JSON',44,'COLUMN_JSON was introduced in MariaDB 10.0.1\n \nSyntax\n------ \nCOLUMN_JSON(dyncol_blob)\n \nDescription\n----------- \nReturns a JSON representation of data in dyncol_blob. Can\nalso be used to display nested columns. See dynamic columns\nfor more information.\n \nExample\n \nselect item_name, COLUMN_JSON(dynamic_cols) from assets;\n+-----------------+----------------------------------------+\n| item_name | COLUMN_JSON(dynamic_cols) |\n+-----------------+----------------------------------------+\n| MariaDB T-shirt | {\"size\":\"XL\",\"color\":\"blue\"} |\n| Thinkpad Laptop | {\"color\":\"black\",\"warranty\":\"3\nyears\"} |\n+-----------------+----------------------------------------+\n \nLimitation: COLUMN_JSON will decode nested dynamic columns\nat a nesting level of not more than 10 levels deep. Dynamic\ncolumns that are nested deeper than 10 levels will be shown\nas BINARY string, without encoding.\n \n\n \n \n \n \n \n \n \n\nURL: https://mariadb.com/kb/en/column_json/','','https://mariadb.com/kb/en/column_json/'),(751,'Instant ADD COLUMN for InnoDB',46,'Instant ALTER TABLE ... ADD COLUMN for InnoDB was introduced\nin MariaDB 10.3.2. The INSTANT option for the ALGORITHM\nclause was introduced in MariaDB 10.3.7.\n \nNormally, adding a column to a table requires the full table\nto be rebuilt. The complexity of the operation is\nproportional to the size of the table, or O(n·m) where n is\nthe number of rows in the table and m is the number of\nindexes. \n \nIn MariaDB 10.0 and later, the ALTER TABLE statement\nsupports online DDL for storage engines that have\nimplemented the relevant online DDL algorithms and locking\nstrategies.\n \nThe InnoDB storage engine has implemented online DDL for\nmany operations. These online DDL optimizations allow\nconcurrent DML to the table in many cases, even if the table\nneeds to be rebuilt.\n \nSee InnoDB Online DDL Overview for more information about\nonline DDL with InnoDB.\n \nAllowing concurrent DML during the operation does not solve\nall problems. When a column was added to a table with the\nolder in-place optimization, the resulting table rebuild\ncould still significantly increase the I/O and memory\nconsumption and cause replication lag.\n \nIn contrast, with the new instant ALTER TABLE ... ADD\nCOLUMN, all that is needed is an O(log n) operation to\ninsert a special hidden record into the table, and an update\nof the data dictionary. For a large table, instead of taking\nseveral hours, the operation would be completed in the blink\nof an eye. The ALTER TABLE ... ADD COLUMN operation is only\nslightly more expensive than a regular INSERT, due to\nlocking constraints.\n \nIn the past, some developers may have implemented a kind of\n\"instant add column\" in the application by encoding\nmultiple columns in a single TEXT or BLOB column. MariaDB\nDynamic Columns was an early example of that. A more recent\nexample is JSON and related string manipulation functions.\n \nAdding real columns has the following advantages over\nencoding columns into a single \"expandable\" column:\nEfficient storage in a native binary format\nData type safety\nIndexes can be built natively\nConstraints are available: UNIQUE, CHECK, FOREIGN KEY\nDEFAULT values can be specified\nTriggers can be written more easily\n \nWith instant ALTER TABLE ... ADD COLUMN, you can enjoy all\nthe benefits of structured storage without the drawback of\nhaving to rebuild the table.\n \nInstant ALTER TABLE ... ADD COLUMN is available for both old\nand new InnoDB tables. Basically you can just upgrade from\nMySQL 5.x or MariaDB and start adding columns instantly.\n \nColumns instantly added to a table exist in a separate data\nstructure from the main table definition, similar to how\nInnoDB separates BLOB columns. If the table ever becomes\nempty, (such as from TRUNCATE or DELETE statements), InnoDB\nincorporates the instantly added columns into the main table\ndefinition. See InnoDB Online DDL Operations with\nALGORITHM=INSTANT: Non-canonical Storage Format Caused by\nSome Operations for more information.\n \nThe operation is also crash safe. If the server is killed\nwhile executing an instant ALTER TABLE ... ADD COLUMN, when\nthe table is restored InnoDB integrates the new column,\nflattening the table definition.\n \nLimitations\n \nIn MariaDB 10.3, instant ALTER TABLE ... ADD COLUMN only\napplies when the added columns appear last in the table. The\nplace specifier LAST is the default. If AFTER col is\nspecified, then col must be the last column, or the\noperation will require the table to be rebuilt. In MariaDB\n10.4, this restriction has been lifted.\n \nIf the table contains a hidden FTS_DOC_ID column due to a\nFULLTEXT INDEX, then instant ALTER TABLE ... ADD COLUMN will\nnot be possible.\n \nInnoDB data files after instant ALTER TABLE ... ADD COLUMN\ncannot be imported to older versions of MariaDB or MySQL\nwithout first being rebuilt.\n \nAfter using Instant ALTER TABLE ... ADD COLUMN, any\ntable-rebuilding operation such as ALTER TABLE … FORCE\nwill incorporate instantaneously added columns into the main\ntable body.\n \nInstant ALTER TABLE ... ADD COLUMN is not available for\nROW_FORMAT=COMPRESSED.\n \nIn MariaDB 10.3, ALTER TABLE … DROP COLUMN requires the\ntable to be rebuilt. In MariaDB 10.4, this restriction has\nbeen lifted.\n \nExample\n \nCREATE TABLE t(id INT PRIMARY KEY, u INT UNSIGNED NOT NULL\nUNIQUE)\nENGINE=InnoDB;\n \nINSERT INTO t(id,u) VALUES(1,1),(2,2),(3,3);\n \nALTER TABLE t ADD COLUMN\n(d DATETIME DEFAULT current_timestamp(),\n p POINT NOT NULL DEFAULT ST_GeomFromText(\'POINT(0 0)\'),\n t TEXT CHARSET utf8 DEFAULT \'The quick brown fox jumps\nover the lazy dog\');\n \nUPDATE t SET t=NULL WHERE id=3;\n \nSELECT id,u,d,ST_AsText(p),t FROM t;\n \nSELECT variable_value FROM information_schema.global_status\nWHERE variable_name = \'innodb_instant_alter_column\';\n \nThe above example illustrates that when the added columns\nare declared NOT NULL, a DEFAULT value must be available,\neither implied by the data type or set explicitly by the\nuser. The expression need not be constant, but it must not\nrefer to the columns of the table, such as DEFAULT u+1 (a\nMariaDB extension). The DEFAULT current_timestamp() would be\nevaluated at the time of the ALTER TABLE and apply to each\nrow, like it does for non-instant ALTER TABLE. If a\nsubsequent ALTER TABLE changes the DEFAULT value for\nsubsequent INSERT, the values of the columns in existing\nrecords will naturally be unaffected.\n \nThe design was brainstormed in April by engineers from\nMariaDB Corporation, Alibaba and Tencent. A prototype was\ndeveloped by Vin Chen (陈福荣) from the Tencent Game DBA\nTeam.\n \n\n \n \n \n \n \n \n \n\nURL:\nhttps://mariadb.com/kb/en/instant-add-column-for-innodb/','','https://mariadb.com/kb/en/instant-add-column-for-innodb/'),(752,'Full-Text Index Overview',48,'MariaDB has support for full-text indexing and searching:\nA full-text index in MariaDB is an index of type FULLTEXT,\nand it allows more options when searching for portions of\ntext from a field.\nFull-text indexes can be used only with MyISAM and Aria\ntables, from MariaDB 10.0.5 with InnoDB tables and from\nMariaDB 10.0.15 with Mroonga tables, and can be created only\nfor CHAR, VARCHAR, or TEXT columns.\nPartitioned tables cannot contain fulltext indexes, even if\nthe storage engine supports them.\nA FULLTEXT index definition can be given in the CREATE TABLE\nstatement when a\n table is created, or added later using ALTER TABLE or\nCREATE INDEX.\nFor large data sets, it is much faster to load your data\ninto a table that\n has no FULLTEXT index and then create the index after that,\nthan to load data\n into a table that has an existing FULLTEXT index.\n \nFull-text searching is performed using MATCH() ... AGAINST\nsyntax.\nMATCH() takes a comma-separated list that names the columns\nto be\nsearched. AGAINST takes a string to search for, and an\noptional\nmodifier that indicates what type of search to perform. The\nsearch\nstring must be a literal string, not a variable or a column\nname.\n \nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n \nExcluded Results\n \nPartial words are excluded.\nWords less than 4 characters in length (3 or less) will not\nbe stored in the fulltext index. This value can be adjusted\nby changing the ft_min_word_length system variable (or, for\nInnoDB, innodb_ft_min_token_size).\nWords longer than 84 characters in length will also not be\nstored in the fulltext index. This values can be adjusted by\nchanging the ft_max_word_length system variable (or, for\nInnoDB, innodb_ft_max_token_size).\nStopwords are a list of common words such as \"once\" or\n\"then\" that do not reflect in the search results unless IN\nBOOLEAN MODE is used. The stopword list for MyISAM/Aria\ntables and InnoDB tables can differ. See stopwords for\ndetails and a full list, as well as for details on how to\nchange the default list.\nFor MyISAM/Aria fulltext indexes only, if a word appears in\nmore than half the rows, it is also excluded from the\nresults of a fulltext search.\nFor InnoDB indexes, only committed rows appear -\nmodifications from the current transaction do not apply.\n \nRelevance\n \nMariaDB calculates a relevance for each result, based on a\nnumber of factors, including the number of words in the\nindex, the number of unique words in a row, the total number\nof words in both the index and the result, and the weight of\nthe word. In English, \'cool\' will be weighted less than\n\'dandy\', at least at present! The relevance can be\nreturned as part of a query simply by using the MATCH\nfunction in the field list.\n \nTypes of Full-Text search\n \nIN NATURAL LANGUAGE MODE\n \nIN NATURAL LANGUAGE MODE is the default type of full-text\nsearch, and the keywords can be omitted. There are no\nspecial operators, and searches consist of one or more\ncomma-separated keywords.\n \nSearches are returned in descending order of relevance.\n \nIN BOOLEAN MODE\n \nBoolean search permits the use of a number of special\noperators:\n \nOperator | Description | \n \n+ | The word is mandatory in all rows returned. | \n \n- | The word cannot appear in any row returned. | \n \n< | The word that follows has a lower relevance than other\nwords, although rows containing it will still match | \n \n> | The word that follows has a higher relevance than other\nwords. | \n \n() | Used to group words into subexpressions. | \n \n~ | The word following contributes negatively to the\nrelevance of the row (which is different to the \'-\'\noperator, which specifically excludes the word, or the \'\n\nURL: https://mariadb.com/kb/en/full-text-index-overview/','','https://mariadb.com/kb/en/full-text-index-overview/'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `index_stats` +-- + +DROP TABLE IF EXISTS `index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `index_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `prefix_arity` int(11) unsigned NOT NULL, + `avg_frequency` decimal(12,4) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `index_stats` +-- + +LOCK TABLES `index_stats` WRITE; +/*!40000 ALTER TABLE `index_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_index_stats` +-- + +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_index_stats` +-- + +LOCK TABLES `innodb_index_stats` WRITE; +/*!40000 ALTER TABLE `innodb_index_stats` DISABLE KEYS */; +INSERT INTO `innodb_index_stats` VALUES ('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:18:29','n_diff_pfx01',0,1,'domain_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:18:29','n_diff_pfx02',0,1,'domain_id,sub_id'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:18:29','n_leaf_pages',1,NULL,'Number of leaf pages in the index'),('mysql','gtid_slave_pos','PRIMARY','2020-05-31 16:18:29','size',1,NULL,'Number of pages in the index'); +/*!40000 ALTER TABLE `innodb_index_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `innodb_table_stats` +-- + +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `innodb_table_stats` +-- + +LOCK TABLES `innodb_table_stats` WRITE; +/*!40000 ALTER TABLE `innodb_table_stats` DISABLE KEYS */; +INSERT INTO `innodb_table_stats` VALUES ('mysql','gtid_slave_pos','2020-05-31 16:18:29',0,1,0); +/*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob DEFAULT NULL, + `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +INSERT INTO `proc` VALUES ('mysql','AddGeometryColumn','PROCEDURE','AddGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64), t_srid int','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','mariadb.sys@localhost','2020-05-31 16:18:29','2020-05-31 16:18:29','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' ADD \', geometry_column,\' GEOMETRY REF_SYSTEM_ID=\', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','NONE'),('mysql','DropGeometryColumn','PROCEDURE','DropGeometryColumn','SQL','CONTAINS_SQL','NO','INVOKER','catalog varchar(64), t_schema varchar(64),\n t_name varchar(64), geometry_column varchar(64)','','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','mariadb.sys@localhost','2020-05-31 16:18:29','2020-05-31 16:18:29','','','utf8','utf8_general_ci','latin1_swedish_ci','begin\n set @qwe= concat(\'ALTER TABLE \', t_schema, \'.\', t_name, \' DROP \', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end','NONE'); +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') COLLATE utf8_bin NOT NULL, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT 0, + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 16:18:28'),('asus','root','','',1,'','2020-05-31 16:18:29'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_mapping` +-- + +DROP TABLE IF EXISTS `roles_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_mapping` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Admin_option` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + UNIQUE KEY `Host` (`Host`,`User`,`Role`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Granted roles'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_mapping` +-- + +LOCK TABLES `roles_mapping` WRITE; +/*!40000 ALTER TABLE `roles_mapping` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_mapping` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` varchar(2048) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(80) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT 0, + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` varchar(512) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `table_stats` +-- + +DROP TABLE IF EXISTS `table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `table_stats` ( + `db_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8_bin NOT NULL, + `cardinality` bigint(21) unsigned DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Tables'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `table_stats` +-- + +LOCK TABLES `table_stats` WRITE; +/*!40000 ALTER TABLE `table_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `table_stats` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(141) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +INSERT INTO `tables_priv` VALUES ('localhost','mysql','mariadb.sys','global_priv','root@localhost','0000-00-00 00:00:00','Select,Update,Delete',''); +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT 0, + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT 0, + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Temporary table structure for view `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!50001 DROP VIEW IF EXISTS `user`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +/*!50001 CREATE TABLE `user` ( + `Host` tinyint NOT NULL, + `User` tinyint NOT NULL, + `Password` tinyint NOT NULL, + `Select_priv` tinyint NOT NULL, + `Insert_priv` tinyint NOT NULL, + `Update_priv` tinyint NOT NULL, + `Delete_priv` tinyint NOT NULL, + `Create_priv` tinyint NOT NULL, + `Drop_priv` tinyint NOT NULL, + `Reload_priv` tinyint NOT NULL, + `Shutdown_priv` tinyint NOT NULL, + `Process_priv` tinyint NOT NULL, + `File_priv` tinyint NOT NULL, + `Grant_priv` tinyint NOT NULL, + `References_priv` tinyint NOT NULL, + `Index_priv` tinyint NOT NULL, + `Alter_priv` tinyint NOT NULL, + `Show_db_priv` tinyint NOT NULL, + `Super_priv` tinyint NOT NULL, + `Create_tmp_table_priv` tinyint NOT NULL, + `Lock_tables_priv` tinyint NOT NULL, + `Execute_priv` tinyint NOT NULL, + `Repl_slave_priv` tinyint NOT NULL, + `Repl_client_priv` tinyint NOT NULL, + `Create_view_priv` tinyint NOT NULL, + `Show_view_priv` tinyint NOT NULL, + `Create_routine_priv` tinyint NOT NULL, + `Alter_routine_priv` tinyint NOT NULL, + `Create_user_priv` tinyint NOT NULL, + `Event_priv` tinyint NOT NULL, + `Trigger_priv` tinyint NOT NULL, + `Create_tablespace_priv` tinyint NOT NULL, + `Delete_history_priv` tinyint NOT NULL, + `ssl_type` tinyint NOT NULL, + `ssl_cipher` tinyint NOT NULL, + `x509_issuer` tinyint NOT NULL, + `x509_subject` tinyint NOT NULL, + `max_questions` tinyint NOT NULL, + `max_updates` tinyint NOT NULL, + `max_connections` tinyint NOT NULL, + `max_user_connections` tinyint NOT NULL, + `plugin` tinyint NOT NULL, + `authentication_string` tinyint NOT NULL, + `password_expired` tinyint NOT NULL, + `is_role` tinyint NOT NULL, + `default_role` tinyint NOT NULL, + `max_statement_time` tinyint NOT NULL +) ENGINE=MyISAM */; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transaction_registry` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `transaction_registry` ( + `transaction_id` bigint(20) unsigned NOT NULL, + `commit_id` bigint(20) unsigned NOT NULL, + `begin_timestamp` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `commit_timestamp` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `isolation_level` enum('READ-UNCOMMITTED','READ-COMMITTED','REPEATABLE-READ','SERIALIZABLE') COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`transaction_id`), + UNIQUE KEY `commit_id` (`commit_id`), + KEY `begin_timestamp` (`begin_timestamp`), + KEY `commit_timestamp` (`commit_timestamp`,`transaction_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Final view structure for view `user` +-- + +/*!50001 DROP TABLE IF EXISTS `user`*/; +/*!50001 DROP VIEW IF EXISTS `user`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = latin1 */; +/*!50001 SET character_set_results = latin1 */; +/*!50001 SET collation_connection = latin1_swedish_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`mariadb.sys`@`localhost` SQL SECURITY DEFINER */ +/*!50001 VIEW `user` AS select `global_priv`.`Host` AS `Host`,`global_priv`.`User` AS `User`,if(json_value(`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `global_priv` */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 20:04:10 diff --git a/mysql-test/std_data/mysql_database_5.5.dump b/mysql-test/std_data/mysql_database_5.5.dump new file mode 100644 index 00000000000..b7a21e7f7c5 --- /dev/null +++ b/mysql-test/std_data/mysql_database_5.5.dump @@ -0,0 +1,737 @@ +-- MySQL dump 10.14 Distrib 5.5.68-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: mysql +-- ------------------------------------------------------ +-- Server version 5.5.68-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `columns_priv` +-- + +DROP TABLE IF EXISTS `columns_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `columns_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `columns_priv` +-- + +LOCK TABLES `columns_priv` WRITE; +/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `columns_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `db` +-- + +DROP TABLE IF EXISTS `db`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `db` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`,`User`), + KEY `User` (`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `db` +-- + +LOCK TABLES `db` WRITE; +/*!40000 ALTER TABLE `db` DISABLE KEYS */; +INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'); +/*!40000 ALTER TABLE `db` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `event` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `body` longblob NOT NULL, + `definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `execute_at` datetime DEFAULT NULL, + `interval_value` int(11) DEFAULT NULL, + `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `last_executed` datetime DEFAULT NULL, + `starts` datetime DEFAULT NULL, + `ends` datetime DEFAULT NULL, + `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', + `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `originator` int(10) unsigned NOT NULL, + `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `func` +-- + +DROP TABLE IF EXISTS `func`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `func` ( + `name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `ret` tinyint(1) NOT NULL DEFAULT '0', + `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', + `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `func` +-- + +LOCK TABLES `func` WRITE; +/*!40000 ALTER TABLE `func` DISABLE KEYS */; +/*!40000 ALTER TABLE `func` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_category` +-- + +DROP TABLE IF EXISTS `help_category`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_category` ( + `help_category_id` smallint(5) unsigned NOT NULL, + `name` char(64) NOT NULL, + `parent_category_id` smallint(5) unsigned DEFAULT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_category_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help categories'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_category` +-- + +LOCK TABLES `help_category` WRITE; +/*!40000 ALTER TABLE `help_category` DISABLE KEYS */; +INSERT INTO `help_category` VALUES (1,'Geographic',0,''),(2,'Polygon properties',34,''),(3,'WKT',34,''),(4,'Numeric Functions',38,''),(5,'Plugins',35,''),(6,'MBR',34,''),(7,'Control flow functions',38,''),(8,'Transactions',35,''),(9,'Help Metadata',35,''),(10,'Account Management',35,''),(11,'Point properties',34,''),(12,'Encryption Functions',38,''),(13,'LineString properties',34,''),(14,'Miscellaneous Functions',38,''),(15,'Logical operators',38,''),(16,'Functions and Modifiers for Use with GROUP BY',35,''),(17,'Information Functions',38,''),(18,'Comparison operators',38,''),(19,'Bit Functions',38,''),(20,'Table Maintenance',35,''),(21,'User-Defined Functions',35,''),(22,'Data Types',35,''),(23,'Compound Statements',35,''),(24,'Geometry constructors',34,''),(25,'GeometryCollection properties',1,''),(26,'Administration',35,''),(27,'Data Manipulation',35,''),(28,'Utility',35,''),(29,'Language Structure',35,''),(30,'Geometry relations',34,''),(31,'Date and Time Functions',38,''),(32,'WKB',34,''),(33,'Procedures',35,''),(34,'Geographic Features',35,''),(35,'Contents',0,''),(36,'Geometry properties',34,''),(37,'String Functions',38,''),(38,'Functions',35,''),(39,'Data Definition',35,''); +/*!40000 ALTER TABLE `help_category` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_keyword` +-- + +DROP TABLE IF EXISTS `help_keyword`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_keyword` ( + `help_keyword_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + PRIMARY KEY (`help_keyword_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help keywords'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_keyword` +-- + +LOCK TABLES `help_keyword` WRITE; +/*!40000 ALTER TABLE `help_keyword` DISABLE KEYS */; +INSERT INTO `help_keyword` VALUES (0,'JOIN'),(1,'HOST'),(2,'REPEAT'),(3,'SERIALIZABLE'),(4,'REPLACE'),(5,'AT'),(6,'SCHEDULE'),(7,'RETURNS'),(8,'STARTS'),(9,'MASTER_SSL_CA'),(10,'NCHAR'),(11,'COLUMNS'),(12,'COMPLETION'),(13,'WORK'),(14,'DATETIME'),(15,'MODE'),(16,'OPEN'),(17,'INTEGER'),(18,'ESCAPE'),(19,'VALUE'),(20,'MASTER_SSL_VERIFY_SERVER_CERT'),(21,'SQL_BIG_RESULT'),(22,'DROP'),(23,'GEOMETRYCOLLECTIONFROMWKB'),(24,'EVENTS'),(25,'MONTH'),(26,'PROFILES'),(27,'DUPLICATE'),(28,'REPLICATION'),(29,'UNLOCK'),(30,'INNODB'),(31,'YEAR_MONTH'),(32,'SUBJECT'),(33,'PREPARE'),(34,'LOCK'),(35,'NDB'),(36,'CHECK'),(37,'FULL'),(38,'INT4'),(39,'BY'),(40,'NO'),(41,'MINUTE'),(42,'PARTITION'),(43,'DATA'),(44,'DAY'),(45,'SHARE'),(46,'REAL'),(47,'SEPARATOR'),(48,'MESSAGE_TEXT'),(49,'MASTER_HEARTBEAT_PERIOD'),(50,'DELETE'),(51,'ON'),(52,'COLUMN_NAME'),(53,'CONNECTION'),(54,'CLOSE'),(55,'X509'),(56,'USE'),(57,'SUBCLASS_ORIGIN'),(58,'WHERE'),(59,'PRIVILEGES'),(60,'SPATIAL'),(61,'EVENT'),(62,'SUPER'),(63,'SQL_BUFFER_RESULT'),(64,'IGNORE'),(65,'SHA2'),(66,'QUICK'),(67,'SIGNED'),(68,'OFFLINE'),(69,'SECURITY'),(70,'AUTOEXTEND_SIZE'),(71,'NDBCLUSTER'),(72,'POLYGONFROMWKB'),(73,'FALSE'),(74,'LEVEL'),(75,'FORCE'),(76,'BINARY'),(77,'TO'),(78,'CHANGE'),(79,'CURRENT_USER'),(80,'HOUR_MINUTE'),(81,'UPDATE'),(82,'PRESERVE'),(83,'TABLE_NAME'),(84,'INTO'),(85,'FEDERATED'),(86,'VARYING'),(87,'MAX_SIZE'),(88,'HOUR_SECOND'),(89,'VARIABLE'),(90,'ROLLBACK'),(91,'PROCEDURE'),(92,'TIMESTAMP'),(93,'IMPORT'),(94,'AGAINST'),(95,'CHECKSUM'),(96,'COUNT'),(97,'LONGBINARY'),(98,'THEN'),(99,'INSERT'),(100,'ENGINES'),(101,'HANDLER'),(102,'PORT'),(103,'DAY_SECOND'),(104,'EXISTS'),(105,'MUTEX'),(106,'HELP_DATE'),(107,'RELEASE'),(108,'BOOLEAN'),(109,'MOD'),(110,'DEFAULT'),(111,'TYPE'),(112,'NO_WRITE_TO_BINLOG'),(113,'OPTIMIZE'),(114,'SQLSTATE'),(115,'RESET'),(116,'CLASS_ORIGIN'),(117,'INSTALL'),(118,'ITERATE'),(119,'DO'),(120,'BIGINT'),(121,'SET'),(122,'ISSUER'),(123,'DATE'),(124,'STATUS'),(125,'FULLTEXT'),(126,'COMMENT'),(127,'MASTER_CONNECT_RETRY'),(128,'INNER'),(129,'RELAYLOG'),(130,'STOP'),(131,'MASTER_LOG_FILE'),(132,'MRG_MYISAM'),(133,'PRECISION'),(134,'REQUIRE'),(135,'TRAILING'),(136,'PARTITIONS'),(137,'LONG'),(138,'OPTION'),(139,'REORGANIZE'),(140,'ELSE'),(141,'DEALLOCATE'),(142,'IO_THREAD'),(143,'CASE'),(144,'CIPHER'),(145,'CONTINUE'),(146,'FROM'),(147,'READ'),(148,'LEFT'),(149,'ELSEIF'),(150,'MINUTE_SECOND'),(151,'COMPACT'),(152,'DEC'),(153,'FOR'),(154,'WARNINGS'),(155,'MIN_ROWS'),(156,'STRING'),(157,'CONDITION'),(158,'ENCLOSED'),(159,'FUNCTION'),(160,'AGGREGATE'),(161,'FIELDS'),(162,'INT3'),(163,'ARCHIVE'),(164,'AVG_ROW_LENGTH'),(165,'ADD'),(166,'KILL'),(167,'FLOAT4'),(168,'TABLESPACE'),(169,'VIEW'),(170,'REPEATABLE'),(171,'INFILE'),(172,'HELP_VERSION'),(173,'ORDER'),(174,'USING'),(175,'CONSTRAINT_CATALOG'),(176,'MIDDLEINT'),(177,'GRANT'),(178,'UNSIGNED'),(179,'DECIMAL'),(180,'GEOMETRYFROMTEXT'),(181,'INDEXES'),(182,'FOREIGN'),(183,'CACHE'),(184,'HOSTS'),(185,'MYSQL_ERRNO'),(186,'COMMIT'),(187,'SCHEMAS'),(188,'LEADING'),(189,'SNAPSHOT'),(190,'CONSTRAINT_NAME'),(191,'DECLARE'),(192,'LOAD'),(193,'SQL_CACHE'),(194,'CONVERT'),(195,'DYNAMIC'),(196,'COLLATE'),(197,'POLYGONFROMTEXT'),(198,'BYTE'),(199,'GLOBAL'),(200,'LINESTRINGFROMWKB'),(201,'WHEN'),(202,'HAVING'),(203,'AS'),(204,'STARTING'),(205,'RELOAD'),(206,'AUTOCOMMIT'),(207,'REVOKE'),(208,'GRANTS'),(209,'OUTER'),(210,'CURSOR_NAME'),(211,'FLOOR'),(212,'EXPLAIN'),(213,'WITH'),(214,'AFTER'),(215,'STD'),(216,'CSV'),(217,'DISABLE'),(218,'UNINSTALL'),(219,'OUTFILE'),(220,'LOW_PRIORITY'),(221,'FILE'),(222,'NODEGROUP'),(223,'SCHEMA'),(224,'SONAME'),(225,'POW'),(226,'DUAL'),(227,'MULTIPOINTFROMWKB'),(228,'INDEX'),(229,'MULTIPOINTFROMTEXT'),(230,'DEFINER'),(231,'MASTER_BIND'),(232,'REMOVE'),(233,'EXTENDED'),(234,'MULTILINESTRINGFROMWKB'),(235,'CROSS'),(236,'CONTRIBUTORS'),(237,'NATIONAL'),(238,'GROUP'),(239,'SHA'),(240,'ONLINE'),(241,'UNDO'),(242,'IGNORE_SERVER_IDS'),(243,'ZEROFILL'),(244,'CLIENT'),(245,'MASTER_PASSWORD'),(246,'OWNER'),(247,'RELAY_LOG_FILE'),(248,'TRUE'),(249,'CHARACTER'),(250,'MASTER_USER'),(251,'SCHEMA_NAME'),(252,'TABLE'),(253,'ENGINE'),(254,'INSERT_METHOD'),(255,'CASCADE'),(256,'RELAY_LOG_POS'),(257,'SQL_CALC_FOUND_ROWS'),(258,'UNION'),(259,'MYISAM'),(260,'LEAVE'),(261,'MODIFY'),(262,'MATCH'),(263,'MASTER_LOG_POS'),(264,'DISTINCTROW'),(265,'DESC'),(266,'TIME'),(267,'NUMERIC'),(268,'EXPANSION'),(269,'CODE'),(270,'CURSOR'),(271,'GEOMETRYCOLLECTIONFROMTEXT'),(272,'CHAIN'),(273,'LOGFILE'),(274,'FLUSH'),(275,'CREATE'),(276,'DESCRIBE'),(277,'EXTENT_SIZE'),(278,'MAX_UPDATES_PER_HOUR'),(279,'INT2'),(280,'PROCESSLIST'),(281,'ENDS'),(282,'LOGS'),(283,'DISCARD'),(284,'HEAP'),(285,'SOUNDS'),(286,'BETWEEN'),(287,'MULTILINESTRINGFROMTEXT'),(288,'REPAIR'),(289,'PACK_KEYS'),(290,'FAST'),(291,'VALUES'),(292,'CALL'),(293,'LOOP'),(294,'VARCHARACTER'),(295,'BEFORE'),(296,'TRUNCATE'),(297,'SHOW'),(298,'ALL'),(299,'REDUNDANT'),(300,'USER_RESOURCES'),(301,'PARTIAL'),(302,'BINLOG'),(303,'END'),(304,'SECOND'),(305,'AND'),(306,'FLOAT8'),(307,'PREV'),(308,'HOUR'),(309,'SELECT'),(310,'DATABASES'),(311,'OR'),(312,'IDENTIFIED'),(313,'WRAPPER'),(314,'MASTER_SSL_CIPHER'),(315,'SQL_SLAVE_SKIP_COUNTER'),(316,'BOTH'),(317,'BOOL'),(318,'YEAR'),(319,'MASTER_PORT'),(320,'CONCURRENT'),(321,'HELP'),(322,'UNIQUE'),(323,'TRIGGERS'),(324,'PROCESS'),(325,'OPTIONS'),(326,'RESIGNAL'),(327,'CONSISTENT'),(328,'MASTER_SSL'),(329,'DATE_ADD'),(330,'MAX_CONNECTIONS_PER_HOUR'),(331,'LIKE'),(332,'PLUGIN'),(333,'FETCH'),(334,'IN'),(335,'COLUMN'),(336,'DUMPFILE'),(337,'USAGE'),(338,'EXECUTE'),(339,'MEMORY'),(340,'CEIL'),(341,'QUERY'),(342,'MASTER_HOST'),(343,'LINES'),(344,'SQL_THREAD'),(345,'SERVER'),(346,'MAX_QUERIES_PER_HOUR'),(347,'MASTER_SSL_CERT'),(348,'MULTIPOLYGONFROMWKB'),(349,'TRANSACTION'),(350,'DAY_MINUTE'),(351,'STDDEV'),(352,'DATE_SUB'),(353,'REBUILD'),(354,'GEOMETRYFROMWKB'),(355,'INT1'),(356,'RENAME'),(357,'PARSER'),(358,'RIGHT'),(359,'ALTER'),(360,'MAX_ROWS'),(361,'SOCKET'),(362,'STRAIGHT_JOIN'),(363,'NATURAL'),(364,'VARIABLES'),(365,'ESCAPED'),(366,'SHA1'),(367,'KEY_BLOCK_SIZE'),(368,'PASSWORD'),(369,'OFFSET'),(370,'CHAR'),(371,'NEXT'),(372,'ERRORS'),(373,'SQL_LOG_BIN'),(374,'TEMPORARY'),(375,'COMMITTED'),(376,'SQL_SMALL_RESULT'),(377,'UPGRADE'),(378,'BEGIN'),(379,'DELAY_KEY_WRITE'),(380,'PROFILE'),(381,'MEDIUM'),(382,'INTERVAL'),(383,'SSL'),(384,'DAY_HOUR'),(385,'NAME'),(386,'REFERENCES'),(387,'AES_ENCRYPT'),(388,'STORAGE'),(389,'ISOLATION'),(390,'CEILING'),(391,'EVERY'),(392,'INT8'),(393,'AUTHORS'),(394,'RESTRICT'),(395,'UNCOMMITTED'),(396,'LINESTRINGFROMTEXT'),(397,'IS'),(398,'NOT'),(399,'ANALYSE'),(400,'DATAFILE'),(401,'DES_KEY_FILE'),(402,'SIGNAL'),(403,'COMPRESSED'),(404,'START'),(405,'PLUGINS'),(406,'SAVEPOINT'),(407,'IF'),(408,'ROWS'),(409,'PRIMARY'),(410,'PURGE'),(411,'LAST'),(412,'USER'),(413,'EXIT'),(414,'KEYS'),(415,'LIMIT'),(416,'KEY'),(417,'MERGE'),(418,'UNTIL'),(419,'SQL_NO_CACHE'),(420,'DELAYED'),(421,'CONSTRAINT_SCHEMA'),(422,'ANALYZE'),(423,'CONSTRAINT'),(424,'SERIAL'),(425,'ACTION'),(426,'WRITE'),(427,'INITIAL_SIZE'),(428,'SESSION'),(429,'DATABASE'),(430,'NULL'),(431,'POWER'),(432,'USE_FRM'),(433,'TERMINATED'),(434,'SLAVE'),(435,'NVARCHAR'),(436,'ASC'),(437,'RETURN'),(438,'OPTIONALLY'),(439,'ENABLE'),(440,'DIRECTORY'),(441,'MAX_USER_CONNECTIONS'),(442,'WHILE'),(443,'LOCAL'),(444,'DISTINCT'),(445,'AES_DECRYPT'),(446,'MASTER_SSL_KEY'),(447,'NONE'),(448,'TABLES'),(449,'<>'),(450,'RLIKE'),(451,'TRIGGER'),(452,'COLLATION'),(453,'SHUTDOWN'),(454,'HIGH_PRIORITY'),(455,'BTREE'),(456,'FIRST'),(457,'COALESCE'),(458,'WAIT'),(459,'CATALOG_NAME'),(460,'MASTER'),(461,'FIXED'),(462,'MULTIPOLYGONFROMTEXT'),(463,'ROW_FORMAT'); +/*!40000 ALTER TABLE `help_keyword` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_relation` +-- + +DROP TABLE IF EXISTS `help_relation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_relation` ( + `help_topic_id` int(10) unsigned NOT NULL, + `help_keyword_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`help_keyword_id`,`help_topic_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='keyword-topic relation'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_relation` +-- + +LOCK TABLES `help_relation` WRITE; +/*!40000 ALTER TABLE `help_relation` DISABLE KEYS */; +INSERT INTO `help_relation` VALUES (1,0),(356,0),(473,1),(232,2),(447,3),(3,4),(130,4),(421,4),(89,5),(89,6),(406,6),(97,7),(89,8),(185,9),(430,10),(21,11),(347,11),(421,11),(463,11),(468,11),(89,12),(406,12),(146,13),(230,14),(88,15),(356,15),(18,16),(106,16),(134,16),(347,16),(97,17),(500,17),(380,18),(3,19),(104,19),(243,19),(374,19),(459,19),(185,20),(356,21),(9,22),(30,22),(34,22),(87,22),(186,22),(237,22),(263,22),(276,22),(300,22),(331,22),(405,22),(415,22),(416,22),(463,22),(478,22),(108,23),(122,24),(170,24),(424,24),(376,25),(82,26),(104,27),(199,28),(36,29),(347,30),(468,30),(376,31),(199,32),(35,33),(237,33),(36,34),(356,34),(468,35),(417,36),(463,36),(468,36),(21,37),(294,37),(347,37),(451,37),(468,37),(500,38),(48,39),(77,39),(83,39),(130,39),(199,39),(356,39),(361,39),(421,39),(463,39),(468,39),(468,40),(472,40),(376,41),(463,42),(468,42),(212,43),(421,43),(468,43),(473,43),(376,44),(356,45),(97,46),(314,46),(361,47),(374,48),(459,48),(185,49),(48,50),(468,50),(472,50),(1,51),(89,51),(406,51),(472,51),(374,52),(459,52),(176,53),(468,53),(51,54),(106,54),(199,55),(1,56),(55,56),(194,56),(374,57),(459,57),(48,58),(83,58),(106,58),(193,59),(199,59),(249,59),(210,60),(463,60),(89,61),(300,61),(358,61),(406,61),(199,62),(356,63),(1,64),(83,64),(104,64),(130,64),(356,64),(421,64),(463,64),(66,65),(48,66),(417,66),(466,66),(230,67),(87,68),(210,68),(463,68),(199,69),(194,70),(468,71),(91,72),(482,72),(385,73),(447,74),(1,75),(39,76),(230,76),(269,76),(185,77),(269,77),(460,77),(185,78),(463,78),(89,79),(406,79),(376,80),(83,81),(104,81),(356,81),(472,81),(89,82),(406,82),(374,83),(459,83),(3,84),(104,84),(304,84),(356,84),(468,85),(257,86),(194,87),(376,88),(129,89),(146,90),(460,90),(17,91),(189,91),(302,91),(328,91),(347,91),(356,91),(416,91),(439,91),(488,91),(99,92),(188,92),(421,93),(463,93),(88,94),(401,95),(468,95),(69,96),(330,96),(433,96),(285,97),(28,98),(57,98),(85,98),(104,99),(195,99),(301,99),(486,99),(282,100),(347,100),(106,101),(313,101),(473,102),(376,103),(9,104),(30,104),(89,104),(155,104),(186,104),(276,104),(300,104),(347,105),(365,105),(109,106),(146,107),(460,107),(24,108),(88,108),(113,109),(174,109),(3,110),(104,110),(155,110),(200,110),(212,110),(243,110),(463,110),(468,110),(463,111),(115,112),(326,112),(466,112),(470,112),(115,113),(463,113),(374,114),(459,114),(38,115),(119,115),(151,115),(264,115),(374,116),(459,116),(419,117),(124,118),(89,119),(125,119),(406,119),(496,119),(221,120),(3,121),(83,121),(104,121),(129,121),(130,121),(146,121),(155,121),(182,121),(212,121),(333,121),(347,121),(356,121),(374,121),(421,121),(459,121),(463,121),(468,121),(472,121),(477,121),(494,121),(199,122),(132,123),(230,123),(262,123),(376,123),(58,124),(137,124),(215,124),(223,124),(328,124),(336,124),(347,124),(365,124),(210,125),(463,125),(468,125),(89,126),(194,126),(210,126),(406,126),(468,126),(185,127),(1,128),(424,129),(52,130),(185,131),(468,132),(314,133),(199,134),(455,135),(255,136),(285,137),(199,138),(249,138),(463,139),(57,140),(85,140),(237,141),(52,142),(324,142),(57,143),(85,143),(199,144),(313,145),(48,146),(122,146),(347,146),(356,146),(424,146),(455,146),(36,147),(106,147),(447,147),(1,148),(28,149),(376,150),(468,151),(209,152),(180,153),(313,153),(347,153),(356,153),(420,153),(330,154),(347,154),(468,155),(97,156),(180,157),(421,158),(34,159),(68,159),(97,159),(211,159),(233,159),(302,159),(336,159),(347,159),(393,159),(405,159),(416,159),(97,160),(347,161),(421,161),(252,162),(468,163),(463,164),(468,164),(60,165),(194,165),(463,165),(478,165),(176,166),(168,167),(194,168),(415,168),(463,168),(478,168),(30,169),(159,169),(454,169),(447,170),(130,171),(421,171),(190,172),(48,173),(83,173),(356,173),(361,173),(463,173),(1,174),(48,174),(86,174),(374,175),(459,175),(252,176),(199,177),(249,177),(24,178),(128,178),(168,178),(209,178),(230,178),(314,178),(500,178),(97,179),(156,179),(230,179),(411,180),(347,181),(463,182),(468,182),(472,182),(473,182),(101,183),(151,183),(304,183),(145,184),(347,184),(374,185),(459,185),(146,186),(160,187),(347,187),(455,188),(146,189),(374,190),(459,190),(180,191),(200,191),(313,191),(420,191),(304,192),(421,192),(356,193),(230,194),(377,194),(468,195),(155,196),(212,196),(468,196),(395,197),(465,198),(129,199),(137,199),(182,199),(349,199),(447,199),(452,200),(57,201),(85,201),(356,202),(1,203),(36,203),(356,203),(421,204),(199,205),(146,206),(249,207),(192,208),(347,208),(1,209),(374,210),(459,210),(221,211),(255,212),(88,213),(199,213),(210,213),(463,213),(468,213),(463,214),(260,215),(421,216),(468,216),(89,217),(406,217),(463,217),(291,218),(356,219),(3,220),(36,220),(48,220),(83,220),(104,220),(130,220),(421,220),(199,221),(194,222),(155,223),(186,223),(212,223),(309,223),(347,223),(97,224),(277,225),(279,226),(464,227),(1,228),(60,228),(87,228),(101,228),(210,228),(304,228),(308,228),(347,228),(463,228),(468,228),(425,229),(89,230),(406,230),(185,231),(463,232),(255,233),(466,233),(272,234),(1,235),(7,236),(347,236),(257,237),(430,237),(194,238),(226,238),(356,238),(427,239),(87,240),(210,240),(463,240),(313,241),(185,242),(24,243),(128,243),(168,243),(209,243),(314,243),(500,243),(199,244),(185,245),(473,246),(185,247),(385,248),(130,249),(155,249),(212,249),(257,249),(333,249),(347,249),(356,249),(421,249),(430,249),(468,249),(185,250),(374,251),(459,251),(60,252),(110,252),(115,252),(215,252),(276,252),(278,252),(321,252),(347,252),(401,252),(417,252),(463,252),(466,252),(468,252),(470,252),(194,253),(347,253),(365,253),(415,253),(463,253),(468,253),(478,253),(468,254),(30,255),(276,255),(468,255),(472,255),(185,256),(356,257),(305,258),(468,259),(310,260),(463,261),(88,262),(185,263),(356,264),(329,265),(356,265),(361,265),(230,266),(315,266),(375,266),(209,267),(88,268),(68,269),(488,269),(420,270),(246,271),(146,272),(194,273),(226,273),(151,274),(326,274),(17,275),(22,275),(60,275),(77,275),(89,275),(97,275),(155,275),(194,275),(210,275),(211,275),(278,275),(302,275),(309,275),(347,275),(358,275),(393,275),(454,275),(468,275),(473,275),(329,276),(194,277),(199,278),(234,279),(347,280),(451,280),(89,281),(39,282),(269,282),(347,282),(463,283),(468,284),(378,285),(147,286),(107,287),(463,288),(466,288),(468,289),(417,290),(3,291),(104,291),(339,292),(344,293),(257,294),(269,295),(321,296),(463,296),(7,297),(10,297),(17,297),(21,297),(25,297),(33,297),(39,297),(58,297),(68,297),(69,297),(82,297),(122,297),(134,297),(137,297),(145,297),(160,297),(170,297),(192,297),(193,297),(215,297),(223,297),(278,297),(282,297),(294,297),(308,297),(309,297),(328,297),(330,297),(333,297),(336,297),(347,297),(349,297),(358,297),(365,297),(393,297),(424,297),(451,297),(487,297),(488,297),(492,297),(38,298),(199,298),(249,298),(305,298),(356,298),(468,299),(326,300),(468,301),(122,302),(350,302),(28,303),(57,303),(85,303),(232,303),(327,303),(344,303),(496,303),(376,304),(147,305),(316,305),(314,306),(106,307),(376,308),(3,309),(104,309),(255,309),(301,309),(356,309),(160,310),(347,310),(141,311),(77,312),(130,312),(199,312),(473,313),(185,314),(182,315),(455,316),(24,317),(111,317),(376,318),(185,319),(130,320),(421,320),(118,321),(390,321),(463,322),(25,323),(347,323),(199,324),(373,325),(473,325),(374,326),(146,327),(185,328),(376,329),(199,330),(347,331),(378,331),(291,332),(347,332),(419,332),(383,333),(88,334),(122,334),(356,334),(424,334),(463,335),(356,336),(199,337),(86,338),(199,338),(356,339),(397,340),(88,341),(151,341),(176,341),(185,342),(130,343),(421,343),(52,344),(324,344),(9,345),(373,345),(473,345),(199,346),(185,347),(123,348),(146,349),(447,349),(376,350),(407,351),(376,352),(463,353),(144,354),(24,355),(110,356),(222,356),(406,356),(463,356),(210,357),(463,357),(468,357),(1,358),(60,359),(159,359),(199,359),(212,359),(226,359),(233,359),(373,359),(406,359),(439,359),(463,359),(478,359),(463,360),(468,360),(473,361),(1,362),(356,362),(1,363),(347,364),(349,364),(421,365),(427,366),(468,367),(77,368),(199,368),(473,368),(477,368),(356,369),(230,370),(465,370),(106,371),(69,372),(347,372),(494,373),(276,374),(447,375),(356,376),(212,377),(417,377),(146,378),(327,378),(468,379),(487,380),(417,381),(89,382),(376,382),(199,383),(376,384),(212,385),(199,386),(468,386),(472,386),(443,387),(282,388),(447,389),(448,390),(89,391),(128,392),(10,393),(347,393),(30,394),(276,394),(472,394),(447,395),(56,396),(84,397),(206,397),(368,397),(456,397),(84,398),(89,398),(155,398),(206,398),(312,398),(189,399),(194,400),(478,400),(326,401),(459,402),(468,403),(146,404),(324,404),(33,405),(460,406),(9,407),(28,407),(30,407),(89,407),(155,407),(186,407),(276,407),(300,407),(479,407),(130,408),(463,409),(269,410),(106,411),(77,412),(222,412),(331,412),(473,412),(313,413),(308,414),(347,414),(463,414),(48,415),(83,415),(106,415),(122,415),(356,415),(424,415),(60,416),(104,416),(463,416),(468,416),(472,416),(468,417),(232,418),(356,419),(3,420),(104,420),(486,420),(374,421),(459,421),(463,422),(470,422),(463,423),(468,423),(243,424),(468,424),(468,425),(472,425),(36,426),(194,427),(478,427),(129,428),(137,428),(349,428),(447,428),(155,429),(186,429),(212,429),(309,429),(347,429),(473,429),(84,430),(368,430),(472,430),(483,431),(466,432),(421,433),(38,434),(52,434),(89,434),(145,434),(223,434),(324,434),(406,434),(257,435),(356,436),(361,436),(491,437),(421,438),(89,439),(406,439),(463,439),(212,440),(468,440),(199,441),(496,442),(36,443),(115,443),(130,443),(326,443),(421,443),(466,443),(470,443),(0,444),(96,444),(288,444),(305,444),(356,444),(361,444),(384,444),(433,444),(497,445),(185,446),(199,447),(36,448),(134,448),(294,448),(347,448),(495,449),(27,450),(22,451),(263,451),(347,451),(347,452),(492,452),(199,453),(104,454),(356,454),(210,455),(106,456),(463,456),(468,456),(463,457),(194,458),(478,458),(374,459),(459,459),(39,460),(58,460),(185,460),(264,460),(269,460),(209,461),(468,461),(201,462),(468,463); +/*!40000 ALTER TABLE `help_relation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `help_topic` +-- + +DROP TABLE IF EXISTS `help_topic`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `help_topic` ( + `help_topic_id` int(10) unsigned NOT NULL, + `name` char(64) NOT NULL, + `help_category_id` smallint(5) unsigned NOT NULL, + `description` text NOT NULL, + `example` text NOT NULL, + `url` text NOT NULL, + PRIMARY KEY (`help_topic_id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='help topics'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `help_topic` +-- + +LOCK TABLES `help_topic` WRITE; +/*!40000 ALTER TABLE `help_topic` DISABLE KEYS */; +INSERT INTO `help_topic` VALUES (0,'MIN',16,'Syntax:\nMIN([DISTINCT] expr)\n\nReturns the minimum value of expr. MIN() may take a string argument; in\nsuch cases, it returns the minimum string value. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html. The DISTINCT\nkeyword can be used to find the minimum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMIN() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(1,'JOIN',27,'MySQL supports the following JOIN syntaxes for the table_references\npart of SELECT statements and multiple-table DELETE and UPDATE\nstatements:\n\ntable_references:\n table_reference [, table_reference] ...\n\ntable_reference:\n table_factor\n | join_table\n\ntable_factor:\n tbl_name [[AS] alias] [index_hint_list]\n | table_subquery [AS] alias\n | ( table_references )\n | { OJ table_reference LEFT OUTER JOIN table_reference\n ON conditional_expr }\n\njoin_table:\n table_reference [INNER | CROSS] JOIN table_factor [join_condition]\n | table_reference STRAIGHT_JOIN table_factor\n | table_reference STRAIGHT_JOIN table_factor ON conditional_expr\n | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition\n | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor\n\njoin_condition:\n ON conditional_expr\n | USING (column_list)\n\nindex_hint_list:\n index_hint [, index_hint] ...\n\nindex_hint:\n USE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])\n | IGNORE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n | FORCE {INDEX|KEY}\n [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)\n\nindex_list:\n index_name [, index_name] ...\n\nA table reference is also known as a join expression.\n\nThe syntax of table_factor is extended in comparison with the SQL\nStandard. The latter accepts only table_reference, not a list of them\ninside a pair of parentheses.\n\nThis is a conservative extension if we consider each comma in a list of\ntable_reference items as equivalent to an inner join. For example:\n\nSELECT * FROM t1 LEFT JOIN (t2, t3, t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nis equivalent to:\n\nSELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)\n ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)\n\nIn MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents\n(they can replace each other). In standard SQL, they are not\nequivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used\notherwise.\n\nIn general, parentheses can be ignored in join expressions containing\nonly inner join operations. MySQL also supports nested joins (see\nhttp://dev.mysql.com/doc/refman/5.5/en/nested-join-optimization.html).\n\nIndex hints can be specified to affect how the MySQL optimizer makes\nuse of indexes. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/index-hints.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/join.html\n\n','SELECT left_tbl.*\n FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id\n WHERE right_tbl.id IS NULL;\n','http://dev.mysql.com/doc/refman/5.5/en/join.html'),(2,'HEX',37,'Syntax:\nHEX(str), HEX(N)\n\nFor a string argument str, HEX() returns a hexadecimal string\nrepresentation of str where each character in str is converted to two\nhexadecimal digits. The inverse of this operation is performed by the\nUNHEX() function.\n\nFor a numeric argument N, HEX() returns a hexadecimal string\nrepresentation of the value of N treated as a longlong (BIGINT) number.\nThis is equivalent to CONV(N,10,16). The inverse of this operation is\nperformed by CONV(HEX(N),16,10).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT 0x616263, HEX(\'abc\'), UNHEX(HEX(\'abc\'));\n -> \'abc\', 616263, \'abc\'\nmysql> SELECT HEX(255), CONV(HEX(255),16,10);\n -> \'FF\', 255\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(3,'REPLACE',27,'Syntax:\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n\nOr:\n\nREPLACE [LOW_PRIORITY | DELAYED]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n\nREPLACE works exactly like INSERT, except that if an old row in the\ntable has the same value as a new row for a PRIMARY KEY or a UNIQUE\nindex, the old row is deleted before the new row is inserted. See [HELP\nINSERT].\n\nREPLACE is a MySQL extension to the SQL standard. It either inserts, or\ndeletes and inserts. For another MySQL extension to standard SQL---that\neither inserts or updates---see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html.\n\nNote that unless the table has a PRIMARY KEY or UNIQUE index, using a\nREPLACE statement makes no sense. It becomes equivalent to INSERT,\nbecause there is no index to be used to determine whether a new row\nduplicates another.\n\nValues for all columns are taken from the values specified in the\nREPLACE statement. Any missing columns are set to their default values,\njust as happens for INSERT. You cannot refer to values from the current\nrow and use them in the new row. If you use an assignment such as SET\ncol_name = col_name + 1, the reference to the column name on the right\nhand side is treated as DEFAULT(col_name), so the assignment is\nequivalent to SET col_name = DEFAULT(col_name) + 1.\n\nTo use REPLACE, you must have both the INSERT and DELETE privileges for\nthe table.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/replace.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/replace.html'),(4,'CONTAINS',30,'Contains(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 completely contains g2. This\ntests the opposite relationship as Within().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(5,'SRID',36,'SRID(g)\n\nReturns an integer indicating the Spatial Reference System ID for the\ngeometry value g.\n\nIn MySQL, the SRID value is just an integer associated with the\ngeometry value. All calculations are done assuming Euclidean (planar)\ngeometry.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','mysql> SELECT SRID(GeomFromText(\'LineString(1 1,2 2)\',101));\n+-----------------------------------------------+\n| SRID(GeomFromText(\'LineString(1 1,2 2)\',101)) |\n+-----------------------------------------------+\n| 101 |\n+-----------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(6,'CURRENT_TIMESTAMP',31,'Syntax:\nCURRENT_TIMESTAMP, CURRENT_TIMESTAMP()\n\nCURRENT_TIMESTAMP and CURRENT_TIMESTAMP() are synonyms for NOW().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(7,'SHOW CONTRIBUTORS',26,'Syntax:\nSHOW CONTRIBUTORS\n\nThe SHOW CONTRIBUTORS statement displays information about the people\nwho contribute to MySQL source or to causes that we support. For each\ncontributor, it displays Name, Location, and Comment values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-contributors.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-contributors.html'),(8,'VARIANCE',16,'Syntax:\nVARIANCE(expr)\n\nReturns the population standard variance of expr. This is an extension\nto standard SQL. The standard SQL function VAR_POP() can be used\ninstead.\n\nVARIANCE() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(9,'DROP SERVER',39,'Syntax:\nDROP SERVER [ IF EXISTS ] server_name\n\nDrops the server definition for the server named server_name. The\ncorresponding row within the mysql.servers table will be deleted. This\nstatement requires the SUPER privilege.\n\nDropping a server for a table does not affect any FEDERATED tables that\nused this connection information when they were created. See [HELP\nCREATE SERVER].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-server.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-server.html'),(10,'SHOW AUTHORS',26,'Syntax:\nSHOW AUTHORS\n\nThe SHOW AUTHORS statement displays information about the people who\nwork on MySQL. For each author, it displays Name, Location, and Comment\nvalues.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-authors.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-authors.html'),(11,'VAR_SAMP',16,'Syntax:\nVAR_SAMP(expr)\n\nReturns the sample variance of expr. That is, the denominator is the\nnumber of rows minus one.\n\nVAR_SAMP() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(12,'CONCAT',37,'Syntax:\nCONCAT(str1,str2,...)\n\nReturns the string that results from concatenating the arguments. May\nhave one or more arguments. If all arguments are nonbinary strings, the\nresult is a nonbinary string. If the arguments include any binary\nstrings, the result is a binary string. A numeric argument is converted\nto its equivalent string form. This is a nonbinary string as of MySQL\n5.5.3. Before 5.5.3, it is a binary string; to to avoid that and\nproduce a nonbinary string, you can use an explicit type cast, as in\nthis example:\n\nSELECT CONCAT(CAST(int_col AS CHAR), char_col);\n\nCONCAT() returns NULL if any argument is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT CONCAT(\'My\', \'S\', \'QL\');\n -> \'MySQL\'\nmysql> SELECT CONCAT(\'My\', NULL, \'QL\');\n -> NULL\nmysql> SELECT CONCAT(14.3);\n -> \'14.3\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(13,'GEOMETRY HIERARCHY',34,'Geometry is the base class. It is an abstract class. The instantiable\nsubclasses of Geometry are restricted to zero-, one-, and\ntwo-dimensional geometric objects that exist in two-dimensional\ncoordinate space. All instantiable geometry classes are defined so that\nvalid instances of a geometry class are topologically closed (that is,\nall defined geometries include their boundary).\n\nThe base Geometry class has subclasses for Point, Curve, Surface, and\nGeometryCollection:\n\no Point represents zero-dimensional objects.\n\no Curve represents one-dimensional objects, and has subclass\n LineString, with sub-subclasses Line and LinearRing.\n\no Surface is designed for two-dimensional objects and has subclass\n Polygon.\n\no GeometryCollection has specialized zero-, one-, and two-dimensional\n collection classes named MultiPoint, MultiLineString, and\n MultiPolygon for modeling geometries corresponding to collections of\n Points, LineStrings, and Polygons, respectively. MultiCurve and\n MultiSurface are introduced as abstract superclasses that generalize\n the collection interfaces to handle Curves and Surfaces.\n\nGeometry, Curve, Surface, MultiCurve, and MultiSurface are defined as\nnoninstantiable classes. They define a common set of methods for their\nsubclasses and are included for extensibility.\n\nPoint, LineString, Polygon, GeometryCollection, MultiPoint,\nMultiLineString, and MultiPolygon are instantiable classes.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/gis-geometry-class-hierarchy.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/gis-geometry-class-hierarchy.html'),(14,'CHAR FUNCTION',37,'Syntax:\nCHAR(N,... [USING charset_name])\n\nCHAR() interprets each argument N as an integer and returns a string\nconsisting of the characters given by the code values of those\nintegers. NULL values are skipped.\nBy default, CHAR() returns a binary string. To produce a string in a\ngiven character set, use the optional USING clause:\n\nmysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));\n+---------------------+--------------------------------+\n| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |\n+---------------------+--------------------------------+\n| binary | utf8 |\n+---------------------+--------------------------------+\n\nIf USING is given and the result string is illegal for the given\ncharacter set, a warning is issued. Also, if strict SQL mode is\nenabled, the result from CHAR() becomes NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT CHAR(77,121,83,81,\'76\');\n -> \'MySQL\'\nmysql> SELECT CHAR(77,77.3,\'77.3\');\n -> \'MMM\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(15,'DATETIME',22,'DATETIME\n\nA date and time combination. The supported range is \'1000-01-01\n00:00:00\' to \'9999-12-31 23:59:59\'. MySQL displays DATETIME values in\n\'YYYY-MM-DD HH:MM:SS\' format, but permits assignment of values to\nDATETIME columns using either strings or numbers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html'),(16,'SHOW CREATE TRIGGER',26,'Syntax:\nSHOW CREATE TRIGGER trigger_name\n\nThis statement shows a CREATE TRIGGER statement that creates the given\ntrigger.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-trigger.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-create-trigger.html'),(17,'SHOW CREATE PROCEDURE',26,'Syntax:\nSHOW CREATE PROCEDURE proc_name\n\nThis statement is a MySQL extension. It returns the exact string that\ncan be used to re-create the named stored procedure. A similar\nstatement, SHOW CREATE FUNCTION, displays information about stored\nfunctions (see [HELP SHOW CREATE FUNCTION]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table. If you do not have privileges\nfor the routine itself, the value displayed for the Create Procedure or\nCreate Function field will be NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-procedure.html\n\n','mysql> SHOW CREATE PROCEDURE test.simpleproc\\G\n*************************** 1. row ***************************\n Procedure: simpleproc\n sql_mode:\n Create Procedure: CREATE PROCEDURE `simpleproc`(OUT param1 INT)\n BEGIN\n SELECT COUNT(*) INTO param1 FROM t;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nmysql> SHOW CREATE FUNCTION test.hello\\G\n*************************** 1. row ***************************\n Function: hello\n sql_mode:\n Create Function: CREATE FUNCTION `hello`(s CHAR(20))\n RETURNS CHAR(50)\n RETURN CONCAT(\'Hello, \',s,\'!\')\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','http://dev.mysql.com/doc/refman/5.5/en/show-create-procedure.html'),(18,'OPEN',23,'Syntax:\nOPEN cursor_name\n\nThis statement opens a previously declared cursor. For an example, see\nhttp://dev.mysql.com/doc/refman/5.5/en/cursors.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/open.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/open.html'),(19,'INTEGER',22,'INTEGER[(M)] [UNSIGNED] [ZEROFILL]\n\nThis type is a synonym for INT.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(20,'LOWER',37,'Syntax:\nLOWER(str)\n\nReturns the string str with all characters changed to lowercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nmysql> SELECT LOWER(\'QUADRATICALLY\');\n -> \'quadratically\'\n\nLOWER() (and UPPER()) are ineffective when applied to binary strings\n(BINARY, VARBINARY, BLOB). To perform lettercase conversion, convert\nthe string to a nonbinary string:\n\nmysql> SET @str = BINARY \'New York\';\nmysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));\n+-------------+-----------------------------------+\n| LOWER(@str) | LOWER(CONVERT(@str USING latin1)) |\n+-------------+-----------------------------------+\n| New York | new york |\n+-------------+-----------------------------------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(21,'SHOW COLUMNS',26,'Syntax:\nSHOW [FULL] COLUMNS {FROM | IN} tbl_name [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW COLUMNS displays information about the columns in a given table.\nIt also works for views. The LIKE clause, if present, indicates which\ncolumn names to match. The WHERE clause can be given to select rows\nusing more general conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nSHOW COLUMNS displays information only for those columns for which you\nhave some privilege.\n\nmysql> SHOW COLUMNS FROM City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nIf the data types differ from what you expect them to be based on a\nCREATE TABLE statement, note that MySQL sometimes changes data types\nwhen you create or alter a table. The conditions under which this\noccurs are described in\nhttp://dev.mysql.com/doc/refman/5.5/en/silent-column-changes.html.\n\nThe FULL keyword causes the output to include the column collation and\ncomments, as well as the privileges you have for each column.\n\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. In other words, these two statements are equivalent:\n\nmysql> SHOW COLUMNS FROM mytable FROM mydb;\nmysql> SHOW COLUMNS FROM mydb.mytable;\n\nSHOW COLUMNS displays the following values for each table column:\n\nField indicates the column name.\n\nType indicates the column data type.\n\nCollation indicates the collation for nonbinary string columns, or NULL\nfor other columns. This value is displayed only if you use the FULL\nkeyword.\n\nThe Null field contains YES if NULL values can be stored in the column,\nNO if not.\n\nThe Key field indicates whether the column is indexed:\n\no If Key is empty, the column either is not indexed or is indexed only\n as a secondary column in a multiple-column, nonunique index.\n\no If Key is PRI, the column is a PRIMARY KEY or is one of the columns\n in a multiple-column PRIMARY KEY.\n\no If Key is UNI, the column is the first column of a UNIQUE index. (A\n UNIQUE index permits multiple NULL values, but you can tell whether\n the column permits NULL by checking the Null field.)\n\no If Key is MUL, the column is the first column of a nonunique index in\n which multiple occurrences of a given value are permitted within the\n column.\n\nIf more than one of the Key values applies to a given column of a\ntable, Key displays the one with the highest priority, in the order\nPRI, UNI, MUL.\n\nA UNIQUE index may be displayed as PRI if it cannot contain NULL values\nand there is no PRIMARY KEY in the table. A UNIQUE index may display as\nMUL if several columns form a composite UNIQUE index; although the\ncombination of the columns is unique, each column can still hold\nmultiple occurrences of a given value.\n\nThe Default field indicates the default value that is assigned to the\ncolumn. This is NULL if the column has an explicit default of NULL, or\nif the column definition has no DEFAULT clause.\n\nThe Extra field contains any additional information that is available\nabout a given column. The value is nonempty in these cases:\nauto_increment for columns that have the AUTO_INCREMENT attribute; on\nupdate CURRENT_TIMESTAMP for TIMESTAMP columns that have the ON UPDATE\nCURRENT_TIMESTAMP attribute.\n\nPrivileges indicates the privileges you have for the column. This value\nis displayed only if you use the FULL keyword.\n\nComment indicates any comment the column has. This value is displayed\nonly if you use the FULL keyword.\n\nSHOW FIELDS is a synonym for SHOW COLUMNS. You can also list a table\'s\ncolumns with the mysqlshow db_name tbl_name command.\n\nThe DESCRIBE statement provides information similar to SHOW COLUMNS.\nSee [HELP DESCRIBE].\n\nThe SHOW CREATE TABLE, SHOW TABLE STATUS, and SHOW INDEX statements\nalso provide information about tables. See [HELP SHOW].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-columns.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-columns.html'),(22,'CREATE TRIGGER',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n TRIGGER trigger_name trigger_time trigger_event\n ON tbl_name FOR EACH ROW trigger_body\n\nThis statement creates a new trigger. A trigger is a named database\nobject that is associated with a table, and that activates when a\nparticular event occurs for the table. The trigger becomes associated\nwith the table named tbl_name, which must refer to a permanent table.\nYou cannot associate a trigger with a TEMPORARY table or a view.\n\nCREATE TRIGGER requires the TRIGGER privilege for the table associated\nwith the trigger. The statement might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section. If\nbinary logging is enabled, CREATE TRIGGER might require the SUPER\nprivilege, as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-logging.html.\n\nThe DEFINER clause determines the security context to be used when\nchecking access privileges at trigger activation time. See later in\nthis section for more information.\n\ntrigger_time is the trigger action time. It can be BEFORE or AFTER to\nindicate that the trigger activates before or after each row to be\nmodified.\n\ntrigger_event indicates the kind of statement that activates the\ntrigger. The trigger_event can be one of the following:\n\no INSERT: The trigger is activated whenever a new row is inserted into\n the table; for example, through INSERT, LOAD DATA, and REPLACE\n statements.\n\no UPDATE: The trigger is activated whenever a row is modified; for\n example, through UPDATE statements.\n\no DELETE: The trigger is activated whenever a row is deleted from the\n table; for example, through DELETE and REPLACE statements. However,\n DROP TABLE and TRUNCATE TABLE statements on the table do not activate\n this trigger, because they do not use DELETE. Dropping a partition\n does not activate DELETE triggers, either. See [HELP TRUNCATE TABLE].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-trigger.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-trigger.html'),(23,'MONTH',31,'Syntax:\nMONTH(date)\n\nReturns the month for date, in the range 1 to 12 for January to\nDecember, or 0 for dates such as \'0000-00-00\' or \'2008-00-00\' that have\na zero month part.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MONTH(\'2008-02-03\');\n -> 2\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(24,'TINYINT',22,'TINYINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA very small integer. The signed range is -128 to 127. The unsigned\nrange is 0 to 255.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(25,'SHOW TRIGGERS',26,'Syntax:\nSHOW TRIGGERS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TRIGGERS lists the triggers currently defined for tables in a\ndatabase (the default database unless a FROM clause is given). This\nstatement returns results only for databases and tables for which you\nhave the TRIGGER privilege. The LIKE clause, if present, indicates\nwhich table names to match and causes the statement to display triggers\nfor those tables. The WHERE clause can be given to select rows using\nmore general conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nFor the trigger ins_sum as defined in\nhttp://dev.mysql.com/doc/refman/5.5/en/triggers.html, the output of\nthis statement is as shown here:\n\nmysql> SHOW TRIGGERS LIKE \'acc%\'\\G\n*************************** 1. row ***************************\n Trigger: ins_sum\n Event: INSERT\n Table: account\n Statement: SET @sum = @sum + NEW.amount\n Timing: BEFORE\n Created: NULL\n sql_mode:\n Definer: myname@localhost\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\ncharacter_set_client is the session value of the character_set_client\nsystem variable when the trigger was created. collation_connection is\nthe session value of the collation_connection system variable when the\ntrigger was created. Database Collation is the collation of the\ndatabase with which the trigger is associated.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-triggers.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-triggers.html'),(26,'MASTER_POS_WAIT',14,'Syntax:\nMASTER_POS_WAIT(log_name,log_pos[,timeout])\n\nThis function is useful for control of master/slave synchronization. It\nblocks until the slave has read and applied all updates up to the\nspecified position in the master log. The return value is the number of\nlog events the slave had to wait for to advance to the specified\nposition. The function returns NULL if the slave SQL thread is not\nstarted, the slave\'s master information is not initialized, the\narguments are incorrect, or an error occurs. It returns -1 if the\ntimeout has been exceeded. If the slave SQL thread stops while\nMASTER_POS_WAIT() is waiting, the function returns NULL. If the slave\nis past the specified position, the function returns immediately.\n\nIf a timeout value is specified, MASTER_POS_WAIT() stops waiting when\ntimeout seconds have elapsed. timeout must be greater than 0; a zero or\nnegative timeout means no timeout.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(27,'REGEXP',37,'Syntax:\nexpr REGEXP pat, expr RLIKE pat\n\nPerforms a pattern match of a string expression expr against a pattern\npat. The pattern can be an extended regular expression. The syntax for\nregular expressions is discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/regexp.html. Returns 1 if expr\nmatches pat; otherwise it returns 0. If either expr or pat is NULL, the\nresult is NULL. RLIKE is a synonym for REGEXP, provided for mSQL\ncompatibility.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\n*Note*: Because MySQL uses the C escape syntax in strings (for example,\n\"\\n\" to represent the newline character), you must double any \"\\\" that\nyou use in your REGEXP strings.\n\nREGEXP is not case sensitive, except when used with binary strings.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/regexp.html\n\n','mysql> SELECT \'Monty!\' REGEXP \'.*\';\n -> 1\nmysql> SELECT \'new*\\n*line\' REGEXP \'new\\\\*.\\\\*line\';\n -> 1\nmysql> SELECT \'a\' REGEXP \'A\', \'a\' REGEXP BINARY \'A\';\n -> 1 0\nmysql> SELECT \'a\' REGEXP \'^[a-d]\';\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/regexp.html'),(28,'IF STATEMENT',23,'Syntax:\nIF search_condition THEN statement_list\n [ELSEIF search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND IF\n\nThe IF statement for stored programs implements a basic conditional\nconstruct.\n\n*Note*: There is also an IF() function, which differs from the IF\nstatement described here. See\nhttp://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html. The\nIF statement can have THEN, ELSE, and ELSEIF clauses, and it is\nterminated with END IF.\n\nIf the search_condition evaluates to true, the corresponding THEN or\nELSEIF clause statement_list executes. If no search_condition matches,\nthe ELSE clause statement_list executes.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/if.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/if.html'),(29,'^',19,'Syntax:\n^\n\nBitwise XOR:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 1 ^ 1;\n -> 0\nmysql> SELECT 1 ^ 0;\n -> 1\nmysql> SELECT 11 ^ 3;\n -> 8\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(30,'DROP VIEW',39,'Syntax:\nDROP VIEW [IF EXISTS]\n view_name [, view_name] ...\n [RESTRICT | CASCADE]\n\nDROP VIEW removes one or more views. You must have the DROP privilege\nfor each view. If any of the views named in the argument list do not\nexist, MySQL returns an error indicating by name which nonexisting\nviews it was unable to drop, but it also drops all of the views in the\nlist that do exist.\n\nThe IF EXISTS clause prevents an error from occurring for views that\ndon\'t exist. When this clause is given, a NOTE is generated for each\nnonexistent view. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE, if given, are parsed and ignored.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-view.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-view.html'),(31,'WITHIN',30,'Within(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially within g2. This\ntests the opposite relationship as Contains().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(32,'WEEK',31,'Syntax:\nWEEK(date[,mode])\n\nThis function returns the week number for date. The two-argument form\nof WEEK() enables you to specify whether the week starts on Sunday or\nMonday and whether the return value should be in the range from 0 to 53\nor from 1 to 53. If the mode argument is omitted, the value of the\ndefault_week_format system variable is used. See\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT WEEK(\'2008-02-20\');\n -> 7\nmysql> SELECT WEEK(\'2008-02-20\',0);\n -> 7\nmysql> SELECT WEEK(\'2008-02-20\',1);\n -> 8\nmysql> SELECT WEEK(\'2008-12-31\',1);\n -> 53\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(33,'SHOW PLUGINS',26,'Syntax:\nSHOW PLUGINS\n\nSHOW PLUGINS displays information about server plugins. Plugin\ninformation is also available in the INFORMATION_SCHEMA.PLUGINS table.\nSee http://dev.mysql.com/doc/refman/5.5/en/plugins-table.html.\n\nExample of SHOW PLUGINS output:\n\nmysql> SHOW PLUGINS\\G\n*************************** 1. row ***************************\n Name: binlog\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 2. row ***************************\n Name: CSV\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 3. row ***************************\n Name: MEMORY\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n*************************** 4. row ***************************\n Name: MyISAM\n Status: ACTIVE\n Type: STORAGE ENGINE\nLibrary: NULL\nLicense: GPL\n...\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-plugins.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-plugins.html'),(34,'DROP FUNCTION UDF',21,'Syntax:\nDROP FUNCTION function_name\n\nThis statement drops the user-defined function (UDF) named\nfunction_name.\n\nTo drop a function, you must have the DELETE privilege for the mysql\ndatabase. This is because DROP FUNCTION removes a row from the\nmysql.func system table that records the function\'s name, type, and\nshared library name.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-function-udf.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-function-udf.html'),(35,'PREPARE',8,'Syntax:\nPREPARE stmt_name FROM preparable_stmt\n\nThe PREPARE statement prepares a statement and assigns it a name,\nstmt_name, by which to refer to the statement later. Statement names\nare not case sensitive. preparable_stmt is either a string literal or a\nuser variable that contains the text of the statement. The text must\nrepresent a single SQL statement, not multiple statements. Within the\nstatement, \"?\" characters can be used as parameter markers to indicate\nwhere data values are to be bound to the query later when you execute\nit. The \"?\" characters should not be enclosed within quotation marks,\neven if you intend to bind them to string values. Parameter markers can\nbe used only where data values should appear, not for SQL keywords,\nidentifiers, and so forth.\n\nIf a prepared statement with the given name already exists, it is\ndeallocated implicitly before the new statement is prepared. This means\nthat if the new statement contains an error and cannot be prepared, an\nerror is returned and no statement with the given name exists.\n\nA prepared statement is executed with EXECUTE and released with\nDEALLOCATE PREPARE.\n\nThe scope of a prepared statement is the session within which it is\ncreated. Other sessions cannot see it.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/prepare.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/prepare.html'),(36,'LOCK',8,'Syntax:\nLOCK TABLES\n tbl_name [[AS] alias] lock_type\n [, tbl_name [[AS] alias] lock_type] ...\n\nlock_type:\n READ [LOCAL]\n | [LOW_PRIORITY] WRITE\n\nUNLOCK TABLES\n\nMySQL enables client sessions to acquire table locks explicitly for the\npurpose of cooperating with other sessions for access to tables, or to\nprevent other sessions from modifying tables during periods when a\nsession requires exclusive access to them. A session can acquire or\nrelease locks only for itself. One session cannot acquire locks for\nanother session or release locks held by another session.\n\nLocks may be used to emulate transactions or to get more speed when\nupdating tables. This is explained in more detail later in this\nsection.\n\nLOCK TABLES explicitly acquires table locks for the current client\nsession. Table locks can be acquired for base tables or views. You must\nhave the LOCK TABLES privilege, and the SELECT privilege for each\nobject to be locked.\n\nFor view locking, LOCK TABLES adds all base tables used in the view to\nthe set of tables to be locked and locks them automatically. If you\nlock a table explicitly with LOCK TABLES, any tables used in triggers\nare also locked implicitly, as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/lock-tables-and-triggers.html.\n\nUNLOCK TABLES explicitly releases any table locks held by the current\nsession. LOCK TABLES implicitly releases any table locks held by the\ncurrent session before acquiring new locks.\n\nAnother use for UNLOCK TABLES is to release the global read lock\nacquired with the FLUSH TABLES WITH READ LOCK statement, which enables\nyou to lock all tables in all databases. See [HELP FLUSH]. (This is a\nvery convenient way to get backups if you have a file system such as\nVeritas that can take snapshots in time.)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html'),(37,'UPDATEXML',37,'Syntax:\nUpdateXML(xml_target, xpath_expr, new_xml)\n\nThis function replaces a single portion of a given fragment of XML\nmarkup xml_target with a new XML fragment new_xml, and then returns the\nchanged XML. The portion of xml_target that is replaced matches an\nXPath expression xpath_expr supplied by the user. In MySQL 5.5, the\nXPath expression can contain at most 127 characters. (This limitation\nis lifted in MySQL 5.6.)\n\nIf no expression matching xpath_expr is found, or if multiple matches\nare found, the function returns the original xml_target XML fragment.\nAll three arguments should be strings.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/xml-functions.html\n\n','mysql> SELECT\n -> UpdateXML(\'ccc\', \'/a\', \'fff\') AS val1,\n -> UpdateXML(\'ccc\', \'/b\', \'fff\') AS val2,\n -> UpdateXML(\'ccc\', \'//b\', \'fff\') AS val3,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val4,\n -> UpdateXML(\'ccc\', \'/a/d\', \'fff\') AS val5\n -> \\G\n\n*************************** 1. row ***************************\nval1: fff\nval2: ccc\nval3: fff\nval4: cccfff\nval5: ccc\n','http://dev.mysql.com/doc/refman/5.5/en/xml-functions.html'),(38,'RESET SLAVE',8,'Syntax:\nRESET SLAVE [ALL]\n\nRESET SLAVE makes the slave forget its replication position in the\nmaster\'s binary log. This statement is meant to be used for a clean\nstart: It deletes the master.info and relay-log.info files, all the\nrelay log files, and starts a new relay log file. To use RESET SLAVE,\nthe slave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\n*Note*: All relay log files are deleted, even if they have not been\ncompletely executed by the slave SQL thread. (This is a condition\nlikely to exist on a replication slave if you have issued a STOP SLAVE\nstatement or if the slave is highly loaded.)\n\nIn MySQL 5.5 (unlike the case in MySQL 5.1 and earlier), RESET SLAVE\ndoes not change any replication connection parameters such as master\nhost, master port, master user, or master password, which are retained\nin memory. This means that START SLAVE can be issued without requiring\na CHANGE MASTER TO statement following RESET SLAVE.\n\nIn MySQL 5.5.16 and later, you can use RESET SLAVE ALL to reset these\nconnection parameters (Bug #11809016). Connection parameters are also\nreset if the slave mysqld is shut down.\n\nIf the slave SQL thread was in the middle of replicating temporary\ntables when it was stopped, and RESET SLAVE is issued, these replicated\ntemporary tables are deleted on the slave.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/reset-slave.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/reset-slave.html'),(39,'SHOW BINARY LOGS',26,'Syntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [HELP PURGE BINARY LOGS], that shows\nhow to determine which logs can be purged.\n\nmysql> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-binary-logs.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-binary-logs.html'),(40,'POLYGON',24,'Polygon(ls1,ls2,...)\n\nConstructs a Polygon value from a number of LineString or WKB\nLineString arguments. If any argument does not represent a LinearRing\n(that is, not a closed and simple LineString), the return value is\nNULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(41,'MINUTE',31,'Syntax:\nMINUTE(time)\n\nReturns the minute for time, in the range 0 to 59.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MINUTE(\'2008-02-03 10:05:03\');\n -> 5\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(42,'DAY',31,'Syntax:\nDAY(date)\n\nDAY() is a synonym for DAYOFMONTH().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(43,'MID',37,'Syntax:\nMID(str,pos,len)\n\nMID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(44,'UUID',14,'Syntax:\nUUID()\n\nReturns a Universal Unique Identifier (UUID) generated according to\n\"DCE 1.1: Remote Procedure Call\" (Appendix A) CAE (Common Applications\nEnvironment) Specifications published by The Open Group in October 1997\n(Document Number C706,\nhttp://www.opengroup.org/public/pubs/catalog/c706.htm).\n\nA UUID is designed as a number that is globally unique in space and\ntime. Two calls to UUID() are expected to generate two different\nvalues, even if these calls are performed on two separate computers\nthat are not connected to each other.\n\nA UUID is a 128-bit number represented by a utf8 string of five\nhexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format:\n\no The first three numbers are generated from a timestamp.\n\no The fourth number preserves temporal uniqueness in case the timestamp\n value loses monotonicity (for example, due to daylight saving time).\n\no The fifth number is an IEEE 802 node number that provides spatial\n uniqueness. A random number is substituted if the latter is not\n available (for example, because the host computer has no Ethernet\n card, or we do not know how to find the hardware address of an\n interface on your operating system). In this case, spatial uniqueness\n cannot be guaranteed. Nevertheless, a collision should have very low\n probability.\n\n Currently, the MAC address of an interface is taken into account only\n on FreeBSD and Linux. On other operating systems, MySQL uses a\n randomly generated 48-bit number.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> SELECT UUID();\n -> \'6ccd780c-baba-1026-9564-0040f4311e29\'\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(45,'LINESTRING',24,'LineString(pt1,pt2,...)\n\nConstructs a LineString value from a number of Point or WKB Point\narguments. If the number of arguments is less than two, the return\nvalue is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(46,'SLEEP',14,'Syntax:\nSLEEP(duration)\n\nSleeps (pauses) for the number of seconds given by the duration\nargument, then returns 0. If SLEEP() is interrupted, it returns 1. The\nduration may have a fractional part given in microseconds.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(47,'CONNECTION_ID',17,'Syntax:\nCONNECTION_ID()\n\nReturns the connection ID (thread ID) for the connection. Every\nconnection has an ID that is unique among the set of currently\nconnected clients.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT CONNECTION_ID();\n -> 23786\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(48,'DELETE',27,'Syntax:\nSingle-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n tbl_name[.*] [, tbl_name[.*]] ...\n FROM table_references\n [WHERE where_condition]\n\nOr:\n\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE]\n FROM tbl_name[.*] [, tbl_name[.*]] ...\n USING table_references\n [WHERE where_condition]\n\nFor the single-table syntax, the DELETE statement deletes rows from\ntbl_name and returns a count of the number of deleted rows. This count\ncan be obtained by calling the ROW_COUNT() function (see\nhttp://dev.mysql.com/doc/refman/5.5/en/information-functions.html). The\nWHERE clause, if given, specifies the conditions that identify which\nrows to delete. With no WHERE clause, all rows are deleted. If the\nORDER BY clause is specified, the rows are deleted in the order that is\nspecified. The LIMIT clause places a limit on the number of rows that\ncan be deleted.\n\nFor the multiple-table syntax, DELETE deletes from each tbl_name the\nrows that satisfy the conditions. In this case, ORDER BY and LIMIT\ncannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe deleted. It is specified as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/select.html.\n\nCurrently, you cannot delete from a table and select from the same\ntable in a subquery.\n\nYou need the DELETE privilege on a table to delete rows from it. You\nneed only the SELECT privilege for any columns that are only read, such\nas those named in the WHERE clause.\n\nAs stated, a DELETE statement with no WHERE clause deletes all rows. A\nfaster way to do this, when you do not need to know the number of\ndeleted rows, is to use TRUNCATE TABLE. However, within a transaction\nor if you have a lock on the table, TRUNCATE TABLE cannot be used\nwhereas DELETE can. See [HELP TRUNCATE TABLE], and [HELP LOCK].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/delete.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/delete.html'),(49,'ROUND',4,'Syntax:\nROUND(X), ROUND(X,D)\n\nRounds the argument X to D decimal places. The rounding algorithm\ndepends on the data type of X. D defaults to 0 if not specified. D can\nbe negative to cause D digits left of the decimal point of the value X\nto become zero.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ROUND(-1.23);\n -> -1\nmysql> SELECT ROUND(-1.58);\n -> -2\nmysql> SELECT ROUND(1.58);\n -> 2\nmysql> SELECT ROUND(1.298, 1);\n -> 1.3\nmysql> SELECT ROUND(1.298, 0);\n -> 1\nmysql> SELECT ROUND(23.298, -1);\n -> 20\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(50,'NULLIF',7,'Syntax:\nNULLIF(expr1,expr2)\n\nReturns NULL if expr1 = expr2 is true, otherwise returns expr1. This is\nthe same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html\n\n','mysql> SELECT NULLIF(1,1);\n -> NULL\nmysql> SELECT NULLIF(1,2);\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html'),(51,'CLOSE',23,'Syntax:\nCLOSE cursor_name\n\nThis statement closes a previously opened cursor. For an example, see\nhttp://dev.mysql.com/doc/refman/5.5/en/cursors.html.\n\nAn error occurs if the cursor is not open.\n\nIf not closed explicitly, a cursor is closed at the end of the BEGIN\n... END block in which it was declared.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/close.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/close.html'),(52,'STOP SLAVE',8,'Syntax:\nSTOP SLAVE [thread_types]\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nStops the slave threads. STOP SLAVE requires the SUPER privilege.\nRecommended best practice is to execute STOP SLAVE on the slave before\nstopping the slave server (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-shutdown.html, for more\ninformation).\n\nWhen using the row-based logging format: You should execute STOP SLAVE\non the slave prior to shutting down the slave server if you are\nreplicating any tables that use a nontransactional storage engine (see\nthe Note later in this section). In MySQL 5.5.9 and later, you can also\nuse STOP SLAVE SQL_THREAD for this purpose.\n\nLike START SLAVE, this statement may be used with the IO_THREAD and\nSQL_THREAD options to name the thread or threads to be stopped.\n\n*Note*: In MySQL 5.5, STOP SLAVE waits until the current replication\nevent group affecting one or more non-transactional tables has finished\nexecuting (if there is any such replication group), or until the user\nissues a KILL QUERY or KILL CONNECTION statement. (Bug #319, Bug\n#38205)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/stop-slave.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/stop-slave.html'),(53,'TIMEDIFF',31,'Syntax:\nTIMEDIFF(expr1,expr2)\n\nTIMEDIFF() returns expr1 - expr2 expressed as a time value. expr1 and\nexpr2 are time or date-and-time expressions, but both must be of the\nsame type.\n\nThe result returned by TIMEDIFF() is limited to the range allowed for\nTIME values. Alternatively, you can use either of the functions\nTIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIMEDIFF(\'2000:01:01 00:00:00\',\n -> \'2000:01:01 00:00:00.000001\');\n -> \'-00:00:00.000001\'\nmysql> SELECT TIMEDIFF(\'2008-12-31 23:59:59.000001\',\n -> \'2008-12-30 01:01:01.000002\');\n -> \'46:58:57.999999\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(54,'REPLACE FUNCTION',37,'Syntax:\nREPLACE(str,from_str,to_str)\n\nReturns the string str with all occurrences of the string from_str\nreplaced by the string to_str. REPLACE() performs a case-sensitive\nmatch when searching for from_str.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT REPLACE(\'www.mysql.com\', \'w\', \'Ww\');\n -> \'WwWwWw.mysql.com\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(55,'USE',28,'Syntax:\nUSE db_name\n\nThe USE db_name statement tells MySQL to use the db_name database as\nthe default (current) database for subsequent statements. The database\nremains the default until the end of the session or another USE\nstatement is issued:\n\nUSE db1;\nSELECT COUNT(*) FROM mytable; # selects from db1.mytable\nUSE db2;\nSELECT COUNT(*) FROM mytable; # selects from db2.mytable\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/use.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/use.html'),(56,'LINEFROMTEXT',3,'LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])\n\nConstructs a LINESTRING value using its WKT representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(57,'CASE OPERATOR',7,'Syntax:\nCASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN\nresult ...] [ELSE result] END\n\nCASE WHEN [condition] THEN result [WHEN [condition] THEN result ...]\n[ELSE result] END\n\nThe first version returns the result where value=compare_value. The\nsecond version returns the result for the first condition that is true.\nIf there was no matching result value, the result after ELSE is\nreturned, or NULL if there is no ELSE part.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html\n\n','mysql> SELECT CASE 1 WHEN 1 THEN \'one\'\n -> WHEN 2 THEN \'two\' ELSE \'more\' END;\n -> \'one\'\nmysql> SELECT CASE WHEN 1>0 THEN \'true\' ELSE \'false\' END;\n -> \'true\'\nmysql> SELECT CASE BINARY \'B\'\n -> WHEN \'a\' THEN 1 WHEN \'b\' THEN 2 END;\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html'),(58,'SHOW MASTER STATUS',26,'Syntax:\nSHOW MASTER STATUS\n\nThis statement provides status information about the binary log files\nof the master. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nExample:\n\nmysql> SHOW MASTER STATUS;\n+---------------+----------+--------------+------------------+\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |\n+---------------+----------+--------------+------------------+\n| mysql-bin.003 | 73 | test | manual,mysql |\n+---------------+----------+--------------+------------------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-master-status.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-master-status.html'),(59,'ADDTIME',31,'Syntax:\nADDTIME(expr1,expr2)\n\nADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time\nor datetime expression, and expr2 is a time expression.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT ADDTIME(\'2007-12-31 23:59:59.999999\', \'1 1:1:1.000002\');\n -> \'2008-01-02 01:01:01.000001\'\nmysql> SELECT ADDTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'03:00:01.999997\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(60,'SPATIAL',34,'For MyISAM tables, MySQL can create spatial indexes using syntax\nsimilar to that for creating regular indexes, but extended with the\nSPATIAL keyword. Currently, columns in spatial indexes must be declared\nNOT NULL. The following examples demonstrate how to create spatial\nindexes:\n\no With CREATE TABLE:\n\nCREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;\n\no With ALTER TABLE:\n\nALTER TABLE geom ADD SPATIAL INDEX(g);\n\no With CREATE INDEX:\n\nCREATE SPATIAL INDEX sp_index ON geom (g);\n\nFor MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage\nengines that support nonspatial indexing of spatial columns, the engine\ncreates a B-tree index. A B-tree index on spatial values will be useful\nfor exact-value lookups, but not for range scans.\n\nFor more information on indexing spatial columns, see [HELP CREATE\nINDEX].\n\nTo drop spatial indexes, use ALTER TABLE or DROP INDEX:\n\no With ALTER TABLE:\n\nALTER TABLE geom DROP INDEX g;\n\no With DROP INDEX:\n\nDROP INDEX sp_index ON geom;\n\nExample: Suppose that a table geom contains more than 32,000\ngeometries, which are stored in the column g of type GEOMETRY. The\ntable also has an AUTO_INCREMENT column fid for storing object ID\nvalues.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-indexes.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-indexes.html'),(61,'TO_SECONDS',31,'Syntax:\nTO_SECONDS(expr)\n\nGiven a date or datetime expr, returns a the number of seconds since\nthe year 0. If expr is not a valid date or datetime value, returns\nNULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TO_SECONDS(950501);\n -> 62966505600\nmysql> SELECT TO_SECONDS(\'2009-11-29\');\n -> 63426672000\nmysql> SELECT TO_SECONDS(\'2009-11-29 13:43:32\');\n -> 63426721412\nmysql> SELECT TO_SECONDS( NOW() );\n -> 63426721458\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(62,'TIMESTAMPDIFF',31,'Syntax:\nTIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)\n\nReturns datetime_expr2 - datetime_expr1, where datetime_expr1 and\ndatetime_expr2 are date or datetime expressions. One expression may be\na date and the other a datetime; a date value is treated as a datetime\nhaving the time part \'00:00:00\' where necessary. The unit for the\nresult (an integer) is given by the unit argument. The legal values for\nunit are the same as those listed in the description of the\nTIMESTAMPADD() function.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIMESTAMPDIFF(MONTH,\'2003-02-01\',\'2003-05-01\');\n -> 3\nmysql> SELECT TIMESTAMPDIFF(YEAR,\'2002-05-01\',\'2001-01-01\');\n -> -1\nmysql> SELECT TIMESTAMPDIFF(MINUTE,\'2003-02-01\',\'2003-05-01 12:05:55\');\n -> 128885\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(63,'UPPER',37,'Syntax:\nUPPER(str)\n\nReturns the string str with all characters changed to uppercase\naccording to the current character set mapping. The default is latin1\n(cp1252 West European).\n\nmysql> SELECT UPPER(\'Hej\');\n -> \'HEJ\'\n\nSee the description of LOWER() for information that also applies to\nUPPER(), such as information about how to perform lettercase conversion\nof binary strings (BINARY, VARBINARY, BLOB) for which these functions\nare ineffective.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(64,'FROM_UNIXTIME',31,'Syntax:\nFROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)\n\nReturns a representation of the unix_timestamp argument as a value in\n\'YYYY-MM-DD HH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on\nwhether the function is used in a string or numeric context. The value\nis expressed in the current time zone. unix_timestamp is an internal\ntimestamp value such as is produced by the UNIX_TIMESTAMP() function.\n\nIf format is given, the result is formatted according to the format\nstring, which is used the same way as listed in the entry for the\nDATE_FORMAT() function.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT FROM_UNIXTIME(1196440219);\n -> \'2007-11-30 10:30:19\'\nmysql> SELECT FROM_UNIXTIME(1196440219) + 0;\n -> 20071130103019.000000\nmysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),\n -> \'%Y %D %M %h:%i:%s %x\');\n -> \'2007 30th November 10:30:59 2007\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(65,'MEDIUMBLOB',22,'MEDIUMBLOB\n\nA BLOB column with a maximum length of 16,777,215 (224 - 1) bytes. Each\nMEDIUMBLOB value is stored using a 3-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(66,'SHA2',12,'Syntax:\nSHA2(str, hash_length)\n\nCalculates the SHA-2 family of hash functions (SHA-224, SHA-256,\nSHA-384, and SHA-512). The first argument is the cleartext string to be\nhashed. The second argument indicates the desired bit length of the\nresult, which must have a value of 224, 256, 384, 512, or 0 (which is\nequivalent to 256). If either argument is NULL or the hash length is\nnot one of the permitted values, the return value is NULL. Otherwise,\nthe function result is a hash value containing the desired number of\nbits. See the notes at the beginning of this section about storing hash\nvalues efficiently.\n\nAs of MySQL 5.5.6, the return value is a nonbinary string in the\nconnection character set. Before 5.5.6, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT SHA2(\'abc\', 224);\n -> \'23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7\'\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(67,'IFNULL',7,'Syntax:\nIFNULL(expr1,expr2)\n\nIf expr1 is not NULL, IFNULL() returns expr1; otherwise it returns\nexpr2. IFNULL() returns a numeric or string value, depending on the\ncontext in which it is used.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html\n\n','mysql> SELECT IFNULL(1,0);\n -> 1\nmysql> SELECT IFNULL(NULL,10);\n -> 10\nmysql> SELECT IFNULL(1/0,10);\n -> 10\nmysql> SELECT IFNULL(1/0,\'yes\');\n -> \'yes\'\n','http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html'),(68,'SHOW FUNCTION CODE',26,'Syntax:\nSHOW FUNCTION CODE func_name\n\nThis statement is similar to SHOW PROCEDURE CODE but for stored\nfunctions. See [HELP SHOW PROCEDURE CODE].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-function-code.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-function-code.html'),(69,'SHOW ERRORS',26,'Syntax:\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW COUNT(*) ERRORS\n\nThis statement is similar to SHOW WARNINGS, except that it displays\ninformation only for errors, rather than for errors, warnings, and\nnotes.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttp://dev.mysql.com/doc/refman/5.5/en/select.html.\n\nThe SHOW COUNT(*) ERRORS statement displays the number of errors. You\ncan also retrieve this number from the error_count variable:\n\nSHOW COUNT(*) ERRORS;\nSELECT @@error_count;\n\nSHOW ERRORS and error_count apply only to errors, not warnings or\nnotes. In other respects, they are similar to SHOW WARNINGS and\nwarning_count. In particular, SHOW ERRORS cannot display information\nfor more than max_error_count messages, and error_count can exceed the\nvalue of max_error_count if the number of errors exceeds\nmax_error_count.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-errors.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-errors.html'),(70,'LEAST',18,'Syntax:\nLEAST(value1,value2,...)\n\nWith two or more arguments, returns the smallest (minimum-valued)\nargument. The arguments are compared using the following rules:\n\no If any argument is NULL, the result is NULL. No comparison is needed.\n\no If the return value is used in an INTEGER context or all arguments\n are integer-valued, they are compared as integers.\n\no If the return value is used in a REAL context or all arguments are\n real-valued, they are compared as reals.\n\no If the arguments comprise a mix of numbers and strings, they are\n compared as numbers.\n\no If any argument is a nonbinary (character) string, the arguments are\n compared as nonbinary strings.\n\no In all other cases, the arguments are compared as binary strings.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT LEAST(2,0);\n -> 0\nmysql> SELECT LEAST(34.0,3.0,5.0,767.0);\n -> 3.0\nmysql> SELECT LEAST(\'B\',\'A\',\'C\');\n -> \'A\'\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(71,'=',18,'=\n\nEqual:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 = 0;\n -> 0\nmysql> SELECT \'0\' = 0;\n -> 1\nmysql> SELECT \'0.0\' = 0;\n -> 1\nmysql> SELECT \'0.01\' = 0;\n -> 0\nmysql> SELECT \'.01\' = 0.01;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(72,'REVERSE',37,'Syntax:\nREVERSE(str)\n\nReturns the string str with the order of the characters reversed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT REVERSE(\'abc\');\n -> \'cba\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(73,'ISNULL',18,'Syntax:\nISNULL(expr)\n\nIf expr is NULL, ISNULL() returns 1, otherwise it returns 0.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT ISNULL(1+1);\n -> 0\nmysql> SELECT ISNULL(1/0);\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(74,'BINARY',22,'BINARY(M)\n\nThe BINARY type is similar to the CHAR type, but stores binary byte\nstrings rather than nonbinary character strings. M represents the\ncolumn length in bytes.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(75,'BLOB DATA TYPE',22,'A BLOB is a binary large object that can hold a variable amount of\ndata. The four BLOB types are TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB.\nThese differ only in the maximum length of the values they can hold.\nThe four TEXT types are TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. These\ncorrespond to the four BLOB types and have the same maximum lengths and\nstorage requirements. See\nhttp://dev.mysql.com/doc/refman/5.5/en/storage-requirements.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/blob.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/blob.html'),(76,'BOUNDARY',36,'Boundary(g)\n\nReturns a geometry that is the closure of the combinatorial boundary of\nthe geometry value g.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(77,'CREATE USER',10,'Syntax:\nCREATE USER user_specification\n [, user_specification] ...\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nThe CREATE USER statement creates new MySQL accounts. To use it, you\nmust have the global CREATE USER privilege or the INSERT privilege for\nthe mysql database. For each account, CREATE USER creates a new row in\nthe mysql.user table and assigns the account no privileges. An error\noccurs if the account already exists.\n\nEach account name uses the format described in\nhttp://dev.mysql.com/doc/refman/5.5/en/account-names.html. For example:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nThe user specification may indicate how the user should authenticate\nwhen connecting to the server:\n\no To enable the user to connect with no password (which is insecure),\n include no IDENTIFIED BY clause:\n\nCREATE USER \'jeffrey\'@\'localhost\';\n\n In this case, the account uses built-in authentication and clients\n must provide no password.\n\no To assign a password, use IDENTIFIED BY with the literal plaintext\n password value:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To avoid specifying the plaintext password if you know its hash value\n (the value that PASSWORD() would return for the password), specify\n the hash value preceded by the keyword PASSWORD:\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED BY PASSWORD \'*90E462C37378CED12064BB3388827D2BA3A9B689\';\n\n The account uses built-in authentication and clients must match the\n given password.\n\no To authenticate the account using a specific authentication plugin,\n use IDENTIFIED WITH, where auth_plugin is the plugin name. It can be\n an unquoted name or a quoted string literal. \'auth_string\' is an\n optional quoted string literal to pass to the plugin. The plugin\n interprets the meaning of the string, so its format is plugin\n specific. Consult the documentation for a given plugin for\n information about the authentication string values it accepts.\n\nCREATE USER \'jeffrey\'@\'localhost\'\nIDENTIFIED WITH my_auth_plugin;\n\n For connections that use this account, the server invokes the named\n plugin and clients must provide credentials as required for the\n authentication method that the plugin implements. If the server\n cannot find the plugin, either at account-creation time or connect\n time, an error occurs. IDENTIFIED WITH can be used as of MySQL 5.5.7.\n\nThe IDENTIFIED BY and IDENTIFIED WITH clauses are mutually exclusive,\nso at most one of them can be specified for a given user.\n\nFor additional information about setting passwords, see\nhttp://dev.mysql.com/doc/refman/5.5/en/assigning-passwords.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-user.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-user.html'),(78,'POINT',24,'Point(x,y)\n\nConstructs a Point using its coordinates.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(79,'CURRENT_USER',17,'Syntax:\nCURRENT_USER, CURRENT_USER()\n\nReturns the user name and host name combination for the MySQL account\nthat the server used to authenticate the current client. This account\ndetermines your access privileges. The return value is a string in the\nutf8 character set.\n\nThe value of CURRENT_USER() can differ from the value of USER().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT USER();\n -> \'davida@localhost\'\nmysql> SELECT * FROM mysql.user;\nERROR 1044: Access denied for user \'\'@\'localhost\' to\ndatabase \'mysql\'\nmysql> SELECT CURRENT_USER();\n -> \'@localhost\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(80,'LCASE',37,'Syntax:\nLCASE(str)\n\nLCASE() is a synonym for LOWER().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(81,'<=',18,'Syntax:\n<=\n\nLess than or equal:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 0.1 <= 2;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(82,'SHOW PROFILES',26,'Syntax:\nSHOW PROFILES\n\nThe SHOW PROFILES statement, together with SHOW PROFILE, displays\nprofiling information that indicates resource usage for statements\nexecuted during the course of the current session. For more\ninformation, see [HELP SHOW PROFILE].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-profiles.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-profiles.html'),(83,'UPDATE',27,'Syntax:\nSingle-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_reference\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n [ORDER BY ...]\n [LIMIT row_count]\n\nMultiple-table syntax:\n\nUPDATE [LOW_PRIORITY] [IGNORE] table_references\n SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...\n [WHERE where_condition]\n\nFor the single-table syntax, the UPDATE statement updates columns of\nexisting rows in the named table with new values. The SET clause\nindicates which columns to modify and the values they should be given.\nEach value can be given as an expression, or the keyword DEFAULT to set\na column explicitly to its default value. The WHERE clause, if given,\nspecifies the conditions that identify which rows to update. With no\nWHERE clause, all rows are updated. If the ORDER BY clause is\nspecified, the rows are updated in the order that is specified. The\nLIMIT clause places a limit on the number of rows that can be updated.\n\nFor the multiple-table syntax, UPDATE updates rows in each table named\nin table_references that satisfy the conditions. In this case, ORDER BY\nand LIMIT cannot be used.\n\nwhere_condition is an expression that evaluates to true for each row to\nbe updated. For expression syntax, see\nhttp://dev.mysql.com/doc/refman/5.5/en/expressions.html.\n\ntable_references and where_condition are is specified as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/select.html.\n\nYou need the UPDATE privilege only for columns referenced in an UPDATE\nthat are actually updated. You need only the SELECT privilege for any\ncolumns that are read but not modified.\n\nThe UPDATE statement supports the following modifiers:\n\no With the LOW_PRIORITY keyword, execution of the UPDATE is delayed\n until no other clients are reading from the table. This affects only\n storage engines that use only table-level locking (such as MyISAM,\n MEMORY, and MERGE).\n\no With the IGNORE keyword, the update statement does not abort even if\n errors occur during the update. Rows for which duplicate-key\n conflicts occur are not updated. Rows for which columns are updated\n to values that would cause data conversion errors are updated to the\n closest valid values instead.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/update.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/update.html'),(84,'IS NOT NULL',18,'Syntax:\nIS NOT NULL\n\nTests whether a value is not NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;\n -> 1, 1, 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(85,'CASE STATEMENT',23,'Syntax:\nCASE case_value\n WHEN when_value THEN statement_list\n [WHEN when_value THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nOr:\n\nCASE\n WHEN search_condition THEN statement_list\n [WHEN search_condition THEN statement_list] ...\n [ELSE statement_list]\nEND CASE\n\nThe CASE statement for stored programs implements a complex conditional\nconstruct.\n\n*Note*: There is also a CASE expression, which differs from the CASE\nstatement described here. See\nhttp://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html. The\nCASE statement cannot have an ELSE NULL clause, and it is terminated\nwith END CASE instead of END.\n\nFor the first syntax, case_value is an expression. This value is\ncompared to the when_value expression in each WHEN clause until one of\nthem is equal. When an equal when_value is found, the corresponding\nTHEN clause statement_list executes. If no when_value is equal, the\nELSE clause statement_list executes, if there is one.\n\nThis syntax cannot be used to test for equality with NULL because NULL\n= NULL is false. See\nhttp://dev.mysql.com/doc/refman/5.5/en/working-with-null.html.\n\nFor the second syntax, each WHEN clause search_condition expression is\nevaluated until one is true, at which point its corresponding THEN\nclause statement_list executes. If no search_condition is equal, the\nELSE clause statement_list executes, if there is one.\n\nIf no when_value or search_condition matches the value tested and the\nCASE statement contains no ELSE clause, a Case not found for CASE\nstatement error results.\n\nEach statement_list consists of one or more SQL statements; an empty\nstatement_list is not permitted.\n\nTo handle situations where no value is matched by any WHEN clause, use\nan ELSE containing an empty BEGIN ... END block, as shown in this\nexample. (The indentation used here in the ELSE clause is for purposes\nof clarity only, and is not otherwise significant.)\n\nDELIMITER |\n\nCREATE PROCEDURE p()\n BEGIN\n DECLARE v INT DEFAULT 1;\n\n CASE v\n WHEN 2 THEN SELECT v;\n WHEN 3 THEN SELECT 0;\n ELSE\n BEGIN\n END;\n END CASE;\n END;\n |\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/case.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/case.html'),(86,'EXECUTE STATEMENT',8,'Syntax:\nEXECUTE stmt_name\n [USING @var_name [, @var_name] ...]\n\nAfter preparing a statement with PREPARE, you execute it with an\nEXECUTE statement that refers to the prepared statement name. If the\nprepared statement contains any parameter markers, you must supply a\nUSING clause that lists user variables containing the values to be\nbound to the parameters. Parameter values can be supplied only by user\nvariables, and the USING clause must name exactly as many variables as\nthe number of parameter markers in the statement.\n\nYou can execute a given prepared statement multiple times, passing\ndifferent variables to it or setting the variables to different values\nbefore each execution.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/execute.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/execute.html'),(87,'DROP INDEX',39,'Syntax:\nDROP [ONLINE|OFFLINE] INDEX index_name ON tbl_name\n\nDROP INDEX drops the index named index_name from the table tbl_name.\nThis statement is mapped to an ALTER TABLE statement to drop the index.\nSee [HELP ALTER TABLE].\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-index.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-index.html'),(88,'MATCH AGAINST',37,'Syntax:\nMATCH (col1,col2,...) AGAINST (expr [search_modifier])\n\nMySQL has support for full-text indexing and searching:\n\no A full-text index in MySQL is an index of type FULLTEXT.\n\no Full-text indexes can be used only with MyISAM tables, and can be\n created only for CHAR, VARCHAR, or TEXT columns.\n\no A FULLTEXT index definition can be given in the CREATE TABLE\n statement when a table is created, or added later using ALTER TABLE\n or CREATE INDEX.\n\no For large data sets, it is much faster to load your data into a table\n that has no FULLTEXT index and then create the index after that, than\n to load data into a table that has an existing FULLTEXT index.\n\nFull-text searching is performed using MATCH() ... AGAINST syntax.\nMATCH() takes a comma-separated list that names the columns to be\nsearched. AGAINST takes a string to search for, and an optional\nmodifier that indicates what type of search to perform. The search\nstring must be a literal string, not a variable or a column name. There\nare three types of full-text searches:\n\no A natural language search interprets the search string as a phrase in\n natural human language (a phrase in free text). There are no special\n operators. The stopword list applies. In addition, words that are\n present in 50% or more of the rows are considered common and do not\n match.\n\n Full-text searches are natural language searches if the IN NATURAL\n LANGUAGE MODE modifier is given or if no modifier is given. For more\n information, see\n http://dev.mysql.com/doc/refman/5.5/en/fulltext-natural-language.html\n .\n\no A boolean search interprets the search string using the rules of a\n special query language. The string contains the words to search for.\n It can also contain operators that specify requirements such that a\n word must be present or absent in matching rows, or that it should be\n weighted higher or lower than usual. Common words such as \"some\" or\n \"then\" are stopwords and do not match if present in the search\n string. The IN BOOLEAN MODE modifier specifies a boolean search. For\n more information, see\n http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html.\n\no A query expansion search is a modification of a natural language\n search. The search string is used to perform a natural language\n search. Then words from the most relevant rows returned by the search\n are added to the search string and the search is done again. The\n query returns the rows from the second search. The IN NATURAL\n LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION modifier\n specifies a query expansion search. For more information, see\n http://dev.mysql.com/doc/refman/5.5/en/fulltext-query-expansion.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html\n\n','mysql> SELECT id, body, MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE) AS score\n -> FROM articles WHERE MATCH (title,body) AGAINST\n -> (\'Security implications of running MySQL as root\'\n -> IN NATURAL LANGUAGE MODE);\n+----+-------------------------------------+-----------------+\n| id | body | score |\n+----+-------------------------------------+-----------------+\n| 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 |\n| 6 | When configured properly, MySQL ... | 1.3114095926285 |\n+----+-------------------------------------+-----------------+\n2 rows in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html'),(89,'CREATE EVENT',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n EVENT\n [IF NOT EXISTS]\n event_name\n ON SCHEDULE schedule\n [ON COMPLETION [NOT] PRESERVE]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n DO event_body;\n\nschedule:\n AT timestamp [+ INTERVAL interval] ...\n | EVERY interval\n [STARTS timestamp [+ INTERVAL interval] ...]\n [ENDS timestamp [+ INTERVAL interval] ...]\n\ninterval:\n quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |\n WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |\n DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}\n\nThis statement creates and schedules a new event. The event will not\nrun unless the Event Scheduler is enabled. For information about\nchecking Event Scheduler status and enabling it if necessary, see\nhttp://dev.mysql.com/doc/refman/5.5/en/events-configuration.html.\n\nCREATE EVENT requires the EVENT privilege for the schema in which the\nevent is to be created. It might also require the SUPER privilege,\ndepending on the DEFINER value, as described later in this section.\n\nThe minimum requirements for a valid CREATE EVENT statement are as\nfollows:\n\no The keywords CREATE EVENT plus an event name, which uniquely\n identifies the event in a database schema.\n\no An ON SCHEDULE clause, which determines when and how often the event\n executes.\n\no A DO clause, which contains the SQL statement to be executed by an\n event.\n\nThis is an example of a minimal CREATE EVENT statement:\n\nCREATE EVENT myevent\n ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n DO\n UPDATE myschema.mytable SET mycol = mycol + 1;\n\nThe previous statement creates an event named myevent. This event\nexecutes once---one hour following its creation---by running an SQL\nstatement that increments the value of the myschema.mytable table\'s\nmycol column by 1.\n\nThe event_name must be a valid MySQL identifier with a maximum length\nof 64 characters. Event names are not case sensitive, so you cannot\nhave two events named myevent and MyEvent in the same schema. In\ngeneral, the rules governing event names are the same as those for\nnames of stored routines. See\nhttp://dev.mysql.com/doc/refman/5.5/en/identifiers.html.\n\nAn event is associated with a schema. If no schema is indicated as part\nof event_name, the default (current) schema is assumed. To create an\nevent in a specific schema, qualify the event name with a schema using\nschema_name.event_name syntax.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-event.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-event.html'),(90,'ABS',4,'Syntax:\nABS(X)\n\nReturns the absolute value of X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ABS(2);\n -> 2\nmysql> SELECT ABS(-32);\n -> 32\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(91,'POLYFROMWKB',32,'PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])\n\nConstructs a POLYGON value using its WKB representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(92,'NOT LIKE',37,'Syntax:\nexpr NOT LIKE pat [ESCAPE \'escape_char\']\n\nThis is the same as NOT (expr LIKE pat [ESCAPE \'escape_char\']).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html'),(93,'SPACE',37,'Syntax:\nSPACE(N)\n\nReturns a string consisting of N space characters.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT SPACE(6);\n -> \' \'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(94,'MBR DEFINITION',6,'Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding\ngeometry, formed by the minimum and maximum (X,Y) coordinates:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/gis-class-geometry.html\n\n','((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n','http://dev.mysql.com/doc/refman/5.5/en/gis-class-geometry.html'),(95,'GEOMETRYCOLLECTION',24,'GeometryCollection(g1,g2,...)\n\nConstructs a GeometryCollection.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(96,'MAX',16,'Syntax:\nMAX([DISTINCT] expr)\n\nReturns the maximum value of expr. MAX() may take a string argument; in\nsuch cases, it returns the maximum string value. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html. The DISTINCT\nkeyword can be used to find the maximum of the distinct values of expr,\nhowever, this produces the same result as omitting DISTINCT.\n\nMAX() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT student_name, MIN(test_score), MAX(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(97,'CREATE FUNCTION UDF',21,'Syntax:\nCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}\n SONAME shared_library_name\n\nA user-defined function (UDF) is a way to extend MySQL with a new\nfunction that works like a native (built-in) MySQL function such as\nABS() or CONCAT().\n\nfunction_name is the name that should be used in SQL statements to\ninvoke the function. The RETURNS clause indicates the type of the\nfunction\'s return value. DECIMAL is a legal value after RETURNS, but\ncurrently DECIMAL functions return string values and should be written\nlike STRING functions.\n\nshared_library_name is the basename of the shared object file that\ncontains the code that implements the function. The file must be\nlocated in the plugin directory. This directory is given by the value\nof the plugin_dir system variable. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/udf-compiling.html.\n\nTo create a function, you must have the INSERT privilege for the mysql\ndatabase. This is necessary because CREATE FUNCTION adds a row to the\nmysql.func system table that records the function\'s name, type, and\nshared library name. If you do not have this table, you should run the\nmysql_upgrade command to create it. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-upgrade.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-function-udf.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-function-udf.html'),(98,'*',4,'Syntax:\n*\n\nMultiplication:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT 3*5;\n -> 15\nmysql> SELECT 18014398509481984*18014398509481984.0;\n -> 324518553658426726783156020576256.0\nmysql> SELECT 18014398509481984*18014398509481984;\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(99,'TIMESTAMP',22,'TIMESTAMP\n\nA timestamp. The range is \'1970-01-01 00:00:01\' UTC to \'2038-01-19\n03:14:07\' UTC. TIMESTAMP values are stored as the number of seconds\nsince the epoch (\'1970-01-01 00:00:00\' UTC). A TIMESTAMP cannot\nrepresent the value \'1970-01-01 00:00:00\' because that is equivalent to\n0 seconds from the epoch and the value 0 is reserved for representing\n\'0000-00-00 00:00:00\', the \"zero\" TIMESTAMP value.\n\nUnless specified otherwise, the first TIMESTAMP column in a table is\ndefined to be automatically set to the date and time of the most recent\nmodification if not explicitly assigned a value. This makes TIMESTAMP\nuseful for recording the timestamp of an INSERT or UPDATE operation.\nYou can also set any TIMESTAMP column to the current date and time by\nassigning it a NULL value, unless it has been defined with the NULL\nattribute to permit NULL values. The automatic initialization and\nupdating to the current date and time can be specified using DEFAULT\nCURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, as described\nin\nhttp://dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html.\n\n*Note*: The TIMESTAMP format that was used prior to MySQL 4.1 is not\nsupported in MySQL 5.5; see MySQL 3.23, 4.0, 4.1 Reference Manual for\ninformation regarding the old format.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html'),(100,'DES_DECRYPT',12,'Syntax:\nDES_DECRYPT(crypt_str[,key_str])\n\nDecrypts a string encrypted with DES_ENCRYPT(). If an error occurs,\nthis function returns NULL.\n\nThis function works only if MySQL has been configured with SSL support.\nSee http://dev.mysql.com/doc/refman/5.5/en/ssl-connections.html.\n\nIf no key_str argument is given, DES_DECRYPT() examines the first byte\nof the encrypted string to determine the DES key number that was used\nto encrypt the original string, and then reads the key from the DES key\nfile to decrypt the message. For this to work, the user must have the\nSUPER privilege. The key file can be specified with the --des-key-file\nserver option.\n\nIf you pass this function a key_str argument, that string is used as\nthe key for decrypting the message.\n\nIf the crypt_str argument does not appear to be an encrypted string,\nMySQL returns the given crypt_str.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(101,'CACHE INDEX',26,'Syntax:\nCACHE INDEX\n tbl_index_list [, tbl_index_list] ...\n [PARTITION (partition_list | ALL)]\n IN key_cache_name\n\ntbl_index_list:\n tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe CACHE INDEX statement assigns table indexes to a specific key\ncache. It is used only for MyISAM tables. After the indexes have been\nassigned, they can be preloaded into the cache if desired with LOAD\nINDEX INTO CACHE.\n\nThe following statement assigns indexes from the tables t1, t2, and t3\nto the key cache named hot_cache:\n\nmysql> CACHE INDEX t1, t2, t3 IN hot_cache;\n+---------+--------------------+----------+----------+\n| Table | Op | Msg_type | Msg_text |\n+---------+--------------------+----------+----------+\n| test.t1 | assign_to_keycache | status | OK |\n| test.t2 | assign_to_keycache | status | OK |\n| test.t3 | assign_to_keycache | status | OK |\n+---------+--------------------+----------+----------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/cache-index.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/cache-index.html'),(102,'ENDPOINT',13,'EndPoint(ls)\n\nReturns the Point that is the endpoint of the LineString value ls.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions\n\n','mysql> SET @ls = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT AsText(EndPoint(GeomFromText(@ls)));\n+-------------------------------------+\n| AsText(EndPoint(GeomFromText(@ls))) |\n+-------------------------------------+\n| POINT(3 3) |\n+-------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions'),(103,'COMPRESS',12,'Syntax:\nCOMPRESS(string_to_compress)\n\nCompresses a string and returns the result as a binary string. This\nfunction requires MySQL to have been compiled with a compression\nlibrary such as zlib. Otherwise, the return value is always NULL. The\ncompressed string can be uncompressed with UNCOMPRESS().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT LENGTH(COMPRESS(REPEAT(\'a\',1000)));\n -> 21\nmysql> SELECT LENGTH(COMPRESS(\'\'));\n -> 0\nmysql> SELECT LENGTH(COMPRESS(\'a\'));\n -> 13\nmysql> SELECT LENGTH(COMPRESS(REPEAT(\'a\',16)));\n -> 15\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(104,'INSERT',27,'Syntax:\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n {VALUES | VALUE} ({expr | DEFAULT},...),(...),...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name\n SET col_name={expr | DEFAULT}, ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nOr:\n\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE\n col_name=expr\n [, col_name=expr] ... ]\n\nINSERT inserts new rows into an existing table. The INSERT ... VALUES\nand INSERT ... SET forms of the statement insert rows based on\nexplicitly specified values. The INSERT ... SELECT form inserts rows\nselected from another table or tables. INSERT ... SELECT is discussed\nfurther in [HELP INSERT SELECT].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/insert.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/insert.html'),(105,'COUNT',16,'Syntax:\nCOUNT(expr)\n\nReturns a count of the number of non-NULL values of expr in the rows\nretrieved by a SELECT statement. The result is a BIGINT value.\n\nCOUNT() returns 0 if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT student.student_name,COUNT(*)\n -> FROM student,course\n -> WHERE student.student_id=course.student_id\n -> GROUP BY student_name;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(106,'HANDLER',27,'Syntax:\nHANDLER tbl_name OPEN [ [AS] alias]\n\nHANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }\n [ WHERE where_condition ] [LIMIT ... ]\nHANDLER tbl_name READ { FIRST | NEXT }\n [ WHERE where_condition ] [LIMIT ... ]\n\nHANDLER tbl_name CLOSE\n\nThe HANDLER statement provides direct access to table storage engine\ninterfaces. It is available for MyISAM and InnoDB tables.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/handler.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/handler.html'),(107,'MLINEFROMTEXT',3,'MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])\n\nConstructs a MULTILINESTRING value using its WKT representation and\nSRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(108,'GEOMCOLLFROMWKB',32,'GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkb[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKB representation and\nSRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(109,'HELP_DATE',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25\n','',''),(110,'RENAME TABLE',39,'Syntax:\nRENAME TABLE tbl_name TO new_tbl_name\n [, tbl_name2 TO new_tbl_name2] ...\n\nThis statement renames one or more tables.\n\nThe rename operation is done atomically, which means that no other\nsession can access any of the tables while the rename is running. For\nexample, if you have an existing table old_table, you can create\nanother table new_table that has the same structure but is empty, and\nthen replace the existing table with the empty one as follows (assuming\nthat backup_table does not already exist):\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/rename-table.html\n\n','CREATE TABLE new_table (...);\nRENAME TABLE old_table TO backup_table, new_table TO old_table;\n','http://dev.mysql.com/doc/refman/5.5/en/rename-table.html'),(111,'BOOLEAN',22,'BOOL, BOOLEAN\n\nThese types are synonyms for TINYINT(1). A value of zero is considered\nfalse. Nonzero values are considered true:\n\nmysql> SELECT IF(0, \'true\', \'false\');\n+------------------------+\n| IF(0, \'true\', \'false\') |\n+------------------------+\n| false |\n+------------------------+\n\nmysql> SELECT IF(1, \'true\', \'false\');\n+------------------------+\n| IF(1, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nmysql> SELECT IF(2, \'true\', \'false\');\n+------------------------+\n| IF(2, \'true\', \'false\') |\n+------------------------+\n| true |\n+------------------------+\n\nHowever, the values TRUE and FALSE are merely aliases for 1 and 0,\nrespectively, as shown here:\n\nmysql> SELECT IF(0 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(0 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| true |\n+--------------------------------+\n\nmysql> SELECT IF(1 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(1 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| true |\n+-------------------------------+\n\nmysql> SELECT IF(2 = TRUE, \'true\', \'false\');\n+-------------------------------+\n| IF(2 = TRUE, \'true\', \'false\') |\n+-------------------------------+\n| false |\n+-------------------------------+\n\nmysql> SELECT IF(2 = FALSE, \'true\', \'false\');\n+--------------------------------+\n| IF(2 = FALSE, \'true\', \'false\') |\n+--------------------------------+\n| false |\n+--------------------------------+\n\nThe last two statements display the results shown because 2 is equal to\nneither 1 nor 0.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(112,'DEFAULT',14,'Syntax:\nDEFAULT(col_name)\n\nReturns the default value for a table column. An error results if the\ncolumn has no default value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(113,'MOD',4,'Syntax:\nMOD(N,M), N % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT MOD(234, 10);\n -> 4\nmysql> SELECT 253 % 7;\n -> 1\nmysql> SELECT MOD(29,9);\n -> 2\nmysql> SELECT 29 MOD 9;\n -> 2\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(114,'TINYTEXT',22,'TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 255 (28 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TINYTEXT value is stored using a 1-byte length prefix\nthat indicates the number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(115,'OPTIMIZE TABLE',20,'Syntax:\nOPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nOPTIMIZE TABLE should be used if you have deleted a large part of a\ntable or if you have made many changes to a table with variable-length\nrows (tables that have VARCHAR, VARBINARY, BLOB, or TEXT columns).\nDeleted rows are maintained in a linked list and subsequent INSERT\noperations reuse old row positions. You can use OPTIMIZE TABLE to\nreclaim the unused space and to defragment the data file. After\nextensive changes to a table, this statement may also improve\nperformance of statements that use the table, sometimes significantly.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nOPTIMIZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... OPTIMIZE PARTITION to optimize one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/optimize-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/optimize-table.html'),(116,'DECODE',12,'Syntax:\nDECODE(crypt_str,pass_str)\n\nDecrypts the encrypted string crypt_str using pass_str as the password.\ncrypt_str should be a string returned from ENCODE().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(117,'<=>',18,'Syntax:\n<=>\n\nNULL-safe equal. This operator performs an equality comparison like the\n= operator, but returns 1 rather than NULL if both operands are NULL,\nand 0 rather than NULL if one operand is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\n -> 1, 1, 0\nmysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;\n -> 1, NULL, NULL\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(118,'HELP STATEMENT',28,'Syntax:\nHELP \'search_string\'\n\nThe HELP statement returns online information from the MySQL Reference\nmanual. Its proper operation requires that the help tables in the mysql\ndatabase be initialized with help topic information (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-side-help-support.html).\n\nThe HELP statement searches the help tables for the given search string\nand displays the result of the search. The search string is not case\nsensitive.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/help.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/help.html'),(119,'RESET',26,'Syntax:\nRESET reset_option [, reset_option] ...\n\nThe RESET statement is used to clear the state of various server\noperations. You must have the RELOAD privilege to execute RESET.\n\nRESET acts as a stronger version of the FLUSH statement. See [HELP\nFLUSH].\n\nThe RESET statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/reset.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/reset.html'),(120,'GET_LOCK',14,'Syntax:\nGET_LOCK(str,timeout)\n\nTries to obtain a lock with a name given by the string str, using a\ntimeout of timeout seconds. Returns 1 if the lock was obtained\nsuccessfully, 0 if the attempt timed out (for example, because another\nclient has previously locked the name), or NULL if an error occurred\n(such as running out of memory or the thread was killed with mysqladmin\nkill). If you have a lock obtained with GET_LOCK(), it is released when\nyou execute RELEASE_LOCK(), execute a new GET_LOCK(), or your\nconnection terminates (either normally or abnormally). Locks obtained\nwith GET_LOCK() do not interact with transactions. That is, committing\na transaction does not release any such locks obtained during the\ntransaction.\n\nThis function can be used to implement application locks or to simulate\nrecord locks. Names are locked on a server-wide basis. If a name has\nbeen locked by one client, GET_LOCK() blocks any request by another\nclient for a lock with the same name. This enables clients that agree\non a given lock name to use the name to perform cooperative advisory\nlocking. But be aware that it also enables a client that is not among\nthe set of cooperating clients to lock a name, either inadvertently or\ndeliberately, and thus prevent any of the cooperating clients from\nlocking that name. One way to reduce the likelihood of this is to use\nlock names that are database-specific or application-specific. For\nexample, use lock names of the form db_name.str or app_name.str.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> SELECT GET_LOCK(\'lock1\',10);\n -> 1\nmysql> SELECT IS_FREE_LOCK(\'lock2\');\n -> 1\nmysql> SELECT GET_LOCK(\'lock2\',10);\n -> 1\nmysql> SELECT RELEASE_LOCK(\'lock2\');\n -> 1\nmysql> SELECT RELEASE_LOCK(\'lock1\');\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(121,'UCASE',37,'Syntax:\nUCASE(str)\n\nUCASE() is a synonym for UPPER().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(122,'SHOW BINLOG EVENTS',26,'Syntax:\nSHOW BINLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the binary log. If you do not specify \'log_name\',\nthe first binary log is displayed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-binlog-events.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-binlog-events.html'),(123,'MPOLYFROMWKB',32,'MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])\n\nConstructs a MULTIPOLYGON value using its WKB representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(124,'ITERATE',23,'Syntax:\nITERATE label\n\nITERATE can appear only within LOOP, REPEAT, and WHILE statements.\nITERATE means \"start the loop again.\"\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/iterate.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/iterate.html'),(125,'DO',27,'Syntax:\nDO expr [, expr] ...\n\nDO executes the expressions but does not return any results. In most\nrespects, DO is shorthand for SELECT expr, ..., but has the advantage\nthat it is slightly faster when you do not care about the result.\n\nDO is useful primarily with functions that have side effects, such as\nRELEASE_LOCK().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/do.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/do.html'),(126,'CURTIME',31,'Syntax:\nCURTIME()\n\nReturns the current time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context. The value is expressed in the current time zone.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT CURTIME();\n -> \'23:50:26\'\nmysql> SELECT CURTIME() + 0;\n -> 235026.000000\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(127,'CHAR_LENGTH',37,'Syntax:\nCHAR_LENGTH(str)\n\nReturns the length of the string str, measured in characters. A\nmulti-byte character counts as a single character. This means that for\na string containing five 2-byte characters, LENGTH() returns 10,\nwhereas CHAR_LENGTH() returns 5.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(128,'BIGINT',22,'BIGINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA large integer. The signed range is -9223372036854775808 to\n9223372036854775807. The unsigned range is 0 to 18446744073709551615.\n\nSERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(129,'SET',26,'Syntax:\nSET variable_assignment [, variable_assignment] ...\n\nvariable_assignment:\n user_var_name = expr\n | [GLOBAL | SESSION] system_var_name = expr\n | [@@global. | @@session. | @@]system_var_name = expr\n\nThe SET statement assigns values to different types of variables that\naffect the operation of the server or your client. Older versions of\nMySQL employed SET OPTION, but this syntax is deprecated in favor of\nSET without OPTION.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/set-statement.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/set-statement.html'),(130,'LOAD XML',27,'Syntax:\nLOAD XML [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE [db_name.]tbl_name\n [CHARACTER SET charset_name]\n [ROWS IDENTIFIED BY \'\']\n [IGNORE number {LINES | ROWS}]\n [(column_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD XML statement reads data from an XML file into a table. The\nfile_name must be given as a literal string. The tagname in the\noptional ROWS IDENTIFIED BY clause must also be given as a literal\nstring, and must be surrounded by angle brackets (< and >).\n\nLOAD XML acts as the complement of running the mysql client in XML\noutput mode (that is, starting the client with the --xml option). To\nwrite data from a table to an XML file, use a command such as the\nfollowing one from the system shell:\n\nshell> mysql --xml -e \'SELECT * FROM mytable\' > file.xml\n\nTo read the file back into a table, use LOAD XML INFILE. By default,\nthe element is considered to be the equivalent of a database\ntable row; this can be changed using the ROWS IDENTIFIED BY clause.\n\nThis statement supports three different XML formats:\n\no Column names as attributes and column values as attribute values:\n\n\n\no Column names as tags and column values as the content of these tags:\n\n\n value1\n value2\n\n\no Column names are the name attributes of tags, and values are\n the contents of these tags:\n\n\n value1\n value2\n\n\n This is the format used by other MySQL tools, such as mysqldump.\n\nAll 3 formats can be used in the same XML file; the import routine\nautomatically detects the format for each row and interprets it\ncorrectly. Tags are matched based on the tag or attribute name and the\ncolumn name.\n\nThe following clauses work essentially the same way for LOAD XML as\nthey do for LOAD DATA:\n\no LOW_PRIORITY or CONCURRENT\n\no LOCAL\n\no REPLACE or IGNORE\n\no CHARACTER SET\n\no (column_or_user_var,...)\n\no SET\n\nSee [HELP LOAD DATA], for more information about these clauses.\n\nThe IGNORE number LINES or IGNORE number ROWS clause causes the first\nnumber rows in the XML file to be skipped. It is analogous to the LOAD\nDATA statement\'s IGNORE ... LINES clause.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/load-xml.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/load-xml.html'),(131,'CONV',4,'Syntax:\nCONV(N,from_base,to_base)\n\nConverts numbers between different number bases. Returns a string\nrepresentation of the number N, converted from base from_base to base\nto_base. Returns NULL if any argument is NULL. The argument N is\ninterpreted as an integer, but may be specified as an integer or a\nstring. The minimum base is 2 and the maximum base is 36. If to_base is\na negative number, N is regarded as a signed number. Otherwise, N is\ntreated as unsigned. CONV() works with 64-bit precision.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT CONV(\'a\',16,2);\n -> \'1010\'\nmysql> SELECT CONV(\'6E\',18,8);\n -> \'172\'\nmysql> SELECT CONV(-17,10,-18);\n -> \'-H\'\nmysql> SELECT CONV(10+\'10\'+\'10\'+0xa,10,10);\n -> \'40\'\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(132,'DATE',22,'DATE\n\nA date. The supported range is \'1000-01-01\' to \'9999-12-31\'. MySQL\ndisplays DATE values in \'YYYY-MM-DD\' format, but permits assignment of\nvalues to DATE columns using either strings or numbers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html'),(133,'ASSIGN-VALUE',15,'Syntax:\n:=\n\nAssignment operator. Causes the user variable on the left hand side of\nthe operator to take on the value to its right. The value on the right\nhand side may be a literal value, another variable storing a value, or\nany legal expression that yields a scalar value, including the result\nof a query (provided that this value is a scalar value). You can\nperform multiple assignments in the same SET statement. You can perform\nmultiple assignments in the same statement-\n\nUnlike =, the := operator is never interpreted as a comparison\noperator. This means you can use := in any valid SQL statement (not\njust in SET statements) to assign a value to a variable.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/assignment-operators.html\n\n','mysql> SELECT @var1, @var2;\n -> NULL, NULL\nmysql> SELECT @var1 := 1, @var2;\n -> 1, NULL\nmysql> SELECT @var1, @var2;\n -> 1, NULL\nmysql> SELECT @var1, @var2 := @var1;\n -> 1, 1\nmysql> SELECT @var1, @var2;\n -> 1, 1\n\nmysql> SELECT @var1:=COUNT(*) FROM t1;\n -> 4\nmysql> SELECT @var1;\n -> 4\n','http://dev.mysql.com/doc/refman/5.5/en/assignment-operators.html'),(134,'SHOW OPEN TABLES',26,'Syntax:\nSHOW OPEN TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW OPEN TABLES lists the non-TEMPORARY tables that are currently open\nin the table cache. See\nhttp://dev.mysql.com/doc/refman/5.5/en/table-cache.html. The FROM\nclause, if present, restricts the tables shown to those present in the\ndb_name database. The LIKE clause, if present, indicates which table\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-open-tables.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-open-tables.html'),(135,'EXTRACT',31,'Syntax:\nEXTRACT(unit FROM date)\n\nThe EXTRACT() function uses the same kinds of unit specifiers as\nDATE_ADD() or DATE_SUB(), but extracts parts from the date rather than\nperforming date arithmetic.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT EXTRACT(YEAR FROM \'2009-07-02\');\n -> 2009\nmysql> SELECT EXTRACT(YEAR_MONTH FROM \'2009-07-02 01:02:03\');\n -> 200907\nmysql> SELECT EXTRACT(DAY_MINUTE FROM \'2009-07-02 01:02:03\');\n -> 20102\nmysql> SELECT EXTRACT(MICROSECOND\n -> FROM \'2003-01-02 10:30:00.000123\');\n -> 123\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(136,'ENCRYPT',12,'Syntax:\nENCRYPT(str[,salt])\n\nEncrypts str using the Unix crypt() system call and returns a binary\nstring. The salt argument must be a string with at least two characters\nor the result will be NULL. If no salt argument is given, a random\nvalue is used.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT ENCRYPT(\'hello\');\n -> \'VxuFAJXVARROc\'\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(137,'SHOW STATUS',26,'Syntax:\nSHOW [GLOBAL | SESSION] STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW STATUS provides server status information. This information also\ncan be obtained using the mysqladmin extended-status command. The LIKE\nclause, if present, indicates which variable names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in http://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\nThis statement does not require any privilege. It requires only the\nability to connect to the server.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern:\n\nmysql> SHOW STATUS LIKE \'Key%\';\n+--------------------+----------+\n| Variable_name | Value |\n+--------------------+----------+\n| Key_blocks_used | 14955 |\n| Key_read_requests | 96854827 |\n| Key_reads | 162040 |\n| Key_write_requests | 7589728 |\n| Key_writes | 3813196 |\n+--------------------+----------+\n\nWith the GLOBAL modifier, SHOW STATUS displays the status values for\nall connections to MySQL. With SESSION, it displays the status values\nfor the current connection. If no modifier is present, the default is\nSESSION. LOCAL is a synonym for SESSION.\n\nSome status variables have only a global value. For these, you get the\nsame value for both GLOBAL and SESSION. The scope for each status\nvariable is listed at\nhttp://dev.mysql.com/doc/refman/5.5/en/server-status-variables.html.\n\nEach invocation of the SHOW STATUS statement uses an internal temporary\ntable and increments the global Created_tmp_tables value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-status.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-status.html'),(138,'EXTRACTVALUE',37,'Syntax:\nExtractValue(xml_frag, xpath_expr)\n\nExtractValue() takes two string arguments, a fragment of XML markup\nxml_frag and an XPath expression xpath_expr (also known as a locator);\nit returns the text (CDATA) of the first text node which is a child of\nthe elements or elements matched by the XPath expression. In MySQL 5.5,\nthe XPath expression can contain at most 127 characters. (This\nlimitation is lifted in MySQL 5.6.)\n\nUsing this function is the equivalent of performing a match using the\nxpath_expr after appending /text(). In other words,\nExtractValue(\'Sakila\', \'/a/b\') and\nExtractValue(\'Sakila\', \'/a/b/text()\') produce the same\nresult.\n\nIf multiple matches are found, the content of the first child text node\nof each matching element is returned (in the order matched) as a\nsingle, space-delimited string.\n\nIf no matching text node is found for the expression (including the\nimplicit /text())---for whatever reason, as long as xpath_expr is\nvalid, and xml_frag consists of elements which are properly nested and\nclosed---an empty string is returned. No distinction is made between a\nmatch on an empty element and no match at all. This is by design.\n\nIf you need to determine whether no matching element was found in\nxml_frag or such an element was found but contained no child text\nnodes, you should test the result of an expression that uses the XPath\ncount() function. For example, both of these statements return an empty\nstring, as shown here:\n\nmysql> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nmysql> SELECT ExtractValue(\'\', \'/a/b\');\n+-------------------------------------+\n| ExtractValue(\'\', \'/a/b\') |\n+-------------------------------------+\n| |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nHowever, you can determine whether there was actually a matching\nelement using the following:\n\nmysql> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 1 |\n+-------------------------------------+\n1 row in set (0.00 sec)\n\nmysql> SELECT ExtractValue(\'\', \'count(/a/b)\');\n+-------------------------------------+\n| ExtractValue(\'\', \'count(/a/b)\') |\n+-------------------------------------+\n| 0 |\n+-------------------------------------+\n1 row in set (0.01 sec)\n\n*Important*: ExtractValue() returns only CDATA, and does not return any\ntags that might be contained within a matching tag, nor any of their\ncontent (see the result returned as val1 in the following example).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/xml-functions.html\n\n','mysql> SELECT\n -> ExtractValue(\'cccddd\', \'/a\') AS val1,\n -> ExtractValue(\'cccddd\', \'/a/b\') AS val2,\n -> ExtractValue(\'cccddd\', \'//b\') AS val3,\n -> ExtractValue(\'cccddd\', \'/b\') AS val4,\n -> ExtractValue(\'cccdddeee\', \'//b\') AS val5;\n\n+------+------+------+------+---------+\n| val1 | val2 | val3 | val4 | val5 |\n+------+------+------+------+---------+\n| ccc | ddd | ddd | | ddd eee |\n+------+------+------+------+---------+\n','http://dev.mysql.com/doc/refman/5.5/en/xml-functions.html'),(139,'OLD_PASSWORD',12,'Syntax:\nOLD_PASSWORD(str)\n\nOLD_PASSWORD() was added when the implementation of PASSWORD() was\nchanged in MySQL 4.1 to improve security. OLD_PASSWORD() returns the\nvalue of the pre-4.1 implementation of PASSWORD() as a string, and is\nintended to permit you to reset passwords for any pre-4.1 clients that\nneed to connect to your version 5.5 MySQL server without locking them\nout. See http://dev.mysql.com/doc/refman/5.5/en/password-hashing.html.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(140,'FORMAT',37,'Syntax:\nFORMAT(X,D[,locale])\n\nFormats the number X to a format like \'#,###,###.##\', rounded to D\ndecimal places, and returns the result as a string. If D is 0, the\nresult has no decimal point or fractional part.\n\nThe optional third parameter enables a locale to be specified to be\nused for the result number\'s decimal point, thousands separator, and\ngrouping between separators. Permissible locale values are the same as\nthe legal values for the lc_time_names system variable (see\nhttp://dev.mysql.com/doc/refman/5.5/en/locale-support.html). If no\nlocale is specified, the default is \'en_US\'.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT FORMAT(12332.123456, 4);\n -> \'12,332.1235\'\nmysql> SELECT FORMAT(12332.1,4);\n -> \'12,332.1000\'\nmysql> SELECT FORMAT(12332.2,0);\n -> \'12,332\'\nmysql> SELECT FORMAT(12332.2,2,\'de_DE\');\n -> \'12.332,20\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(141,'||',15,'Syntax:\nOR, ||\n\nLogical OR. When both operands are non-NULL, the result is 1 if any\noperand is nonzero, and 0 otherwise. With a NULL operand, the result is\n1 if the other operand is nonzero, and NULL otherwise. If both operands\nare NULL, the result is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html\n\n','mysql> SELECT 1 || 1;\n -> 1\nmysql> SELECT 1 || 0;\n -> 1\nmysql> SELECT 0 || 0;\n -> 0\nmysql> SELECT 0 || NULL;\n -> NULL\nmysql> SELECT 1 || NULL;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html'),(142,'BIT_LENGTH',37,'Syntax:\nBIT_LENGTH(str)\n\nReturns the length of the string str in bits.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT BIT_LENGTH(\'text\');\n -> 32\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(143,'EXTERIORRING',2,'ExteriorRing(poly)\n\nReturns the exterior ring of the Polygon value poly as a LineString.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions\n\n','mysql> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nmysql> SELECT AsText(ExteriorRing(GeomFromText(@poly)));\n+-------------------------------------------+\n| AsText(ExteriorRing(GeomFromText(@poly))) |\n+-------------------------------------------+\n| LINESTRING(0 0,0 3,3 3,3 0,0 0) |\n+-------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions'),(144,'GEOMFROMWKB',32,'GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkb[,srid])\n\nConstructs a geometry value of any type using its WKB representation\nand SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(145,'SHOW SLAVE HOSTS',26,'Syntax:\nSHOW SLAVE HOSTS\n\nDisplays a list of replication slaves currently registered with the\nmaster. (Before MySQL 5.5.3, only slaves started with the\n--report-host=host_name option are visible in this list.)\n\nThe list is displayed on any server (not just the master server). The\noutput looks like this:\n\nmysql> SHOW SLAVE HOSTS;\n+------------+-----------+------+-----------+\n| Server_id | Host | Port | Master_id |\n+------------+-----------+------+-----------+\n| 192168010 | iconnect2 | 3306 | 192168011 |\n| 1921680101 | athena | 3306 | 192168011 |\n+------------+-----------+------+-----------+\n\no Server_id: The unique server ID of the slave server, as configured in\n the server\'s option file, or on the command line with\n --server-id=value.\n\no Host: The host name of the slave server, as configured in the\n server\'s option file, or on the command line with\n --report-host=host_name. Note that this can differ from the machine\n name as configured in the operating system.\n\no Port: The port the slave server is listening on.\n\n In MySQL 5.5.23 and later, a zero in this column means that the slave\n port (--report-port) was not set. Prior to MySQL 5.5.23, 3306 was\n used as the default in such cases (Bug #13333431).\n\no Master_id: The unique server ID of the master server that the slave\n server is replicating from.\n\nSome MySQL versions report another variable, Rpl_recovery_rank. This\nvariable was never used, and was removed in MySQL 5.5.3. (Bug #13963)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-slave-hosts.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-slave-hosts.html'),(146,'START TRANSACTION',8,'Syntax:\nSTART TRANSACTION [WITH CONSISTENT SNAPSHOT]\nBEGIN [WORK]\nCOMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]\nSET autocommit = {0 | 1}\n\nThese statements provide control over use of transactions:\n\no START TRANSACTION or BEGIN start a new transaction.\n\no COMMIT commits the current transaction, making its changes permanent.\n\no ROLLBACK rolls back the current transaction, canceling its changes.\n\no SET autocommit disables or enables the default autocommit mode for\n the current session.\n\nBy default, MySQL runs with autocommit mode enabled. This means that as\nsoon as you execute a statement that updates (modifies) a table, MySQL\nstores the update on disk to make it permanent. The change cannot be\nrolled back.\n\nTo disable autocommit mode implicitly for a single series of\nstatements, use the START TRANSACTION statement:\n\nSTART TRANSACTION;\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\nUPDATE table2 SET summary=@A WHERE type=1;\nCOMMIT;\n\nWith START TRANSACTION, autocommit remains disabled until you end the\ntransaction with COMMIT or ROLLBACK. The autocommit mode then reverts\nto its previous state.\n\nYou can also begin a transaction like this:\n\nSTART TRANSACTION WITH CONSISTENT SNAPSHOT;\n\nThe WITH CONSISTENT SNAPSHOT option starts a consistent read for\nstorage engines that are capable of it. This applies only to InnoDB.\nThe effect is the same as issuing a START TRANSACTION followed by a\nSELECT from any InnoDB table. See\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html. The\nWITH CONSISTENT SNAPSHOT option does not change the current transaction\nisolation level, so it provides a consistent snapshot only if the\ncurrent isolation level is one that permits consistent read (REPEATABLE\nREAD or SERIALIZABLE).\n\n*Important*: Many APIs used for writing MySQL client applications (such\nas JDBC) provide their own methods for starting transactions that can\n(and sometimes should) be used instead of sending a START TRANSACTION\nstatement from the client. See\nhttp://dev.mysql.com/doc/refman/5.5/en/connectors-apis.html, or the\ndocumentation for your API, for more information.\n\nTo disable autocommit mode explicitly, use the following statement:\n\nSET autocommit=0;\n\nAfter disabling autocommit mode by setting the autocommit variable to\nzero, changes to transaction-safe tables (such as those for InnoDB or\nNDBCLUSTER) are not made permanent immediately. You must use COMMIT to\nstore your changes to disk or ROLLBACK to ignore the changes.\n\nautocommit is a session variable and must be set for each session. To\ndisable autocommit mode for each new connection, see the description of\nthe autocommit system variable at\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nBEGIN and BEGIN WORK are supported as aliases of START TRANSACTION for\ninitiating a transaction. START TRANSACTION is standard SQL syntax and\nis the recommended way to start an ad-hoc transaction.\n\nThe BEGIN statement differs from the use of the BEGIN keyword that\nstarts a BEGIN ... END compound statement. The latter does not begin a\ntransaction. See [HELP BEGIN END].\n\n*Note*: Within all stored programs (stored procedures and functions,\ntriggers, and events), the parser treats BEGIN [WORK] as the beginning\nof a BEGIN ... END block. Begin a transaction in this context with\nSTART TRANSACTION instead.\n\nThe optional WORK keyword is supported for COMMIT and ROLLBACK, as are\nthe CHAIN and RELEASE clauses. CHAIN and RELEASE can be used for\nadditional control over transaction completion. The value of the\ncompletion_type system variable determines the default completion\nbehavior. See\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nThe AND CHAIN clause causes a new transaction to begin as soon as the\ncurrent one ends, and the new transaction has the same isolation level\nas the just-terminated transaction. The RELEASE clause causes the\nserver to disconnect the current client session after terminating the\ncurrent transaction. Including the NO keyword suppresses CHAIN or\nRELEASE completion, which can be useful if the completion_type system\nvariable is set to cause chaining or release completion by default.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/commit.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/commit.html'),(147,'BETWEEN AND',18,'Syntax:\nexpr BETWEEN min AND max\n\nIf expr is greater than or equal to min and expr is less than or equal\nto max, BETWEEN returns 1, otherwise it returns 0. This is equivalent\nto the expression (min <= expr AND expr <= max) if all the arguments\nare of the same type. Otherwise type conversion takes place according\nto the rules described in\nhttp://dev.mysql.com/doc/refman/5.5/en/type-conversion.html, but\napplied to all the three arguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;\n -> 1, 0\nmysql> SELECT 1 BETWEEN 2 AND 3;\n -> 0\nmysql> SELECT \'b\' BETWEEN \'a\' AND \'c\';\n -> 1\nmysql> SELECT 2 BETWEEN 2 AND \'3\';\n -> 1\nmysql> SELECT 2 BETWEEN 2 AND \'x-3\';\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(148,'MULTIPOLYGON',24,'MultiPolygon(poly1,poly2,...)\n\nConstructs a MultiPolygon value from a set of Polygon or WKB Polygon\narguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(149,'TIME_FORMAT',31,'Syntax:\nTIME_FORMAT(time,format)\n\nThis is used like the DATE_FORMAT() function, but the format string may\ncontain format specifiers only for hours, minutes, seconds, and\nmicroseconds. Other specifiers produce a NULL value or 0.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIME_FORMAT(\'100:00:00\', \'%H %k %h %I %l\');\n -> \'100 100 04 04 4\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(150,'LEFT',37,'Syntax:\nLEFT(str,len)\n\nReturns the leftmost len characters from the string str, or NULL if any\nargument is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT LEFT(\'foobarbar\', 5);\n -> \'fooba\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(151,'FLUSH QUERY CACHE',26,'You can defragment the query cache to better utilize its memory with\nthe FLUSH QUERY CACHE statement. The statement does not remove any\nqueries from the cache.\n\nThe RESET QUERY CACHE statement removes all query results from the\nquery cache. The FLUSH TABLES statement also does this.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/query-cache-status-and-maintenance.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/query-cache-status-and-maintenance.html'),(152,'SET DATA TYPE',22,'SET(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA set. A string object that can have zero or more values, each of which\nmust be chosen from the list of values \'value1\', \'value2\', ... A SET\ncolumn can have a maximum of 64 members. SET values are represented\ninternally as integers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(153,'RAND',4,'Syntax:\nRAND(), RAND(N)\n\nReturns a random floating-point value v in the range 0 <= v < 1.0. If a\nconstant integer argument N is specified, it is used as the seed value,\nwhich produces a repeatable sequence of column values. In the following\nexample, note that the sequences of values produced by RAND(3) is the\nsame both places where it occurs.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> CREATE TABLE t (i INT);\nQuery OK, 0 rows affected (0.42 sec)\n\nmysql> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nmysql> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.61914388706828 |\n| 2 | 0.93845168309142 |\n| 3 | 0.83482678498591 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nmysql> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nmysql> SELECT i, RAND() FROM t;\n+------+------------------+\n| i | RAND() |\n+------+------------------+\n| 1 | 0.35877890638893 |\n| 2 | 0.28941420772058 |\n| 3 | 0.37073435016976 |\n+------+------------------+\n3 rows in set (0.00 sec)\n\nmysql> SELECT i, RAND(3) FROM t;\n+------+------------------+\n| i | RAND(3) |\n+------+------------------+\n| 1 | 0.90576975597606 |\n| 2 | 0.37307905813035 |\n| 3 | 0.14808605345719 |\n+------+------------------+\n3 rows in set (0.01 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(154,'RPAD',37,'Syntax:\nRPAD(str,len,padstr)\n\nReturns the string str, right-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT RPAD(\'hi\',5,\'?\');\n -> \'hi???\'\nmysql> SELECT RPAD(\'hi\',1,\'?\');\n -> \'h\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(155,'CREATE DATABASE',39,'Syntax:\nCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n [create_specification] ...\n\ncreate_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nCREATE DATABASE creates a database with the given name. To use this\nstatement, you need the CREATE privilege for the database. CREATE\nSCHEMA is a synonym for CREATE DATABASE.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-database.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-database.html'),(156,'DEC',22,'DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED]\n[ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nThese types are synonyms for DECIMAL. The FIXED synonym is available\nfor compatibility with other database systems.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(157,'VAR_POP',16,'Syntax:\nVAR_POP(expr)\n\nReturns the population standard variance of expr. It considers rows as\nthe whole population, not as a sample, so it has the number of rows as\nthe denominator. You can also use VARIANCE(), which is equivalent but\nis not standard SQL.\n\nVAR_POP() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(158,'ELT',37,'Syntax:\nELT(N,str1,str2,str3,...)\n\nReturns str1 if N = 1, str2 if N = 2, and so on. Returns NULL if N is\nless than 1 or greater than the number of arguments. ELT() is the\ncomplement of FIELD().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT ELT(1, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'ej\'\nmysql> SELECT ELT(4, \'ej\', \'Heja\', \'hej\', \'foo\');\n -> \'foo\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(159,'ALTER VIEW',39,'Syntax:\nALTER\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThis statement changes the definition of a view, which must exist. The\nsyntax is similar to that for CREATE VIEW and the effect is the same as\nfor CREATE OR REPLACE VIEW. See [HELP CREATE VIEW]. This statement\nrequires the CREATE VIEW and DROP privileges for the view, and some\nprivilege for each column referred to in the SELECT statement. ALTER\nVIEW is permitted only to the definer or users with the SUPER\nprivilege.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-view.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-view.html'),(160,'SHOW DATABASES',26,'Syntax:\nSHOW {DATABASES | SCHEMAS}\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW DATABASES lists the databases on the MySQL server host. SHOW\nSCHEMAS is a synonym for SHOW DATABASES. The LIKE clause, if present,\nindicates which database names to match. The WHERE clause can be given\nto select rows using more general conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nYou see only those databases for which you have some kind of privilege,\nunless you have the global SHOW DATABASES privilege. You can also get\nthis list using the mysqlshow command.\n\nIf the server was started with the --skip-show-database option, you\ncannot use this statement at all unless you have the SHOW DATABASES\nprivilege.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-databases.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-databases.html'),(161,'~',19,'Syntax:\n~\n\nInvert all bits.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 5 & ~1;\n -> 4\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(162,'TEXT',22,'TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 65,535 (216 - 1) characters. The\neffective maximum length is less if the value contains multi-byte\ncharacters. Each TEXT value is stored using a 2-byte length prefix that\nindicates the number of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest TEXT type large enough to hold\nvalues M characters long.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(163,'CONCAT_WS',37,'Syntax:\nCONCAT_WS(separator,str1,str2,...)\n\nCONCAT_WS() stands for Concatenate With Separator and is a special form\nof CONCAT(). The first argument is the separator for the rest of the\narguments. The separator is added between the strings to be\nconcatenated. The separator can be a string, as can the rest of the\narguments. If the separator is NULL, the result is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT CONCAT_WS(\',\',\'First name\',\'Second name\',\'Last Name\');\n -> \'First name,Second name,Last Name\'\nmysql> SELECT CONCAT_WS(\',\',\'First name\',NULL,\'Last Name\');\n -> \'First name,Last Name\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(164,'ROW_COUNT',17,'Syntax:\nROW_COUNT()\n\nBefore MySQL 5.5.5, ROW_COUNT() returns the number of rows changed,\ndeleted, or inserted by the last statement if it was an UPDATE, DELETE,\nor INSERT. For other statements, the value may not be meaningful.\n\nAs of MySQL 5.5.5, ROW_COUNT() returns a value as follows:\n\no DDL statements: 0. This applies to statements such as CREATE TABLE or\n DROP TABLE.\n\no DML statements other than SELECT: The number of affected rows. This\n applies to statements such as UPDATE, INSERT, or DELETE (as before),\n but now also to statements such as ALTER TABLE and LOAD DATA INFILE.\n\no SELECT: -1 if the statement returns a result set, or the number of\n rows \"affected\" if it does not. For example, for SELECT * FROM t1,\n ROW_COUNT() returns -1. For SELECT * FROM t1 INTO OUTFILE\n \'file_name\', ROW_COUNT() returns the number of rows written to the\n file.\n\no SIGNAL statements: 0.\n\nFor UPDATE statements, the affected-rows value by default is the number\nof rows actually changed. If you specify the CLIENT_FOUND_ROWS flag to\nmysql_real_connect() when connecting to mysqld, the affected-rows value\nis the number of rows \"found\"; that is, matched by the WHERE clause.\n\nFor REPLACE statements, the affected-rows value is 2 if the new row\nreplaced an old row, because in this case, one row was inserted after\nthe duplicate was deleted.\n\nFor INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows\nvalue is 1 if the row is inserted as a new row and 2 if an existing row\nis updated.\n\nThe ROW_COUNT() value is similar to the value from the\nmysql_affected_rows() C API function and the row count that the mysql\nclient displays following statement execution.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> INSERT INTO t VALUES(1),(2),(3);\nQuery OK, 3 rows affected (0.00 sec)\nRecords: 3 Duplicates: 0 Warnings: 0\n\nmysql> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 3 |\n+-------------+\n1 row in set (0.00 sec)\n\nmysql> DELETE FROM t WHERE i IN(1,2);\nQuery OK, 2 rows affected (0.00 sec)\n\nmysql> SELECT ROW_COUNT();\n+-------------+\n| ROW_COUNT() |\n+-------------+\n| 2 |\n+-------------+\n1 row in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(165,'ASIN',4,'Syntax:\nASIN(X)\n\nReturns the arc sine of X, that is, the value whose sine is X. Returns\nNULL if X is not in the range -1 to 1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ASIN(0.2);\n -> 0.20135792079033\nmysql> SELECT ASIN(\'foo\');\n\n+-------------+\n| ASIN(\'foo\') |\n+-------------+\n| 0 |\n+-------------+\n1 row in set, 1 warning (0.00 sec)\n\nmysql> SHOW WARNINGS;\n+---------+------+-----------------------------------------+\n| Level | Code | Message |\n+---------+------+-----------------------------------------+\n| Warning | 1292 | Truncated incorrect DOUBLE value: \'foo\' |\n+---------+------+-----------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(166,'SIGN',4,'Syntax:\nSIGN(X)\n\nReturns the sign of the argument as -1, 0, or 1, depending on whether X\nis negative, zero, or positive.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT SIGN(-32);\n -> -1\nmysql> SELECT SIGN(0);\n -> 0\nmysql> SELECT SIGN(234);\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(167,'SEC_TO_TIME',31,'Syntax:\nSEC_TO_TIME(seconds)\n\nReturns the seconds argument, converted to hours, minutes, and seconds,\nas a TIME value. The range of the result is constrained to that of the\nTIME data type. A warning occurs if the argument corresponds to a value\noutside that range.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT SEC_TO_TIME(2378);\n -> \'00:39:38\'\nmysql> SELECT SEC_TO_TIME(2378) + 0;\n -> 3938\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(168,'FLOAT',22,'FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA small (single-precision) floating-point number. Permissible values\nare -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to\n3.402823466E+38. These are the theoretical limits, based on the IEEE\nstandard. The actual range might be slightly smaller depending on your\nhardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A single-precision floating-point\nnumber is accurate to approximately 7 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nUsing FLOAT might give you some unexpected problems because all\ncalculations in MySQL are done with double precision. See\nhttp://dev.mysql.com/doc/refman/5.5/en/no-matching-rows.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(169,'LOCATE',37,'Syntax:\nLOCATE(substr,str), LOCATE(substr,str,pos)\n\nThe first syntax returns the position of the first occurrence of\nsubstring substr in string str. The second syntax returns the position\nof the first occurrence of substring substr in string str, starting at\nposition pos. Returns 0 if substr is not in str.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT LOCATE(\'bar\', \'foobarbar\');\n -> 4\nmysql> SELECT LOCATE(\'xbar\', \'foobar\');\n -> 0\nmysql> SELECT LOCATE(\'bar\', \'foobarbar\', 5);\n -> 7\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(170,'SHOW EVENTS',26,'Syntax:\nSHOW EVENTS [{FROM | IN} schema_name]\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement displays information about Event Manager events. It\nrequires the EVENT privilege for the database from which the events are\nto be shown.\n\nIn its simplest form, SHOW EVENTS lists all of the events in the\ncurrent schema:\n\nmysql> SELECT CURRENT_USER(), SCHEMA();\n+----------------+----------+\n| CURRENT_USER() | SCHEMA() |\n+----------------+----------+\n| jon@ghidora | myschema |\n+----------------+----------+\n1 row in set (0.00 sec)\n\nmysql> SHOW EVENTS\\G\n*************************** 1. row ***************************\n Db: myschema\n Name: e_daily\n Definer: jon@ghidora\n Time zone: SYSTEM\n Type: RECURRING\n Execute at: NULL\n Interval value: 10\n Interval field: SECOND\n Starts: 2006-02-09 10:41:23\n Ends: NULL\n Status: ENABLED\n Originator: 0\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n\nTo see events for a specific schema, use the FROM clause. For example,\nto see events for the test schema, use the following statement:\n\nSHOW EVENTS FROM test;\n\nThe LIKE clause, if present, indicates which event names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-events.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-events.html'),(171,'CHARSET',17,'Syntax:\nCHARSET(str)\n\nReturns the character set of the string argument.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT CHARSET(\'abc\');\n -> \'latin1\'\nmysql> SELECT CHARSET(CONVERT(\'abc\' USING utf8));\n -> \'utf8\'\nmysql> SELECT CHARSET(USER());\n -> \'utf8\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(172,'SUBDATE',31,'Syntax:\nSUBDATE(date,INTERVAL expr unit), SUBDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, SUBDATE()\nis a synonym for DATE_SUB(). For information on the INTERVAL unit\nargument, see the discussion for DATE_ADD().\n\nmysql> SELECT DATE_SUB(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\nmysql> SELECT SUBDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2007-12-02\'\n\nThe second form enables the use of an integer value for days. In such\ncases, it is interpreted as the number of days to be subtracted from\nthe date or datetime expression expr.\n\nmysql> SELECT SUBDATE(\'2008-01-02 12:00:00\', 31);\n -> \'2007-12-02 12:00:00\'\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(173,'DAYOFYEAR',31,'Syntax:\nDAYOFYEAR(date)\n\nReturns the day of the year for date, in the range 1 to 366.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DAYOFYEAR(\'2007-02-03\');\n -> 34\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(174,'%',4,'Syntax:\nN % M, N MOD M\n\nModulo operation. Returns the remainder of N divided by M. For more\ninformation, see the description for the MOD() function in\nhttp://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(175,'LONGTEXT',22,'LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\ncharacters. The effective maximum length is less if the value contains\nmulti-byte characters. The effective maximum length of LONGTEXT columns\nalso depends on the configured maximum packet size in the client/server\nprotocol and available memory. Each LONGTEXT value is stored using a\n4-byte length prefix that indicates the number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(176,'KILL',26,'Syntax:\nKILL [CONNECTION | QUERY] thread_id\n\nEach connection to mysqld runs in a separate thread. You can see which\nthreads are running with the SHOW PROCESSLIST statement and kill a\nthread with the KILL thread_id statement.\n\nKILL permits an optional CONNECTION or QUERY modifier:\n\no KILL CONNECTION is the same as KILL with no modifier: It terminates\n the connection associated with the given thread_id.\n\no KILL QUERY terminates the statement that the connection is currently\n executing, but leaves the connection itself intact.\n\nIf you have the PROCESS privilege, you can see all threads. If you have\nthe SUPER privilege, you can kill all threads and statements.\nOtherwise, you can see and kill only your own threads and statements.\n\nYou can also use the mysqladmin processlist and mysqladmin kill\ncommands to examine and kill threads.\n\n*Note*: You cannot use KILL with the Embedded MySQL Server library\nbecause the embedded server merely runs inside the threads of the host\napplication. It does not create any connection threads of its own.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/kill.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/kill.html'),(177,'DISJOINT',30,'Disjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially disjoint from (does\nnot intersect) g2.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(178,'ASTEXT',3,'AsText(g), AsWKT(g)\n\nConverts a value in internal geometry format to its WKT representation\nand returns the string result.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html\n\n','mysql> SET @g = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT AsText(GeomFromText(@g));\n+--------------------------+\n| AsText(GeomFromText(@g)) |\n+--------------------------+\n| LINESTRING(1 1,2 2,3 3) |\n+--------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html'),(179,'LPAD',37,'Syntax:\nLPAD(str,len,padstr)\n\nReturns the string str, left-padded with the string padstr to a length\nof len characters. If str is longer than len, the return value is\nshortened to len characters.\n\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT LPAD(\'hi\',4,\'??\');\n -> \'??hi\'\nmysql> SELECT LPAD(\'hi\',1,\'??\');\n -> \'h\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(180,'DECLARE CONDITION',23,'Syntax:\nDECLARE condition_name CONDITION FOR condition_value\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n\nThe DECLARE ... CONDITION statement declares a named error condition,\nassociating a name with a condition that needs specific handling. The\nname can be referred to in a subsequent DECLARE ... HANDLER statement\n(see [HELP DECLARE HANDLER]).\n\nCondition declarations must appear before cursor or handler\ndeclarations.\n\nThe condition_value for DECLARE ... CONDITION can be a MySQL error code\n(a number) or an SQLSTATE value (a 5-character string literal). You\nshould not use MySQL error code 0 or SQLSTATE values that begin with\n\'00\', because those indicate success rather than an error condition.\nFor a list of MySQL error codes and SQLSTATE values, see\nhttp://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/declare-condition.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/declare-condition.html'),(181,'OVERLAPS',30,'Overlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially overlaps g2. The term\nspatially overlaps is used if two geometries intersect and their\nintersection results in a geometry of the same dimension but not equal\nto either of the given geometries.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(182,'SET GLOBAL SQL_SLAVE_SKIP_COUNTER',8,'Syntax:\nSET GLOBAL sql_slave_skip_counter = N\n\nThis statement skips the next N events from the master. This is useful\nfor recovering from replication stops caused by a statement.\n\nThis statement is valid only when the slave threads are not running.\nOtherwise, it produces an error.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/set-global-sql-slave-skip-counter.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/set-global-sql-slave-skip-counter.html'),(183,'NUMGEOMETRIES',25,'NumGeometries(gc)\n\nReturns the number of geometries in the GeometryCollection value gc.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#geometrycollection-property-functions\n\n','mysql> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nmysql> SELECT NumGeometries(GeomFromText(@gc));\n+----------------------------------+\n| NumGeometries(GeomFromText(@gc)) |\n+----------------------------------+\n| 2 |\n+----------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#geometrycollection-property-functions'),(184,'MONTHNAME',31,'Syntax:\nMONTHNAME(date)\n\nReturns the full name of the month for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(http://dev.mysql.com/doc/refman/5.5/en/locale-support.html).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MONTHNAME(\'2008-02-03\');\n -> \'February\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(185,'CHANGE MASTER TO',8,'Syntax:\nCHANGE MASTER TO option [, option] ...\n\noption:\n MASTER_BIND = \'interface_name\'\n | MASTER_HOST = \'host_name\'\n | MASTER_USER = \'user_name\'\n | MASTER_PASSWORD = \'password\'\n | MASTER_PORT = port_num\n | MASTER_CONNECT_RETRY = interval\n | MASTER_HEARTBEAT_PERIOD = interval\n | MASTER_LOG_FILE = \'master_log_name\'\n | MASTER_LOG_POS = master_log_pos\n | RELAY_LOG_FILE = \'relay_log_name\'\n | RELAY_LOG_POS = relay_log_pos\n | MASTER_SSL = {0|1}\n | MASTER_SSL_CA = \'ca_file_name\'\n | MASTER_SSL_CAPATH = \'ca_directory_name\'\n | MASTER_SSL_CERT = \'cert_file_name\'\n | MASTER_SSL_KEY = \'key_file_name\'\n | MASTER_SSL_CIPHER = \'cipher_list\'\n | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}\n | IGNORE_SERVER_IDS = (server_id_list)\n\nserver_id_list:\n [server_id [, server_id] ... ]\n\nCHANGE MASTER TO changes the parameters that the slave server uses for\nconnecting to the master server, for reading the master binary log, and\nreading the slave relay log. It also updates the contents of the\nmaster.info and relay-log.info files. To use CHANGE MASTER TO, the\nslave replication threads must be stopped (use STOP SLAVE if\nnecessary).\n\nOptions not specified retain their value, except as indicated in the\nfollowing discussion. Thus, in most cases, there is no need to specify\noptions that do not change. For example, if the password to connect to\nyour MySQL master has changed, you just need to issue these statements\nto tell the slave about the new password:\n\nSTOP SLAVE; -- if replication was running\nCHANGE MASTER TO MASTER_PASSWORD=\'new3cret\';\nSTART SLAVE; -- if you want to restart replication\n\nMASTER_HOST, MASTER_USER, MASTER_PASSWORD, and MASTER_PORT provide\ninformation to the slave about how to connect to its master:\n\no MASTER_HOST and MASTER_PORT are the host name (or IP address) of the\n master host and its TCP/IP port.\n\n *Note*: Replication cannot use Unix socket files. You must be able to\n connect to the master MySQL server using TCP/IP.\n\n If you specify the MASTER_HOST or MASTER_PORT option, the slave\n assumes that the master server is different from before (even if the\n option value is the same as its current value.) In this case, the old\n values for the master binary log file name and position are\n considered no longer applicable, so if you do not specify\n MASTER_LOG_FILE and MASTER_LOG_POS in the statement,\n MASTER_LOG_FILE=\'\' and MASTER_LOG_POS=4 are silently appended to it.\n\n Setting MASTER_HOST=\'\' (that is, setting its value explicitly to an\n empty string) is not the same as not setting MASTER_HOST at all.\n Beginning with MySQL 5.5, trying to set MASTER_HOST to an empty\n string fails with an error. Previously, setting MASTER_HOST to an\n empty string caused START SLAVE subsequently to fail. (Bug #28796)\n\no MASTER_USER and MASTER_PASSWORD are the user name and password of the\n account to use for connecting to the master.\n\n In MySQL 5.5.20 and later, MASTER_USER cannot be made empty; setting\n MASTER_USER = \'\' or leaving it unset when setting a value for for\n MASTER_PASSWORD causes an error (Bug #13427949).\n\n Currently, a password used for a replication slave account is\n effectively limited to 32 characters in length; the password can be\n longer, but any excess characters are truncated. This is not due to\n any limit imposed by the MySQL Server generally, but rather is an\n issue specific to MySQL Replication. (For more information, see Bug\n #43439.)\n\n The text of a running CHANGE MASTER TO statement, including values\n for MASTER_USER and MASTER_PASSWORD, can be seen in the output of a\n concurrent SHOW PROCESSLIST statement.\n\nThe MASTER_SSL_xxx options provide information about using SSL for the\nconnection. They correspond to the --ssl-xxx options described in\nhttp://dev.mysql.com/doc/refman/5.5/en/ssl-options.html, and\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-solutions-ssl.html.\nThese options can be changed even on slaves that are compiled without\nSSL support. They are saved to the master.info file, but are ignored if\nthe slave does not have SSL support enabled.\n\nMASTER_CONNECT_RETRY specifies how many seconds to wait between connect\nretries. The default is 60. The number of reconnection attempts is\nlimited by the --master-retry-count server option; for more\ninformation, see\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-options.html.\n\nThe MASTER_BIND option is available in MySQL Cluster NDB 7.2 and later,\nbut is not supported in mainline MySQL 5.5.\n\nMASTER_BIND is for use on replication slaves having multiple network\ninterfaces, and determines which of the slave\'s network interfaces is\nchosen for connecting to the master.\n\nMASTER_HEARTBEAT_PERIOD sets the interval in seconds between\nreplication heartbeats. Whenever the master\'s binary log is updated\nwith an event, the waiting period for the next heartbeat is reset.\ninterval is a decimal value having the range 0 to 4294967 seconds and a\nresolution in milliseconds; the smallest nonzero value is 0.001.\nHeartbeats are sent by the master only if there are no unsent events in\nthe binary log file for a period longer than interval.\n\nSetting interval to 0 disables heartbeats altogether. The default value\nfor interval is equal to the value of slave_net_timeout divided by 2.\n\nSetting @@global.slave_net_timeout to a value less than that of the\ncurrent heartbeat interval results in a warning being issued. The\neffect of issuing RESET SLAVE on the heartbeat interval is to reset it\nto the default value.\n\nMASTER_LOG_FILE and MASTER_LOG_POS are the coordinates at which the\nslave I/O thread should begin reading from the master the next time the\nthread starts. RELAY_LOG_FILE and RELAY_LOG_POS are the coordinates at\nwhich the slave SQL thread should begin reading from the relay log the\nnext time the thread starts. If you specify either of MASTER_LOG_FILE\nor MASTER_LOG_POS, you cannot specify RELAY_LOG_FILE or RELAY_LOG_POS.\nIf neither of MASTER_LOG_FILE or MASTER_LOG_POS is specified, the slave\nuses the last coordinates of the slave SQL thread before CHANGE MASTER\nTO was issued. This ensures that there is no discontinuity in\nreplication, even if the slave SQL thread was late compared to the\nslave I/O thread, when you merely want to change, say, the password to\nuse.\n\nCHANGE MASTER TO deletes all relay log files and starts a new one,\nunless you specify RELAY_LOG_FILE or RELAY_LOG_POS. In that case, relay\nlog files are kept; the relay_log_purge global variable is set silently\nto 0.\n\nPrior to MySQL 5.5, RELAY_LOG_FILE required an absolute path. In MySQL\n5.5, the path can be relative, in which case the path is assumed to be\nrelative to the slave\'s data directory. (Bug #12190)\n\nIGNORE_SERVER_IDS was added in MySQL 5.5. This option takes a\ncomma-separated list of 0 or more server IDs. Events originating from\nthe corresponding servers are ignored, with the exception of log\nrotation and deletion events, which are still recorded in the relay\nlog.\n\nIn circular replication, the originating server normally acts as the\nterminator of its own events, so that they are not applied more than\nonce. Thus, this option is useful in circular replication when one of\nthe servers in the circle is removed. Suppose that you have a circular\nreplication setup with 4 servers, having server IDs 1, 2, 3, and 4, and\nserver 3 fails. When bridging the gap by starting replication from\nserver 2 to server 4, you can include IGNORE_SERVER_IDS = (3) in the\nCHANGE MASTER TO statement that you issue on server 4 to tell it to use\nserver 2 as its master instead of server 3. Doing so causes it to\nignore and not to propagate any statements that originated with the\nserver that is no longer in use.\n\nIf a CHANGE MASTER TO statement is issued without any IGNORE_SERVER_IDS\noption, any existing list is preserved; RESET SLAVE also has no effect\non the server ID list. To clear the list of ignored servers, it is\nnecessary to use the option with an empty list:\n\nCHANGE MASTER TO IGNORE_SERVER_IDS = ();\n\nIf IGNORE_SERVER_IDS contains the server\'s own ID and the server was\nstarted with the --replicate-same-server-id option enabled, an error\nresults.\n\nAlso beginning with MySQL 5.5, the master.info file and the output of\nSHOW SLAVE STATUS are extended to provide the list of servers that are\ncurrently ignored. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/slave-logs-status.html, and\n[HELP SHOW SLAVE STATUS].\n\nBeginning with MySQL 5.5.5, invoking CHANGE MASTER TO causes the\nprevious values for MASTER_HOST, MASTER_PORT, MASTER_LOG_FILE, and\nMASTER_LOG_POS to be written to the error log, along with other\ninformation about the slave\'s state prior to execution.\n\nCHANGE MASTER TO is useful for setting up a slave when you have the\nsnapshot of the master and have recorded the master binary log\ncoordinates corresponding to the time of the snapshot. After loading\nthe snapshot into the slave to synchronize it to the slave, you can run\nCHANGE MASTER TO MASTER_LOG_FILE=\'log_name\', MASTER_LOG_POS=log_pos on\nthe slave to specify the coordinates at which the slave should begin\nreading the master binary log.\n\nThe following example changes the master server the slave uses and\nestablishes the master binary log coordinates from which the slave\nbegins reading. This is used when you want to set up the slave to\nreplicate the master:\n\nCHANGE MASTER TO\n MASTER_HOST=\'master2.mycompany.com\',\n MASTER_USER=\'replication\',\n MASTER_PASSWORD=\'bigs3cret\',\n MASTER_PORT=3306,\n MASTER_LOG_FILE=\'master2-bin.001\',\n MASTER_LOG_POS=4,\n MASTER_CONNECT_RETRY=10;\n\nThe next example shows an operation that is less frequently employed.\nIt is used when the slave has relay log files that you want it to\nexecute again for some reason. To do this, the master need not be\nreachable. You need only use CHANGE MASTER TO and start the SQL thread\n(START SLAVE SQL_THREAD):\n\nCHANGE MASTER TO\n RELAY_LOG_FILE=\'slave-relay-bin.006\',\n RELAY_LOG_POS=4025;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/change-master-to.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/change-master-to.html'),(186,'DROP DATABASE',39,'Syntax:\nDROP {DATABASE | SCHEMA} [IF EXISTS] db_name\n\nDROP DATABASE drops all tables in the database and deletes the\ndatabase. Be very careful with this statement! To use DROP DATABASE,\nyou need the DROP privilege on the database. DROP SCHEMA is a synonym\nfor DROP DATABASE.\n\n*Important*: When a database is dropped, user privileges on the\ndatabase are not automatically dropped. See [HELP GRANT].\n\nIF EXISTS is used to prevent an error from occurring if the database\ndoes not exist.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-database.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-database.html'),(187,'MBREQUAL',6,'MBREqual(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are the same.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(188,'TIMESTAMP FUNCTION',31,'Syntax:\nTIMESTAMP(expr), TIMESTAMP(expr1,expr2)\n\nWith a single argument, this function returns the date or datetime\nexpression expr as a datetime value. With two arguments, it adds the\ntime expression expr2 to the date or datetime expression expr1 and\nreturns the result as a datetime value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIMESTAMP(\'2003-12-31\');\n -> \'2003-12-31 00:00:00\'\nmysql> SELECT TIMESTAMP(\'2003-12-31 12:00:00\',\'12:00:00\');\n -> \'2004-01-01 00:00:00\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(189,'PROCEDURE ANALYSE',33,'Syntax:\nANALYSE([max_elements[,max_memory]])\n\nANALYSE() examines the result from a query and returns an analysis of\nthe results that suggests optimal data types for each column that may\nhelp reduce table sizes. To obtain this analysis, append PROCEDURE\nANALYSE to the end of a SELECT statement:\n\nSELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])\n\nFor example:\n\nSELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);\n\nThe results show some statistics for the values returned by the query,\nand propose an optimal data type for the columns. This can be helpful\nfor checking your existing tables, or after importing new data. You may\nneed to try different settings for the arguments so that PROCEDURE\nANALYSE() does not suggest the ENUM data type when it is not\nappropriate.\n\nThe arguments are optional and are used as follows:\n\no max_elements (default 256) is the maximum number of distinct values\n that ANALYSE() notices per column. This is used by ANALYSE() to check\n whether the optimal data type should be of type ENUM; if there are\n more than max_elements distinct values, then ENUM is not a suggested\n type.\n\no max_memory (default 8192) is the maximum amount of memory that\n ANALYSE() should allocate per column while trying to find all\n distinct values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/procedure-analyse.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/procedure-analyse.html'),(190,'HELP_VERSION',9,'This help information was generated from the MySQL 5.5 Reference Manual\non: 2012-08-25 (revision: 31914)\n\nThis information applies to MySQL 5.5 through 5.5.29.\n','',''),(191,'CHARACTER_LENGTH',37,'Syntax:\nCHARACTER_LENGTH(str)\n\nCHARACTER_LENGTH() is a synonym for CHAR_LENGTH().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(192,'SHOW GRANTS',26,'Syntax:\nSHOW GRANTS [FOR user]\n\nThis statement lists the GRANT statement or statements that must be\nissued to duplicate the privileges that are granted to a MySQL user\naccount. The account is named using the same format as for the GRANT\nstatement; for example, \'jeffrey\'@\'localhost\'. If you specify only the\nuser name part of the account name, a host name part of \'%\' is used.\nFor additional information about specifying account names, see [HELP\nGRANT].\n\nmysql> SHOW GRANTS FOR \'root\'@\'localhost\';\n+---------------------------------------------------------------------+\n| Grants for root@localhost |\n+---------------------------------------------------------------------+\n| GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION |\n+---------------------------------------------------------------------+\n\nTo list the privileges granted to the account that you are using to\nconnect to the server, you can use any of the following statements:\n\nSHOW GRANTS;\nSHOW GRANTS FOR CURRENT_USER;\nSHOW GRANTS FOR CURRENT_USER();\n\nIf SHOW GRANTS FOR CURRENT_USER (or any of the equivalent syntaxes) is\nused in DEFINER context, such as within a stored procedure that is\ndefined with SQL SECURITY DEFINER), the grants displayed are those of\nthe definer and not the invoker.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-grants.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-grants.html'),(193,'SHOW PRIVILEGES',26,'Syntax:\nSHOW PRIVILEGES\n\nSHOW PRIVILEGES shows the list of system privileges that the MySQL\nserver supports. The exact list of privileges depends on the version of\nyour server.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-privileges.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-privileges.html'),(194,'CREATE TABLESPACE',39,'Syntax:\nCREATE TABLESPACE tablespace_name\n ADD DATAFILE \'file_name\'\n USE LOGFILE GROUP logfile_group\n [EXTENT_SIZE [=] extent_size]\n [INITIAL_SIZE [=] initial_size]\n [AUTOEXTEND_SIZE [=] autoextend_size]\n [MAX_SIZE [=] max_size]\n [NODEGROUP [=] nodegroup_id]\n [WAIT]\n [COMMENT [=] comment_text]\n ENGINE [=] engine_name\n\nThis statement is used to create a tablespace, which can contain one or\nmore data files, providing storage space for tables. One data file is\ncreated and added to the tablespace using this statement. Additional\ndata files may be added to the tablespace by using the ALTER TABLESPACE\nstatement (see [HELP ALTER TABLESPACE]). For rules covering the naming\nof tablespaces, see\nhttp://dev.mysql.com/doc/refman/5.5/en/identifiers.html.\n\n*Note*: All MySQL Cluster Disk Data objects share the same namespace.\nThis means that each Disk Data object must be uniquely named (and not\nmerely each Disk Data object of a given type). For example, you cannot\nhave a tablespace and a log file group with the same name, or a\ntablespace and a data file with the same name.\n\nA log file group of one or more UNDO log files must be assigned to the\ntablespace to be created with the USE LOGFILE GROUP clause.\nlogfile_group must be an existing log file group created with CREATE\nLOGFILE GROUP (see\nhttp://dev.mysql.com/doc/refman/5.5/en/create-logfile-group.html).\nMultiple tablespaces may use the same log file group for UNDO logging.\n\nThe EXTENT_SIZE sets the size, in bytes, of the extents used by any\nfiles belonging to the tablespace. The default value is 1M. The minimum\nsize is 32K, and theoretical maximum is 2G, although the practical\nmaximum size depends on a number of factors. In most cases, changing\nthe extent size does not have any measurable effect on performance, and\nthe default value is recommended for all but the most unusual\nsituations.\n\nAn extent is a unit of disk space allocation. One extent is filled with\nas much data as that extent can contain before another extent is used.\nIn theory, up to 65,535 (64K) extents may used per data file; however,\nthe recommended maximum is 32,768 (32K). The recommended maximum size\nfor a single data file is 32G---that is, 32K extents x 1 MB per extent.\nIn addition, once an extent is allocated to a given partition, it\ncannot be used to store data from a different partition; an extent\ncannot store data from more than one partition. This means, for example\nthat a tablespace having a single datafile whose INITIAL_SIZE is 256 MB\nand whose EXTENT_SIZE is 128M has just two extents, and so can be used\nto store data from at most two different disk data table partitions.\n\nYou can see how many extents remain free in a given data file by\nquerying the INFORMATION_SCHEMA.FILES table, and so derive an estimate\nfor how much space remains free in the file. For further discussion and\nexamples, see http://dev.mysql.com/doc/refman/5.5/en/files-table.html.\n\nThe INITIAL_SIZE parameter sets the data file\'s total size in bytes.\nOnce the file has been created, its size cannot be changed; however,\nyou can add more data files to the tablespace using ALTER TABLESPACE\n... ADD DATAFILE. See [HELP ALTER TABLESPACE].\n\nINITIAL_SIZE is optional; its default value is 128M.\n\nOn 32-bit systems, the maximum supported value for INITIAL_SIZE is 4G.\n(Bug #29186)\n\nWhen setting EXTENT_SIZE or INITIAL_SIZE (either or both), you may\noptionally follow the number with a one-letter abbreviation for an\norder of magnitude, similar to those used in my.cnf. Generally, this is\none of the letters M (for megabytes) or G (for gigabytes).\n\nINITIAL_SIZE, EXTENT_SIZE, and UNDO_BUFFER_SIZE are subject to rounding\nas follows:\n\no EXTENT_SIZE and UNDO_BUFFER_SIZE are each rounded up to the nearest\n whole multiple of 32K.\n\no INITIAL_SIZE is rounded down to the nearest whole multiple of 32K.\n\n For data files, INITIAL_SIZE is subject to further rounding; the\n result just obtained is rounded up to the nearest whole multiple of\n EXTENT_SIZE (after any rounding).\n\nThe rounding just described is done explicitly, and a warning is issued\nby the MySQL Server when any such rounding is performed. The rounded\nvalues are also used by the NDB kernel for calculating\nINFORMATION_SCHEMA.FILES column values and other purposes. However, to\navoid an unexpected result, we suggest that you always use whole\nmultiples of 32K in specifying these options.\n\nAUTOEXTEND_SIZE, MAX_SIZE, NODEGROUP, WAIT, and COMMENT are parsed but\nignored, and so currently have no effect. These options are intended\nfor future expansion.\n\nThe ENGINE parameter determines the storage engine which uses this\ntablespace, with engine_name being the name of the storage engine.\nCurrently, engine_name must be one of the values NDB or NDBCLUSTER.\n\nWhen CREATE TABLESPACE is used with ENGINE = NDB, a tablespace and\nassociated data file are created on each Cluster data node. You can\nverify that the data files were created and obtain information about\nthem by querying the INFORMATION_SCHEMA.FILES table. For example:\n\nmysql> SELECT LOGFILE_GROUP_NAME, FILE_NAME, EXTRA\n -> FROM INFORMATION_SCHEMA.FILES\n -> WHERE TABLESPACE_NAME = \'newts\' AND FILE_TYPE = \'DATAFILE\';\n+--------------------+-------------+----------------+\n| LOGFILE_GROUP_NAME | FILE_NAME | EXTRA |\n+--------------------+-------------+----------------+\n| lg_3 | newdata.dat | CLUSTER_NODE=3 |\n| lg_3 | newdata.dat | CLUSTER_NODE=4 |\n+--------------------+-------------+----------------+\n2 rows in set (0.01 sec)\n\n(See http://dev.mysql.com/doc/refman/5.5/en/files-table.html.)\n\nCREATE TABLESPACE is useful only with Disk Data storage for MySQL\nCluster. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-cluster-disk-data.html.\n\nTo drop a primary key, the index name is always PRIMARY, which must be\nspecified as a quoted identifier because PRIMARY is a reserved word:\n\nDROP INDEX `PRIMARY` ON t;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-tablespace.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-tablespace.html'),(195,'INSERT FUNCTION',37,'Syntax:\nINSERT(str,pos,len,newstr)\n\nReturns the string str, with the substring beginning at position pos\nand len characters long replaced by the string newstr. Returns the\noriginal string if pos is not within the length of the string. Replaces\nthe rest of the string from position pos if len is not within the\nlength of the rest of the string. Returns NULL if any argument is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT INSERT(\'Quadratic\', 3, 4, \'What\');\n -> \'QuWhattic\'\nmysql> SELECT INSERT(\'Quadratic\', -1, 4, \'What\');\n -> \'Quadratic\'\nmysql> SELECT INSERT(\'Quadratic\', 3, 100, \'What\');\n -> \'QuWhat\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(196,'CRC32',4,'Syntax:\nCRC32(expr)\n\nComputes a cyclic redundancy check value and returns a 32-bit unsigned\nvalue. The result is NULL if the argument is NULL. The argument is\nexpected to be a string and (if possible) is treated as one if it is\nnot.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT CRC32(\'MySQL\');\n -> 3259397556\nmysql> SELECT CRC32(\'mysql\');\n -> 2501908538\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(197,'XOR',15,'Syntax:\nXOR\n\nLogical XOR. Returns NULL if either operand is NULL. For non-NULL\noperands, evaluates to 1 if an odd number of operands is nonzero,\notherwise 0 is returned.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html\n\n','mysql> SELECT 1 XOR 1;\n -> 0\nmysql> SELECT 1 XOR 0;\n -> 1\nmysql> SELECT 1 XOR NULL;\n -> NULL\nmysql> SELECT 1 XOR 1 XOR 1;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html'),(198,'STARTPOINT',13,'StartPoint(ls)\n\nReturns the Point that is the start point of the LineString value ls.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions\n\n','mysql> SET @ls = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT AsText(StartPoint(GeomFromText(@ls)));\n+---------------------------------------+\n| AsText(StartPoint(GeomFromText(@ls))) |\n+---------------------------------------+\n| POINT(1 1) |\n+---------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions'),(199,'GRANT',10,'Syntax:\nGRANT\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n TO user_specification [, user_specification] ...\n [REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]\n [WITH with_option ...]\n\nGRANT PROXY ON user_specification\n TO user_specification [, user_specification] ...\n [WITH GRANT OPTION]\n\nobject_type:\n TABLE\n | FUNCTION\n | PROCEDURE\n\npriv_level:\n *\n | *.*\n | db_name.*\n | db_name.tbl_name\n | tbl_name\n | db_name.routine_name\n\nuser_specification:\n user\n [\n IDENTIFIED BY [PASSWORD] \'password\'\n | IDENTIFIED WITH auth_plugin [AS \'auth_string\']\n ]\n\nssl_option:\n SSL\n | X509\n | CIPHER \'cipher\'\n | ISSUER \'issuer\'\n | SUBJECT \'subject\'\n\nwith_option:\n GRANT OPTION\n | MAX_QUERIES_PER_HOUR count\n | MAX_UPDATES_PER_HOUR count\n | MAX_CONNECTIONS_PER_HOUR count\n | MAX_USER_CONNECTIONS count\n\nThe GRANT statement grants privileges to MySQL user accounts. GRANT\nalso serves to specify other account characteristics such as use of\nsecure connections and limits on access to server resources. To use\nGRANT, you must have the GRANT OPTION privilege, and you must have the\nprivileges that you are granting.\n\nNormally, a database administrator first uses CREATE USER to create an\naccount, then GRANT to define its privileges and characteristics. For\nexample:\n\nCREATE USER \'jeffrey\'@\'localhost\' IDENTIFIED BY \'mypass\';\nGRANT ALL ON db1.* TO \'jeffrey\'@\'localhost\';\nGRANT SELECT ON db2.invoice TO \'jeffrey\'@\'localhost\';\nGRANT USAGE ON *.* TO \'jeffrey\'@\'localhost\' WITH MAX_QUERIES_PER_HOUR 90;\n\nHowever, if an account named in a GRANT statement does not already\nexist, GRANT may create it under the conditions described later in the\ndiscussion of the NO_AUTO_CREATE_USER SQL mode.\n\nThe REVOKE statement is related to GRANT and enables administrators to\nremove account privileges. See [HELP REVOKE].\n\nWhen successfully executed from the mysql program, GRANT responds with\nQuery OK, 0 rows affected. To determine what privileges result from the\noperation, use SHOW GRANTS. See [HELP SHOW GRANTS].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/grant.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/grant.html'),(200,'DECLARE VARIABLE',23,'Syntax:\nDECLARE var_name [, var_name] ... type [DEFAULT value]\n\nThis statement declares local variables within stored programs. To\nprovide a default value for a variable, include a DEFAULT clause. The\nvalue can be specified as an expression; it need not be a constant. If\nthe DEFAULT clause is missing, the initial value is NULL.\n\nLocal variables are treated like stored routine parameters with respect\nto data type and overflow checking. See [HELP CREATE PROCEDURE].\n\nVariable declarations must appear before cursor or handler\ndeclarations.\n\nLocal variable names are not case sensitive. Permissible characters and\nquoting rules are the same as for other identifiers, as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/identifiers.html.\n\nThe scope of a local variable is the BEGIN ... END block within which\nit is declared. The variable can be referred to in blocks nested within\nthe declaring block, except those blocks that declare a variable with\nthe same name.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/declare-local-variable.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/declare-local-variable.html'),(201,'MPOLYFROMTEXT',3,'MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])\n\nConstructs a MULTIPOLYGON value using its WKT representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(202,'MBRINTERSECTS',6,'MBRIntersects(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 intersect.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(203,'BIT_OR',16,'Syntax:\nBIT_OR(expr)\n\nReturns the bitwise OR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(204,'YEARWEEK',31,'Syntax:\nYEARWEEK(date), YEARWEEK(date,mode)\n\nReturns year and week for a date. The mode argument works exactly like\nthe mode argument to WEEK(). The year in the result may be different\nfrom the year in the date argument for the first and the last week of\nthe year.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT YEARWEEK(\'1987-01-01\');\n -> 198653\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(205,'NOT BETWEEN',18,'Syntax:\nexpr NOT BETWEEN min AND max\n\nThis is the same as NOT (expr BETWEEN min AND max).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(206,'IS NOT',18,'Syntax:\nIS NOT boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;\n -> 1, 1, 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(207,'LOG10',4,'Syntax:\nLOG10(X)\n\nReturns the base-10 logarithm of X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT LOG10(2);\n -> 0.30102999566398\nmysql> SELECT LOG10(100);\n -> 2\nmysql> SELECT LOG10(-100);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(208,'SQRT',4,'Syntax:\nSQRT(X)\n\nReturns the square root of a nonnegative number X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT SQRT(4);\n -> 2\nmysql> SELECT SQRT(20);\n -> 4.4721359549996\nmysql> SELECT SQRT(-16);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(209,'DECIMAL',22,'DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]\n\nA packed \"exact\" fixed-point number. M is the total number of digits\n(the precision) and D is the number of digits after the decimal point\n(the scale). The decimal point and (for negative numbers) the \"-\" sign\nare not counted in M. If D is 0, values have no decimal point or\nfractional part. The maximum number of digits (M) for DECIMAL is 65.\nThe maximum number of supported decimals (D) is 30. If D is omitted,\nthe default is 0. If M is omitted, the default is 10.\n\nUNSIGNED, if specified, disallows negative values.\n\nAll basic calculations (+, -, *, /) with DECIMAL columns are done with\na precision of 65 digits.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(210,'CREATE INDEX',39,'Syntax:\nCREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name\n [index_type]\n ON tbl_name (index_col_name,...)\n [index_option] ...\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nCREATE INDEX is mapped to an ALTER TABLE statement to create indexes.\nSee [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY\nKEY; use ALTER TABLE instead. For more information about indexes, see\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-indexes.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-index.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-index.html'),(211,'CREATE FUNCTION',39,'The CREATE FUNCTION statement is used to create stored functions and\nuser-defined functions (UDFs):\n\no For information about creating stored functions, see [HELP CREATE\n PROCEDURE].\n\no For information about creating user-defined functions, see [HELP\n CREATE FUNCTION UDF].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-function.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-function.html'),(212,'ALTER DATABASE',39,'Syntax:\nALTER {DATABASE | SCHEMA} [db_name]\n alter_specification ...\nALTER {DATABASE | SCHEMA} db_name\n UPGRADE DATA DIRECTORY NAME\n\nalter_specification:\n [DEFAULT] CHARACTER SET [=] charset_name\n | [DEFAULT] COLLATE [=] collation_name\n\nALTER DATABASE enables you to change the overall characteristics of a\ndatabase. These characteristics are stored in the db.opt file in the\ndatabase directory. To use ALTER DATABASE, you need the ALTER privilege\non the database. ALTER SCHEMA is a synonym for ALTER DATABASE.\n\nThe database name can be omitted from the first syntax, in which case\nthe statement applies to the default database.\n\nNational Language Characteristics\n\nThe CHARACTER SET clause changes the default database character set.\nThe COLLATE clause changes the default database collation.\nhttp://dev.mysql.com/doc/refman/5.5/en/charset.html, discusses\ncharacter set and collation names.\n\nYou can see what character sets and collations are available using,\nrespectively, the SHOW CHARACTER SET and SHOW COLLATION statements. See\n[HELP SHOW CHARACTER SET], and [HELP SHOW COLLATION], for more\ninformation.\n\nIf you change the default character set or collation for a database,\nstored routines that use the database defaults must be dropped and\nrecreated so that they use the new defaults. (In a stored routine,\nvariables with character data types use the database defaults if the\ncharacter set or collation are not specified explicitly. See [HELP\nCREATE PROCEDURE].)\n\nUpgrading from Versions Older than MySQL 5.1\n\nThe syntax that includes the UPGRADE DATA DIRECTORY NAME clause updates\nthe name of the directory associated with the database to use the\nencoding implemented in MySQL 5.1 for mapping database names to\ndatabase directory names (see\nhttp://dev.mysql.com/doc/refman/5.5/en/identifier-mapping.html). This\nclause is for use under these conditions:\n\no It is intended when upgrading MySQL to 5.1 or later from older\n versions.\n\no It is intended to update a database directory name to the current\n encoding format if the name contains special characters that need\n encoding.\n\no The statement is used by mysqlcheck (as invoked by mysql_upgrade).\n\nFor example, if a database in MySQL 5.0 has the name a-b-c, the name\ncontains instances of the - (dash) character. In MySQL 5.0, the\ndatabase directory is also named a-b-c, which is not necessarily safe\nfor all file systems. In MySQL 5.1 and later, the same database name is\nencoded as a@002db@002dc to produce a file system-neutral directory\nname.\n\nWhen a MySQL installation is upgraded to MySQL 5.1 or later from an\nolder version,the server displays a name such as a-b-c (which is in the\nold format) as #mysql50#a-b-c, and you must refer to the name using the\n#mysql50# prefix. Use UPGRADE DATA DIRECTORY NAME in this case to\nexplicitly tell the server to re-encode the database directory name to\nthe current encoding format:\n\nALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME;\n\nAfter executing this statement, you can refer to the database as a-b-c\nwithout the special #mysql50# prefix.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-database.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-database.html'),(213,'GEOMETRYN',25,'GeometryN(gc,N)\n\nReturns the N-th geometry in the GeometryCollection value gc.\nGeometries are numbered beginning with 1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#geometrycollection-property-functions\n\n','mysql> SET @gc = \'GeometryCollection(Point(1 1),LineString(2 2, 3 3))\';\nmysql> SELECT AsText(GeometryN(GeomFromText(@gc),1));\n+----------------------------------------+\n| AsText(GeometryN(GeomFromText(@gc),1)) |\n+----------------------------------------+\n| POINT(1 1) |\n+----------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#geometrycollection-property-functions'),(214,'<<',19,'Syntax:\n<<\n\nShifts a longlong (BIGINT) number to the left.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 1 << 2;\n -> 4\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(215,'SHOW TABLE STATUS',26,'Syntax:\nSHOW TABLE STATUS [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLE STATUS works likes SHOW TABLES, but provides a lot of\ninformation about each non-TEMPORARY table. You can also get this list\nusing the mysqlshow --status db_name command. The LIKE clause, if\npresent, indicates which table names to match. The WHERE clause can be\ngiven to select rows using more general conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-table-status.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-table-status.html'),(216,'MD5',12,'Syntax:\nMD5(str)\n\nCalculates an MD5 128-bit checksum for the string. The value is\nreturned as a string of 32 hex digits, or NULL if the argument was\nNULL. The return value can, for example, be used as a hash key. See the\nnotes at the beginning of this section about storing hash values\nefficiently.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT MD5(\'testing\');\n -> \'ae2b1fca515949e5d54fb22b8ed95575\'\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(217,'<',18,'Syntax:\n<\n\nLess than:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 2 < 2;\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(218,'UNIX_TIMESTAMP',31,'Syntax:\nUNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)\n\nIf called with no argument, returns a Unix timestamp (seconds since\n\'1970-01-01 00:00:00\' UTC) as an unsigned integer. If UNIX_TIMESTAMP()\nis called with a date argument, it returns the value of the argument as\nseconds since \'1970-01-01 00:00:00\' UTC. date may be a DATE string, a\nDATETIME string, a TIMESTAMP, or a number in the format YYMMDD or\nYYYYMMDD. The server interprets date as a value in the current time\nzone and converts it to an internal value in UTC. Clients can set their\ntime zone as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT UNIX_TIMESTAMP();\n -> 1196440210\nmysql> SELECT UNIX_TIMESTAMP(\'2007-11-30 10:30:19\');\n -> 1196440219\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(219,'DAYOFMONTH',31,'Syntax:\nDAYOFMONTH(date)\n\nReturns the day of the month for date, in the range 1 to 31, or 0 for\ndates such as \'0000-00-00\' or \'2008-00-00\' that have a zero day part.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DAYOFMONTH(\'2007-02-03\');\n -> 3\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(220,'ASCII',37,'Syntax:\nASCII(str)\n\nReturns the numeric value of the leftmost character of the string str.\nReturns 0 if str is the empty string. Returns NULL if str is NULL.\nASCII() works for 8-bit characters.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT ASCII(\'2\');\n -> 50\nmysql> SELECT ASCII(2);\n -> 50\nmysql> SELECT ASCII(\'dx\');\n -> 100\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(221,'DIV',4,'Syntax:\nDIV\n\nInteger division. Similar to FLOOR(), but is safe with BIGINT values.\n\nAs of MySQL 5.5.3, if either operand has a noninteger type, the\noperands are converted to DECIMAL and divided using DECIMAL arithmetic\nbefore converting the result to BIGINT. If the result exceeds BIGINT\nrange, an error occurs. Before MySQL 5.5.3, incorrect results may occur\nfor noninteger operands that exceed BIGINT range.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT 5 DIV 2;\n -> 2\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(222,'RENAME USER',10,'Syntax:\nRENAME USER old_user TO new_user\n [, old_user TO new_user] ...\n\nThe RENAME USER statement renames existing MySQL accounts. To use it,\nyou must have the global CREATE USER privilege or the UPDATE privilege\nfor the mysql database. An error occurs if any old account does not\nexist or any new account exists. Each account name uses the format\ndescribed in http://dev.mysql.com/doc/refman/5.5/en/account-names.html.\nFor example:\n\nRENAME USER \'jeffrey\'@\'localhost\' TO \'jeff\'@\'127.0.0.1\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nRENAME USER causes the privileges held by the old user to be those held\nby the new user. However, RENAME USER does not automatically drop or\ninvalidate databases or objects within them that the old user created.\nThis includes stored programs or views for which the DEFINER attribute\nnames the old user. Attempts to access such objects may produce an\nerror if they execute in definer security context. (For information\nabout security context, see\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-security.html.)\n\nThe privilege changes take effect as indicated in\nhttp://dev.mysql.com/doc/refman/5.5/en/privilege-changes.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/rename-user.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/rename-user.html'),(223,'SHOW SLAVE STATUS',26,'Syntax:\nSHOW SLAVE STATUS\n\nThis statement provides status information on essential parameters of\nthe slave threads. It requires either the SUPER or REPLICATION CLIENT\nprivilege.\n\nIf you issue this statement using the mysql client, you can use a \\G\nstatement terminator rather than a semicolon to obtain a more readable\nvertical layout:\n\nmysql> SHOW SLAVE STATUS\\G\n*************************** 1. row ***************************\n Slave_IO_State: Waiting for master to send event\n Master_Host: localhost\n Master_User: root\n Master_Port: 3306\n Connect_Retry: 3\n Master_Log_File: gbichot-bin.005\n Read_Master_Log_Pos: 79\n Relay_Log_File: gbichot-relay-bin.005\n Relay_Log_Pos: 548\n Relay_Master_Log_File: gbichot-bin.005\n Slave_IO_Running: Yes\n Slave_SQL_Running: Yes\n Replicate_Do_DB:\n Replicate_Ignore_DB:\n Replicate_Do_Table:\n Replicate_Ignore_Table:\n Replicate_Wild_Do_Table:\n Replicate_Wild_Ignore_Table:\n Last_Errno: 0\n Last_Error:\n Skip_Counter: 0\n Exec_Master_Log_Pos: 79\n Relay_Log_Space: 552\n Until_Condition: None\n Until_Log_File:\n Until_Log_Pos: 0\n Master_SSL_Allowed: No\n Master_SSL_CA_File:\n Master_SSL_CA_Path:\n Master_SSL_Cert:\n Master_SSL_Cipher:\n Master_SSL_Key:\n Seconds_Behind_Master: 8\nMaster_SSL_Verify_Server_Cert: No\n Last_IO_Errno: 0\n Last_IO_Error:\n Last_SQL_Errno: 0\n Last_SQL_Error:\n Replicate_Ignore_Server_Ids: 0\n Master_Server_Id: 1\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-slave-status.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-slave-status.html'),(224,'GEOMETRY',34,'MySQL provides a standard way of creating spatial columns for geometry\ntypes, for example, with CREATE TABLE or ALTER TABLE. Currently,\nspatial columns are supported for MyISAM, InnoDB, NDB, and ARCHIVE\ntables. See also the annotations about spatial indexes under [HELP\nSPATIAL].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-columns.html\n\n','CREATE TABLE geom (g GEOMETRY);\n','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-columns.html'),(225,'NUMPOINTS',13,'NumPoints(ls)\n\nReturns the number of Point objects in the LineString value ls.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions\n\n','mysql> SET @ls = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT NumPoints(GeomFromText(@ls));\n+------------------------------+\n| NumPoints(GeomFromText(@ls)) |\n+------------------------------+\n| 3 |\n+------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions'),(226,'ALTER LOGFILE GROUP',39,'Syntax:\nALTER LOGFILE GROUP logfile_group\n ADD UNDOFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement adds an UNDO file named \'file_name\' to an existing log\nfile group logfile_group. An ALTER LOGFILE GROUP statement has one and\nonly one ADD UNDOFILE clause. No DROP UNDOFILE clause is currently\nsupported.\n\n*Note*: All MySQL Cluster Disk Data objects share the same namespace.\nThis means that each Disk Data object must be uniquely named (and not\nmerely each Disk Data object of a given type). For example, you cannot\nhave a tablespace and an undo log file with the same name, or an undo\nlog file and a data file with the same name.\n\nThe optional INITIAL_SIZE parameter sets the UNDO file\'s initial size\nin bytes; if not specified, the initial size default to 128M (128\nmegabytes). You may optionally follow size with a one-letter\nabbreviation for an order of magnitude, similar to those used in\nmy.cnf. Generally, this is one of the letters M (for megabytes) or G\n(for gigabytes).\n\nOn 32-bit systems, the maximum supported value for INITIAL_SIZE is 4G.\n(Bug #29186)\n\nThe minimum permitted value for INITIAL_SIZE is 1M. (Bug #29574)\n\n*Note*: WAIT is parsed but otherwise ignored. This keyword currently\nhas no effect, and is intended for future expansion.\n\nThe ENGINE parameter (required) determines the storage engine which is\nused by this log file group, with engine_name being the name of the\nstorage engine. Currently, the only accepted values for engine_name are\n\"NDBCLUSTER\" and \"NDB\". The two values are equivalent.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-logfile-group.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-logfile-group.html'),(227,'&',19,'Syntax:\n&\n\nBitwise AND:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 29 & 15;\n -> 13\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(228,'LOCALTIMESTAMP',31,'Syntax:\nLOCALTIMESTAMP, LOCALTIMESTAMP()\n\nLOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(229,'ASSIGN-EQUAL',15,'Syntax:\n=\n\nThis operator is used to perform value assignments in two cases,\ndescribed in the next two paragraphs.\n\nWithin a SET statement, = is treated as an assignment operator that\ncauses the user variable on the left hand side of the operator to take\non the value to its right. (In other words, when used in a SET\nstatement, = is treated identically to :=.) The value on the right hand\nside may be a literal value, another variable storing a value, or any\nlegal expression that yields a scalar value, including the result of a\nquery (provided that this value is a scalar value). You can perform\nmultiple assignments in the same SET statement.\n\nIn the SET clause of an UPDATE statement, = also acts as an assignment\noperator; in this case, however, it causes the column named on the left\nhand side of the operator to assume the value given to the right,\nprovided any WHERE conditions that are part of the UPDATE are met. You\ncan make multiple assignments in the same SET clause of an UPDATE\nstatement.\n\nIn any other context, = is treated as a comparison operator.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/assignment-operators.html\n\n','mysql> SELECT @var1, @var2;\n -> NULL, NULL\nmysql> SELECT @var1 := 1, @var2;\n -> 1, NULL\nmysql> SELECT @var1, @var2;\n -> 1, NULL\nmysql> SELECT @var1, @var2 := @var1;\n -> 1, 1\nmysql> SELECT @var1, @var2;\n -> 1, 1\n','http://dev.mysql.com/doc/refman/5.5/en/assignment-operators.html'),(230,'CONVERT',37,'Syntax:\nCONVERT(expr,type), CONVERT(expr USING transcoding_name)\n\nThe CONVERT() and CAST() functions take an expression of any type and\nproduce a result value of a specified type.\n\nThe type for the result can be one of the following values:\n\no BINARY[(N)]\n\no CHAR[(N)]\n\no DATE\n\no DATETIME\n\no DECIMAL[(M[,D])]\n\no SIGNED [INTEGER]\n\no TIME\n\no UNSIGNED [INTEGER]\n\nBINARY produces a string with the BINARY data type. See\nhttp://dev.mysql.com/doc/refman/5.5/en/binary-varbinary.html for a\ndescription of how this affects comparisons. If the optional length N\nis given, BINARY(N) causes the cast to use no more than N bytes of the\nargument. Values shorter than N bytes are padded with 0x00 bytes to a\nlength of N.\n\nCHAR(N) causes the cast to use no more than N characters of the\nargument.\n\nCAST() and CONVERT(... USING ...) are standard SQL syntax. The\nnon-USING form of CONVERT() is ODBC syntax.\n\nCONVERT() with USING is used to convert data between different\ncharacter sets. In MySQL, transcoding names are the same as the\ncorresponding character set names. For example, this statement converts\nthe string \'abc\' in the default character set to the corresponding\nstring in the utf8 character set:\n\nSELECT CONVERT(\'abc\' USING utf8);\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html\n\n','SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);\n','http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html'),(231,'ADDDATE',31,'Syntax:\nADDDATE(date,INTERVAL expr unit), ADDDATE(expr,days)\n\nWhen invoked with the INTERVAL form of the second argument, ADDDATE()\nis a synonym for DATE_ADD(). The related function SUBDATE() is a\nsynonym for DATE_SUB(). For information on the INTERVAL unit argument,\nsee the discussion for DATE_ADD().\n\nmysql> SELECT DATE_ADD(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\nmysql> SELECT ADDDATE(\'2008-01-02\', INTERVAL 31 DAY);\n -> \'2008-02-02\'\n\nWhen invoked with the days form of the second argument, MySQL treats it\nas an integer number of days to be added to expr.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT ADDDATE(\'2008-01-02\', 31);\n -> \'2008-02-02\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(232,'REPEAT LOOP',23,'Syntax:\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\nThe statement list within a REPEAT statement is repeated until the\nsearch_condition expression is true. Thus, a REPEAT always enters the\nloop at least once. statement_list consists of one or more statements,\neach terminated by a semicolon (;) statement delimiter.\n\nA REPEAT statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/repeat.html\n\n','mysql> delimiter //\n\nmysql> CREATE PROCEDURE dorepeat(p1 INT)\n -> BEGIN\n -> SET @x = 0;\n -> REPEAT\n -> SET @x = @x + 1;\n -> UNTIL @x > p1 END REPEAT;\n -> END\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> CALL dorepeat(1000)//\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT @x//\n+------+\n| @x |\n+------+\n| 1001 |\n+------+\n1 row in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/repeat.html'),(233,'ALTER FUNCTION',39,'Syntax:\nALTER FUNCTION func_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nfunction. More than one change may be specified in an ALTER FUNCTION\nstatement. However, you cannot change the parameters or body of a\nstored function using this statement; to make such changes, you must\ndrop and re-create the function using DROP FUNCTION and CREATE\nFUNCTION.\n\nYou must have the ALTER ROUTINE privilege for the function. (That\nprivilege is granted automatically to the function creator.) If binary\nlogging is enabled, the ALTER FUNCTION statement might also require the\nSUPER privilege, as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-logging.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-function.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-function.html'),(234,'SMALLINT',22,'SMALLINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA small integer. The signed range is -32768 to 32767. The unsigned\nrange is 0 to 65535.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(235,'DOUBLE PRECISION',22,'DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED]\n[ZEROFILL]\n\nThese types are synonyms for DOUBLE. Exception: If the REAL_AS_FLOAT\nSQL mode is enabled, REAL is a synonym for FLOAT rather than DOUBLE.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(236,'ORD',37,'Syntax:\nORD(str)\n\nIf the leftmost character of the string str is a multi-byte character,\nreturns the code for that character, calculated from the numeric values\nof its constituent bytes using this formula:\n\n (1st byte code)\n+ (2nd byte code * 256)\n+ (3rd byte code * 2562) ...\n\nIf the leftmost character is not a multi-byte character, ORD() returns\nthe same value as the ASCII() function.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT ORD(\'2\');\n -> 50\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(237,'DEALLOCATE PREPARE',8,'Syntax:\n{DEALLOCATE | DROP} PREPARE stmt_name\n\nTo deallocate a prepared statement produced with PREPARE, use a\nDEALLOCATE PREPARE statement that refers to the prepared statement\nname. Attempting to execute a prepared statement after deallocating it\nresults in an error.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/deallocate-prepare.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/deallocate-prepare.html'),(238,'ENVELOPE',36,'Envelope(g)\n\nReturns the Minimum Bounding Rectangle (MBR) for the geometry value g.\nThe result is returned as a Polygon value.\n\nThe polygon is defined by the corner points of the bounding box:\n\nPOLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','mysql> SELECT AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\')));\n+-------------------------------------------------------+\n| AsText(Envelope(GeomFromText(\'LineString(1 1,2 2)\'))) |\n+-------------------------------------------------------+\n| POLYGON((1 1,2 1,2 2,1 2,1 1)) |\n+-------------------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(239,'IS_FREE_LOCK',14,'Syntax:\nIS_FREE_LOCK(str)\n\nChecks whether the lock named str is free to use (that is, not locked).\nReturns 1 if the lock is free (no one is using the lock), 0 if the lock\nis in use, and NULL if an error occurs (such as an incorrect argument).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(240,'TOUCHES',30,'Touches(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially touches g2. Two\ngeometries spatially touch if the interiors of the geometries do not\nintersect, but the boundary of one of the geometries intersects either\nthe boundary or the interior of the other.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(241,'INET_ATON',14,'Syntax:\nINET_ATON(expr)\n\nGiven the dotted-quad representation of an IPv4 network address as a\nstring, returns an integer that represents the numeric value of the\naddress in network byte order (big endian). INET_ATON() returns NULL if\nit does not understand its argument.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> SELECT INET_ATON(\'10.0.5.9\');\n -> 167773449\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(242,'UNCOMPRESS',12,'Syntax:\nUNCOMPRESS(string_to_uncompress)\n\nUncompresses a string compressed by the COMPRESS() function. If the\nargument is not a compressed value, the result is NULL. This function\nrequires MySQL to have been compiled with a compression library such as\nzlib. Otherwise, the return value is always NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT UNCOMPRESS(COMPRESS(\'any string\'));\n -> \'any string\'\nmysql> SELECT UNCOMPRESS(\'any string\');\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(243,'AUTO_INCREMENT',22,'The AUTO_INCREMENT attribute can be used to generate a unique identity\nfor new rows:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html\n\n','CREATE TABLE animals (\n id MEDIUMINT NOT NULL AUTO_INCREMENT,\n name CHAR(30) NOT NULL,\n PRIMARY KEY (id)\n);\n\nINSERT INTO animals (name) VALUES\n (\'dog\'),(\'cat\'),(\'penguin\'),\n (\'lax\'),(\'whale\'),(\'ostrich\');\n\nSELECT * FROM animals;\n','http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html'),(244,'ISSIMPLE',36,'IsSimple(g)\n\nCurrently, this function is a placeholder and should not be used. If\nimplemented, its behavior will be as described in the next paragraph.\n\nReturns 1 if the geometry value g has no anomalous geometric points,\nsuch as self-intersection or self-tangency. IsSimple() returns 0 if the\nargument is not simple, and -1 if it is NULL.\n\nThe description of each instantiable geometric class given earlier in\nthe chapter includes the specific conditions that cause an instance of\nthat class to be classified as not simple. (See [HELP Geometry\nhierarchy].)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(245,'- BINARY',4,'Syntax:\n-\n\nSubtraction:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT 3-5;\n -> -2\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(246,'GEOMCOLLFROMTEXT',3,'GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])\n\nConstructs a GEOMETRYCOLLECTION value using its WKT representation and\nSRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(247,'WKT DEFINITION',3,'The Well-Known Text (WKT) representation of Geometry is designed to\nexchange geometry data in ASCII form. For a Backus-Naur grammar that\nspecifies the formal production rules for writing WKT values, see the\nOpenGIS specification document referenced in\nhttp://dev.mysql.com/doc/refman/5.5/en/spatial-extensions.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/gis-wkt-format.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/gis-wkt-format.html'),(248,'CURRENT_TIME',31,'Syntax:\nCURRENT_TIME, CURRENT_TIME()\n\nCURRENT_TIME and CURRENT_TIME() are synonyms for CURTIME().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(249,'REVOKE',10,'Syntax:\nREVOKE\n priv_type [(column_list)]\n [, priv_type [(column_list)]] ...\n ON [object_type] priv_level\n FROM user [, user] ...\n\nREVOKE ALL PRIVILEGES, GRANT OPTION\n FROM user [, user] ...\n\nREVOKE PROXY ON user\n FROM user [, user] ...\n\nThe REVOKE statement enables system administrators to revoke privileges\nfrom MySQL accounts. Each account name uses the format described in\nhttp://dev.mysql.com/doc/refman/5.5/en/account-names.html. For example:\n\nREVOKE INSERT ON *.* FROM \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nFor details on the levels at which privileges exist, the permissible\npriv_type and priv_level values, and the syntax for specifying users\nand passwords, see [HELP GRANT]\n\nTo use the first REVOKE syntax, you must have the GRANT OPTION\nprivilege, and you must have the privileges that you are revoking.\n\nTo revoke all privileges, use the second syntax, which drops all\nglobal, database, table, column, and routine privileges for the named\nuser or users:\n\nREVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...\n\nTo use this REVOKE syntax, you must have the global CREATE USER\nprivilege or the UPDATE privilege for the mysql database.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/revoke.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/revoke.html'),(250,'LAST_INSERT_ID',17,'Syntax:\nLAST_INSERT_ID(), LAST_INSERT_ID(expr)\n\nLAST_INSERT_ID() (with no argument) returns a BIGINT (64-bit) value\nrepresenting the first automatically generated value successfully\ninserted for an AUTO_INCREMENT column as a result of the most recently\nexecuted INSERT statement. The value of LAST_INSERT_ID() remains\nunchanged if no rows are successfully inserted.\n\nFor example, after inserting a row that generates an AUTO_INCREMENT\nvalue, you can get the value like this:\n\nmysql> SELECT LAST_INSERT_ID();\n -> 195\n\nThe currently executing statement does not affect the value of\nLAST_INSERT_ID(). Suppose that you generate an AUTO_INCREMENT value\nwith one statement, and then refer to LAST_INSERT_ID() in a\nmultiple-row INSERT statement that inserts rows into a table with its\nown AUTO_INCREMENT column. The value of LAST_INSERT_ID() will remain\nstable in the second statement; its value for the second and later rows\nis not affected by the earlier row insertions. (However, if you mix\nreferences to LAST_INSERT_ID() and LAST_INSERT_ID(expr), the effect is\nundefined.)\n\nIf the previous statement returned an error, the value of\nLAST_INSERT_ID() is undefined. For transactional tables, if the\nstatement is rolled back due to an error, the value of LAST_INSERT_ID()\nis left undefined. For manual ROLLBACK, the value of LAST_INSERT_ID()\nis not restored to that before the transaction; it remains as it was at\nthe point of the ROLLBACK.\n\nWithin the body of a stored routine (procedure or function) or a\ntrigger, the value of LAST_INSERT_ID() changes the same way as for\nstatements executed outside the body of these kinds of objects. The\neffect of a stored routine or trigger upon the value of\nLAST_INSERT_ID() that is seen by following statements depends on the\nkind of routine:\n\no If a stored procedure executes statements that change the value of\n LAST_INSERT_ID(), the changed value is seen by statements that follow\n the procedure call.\n\no For stored functions and triggers that change the value, the value is\n restored when the function or trigger ends, so following statements\n will not see a changed value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(251,'LAST_DAY',31,'Syntax:\nLAST_DAY(date)\n\nTakes a date or datetime value and returns the corresponding value for\nthe last day of the month. Returns NULL if the argument is invalid.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT LAST_DAY(\'2003-02-05\');\n -> \'2003-02-28\'\nmysql> SELECT LAST_DAY(\'2004-02-05\');\n -> \'2004-02-29\'\nmysql> SELECT LAST_DAY(\'2004-01-01 01:01:01\');\n -> \'2004-01-31\'\nmysql> SELECT LAST_DAY(\'2003-03-32\');\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(252,'MEDIUMINT',22,'MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]\n\nA medium-sized integer. The signed range is -8388608 to 8388607. The\nunsigned range is 0 to 16777215.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(253,'FLOOR',4,'Syntax:\nFLOOR(X)\n\nReturns the largest integer value not greater than X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT FLOOR(1.23);\n -> 1\nmysql> SELECT FLOOR(-1.23);\n -> -2\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(254,'RTRIM',37,'Syntax:\nRTRIM(str)\n\nReturns the string str with trailing space characters removed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT RTRIM(\'barbar \');\n -> \'barbar\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(255,'EXPLAIN',28,'Syntax:\nEXPLAIN [explain_type] SELECT select_options\n\nexplain_type:\n EXTENDED\n | PARTITIONS\n\nOr:\n\nEXPLAIN tbl_name\n\nThe EXPLAIN statement can be used either as a way to obtain information\nabout how MySQL executes a statement, or as a synonym for DESCRIBE:\n\no When you precede a SELECT statement with the keyword EXPLAIN, MySQL\n displays information from the optimizer about the query execution\n plan. That is, MySQL explains how it would process the statement,\n including information about how tables are joined and in which order.\n EXPLAIN EXTENDED can be used to obtain additional information.\n\n For information about using EXPLAIN and EXPLAIN EXTENDED to obtain\n query execution plan information, see\n http://dev.mysql.com/doc/refman/5.5/en/using-explain.html.\n\no EXPLAIN PARTITIONS is useful only when examining queries involving\n partitioned tables. For details, see\n http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.\n\no EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS\n FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see\n [HELP DESCRIBE], and [HELP SHOW COLUMNS].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/explain.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/explain.html'),(256,'DEGREES',4,'Syntax:\nDEGREES(X)\n\nReturns the argument X, converted from radians to degrees.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT DEGREES(PI());\n -> 180\nmysql> SELECT DEGREES(PI() / 2);\n -> 90\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(257,'VARCHAR',22,'[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA variable-length string. M represents the maximum column length in\ncharacters. The range of M is 0 to 65,535. The effective maximum length\nof a VARCHAR is subject to the maximum row size (65,535 bytes, which is\nshared among all columns) and the character set used. For example, utf8\ncharacters can require up to three bytes per character, so a VARCHAR\ncolumn that uses the utf8 character set can be declared to be a maximum\nof 21,844 characters. See\nhttp://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html.\n\nMySQL stores VARCHAR values as a 1-byte or 2-byte length prefix plus\ndata. The length prefix indicates the number of bytes in the value. A\nVARCHAR column uses one length byte if values require no more than 255\nbytes, two length bytes if values may require more than 255 bytes.\n\n*Note*: MySQL 5.5 follows the standard SQL specification, and does not\nremove trailing spaces from VARCHAR values.\n\nVARCHAR is shorthand for CHARACTER VARYING. NATIONAL VARCHAR is the\nstandard SQL way to define that a VARCHAR column should use some\npredefined character set. MySQL 4.1 and up uses utf8 as this predefined\ncharacter set.\nhttp://dev.mysql.com/doc/refman/5.5/en/charset-national.html. NVARCHAR\nis shorthand for NATIONAL VARCHAR.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(258,'UNHEX',37,'Syntax:\n\nUNHEX(str)\n\nFor a string argument str, UNHEX(str) performs the inverse operation of\nHEX(str). That is, it interprets each pair of characters in the\nargument as a hexadecimal number and converts it to the character\nrepresented by the number. The return value is a binary string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT UNHEX(\'4D7953514C\');\n -> \'MySQL\'\nmysql> SELECT 0x4D7953514C;\n -> \'MySQL\'\nmysql> SELECT UNHEX(HEX(\'string\'));\n -> \'string\'\nmysql> SELECT HEX(UNHEX(\'1267\'));\n -> \'1267\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(259,'- UNARY',4,'Syntax:\n-\n\nUnary minus. This operator changes the sign of the operand.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT - 2;\n -> -2\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(260,'STD',16,'Syntax:\nSTD(expr)\n\nReturns the population standard deviation of expr. This is an extension\nto standard SQL. The standard SQL function STDDEV_POP() can be used\ninstead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(261,'COS',4,'Syntax:\nCOS(X)\n\nReturns the cosine of X, where X is given in radians.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT COS(PI());\n -> -1\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(262,'DATE FUNCTION',31,'Syntax:\nDATE(expr)\n\nExtracts the date part of the date or datetime expression expr.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DATE(\'2003-12-31 01:02:03\');\n -> \'2003-12-31\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(263,'DROP TRIGGER',39,'Syntax:\nDROP TRIGGER [IF EXISTS] [schema_name.]trigger_name\n\nThis statement drops a trigger. The schema (database) name is optional.\nIf the schema is omitted, the trigger is dropped from the default\nschema. DROP TRIGGER requires the TRIGGER privilege for the table\nassociated with the trigger.\n\nUse IF EXISTS to prevent an error from occurring for a trigger that\ndoes not exist. A NOTE is generated for a nonexistent trigger when\nusing IF EXISTS. See [HELP SHOW WARNINGS].\n\nTriggers for a table are also dropped if you drop the table.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-trigger.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-trigger.html'),(264,'RESET MASTER',8,'Syntax:\nRESET MASTER\n\nDeletes all binary log files listed in the index file, resets the\nbinary log index file to be empty, and creates a new binary log file.\nThis statement is intended to be used only when the master is started\nfor the first time.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/reset-master.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/reset-master.html'),(265,'TAN',4,'Syntax:\nTAN(X)\n\nReturns the tangent of X, where X is given in radians.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT TAN(PI());\n -> -1.2246063538224e-16\nmysql> SELECT TAN(PI()+1);\n -> 1.5574077246549\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(266,'PI',4,'Syntax:\nPI()\n\nReturns the value of π (pi). The default number of decimal places\ndisplayed is seven, but MySQL uses the full double-precision value\ninternally.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT PI();\n -> 3.141593\nmysql> SELECT PI()+0.000000000000000000;\n -> 3.141592653589793116\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(267,'WEEKOFYEAR',31,'Syntax:\nWEEKOFYEAR(date)\n\nReturns the calendar week of the date as a number in the range from 1\nto 53. WEEKOFYEAR() is a compatibility function that is equivalent to\nWEEK(date,3).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT WEEKOFYEAR(\'2008-02-20\');\n -> 8\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(268,'/',4,'Syntax:\n/\n\nDivision:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT 3/5;\n -> 0.60\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(269,'PURGE BINARY LOGS',8,'Syntax:\nPURGE { BINARY | MASTER } LOGS\n { TO \'log_name\' | BEFORE datetime_expr }\n\nThe binary log is a set of files that contain information about data\nmodifications made by the MySQL server. The log consists of a set of\nbinary log files, plus an index file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/binary-log.html).\n\nThe PURGE BINARY LOGS statement deletes all the binary log files listed\nin the log index file prior to the specified log file name or date.\nBINARY and MASTER are synonyms. Deleted log files also are removed from\nthe list recorded in the index file, so that the given log file becomes\nthe first in the list.\n\nThis statement has no effect if the server was not started with the\n--log-bin option to enable binary logging.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/purge-binary-logs.html\n\n','PURGE BINARY LOGS TO \'mysql-bin.010\';\nPURGE BINARY LOGS BEFORE \'2008-04-02 22:46:26\';\n','http://dev.mysql.com/doc/refman/5.5/en/purge-binary-logs.html'),(270,'STDDEV_SAMP',16,'Syntax:\nSTDDEV_SAMP(expr)\n\nReturns the sample standard deviation of expr (the square root of\nVAR_SAMP().\n\nSTDDEV_SAMP() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(271,'SCHEMA',17,'Syntax:\nSCHEMA()\n\nThis function is a synonym for DATABASE().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(272,'MLINEFROMWKB',32,'MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])\n\nConstructs a MULTILINESTRING value using its WKB representation and\nSRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(273,'LOG2',4,'Syntax:\nLOG2(X)\n\nReturns the base-2 logarithm of X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT LOG2(65536);\n -> 16\nmysql> SELECT LOG2(-100);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(274,'SUBTIME',31,'Syntax:\nSUBTIME(expr1,expr2)\n\nSUBTIME() returns expr1 - expr2 expressed as a value in the same format\nas expr1. expr1 is a time or datetime expression, and expr2 is a time\nexpression.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT SUBTIME(\'2007-12-31 23:59:59.999999\',\'1 1:1:1.000002\');\n -> \'2007-12-30 22:58:58.999997\'\nmysql> SELECT SUBTIME(\'01:00:00.999999\', \'02:00:00.999998\');\n -> \'-00:59:59.999999\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(275,'UNCOMPRESSED_LENGTH',12,'Syntax:\nUNCOMPRESSED_LENGTH(compressed_string)\n\nReturns the length that the compressed string had before being\ncompressed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT(\'a\',30)));\n -> 30\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(276,'DROP TABLE',39,'Syntax:\nDROP [TEMPORARY] TABLE [IF EXISTS]\n tbl_name [, tbl_name] ...\n [RESTRICT | CASCADE]\n\nDROP TABLE removes one or more tables. You must have the DROP privilege\nfor each table. All table data and the table definition are removed, so\nbe careful with this statement! If any of the tables named in the\nargument list do not exist, MySQL returns an error indicating by name\nwhich nonexisting tables it was unable to drop, but it also drops all\nof the tables in the list that do exist.\n\n*Important*: When a table is dropped, user privileges on the table are\nnot automatically dropped. See [HELP GRANT].\n\nNote that for a partitioned table, DROP TABLE permanently removes the\ntable definition, all of its partitions, and all of the data which was\nstored in those partitions. It also removes the partitioning definition\n(.par) file associated with the dropped table.\n\nUse IF EXISTS to prevent an error from occurring for tables that do not\nexist. A NOTE is generated for each nonexistent table when using IF\nEXISTS. See [HELP SHOW WARNINGS].\n\nRESTRICT and CASCADE are permitted to make porting easier. In MySQL\n5.5, they do nothing.\n\n*Note*: DROP TABLE automatically commits the current active\ntransaction, unless you use the TEMPORARY keyword.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-table.html'),(277,'POW',4,'Syntax:\nPOW(X,Y)\n\nReturns the value of X raised to the power of Y.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT POW(2,2);\n -> 4\nmysql> SELECT POW(2,-2);\n -> 0.25\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(278,'SHOW CREATE TABLE',26,'Syntax:\nSHOW CREATE TABLE tbl_name\n\nShows the CREATE TABLE statement that creates the given table. To use\nthis statement, you must have some privilege for the table. This\nstatement also works with views.\nSHOW CREATE TABLE quotes table and column names according to the value\nof the sql_quote_show_create option. See\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-table.html\n\n','mysql> SHOW CREATE TABLE t\\G\n*************************** 1. row ***************************\n Table: t\nCreate Table: CREATE TABLE t (\n id INT(11) default NULL auto_increment,\n s char(60) default NULL,\n PRIMARY KEY (id)\n) ENGINE=MyISAM\n','http://dev.mysql.com/doc/refman/5.5/en/show-create-table.html'),(279,'DUAL',27,'You are permitted to specify DUAL as a dummy table name in situations\nwhere no tables are referenced:\n\nmysql> SELECT 1 + 1 FROM DUAL;\n -> 2\n\nDUAL is purely for the convenience of people who require that all\nSELECT statements should have FROM and possibly other clauses. MySQL\nmay ignore the clauses. MySQL does not require FROM DUAL if no tables\nare referenced.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/select.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/select.html'),(280,'INSTR',37,'Syntax:\nINSTR(str,substr)\n\nReturns the position of the first occurrence of substring substr in\nstring str. This is the same as the two-argument form of LOCATE(),\nexcept that the order of the arguments is reversed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT INSTR(\'foobarbar\', \'bar\');\n -> 4\nmysql> SELECT INSTR(\'xbar\', \'foobar\');\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(281,'NOW',31,'Syntax:\nNOW()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context. The value is expressed in the\ncurrent time zone.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT NOW();\n -> \'2007-12-15 23:50:26\'\nmysql> SELECT NOW() + 0;\n -> 20071215235026.000000\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(282,'SHOW ENGINES',26,'Syntax:\nSHOW [STORAGE] ENGINES\n\nSHOW ENGINES displays status information about the server\'s storage\nengines. This is particularly useful for checking whether a storage\nengine is supported, or to see what the default engine is.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-engines.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-engines.html'),(283,'>=',18,'Syntax:\n>=\n\nGreater than or equal:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 2 >= 2;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(284,'EXP',4,'Syntax:\nEXP(X)\n\nReturns the value of e (the base of natural logarithms) raised to the\npower of X. The inverse of this function is LOG() (using a single\nargument only) or LN().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT EXP(2);\n -> 7.3890560989307\nmysql> SELECT EXP(-2);\n -> 0.13533528323661\nmysql> SELECT EXP(0);\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(285,'LONGBLOB',22,'LONGBLOB\n\nA BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1)\nbytes. The effective maximum length of LONGBLOB columns depends on the\nconfigured maximum packet size in the client/server protocol and\navailable memory. Each LONGBLOB value is stored using a 4-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(286,'POINTN',13,'PointN(ls,N)\n\nReturns the N-th Point in the Linestring value ls. Points are numbered\nbeginning with 1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions\n\n','mysql> SET @ls = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT AsText(PointN(GeomFromText(@ls),2));\n+-------------------------------------+\n| AsText(PointN(GeomFromText(@ls),2)) |\n+-------------------------------------+\n| POINT(2 2) |\n+-------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions'),(287,'YEAR DATA TYPE',22,'YEAR[(2|4)]\n\nA year in two-digit or four-digit format. The default is four-digit\nformat. YEAR(2) or YEAR(4) differ in display format, but have the same\nrange of values. In four-digit format, values display as 1901 to 2155,\nand 0000. In two-digit format, values display as 70 to 69, representing\nyears from 1970 to 2069. MySQL displays YEAR values in YYYY or\nYYformat, but permits assignment of values to YEAR columns using either\nstrings or numbers.\n\n*Note*: The YEAR(2) data type has certain issues that you should\nconsider before choosing to use it. As of MySQL 5.5.27, YEAR(2) is\ndeprecated. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/migrating-to-year4.html.\n\nFor additional information about YEAR display format and inerpretation\nof input values, see http://dev.mysql.com/doc/refman/5.5/en/year.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html'),(288,'SUM',16,'Syntax:\nSUM([DISTINCT] expr)\n\nReturns the sum of expr. If the return set has no rows, SUM() returns\nNULL. The DISTINCT keyword can be used to sum only the distinct values\nof expr.\n\nSUM() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(289,'OCT',37,'Syntax:\nOCT(N)\n\nReturns a string representation of the octal value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,8). Returns\nNULL if N is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT OCT(12);\n -> \'14\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(290,'SYSDATE',31,'Syntax:\nSYSDATE()\n\nReturns the current date and time as a value in \'YYYY-MM-DD HH:MM:SS\'\nor YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is\nused in a string or numeric context.\n\nSYSDATE() returns the time at which it executes. This differs from the\nbehavior for NOW(), which returns a constant time that indicates the\ntime at which the statement began to execute. (Within a stored function\nor trigger, NOW() returns the time at which the function or triggering\nstatement began to execute.)\n\nmysql> SELECT NOW(), SLEEP(2), NOW();\n+---------------------+----------+---------------------+\n| NOW() | SLEEP(2) | NOW() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |\n+---------------------+----------+---------------------+\n\nmysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();\n+---------------------+----------+---------------------+\n| SYSDATE() | SLEEP(2) | SYSDATE() |\n+---------------------+----------+---------------------+\n| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |\n+---------------------+----------+---------------------+\n\nIn addition, the SET TIMESTAMP statement affects the value returned by\nNOW() but not by SYSDATE(). This means that timestamp settings in the\nbinary log have no effect on invocations of SYSDATE().\n\nBecause SYSDATE() can return different values even within the same\nstatement, and is not affected by SET TIMESTAMP, it is nondeterministic\nand therefore unsafe for replication if statement-based binary logging\nis used. If that is a problem, you can use row-based logging.\n\nAlternatively, you can use the --sysdate-is-now option to cause\nSYSDATE() to be an alias for NOW(). This works if the option is used on\nboth the master and the slave.\n\nThe nondeterministic nature of SYSDATE() also means that indexes cannot\nbe used for evaluating expressions that refer to it.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(291,'UNINSTALL PLUGIN',5,'Syntax:\nUNINSTALL PLUGIN plugin_name\n\nThis statement removes an installed server plugin. It requires the\nDELETE privilege for the mysql.plugin table.\n\nplugin_name must be the name of some plugin that is listed in the\nmysql.plugin table. The server executes the plugin\'s deinitialization\nfunction and removes the row for the plugin from the mysql.plugin\ntable, so that subsequent server restarts will not load and initialize\nthe plugin. UNINSTALL PLUGIN does not remove the plugin\'s shared\nlibrary file.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/uninstall-plugin.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/uninstall-plugin.html'),(292,'ASBINARY',32,'AsBinary(g), AsWKB(g)\n\nConverts a value in internal geometry format to its WKB representation\nand returns the binary result.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html\n\n','SELECT AsBinary(g) FROM geom;\n','http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html'),(293,'REPEAT FUNCTION',37,'Syntax:\nREPEAT(str,count)\n\nReturns a string consisting of the string str repeated count times. If\ncount is less than 1, returns an empty string. Returns NULL if str or\ncount are NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT REPEAT(\'MySQL\', 3);\n -> \'MySQLMySQLMySQL\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(294,'SHOW TABLES',26,'Syntax:\nSHOW [FULL] TABLES [{FROM | IN} db_name]\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW TABLES lists the non-TEMPORARY tables in a given database. You can\nalso get this list using the mysqlshow db_name command. The LIKE\nclause, if present, indicates which table names to match. The WHERE\nclause can be given to select rows using more general conditions, as\ndiscussed in http://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nThis statement also lists any views in the database. The FULL modifier\nis supported such that SHOW FULL TABLES displays a second output\ncolumn. Values for the second column are BASE TABLE for a table and\nVIEW for a view.\n\nIf you have no privileges for a base table or view, it does not show up\nin the output from SHOW TABLES or mysqlshow db_name.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-tables.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-tables.html'),(295,'MAKEDATE',31,'Syntax:\nMAKEDATE(year,dayofyear)\n\nReturns a date, given year and day-of-year values. dayofyear must be\ngreater than 0 or the result is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MAKEDATE(2011,31), MAKEDATE(2011,32);\n -> \'2011-01-31\', \'2011-02-01\'\nmysql> SELECT MAKEDATE(2011,365), MAKEDATE(2014,365);\n -> \'2011-12-31\', \'2014-12-31\'\nmysql> SELECT MAKEDATE(2011,0);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(296,'BINARY OPERATOR',37,'Syntax:\nBINARY\n\nThe BINARY operator casts the string following it to a binary string.\nThis is an easy way to force a column comparison to be done byte by\nbyte rather than character by character. This causes the comparison to\nbe case sensitive even if the column is not defined as BINARY or BLOB.\nBINARY also causes trailing spaces to be significant.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html\n\n','mysql> SELECT \'a\' = \'A\';\n -> 1\nmysql> SELECT BINARY \'a\' = \'A\';\n -> 0\nmysql> SELECT \'a\' = \'a \';\n -> 1\nmysql> SELECT BINARY \'a\' = \'a \';\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html'),(297,'MBROVERLAPS',6,'MBROverlaps(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 overlap. The term spatially overlaps is\nused if two geometries intersect and their intersection results in a\ngeometry of the same dimension but not equal to either of the given\ngeometries.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(298,'SOUNDEX',37,'Syntax:\nSOUNDEX(str)\n\nReturns a soundex string from str. Two strings that sound almost the\nsame should have identical soundex strings. A standard soundex string\nis four characters long, but the SOUNDEX() function returns an\narbitrarily long string. You can use SUBSTRING() on the result to get a\nstandard soundex string. All nonalphabetic characters in str are\nignored. All international alphabetic characters outside the A-Z range\nare treated as vowels.\n\n*Important*: When using SOUNDEX(), you should be aware of the following\nlimitations:\n\no This function, as currently implemented, is intended to work well\n with strings that are in the English language only. Strings in other\n languages may not produce reliable results.\n\no This function is not guaranteed to provide consistent results with\n strings that use multi-byte character sets, including utf-8.\n\n We hope to remove these limitations in a future release. See Bug\n #22638 for more information.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT SOUNDEX(\'Hello\');\n -> \'H400\'\nmysql> SELECT SOUNDEX(\'Quadratically\');\n -> \'Q36324\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(299,'MBRTOUCHES',6,'MBRTouches(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 touch. Two geometries spatially touch if\nthe interiors of the geometries do not intersect, but the boundary of\none of the geometries intersects either the boundary or the interior of\nthe other.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(300,'DROP EVENT',39,'Syntax:\nDROP EVENT [IF EXISTS] event_name\n\nThis statement drops the event named event_name. The event immediately\nceases being active, and is deleted completely from the server.\n\nIf the event does not exist, the error ERROR 1517 (HY000): Unknown\nevent \'event_name\' results. You can override this and cause the\nstatement to generate a warning for nonexistent events instead using IF\nEXISTS.\n\nThis statement requires the EVENT privilege for the schema to which the\nevent to be dropped belongs.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-event.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-event.html'),(301,'INSERT SELECT',27,'Syntax:\nINSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]\n [INTO] tbl_name [(col_name,...)]\n SELECT ...\n [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]\n\nWith INSERT ... SELECT, you can quickly insert many rows into a table\nfrom one or many tables. For example:\n\nINSERT INTO tbl_temp2 (fld_id)\n SELECT tbl_temp1.fld_order_id\n FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/insert-select.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/insert-select.html'),(302,'CREATE PROCEDURE',39,'Syntax:\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n PROCEDURE sp_name ([proc_parameter[,...]])\n [characteristic ...] routine_body\n\nCREATE\n [DEFINER = { user | CURRENT_USER }]\n FUNCTION sp_name ([func_parameter[,...]])\n RETURNS type\n [characteristic ...] routine_body\n\nproc_parameter:\n [ IN | OUT | INOUT ] param_name type\n\nfunc_parameter:\n param_name type\n\ntype:\n Any valid MySQL data type\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | [NOT] DETERMINISTIC\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nroutine_body:\n Valid SQL routine statement\n\nThese statements create stored routines. By default, a routine is\nassociated with the default database. To associate the routine\nexplicitly with a given database, specify the name as db_name.sp_name\nwhen you create it.\n\nThe CREATE FUNCTION statement is also used in MySQL to support UDFs\n(user-defined functions). See\nhttp://dev.mysql.com/doc/refman/5.5/en/adding-functions.html. A UDF can\nbe regarded as an external stored function. Stored functions share\ntheir namespace with UDFs. See\nhttp://dev.mysql.com/doc/refman/5.5/en/function-resolution.html, for\nthe rules describing how the server interprets references to different\nkinds of functions.\n\nTo invoke a stored procedure, use the CALL statement (see [HELP CALL]).\nTo invoke a stored function, refer to it in an expression. The function\nreturns a value during expression evaluation.\n\nCREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE\nprivilege. They might also require the SUPER privilege, depending on\nthe DEFINER value, as described later in this section. If binary\nlogging is enabled, CREATE FUNCTION might require the SUPER privilege,\nas described in\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-logging.html.\n\nBy default, MySQL automatically grants the ALTER ROUTINE and EXECUTE\nprivileges to the routine creator. This behavior can be changed by\ndisabling the automatic_sp_privileges system variable. See\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-routines-privileges.html.\n\nThe DEFINER and SQL SECURITY clauses specify the security context to be\nused when checking access privileges at routine execution time, as\ndescribed later in this section.\n\nIf the routine name is the same as the name of a built-in SQL function,\na syntax error occurs unless you use a space between the name and the\nfollowing parenthesis when defining the routine or invoking it later.\nFor this reason, avoid using the names of existing SQL functions for\nyour own stored routines.\n\nThe IGNORE_SPACE SQL mode applies to built-in functions, not to stored\nroutines. It is always permissible to have spaces after a stored\nroutine name, regardless of whether IGNORE_SPACE is enabled.\n\nThe parameter list enclosed within parentheses must always be present.\nIf there are no parameters, an empty parameter list of () should be\nused. Parameter names are not case sensitive.\n\nEach parameter is an IN parameter by default. To specify otherwise for\na parameter, use the keyword OUT or INOUT before the parameter name.\n\n*Note*: Specifying a parameter as IN, OUT, or INOUT is valid only for a\nPROCEDURE. For a FUNCTION, parameters are always regarded as IN\nparameters.\n\nAn IN parameter passes a value into a procedure. The procedure might\nmodify the value, but the modification is not visible to the caller\nwhen the procedure returns. An OUT parameter passes a value from the\nprocedure back to the caller. Its initial value is NULL within the\nprocedure, and its value is visible to the caller when the procedure\nreturns. An INOUT parameter is initialized by the caller, can be\nmodified by the procedure, and any change made by the procedure is\nvisible to the caller when the procedure returns.\n\nFor each OUT or INOUT parameter, pass a user-defined variable in the\nCALL statement that invokes the procedure so that you can obtain its\nvalue when the procedure returns. If you are calling the procedure from\nwithin another stored procedure or function, you can also pass a\nroutine parameter or local routine variable as an IN or INOUT\nparameter.\n\nThe following example shows a simple stored procedure that uses an OUT\nparameter:\n\nmysql> delimiter //\n\nmysql> CREATE PROCEDURE simpleproc (OUT param1 INT)\n -> BEGIN\n -> SELECT COUNT(*) INTO param1 FROM t;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> delimiter ;\n\nmysql> CALL simpleproc(@a);\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT @a;\n+------+\n| @a |\n+------+\n| 3 |\n+------+\n1 row in set (0.00 sec)\n\nThe example uses the mysql client delimiter command to change the\nstatement delimiter from ; to // while the procedure is being defined.\nThis enables the ; delimiter used in the procedure body to be passed\nthrough to the server rather than being interpreted by mysql itself.\nSee\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-defining.html.\n\nThe RETURNS clause may be specified only for a FUNCTION, for which it\nis mandatory. It indicates the return type of the function, and the\nfunction body must contain a RETURN value statement. If the RETURN\nstatement returns a value of a different type, the value is coerced to\nthe proper type. For example, if a function specifies an ENUM or SET\nvalue in the RETURNS clause, but the RETURN statement returns an\ninteger, the value returned from the function is the string for the\ncorresponding ENUM member of set of SET members.\n\nThe following example function takes a parameter, performs an operation\nusing an SQL function, and returns the result. In this case, it is\nunnecessary to use delimiter because the function definition contains\nno internal ; statement delimiters:\n\nmysql> CREATE FUNCTION hello (s CHAR(20))\nmysql> RETURNS CHAR(50) DETERMINISTIC\n -> RETURN CONCAT(\'Hello, \',s,\'!\');\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT hello(\'world\');\n+----------------+\n| hello(\'world\') |\n+----------------+\n| Hello, world! |\n+----------------+\n1 row in set (0.00 sec)\n\nParameter types and function return types can be declared to use any\nvalid data type, except that the COLLATE attribute cannot be used prior\nto MySQL 5.5.3. As of 5.5.3, COLLATE can be used if preceded by the\nCHARACTER SET attribute.\n\nThe routine_body consists of a valid SQL routine statement. This can be\na simple statement such as SELECT or INSERT, or a compound statement\nwritten using BEGIN and END. Compound statements can contain\ndeclarations, loops, and other control structure statements. The syntax\nfor these statements is described in\nhttp://dev.mysql.com/doc/refman/5.5/en/sql-syntax-compound-statements.h\ntml.\n\nMySQL permits routines to contain DDL statements, such as CREATE and\nDROP. MySQL also permits stored procedures (but not stored functions)\nto contain SQL transaction statements such as COMMIT. Stored functions\nmay not contain statements that perform explicit or implicit commit or\nrollback. Support for these statements is not required by the SQL\nstandard, which states that each DBMS vendor may decide whether to\npermit them.\n\nStatements that return a result set can be used within a stored\nprocedure but not within a stored function. This prohibition includes\nSELECT statements that do not have an INTO var_list clause and other\nstatements such as SHOW, EXPLAIN, and CHECK TABLE. For statements that\ncan be determined at function definition time to return a result set, a\nNot allowed to return a result set from a function error occurs\n(ER_SP_NO_RETSET). For statements that can be determined only at\nruntime to return a result set, a PROCEDURE %s can\'t return a result\nset in the given context error occurs (ER_SP_BADSELECT).\n\nUSE statements within stored routines are not permitted. When a routine\nis invoked, an implicit USE db_name is performed (and undone when the\nroutine terminates). The causes the routine to have the given default\ndatabase while it executes. References to objects in databases other\nthan the routine default database should be qualified with the\nappropriate database name.\n\nFor additional information about statements that are not permitted in\nstored routines, see\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-program-restrictions.html\n.\n\nFor information about invoking stored procedures from within programs\nwritten in a language that has a MySQL interface, see [HELP CALL].\n\nMySQL stores the sql_mode system variable setting that is in effect at\nthe time a routine is created, and always executes the routine with\nthis setting in force, regardless of the server SQL mode in effect when\nthe routine is invoked.\n\nThe switch from the SQL mode of the invoker to that of the routine\noccurs after evaluation of arguments and assignment of the resulting\nvalues to routine parameters. If you define a routine in strict SQL\nmode but invoke it in nonstrict mode, assignment of arguments to\nroutine parameters does not take place in strict mode. If you require\nthat expressions passed to a routine be assigned in strict SQL mode,\nyou should invoke the routine with strict mode in effect.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html'),(303,'VARBINARY',22,'VARBINARY(M)\n\nThe VARBINARY type is similar to the VARCHAR type, but stores binary\nbyte strings rather than nonbinary character strings. M represents the\nmaximum column length in bytes.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(304,'LOAD INDEX',26,'Syntax:\nLOAD INDEX INTO CACHE\n tbl_index_list [, tbl_index_list] ...\n\ntbl_index_list:\n tbl_name\n [PARTITION (partition_list | ALL)]\n [[INDEX|KEY] (index_name[, index_name] ...)]\n [IGNORE LEAVES]\n\npartition_list:\n partition_name[, partition_name][, ...]\n\nThe LOAD INDEX INTO CACHE statement preloads a table index into the key\ncache to which it has been assigned by an explicit CACHE INDEX\nstatement, or into the default key cache otherwise.\n\nLOAD INDEX INTO CACHE is used only for MyISAM tables. In MySQL 5.5, it\nis also supported for partitioned MyISAM tables; in addition, indexes\non partitioned tables can be preloaded for one, several, or all\npartitions.\n\nThe IGNORE LEAVES modifier causes only blocks for the nonleaf nodes of\nthe index to be preloaded.\n\nIGNORE LEAVES is also supported for partitioned MyISAM tables.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/load-index.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/load-index.html'),(305,'UNION',27,'Syntax:\nSELECT ...\nUNION [ALL | DISTINCT] SELECT ...\n[UNION [ALL | DISTINCT] SELECT ...]\n\nUNION is used to combine the result from multiple SELECT statements\ninto a single result set.\n\nThe column names from the first SELECT statement are used as the column\nnames for the results returned. Selected columns listed in\ncorresponding positions of each SELECT statement should have the same\ndata type. (For example, the first column selected by the first\nstatement should have the same type as the first column selected by the\nother statements.)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/union.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/union.html'),(306,'TO_DAYS',31,'Syntax:\nTO_DAYS(date)\n\nGiven a date date, returns a day number (the number of days since year\n0).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TO_DAYS(950501);\n -> 728779\nmysql> SELECT TO_DAYS(\'2007-10-07\');\n -> 733321\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(307,'NOT REGEXP',37,'Syntax:\nexpr NOT REGEXP pat, expr NOT RLIKE pat\n\nThis is the same as NOT (expr REGEXP pat).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/regexp.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/regexp.html'),(308,'SHOW INDEX',26,'Syntax:\nSHOW {INDEX | INDEXES | KEYS}\n {FROM | IN} tbl_name\n [{FROM | IN} db_name]\n [WHERE expr]\n\nSHOW INDEX returns table index information. The format resembles that\nof the SQLStatistics call in ODBC. This statement requires some\nprivilege for any column in the table.\nYou can use db_name.tbl_name as an alternative to the tbl_name FROM\ndb_name syntax. These two statements are equivalent:\n\nSHOW INDEX FROM mytable FROM mydb;\nSHOW INDEX FROM mydb.mytable;\n\nThe WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nYou can also list a table\'s indexes with the mysqlshow -k db_name\ntbl_name command.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-index.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-index.html'),(309,'SHOW CREATE DATABASE',26,'Syntax:\nSHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name\n\nShows the CREATE DATABASE statement that creates the given database. If\nthe SHOW statement includes an IF NOT EXISTS clause, the output too\nincludes such a clause. SHOW CREATE SCHEMA is a synonym for SHOW CREATE\nDATABASE.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-database.html\n\n','mysql> SHOW CREATE DATABASE test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n\nmysql> SHOW CREATE SCHEMA test\\G\n*************************** 1. row ***************************\n Database: test\nCreate Database: CREATE DATABASE `test`\n /*!40100 DEFAULT CHARACTER SET latin1 */\n','http://dev.mysql.com/doc/refman/5.5/en/show-create-database.html'),(310,'LEAVE',23,'Syntax:\nLEAVE label\n\nThis statement is used to exit the flow control construct that has the\ngiven label. If the label is for the outermost stored program block,\nLEAVE exits the program.\n\nLEAVE can be used within BEGIN ... END or loop constructs (LOOP,\nREPEAT, WHILE).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/leave.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/leave.html'),(311,'NOT IN',18,'Syntax:\nexpr NOT IN (value,...)\n\nThis is the same as NOT (expr IN (value,...)).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(312,'!',15,'Syntax:\nNOT, !\n\nLogical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is\nnonzero, and NOT NULL returns NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html\n\n','mysql> SELECT NOT 10;\n -> 0\nmysql> SELECT NOT 0;\n -> 1\nmysql> SELECT NOT NULL;\n -> NULL\nmysql> SELECT ! (1+1);\n -> 0\nmysql> SELECT ! 1+1;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html'),(313,'DECLARE HANDLER',23,'Syntax:\nDECLARE handler_action HANDLER\n FOR condition_value [, condition_value] ...\n statement\n\nhandler_action:\n CONTINUE\n | EXIT\n | UNDO\n\ncondition_value:\n mysql_error_code\n | SQLSTATE [VALUE] sqlstate_value\n | condition_name\n | SQLWARNING\n | NOT FOUND\n | SQLEXCEPTION\n\nThe DECLARE ... HANDLER statement specifies a handler that deals with\none or more conditions. If one of these conditions occurs, the\nspecified statement executes. statement can be a simple statement such\nas SET var_name = value, or a compound statement written using BEGIN\nand END (see [HELP BEGIN END]).\n\nHandler declarations must appear after variable or condition\ndeclarations.\n\nThe handler_action value indicates what action the handler takes after\nexecution of the handler statement:\n\no CONTINUE: Execution of the current program continues.\n\no EXIT: Execution terminates for the BEGIN ... END compound statement\n in which the handler is declared. This is true even if the condition\n occurs in an inner block.\n\no UNDO: Not supported.\n\nThe condition_value for DECLARE ... HANDLER indicates the specific\ncondition or class of conditions that activates the handler:\n\no A MySQL error code (a number) or an SQLSTATE value (a 5-character\n string literal). You should not use MySQL error code 0 or SQLSTATE\n values that begin with \'00\', because those indicate success rather\n than an error condition. For a list of MySQL error codes and SQLSTATE\n values, see\n http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html.\n\no A condition name previously specified with DECLARE ... CONDITION. A\n condition name can be associated with a MySQL error code or SQLSTATE\n value. See [HELP DECLARE CONDITION].\n\no SQLWARNING is shorthand for the class of SQLSTATE values that begin\n with \'01\'.\n\no NOT FOUND is shorthand for the class of SQLSTATE values that begin\n with \'02\'. This is relevant within the context of cursors and is used\n to control what happens when a cursor reaches the end of a data set.\n If no more rows are available, a No Data condition occurs with\n SQLSTATE value \'02000\'. To detect this condition, you can set up a\n handler for it (or for a NOT FOUND condition). For an example, see\n http://dev.mysql.com/doc/refman/5.5/en/cursors.html. This condition\n also occurs for SELECT ... INTO var_list statements that retrieve no\n rows.\n\no SQLEXCEPTION is shorthand for the class of SQLSTATE values that do\n not begin with \'00\', \'01\', or \'02\'.\n\nIf a condition occurs for which no handler has been declared, the\naction taken depends on the condition class:\n\no For SQLEXCEPTION conditions, the stored program terminates at the\n statement that raised the condition, as if there were an EXIT\n handler. If the program was called by another stored program, the\n calling program handles the condition using the handler selection\n rules applied to its own handlers.\n\no For SQLWARNING conditions, the program continues executing, as if\n there were a CONTINUE handler.\n\no For NOT FOUND conditions, if the condition was raised normally, the\n action is CONTINUE. If it was raised by SIGNAL or RESIGNAL, the\n action is EXIT.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/declare-handler.html\n\n','mysql> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> delimiter //\n\nmysql> CREATE PROCEDURE handlerdemo ()\n -> BEGIN\n -> DECLARE CONTINUE HANDLER FOR SQLSTATE \'23000\' SET @x2 = 1;\n -> SET @x = 1;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 2;\n -> INSERT INTO test.t VALUES (1);\n -> SET @x = 3;\n -> END;\n -> //\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> CALL handlerdemo()//\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT @x//\n +------+\n | @x |\n +------+\n | 3 |\n +------+\n 1 row in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/declare-handler.html'),(314,'DOUBLE',22,'DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]\n\nA normal-size (double-precision) floating-point number. Permissible\nvalues are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and\n2.2250738585072014E-308 to 1.7976931348623157E+308. These are the\ntheoretical limits, based on the IEEE standard. The actual range might\nbe slightly smaller depending on your hardware or operating system.\n\nM is the total number of digits and D is the number of digits following\nthe decimal point. If M and D are omitted, values are stored to the\nlimits permitted by the hardware. A double-precision floating-point\nnumber is accurate to approximately 15 decimal places.\n\nUNSIGNED, if specified, disallows negative values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(315,'TIME',22,'TIME\n\nA time. The range is \'-838:59:59\' to \'838:59:59\'. MySQL displays TIME\nvalues in \'HH:MM:SS\' format, but permits assignment of values to TIME\ncolumns using either strings or numbers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-type-overview.html'),(316,'&&',15,'Syntax:\nAND, &&\n\nLogical AND. Evaluates to 1 if all operands are nonzero and not NULL,\nto 0 if one or more operands are 0, otherwise NULL is returned.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html\n\n','mysql> SELECT 1 && 1;\n -> 1\nmysql> SELECT 1 && 0;\n -> 0\nmysql> SELECT 1 && NULL;\n -> NULL\nmysql> SELECT 0 && NULL;\n -> 0\nmysql> SELECT NULL && 0;\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html'),(317,'X',11,'X(p)\n\nReturns the X-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#point-property-functions\n\n','mysql> SELECT X(POINT(56.7, 53.34));\n+-----------------------+\n| X(POINT(56.7, 53.34)) |\n+-----------------------+\n| 56.7 |\n+-----------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#point-property-functions'),(318,'SYSTEM_USER',17,'Syntax:\nSYSTEM_USER()\n\nSYSTEM_USER() is a synonym for USER().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(319,'FOUND_ROWS',17,'Syntax:\nFOUND_ROWS()\n\nA SELECT statement may include a LIMIT clause to restrict the number of\nrows the server returns to the client. In some cases, it is desirable\nto know how many rows the statement would have returned without the\nLIMIT, but without running the statement again. To obtain this row\ncount, include a SQL_CALC_FOUND_ROWS option in the SELECT statement,\nand then invoke FOUND_ROWS() afterward:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name\n -> WHERE id > 100 LIMIT 10;\nmysql> SELECT FOUND_ROWS();\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(320,'CROSSES',30,'Crosses(g1,g2)\n\nReturns 1 if g1 spatially crosses g2. Returns NULL if g1 is a Polygon\nor a MultiPolygon, or if g2 is a Point or a MultiPoint. Otherwise,\nreturns 0.\n\nThe term spatially crosses denotes a spatial relation between two given\ngeometries that has the following properties:\n\no The two geometries intersect\n\no Their intersection results in a geometry that has a dimension that is\n one less than the maximum dimension of the two given geometries\n\no Their intersection is not equal to either of the two given geometries\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(321,'TRUNCATE TABLE',39,'Syntax:\nTRUNCATE [TABLE] tbl_name\n\nTRUNCATE TABLE empties a table completely. It requires the DROP\nprivilege.\n\nLogically, TRUNCATE TABLE is similar to a DELETE statement that deletes\nall rows, or a sequence of DROP TABLE and CREATE TABLE statements. To\nachieve high performance, it bypasses the DML method of deleting data.\nThus, it cannot be rolled back, it does not cause ON DELETE triggers to\nfire, and it cannot be performed for InnoDB tables with parent-child\nforeign key relationships.\n\nAlthough TRUNCATE TABLE is similar to DELETE, it is classified as a DDL\nstatement rather than a DML statement. It differs from DELETE in the\nfollowing ways in MySQL 5.5:\n\no Truncate operations drop and re-create the table, which is much\n faster than deleting rows one by one, particularly for large tables.\n\no Truncate operations cause an implicit commit, and so cannot be rolled\n back.\n\no Truncation operations cannot be performed if the session holds an\n active table lock.\n\no TRUNCATE TABLE fails for an InnoDB table if there are any FOREIGN KEY\n constraints from other tables that reference the table. Foreign key\n constraints between columns of the same table are permitted.\n\no Truncation operations do not return a meaningful value for the number\n of deleted rows. The usual result is \"0 rows affected,\" which should\n be interpreted as \"no information.\"\n\no As long as the table format file tbl_name.frm is valid, the table can\n be re-created as an empty table with TRUNCATE TABLE, even if the data\n or index files have become corrupted.\n\no Any AUTO_INCREMENT value is reset to its start value. This is true\n even for MyISAM and InnoDB, which normally do not reuse sequence\n values.\n\no When used with partitioned tables, TRUNCATE TABLE preserves the\n partitioning; that is, the data and index files are dropped and\n re-created, while the partition definitions (.par) file is\n unaffected.\n\no The TRUNCATE TABLE statement does not invoke ON DELETE triggers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/truncate-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/truncate-table.html'),(322,'BIT_XOR',16,'Syntax:\nBIT_XOR(expr)\n\nReturns the bitwise XOR of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(323,'CURRENT_DATE',31,'Syntax:\nCURRENT_DATE, CURRENT_DATE()\n\nCURRENT_DATE and CURRENT_DATE() are synonyms for CURDATE().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(324,'START SLAVE',8,'Syntax:\nSTART SLAVE [thread_types]\n\nSTART SLAVE [SQL_THREAD] UNTIL\n MASTER_LOG_FILE = \'log_name\', MASTER_LOG_POS = log_pos\n\nSTART SLAVE [SQL_THREAD] UNTIL\n RELAY_LOG_FILE = \'log_name\', RELAY_LOG_POS = log_pos\n\nthread_types:\n [thread_type [, thread_type] ... ]\n\nthread_type: IO_THREAD | SQL_THREAD\n\nSTART SLAVE with no thread_type options starts both of the slave\nthreads. The I/O thread reads events from the master server and stores\nthem in the relay log. The SQL thread reads events from the relay log\nand executes them. START SLAVE requires the SUPER privilege.\n\nIf START SLAVE succeeds in starting the slave threads, it returns\nwithout any error. However, even in that case, it might be that the\nslave threads start and then later stop (for example, because they do\nnot manage to connect to the master or read its binary log, or some\nother problem). START SLAVE does not warn you about this. You must\ncheck the slave\'s error log for error messages generated by the slave\nthreads, or check that they are running satisfactorily with SHOW SLAVE\nSTATUS.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/start-slave.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/start-slave.html'),(325,'AREA',2,'Area(poly)\n\nReturns as a double-precision number the area of the Polygon value\npoly, as measured in its spatial reference system.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions\n\n','mysql> SET @poly = \'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))\';\nmysql> SELECT Area(GeomFromText(@poly));\n+---------------------------+\n| Area(GeomFromText(@poly)) |\n+---------------------------+\n| 4 |\n+---------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions'),(326,'FLUSH',26,'Syntax:\nFLUSH [NO_WRITE_TO_BINLOG | LOCAL]\n flush_option [, flush_option] ...\n\nThe FLUSH statement has several variant forms that clear or reload\nvarious internal caches, flush tables, or acquire locks. To execute\nFLUSH, you must have the RELOAD privilege. Specific flush options might\nrequire additional privileges, as described later.\n\nBy default, the server writes FLUSH statements to the binary log so\nthat they replicate to replication slaves. To suppress logging, use the\noptional NO_WRITE_TO_BINLOG keyword or its alias LOCAL.\n\n*Note*: FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH\nREAD LOCK (with or without a table list) are not written to the binary\nlog in any case because they would cause problems if replicated to a\nslave.\n\nThe FLUSH statement causes an implicit commit. See\nhttp://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html.\n\nThe RESET statement is similar to FLUSH. See [HELP RESET], for\ninformation about using the RESET statement with replication.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/flush.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/flush.html'),(327,'BEGIN END',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\nBEGIN ... END syntax is used for writing compound statements, which can\nappear within stored programs (stored procedures and functions,\ntriggers, and events). A compound statement can contain multiple\nstatements, enclosed by the BEGIN and END keywords. statement_list\nrepresents a list of one or more statements, each terminated by a\nsemicolon (;) statement delimiter. The statement_list itself is\noptional, so the empty compound statement (BEGIN END) is legal.\n\nBEGIN ... END blocks can be nested.\n\nUse of multiple statements requires that a client is able to send\nstatement strings containing the ; statement delimiter. In the mysql\ncommand-line client, this is handled with the delimiter command.\nChanging the ; end-of-statement delimiter (for example, to //) permit ;\nto be used in a program body. For an example, see\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-defining.html.\n\nA BEGIN ... END block can be labeled. See [HELP labels].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/begin-end.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/begin-end.html'),(328,'SHOW PROCEDURE STATUS',26,'Syntax:\nSHOW PROCEDURE STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is a MySQL extension. It returns characteristics of a\nstored procedure, such as the database, name, type, creator, creation\nand modification dates, and character set information. A similar\nstatement, SHOW FUNCTION STATUS, displays information about stored\nfunctions (see [HELP SHOW FUNCTION STATUS]).\n\nThe LIKE clause, if present, indicates which procedure or function\nnames to match. The WHERE clause can be given to select rows using more\ngeneral conditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-procedure-status.html\n\n','mysql> SHOW PROCEDURE STATUS LIKE \'sp1\'\\G\n*************************** 1. row ***************************\n Db: test\n Name: sp1\n Type: PROCEDURE\n Definer: testuser@localhost\n Modified: 2004-08-03 15:29:37\n Created: 2004-08-03 15:29:37\n Security_type: DEFINER\n Comment:\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','http://dev.mysql.com/doc/refman/5.5/en/show-procedure-status.html'),(329,'DESCRIBE',28,'Syntax:\n{DESCRIBE | DESC} tbl_name [col_name | wild]\n\nDESCRIBE provides information about the columns in a table. It is a\nshortcut for SHOW COLUMNS FROM. These statements also display\ninformation for views. (See [HELP SHOW COLUMNS].)\n\ncol_name can be a column name, or a string containing the SQL \"%\" and\n\"_\" wildcard characters to obtain output only for the columns with\nnames matching the string. There is no need to enclose the string\nwithin quotation marks unless it contains spaces or other special\ncharacters.\n\nmysql> DESCRIBE City;\n+------------+----------+------+-----+---------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+------------+----------+------+-----+---------+----------------+\n| Id | int(11) | NO | PRI | NULL | auto_increment |\n| Name | char(35) | NO | | | |\n| Country | char(3) | NO | UNI | | |\n| District | char(20) | YES | MUL | | |\n| Population | int(11) | NO | | 0 | |\n+------------+----------+------+-----+---------+----------------+\n5 rows in set (0.00 sec)\n\nThe description for SHOW COLUMNS provides more information about the\noutput columns (see [HELP SHOW COLUMNS]).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/describe.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/describe.html'),(330,'SHOW WARNINGS',26,'Syntax:\nSHOW WARNINGS [LIMIT [offset,] row_count]\nSHOW COUNT(*) WARNINGS\n\nSHOW WARNINGS shows information about the conditions (errors, warnings,\nand notes) that resulted from the last statement in the current session\nthat generated messages. It shows nothing if the last statement used a\ntable and generated no messages. (That is, a statement that uses a\ntable but generates no messages clears the message list.) Statements\nthat do not use tables and do not generate messages have no effect on\nthe message list.\n\nWarnings are generated for DML statements such as INSERT, UPDATE, and\nLOAD DATA INFILE as well as DDL statements such as CREATE TABLE and\nALTER TABLE.\n\nSHOW WARNINGS is also used following EXPLAIN EXTENDED, to display the\nextra information generated by EXPLAIN when the EXTENDED keyword is\nused. See http://dev.mysql.com/doc/refman/5.5/en/explain-extended.html.\n\nThe LIMIT clause has the same syntax as for the SELECT statement. See\nhttp://dev.mysql.com/doc/refman/5.5/en/select.html.\n\nA related statement, SHOW ERRORS, shows only the error conditions (it\nexcludes warnings and notes). See [HELP SHOW ERRORS].\n\nThe SHOW COUNT(*) WARNINGS statement displays the total number of\nerrors, warnings, and notes. You can also retrieve this number from the\nwarning_count system variable:\n\nSHOW COUNT(*) WARNINGS;\nSELECT @@warning_count;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-warnings.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-warnings.html'),(331,'DROP USER',10,'Syntax:\nDROP USER user [, user] ...\n\nThe DROP USER statement removes one or more MySQL accounts and their\nprivileges. It removes privilege rows for the account from all grant\ntables. To use this statement, you must have the global CREATE USER\nprivilege or the DELETE privilege for the mysql database. Each account\nname uses the format described in\nhttp://dev.mysql.com/doc/refman/5.5/en/account-names.html. For example:\n\nDROP USER \'jeffrey\'@\'localhost\';\n\nIf you specify only the user name part of the account name, a host name\npart of \'%\' is used.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-user.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-user.html'),(332,'STDDEV_POP',16,'Syntax:\nSTDDEV_POP(expr)\n\nReturns the population standard deviation of expr (the square root of\nVAR_POP()). You can also use STD() or STDDEV(), which are equivalent\nbut not standard SQL.\n\nSTDDEV_POP() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(333,'SHOW CHARACTER SET',26,'Syntax:\nSHOW CHARACTER SET\n [LIKE \'pattern\' | WHERE expr]\n\nThe SHOW CHARACTER SET statement shows all available character sets.\nThe LIKE clause, if present, indicates which character set names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html. For example:\n\nmysql> SHOW CHARACTER SET LIKE \'latin%\';\n+---------+-----------------------------+-------------------+--------+\n| Charset | Description | Default collation | Maxlen |\n+---------+-----------------------------+-------------------+--------+\n| latin1 | cp1252 West European | latin1_swedish_ci | 1 |\n| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |\n| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |\n| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |\n+---------+-----------------------------+-------------------+--------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-character-set.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-character-set.html'),(334,'SUBSTRING',37,'Syntax:\nSUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len),\nSUBSTRING(str FROM pos FOR len)\n\nThe forms without a len argument return a substring from string str\nstarting at position pos. The forms with a len argument return a\nsubstring len characters long from string str, starting at position\npos. The forms that use FROM are standard SQL syntax. It is also\npossible to use a negative value for pos. In this case, the beginning\nof the substring is pos characters from the end of the string, rather\nthan the beginning. A negative value may be used for pos in any of the\nforms of this function.\n\nFor all forms of SUBSTRING(), the position of the first character in\nthe string from which the substring is to be extracted is reckoned as\n1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT SUBSTRING(\'Quadratically\',5);\n -> \'ratically\'\nmysql> SELECT SUBSTRING(\'foobarbar\' FROM 4);\n -> \'barbar\'\nmysql> SELECT SUBSTRING(\'Quadratically\',5,6);\n -> \'ratica\'\nmysql> SELECT SUBSTRING(\'Sakila\', -3);\n -> \'ila\'\nmysql> SELECT SUBSTRING(\'Sakila\', -5, 3);\n -> \'aki\'\nmysql> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);\n -> \'ki\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(335,'ISEMPTY',36,'IsEmpty(g)\n\nReturns 1 if the geometry value g is the empty geometry, 0 if it is not\nempty, and -1 if the argument is NULL. If the geometry is empty, it\nrepresents the empty point set.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(336,'SHOW FUNCTION STATUS',26,'Syntax:\nSHOW FUNCTION STATUS\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement is similar to SHOW PROCEDURE STATUS but for stored\nfunctions. See [HELP SHOW PROCEDURE STATUS].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-function-status.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-function-status.html'),(337,'LTRIM',37,'Syntax:\nLTRIM(str)\n\nReturns the string str with leading space characters removed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT LTRIM(\' barbar\');\n -> \'barbar\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(338,'INTERSECTS',30,'Intersects(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 spatially intersects g2.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(339,'CALL',27,'Syntax:\nCALL sp_name([parameter[,...]])\nCALL sp_name[()]\n\nThe CALL statement invokes a stored procedure that was defined\npreviously with CREATE PROCEDURE.\n\nStored procedures that take no arguments can be invoked without\nparentheses. That is, CALL p() and CALL p are equivalent.\n\nCALL can pass back values to its caller using parameters that are\ndeclared as OUT or INOUT parameters. When the procedure returns, a\nclient program can also obtain the number of rows affected for the\nfinal statement executed within the routine: At the SQL level, call the\nROW_COUNT() function; from the C API, call the mysql_affected_rows()\nfunction.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/call.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/call.html'),(340,'MBRDISJOINT',6,'MBRDisjoint(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangles of\nthe two geometries g1 and g2 are disjoint (do not intersect).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(341,'VALUES',14,'Syntax:\nVALUES(col_name)\n\nIn an INSERT ... ON DUPLICATE KEY UPDATE statement, you can use the\nVALUES(col_name) function in the UPDATE clause to refer to column\nvalues from the INSERT portion of the statement. In other words,\nVALUES(col_name) in the UPDATE clause refers to the value of col_name\nthat would be inserted, had no duplicate-key conflict occurred. This\nfunction is especially useful in multiple-row inserts. The VALUES()\nfunction is meaningful only in the ON DUPLICATE KEY UPDATE clause of\nINSERT statements and returns NULL otherwise. See\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)\n -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(342,'SUBSTRING_INDEX',37,'Syntax:\nSUBSTRING_INDEX(str,delim,count)\n\nReturns the substring from string str before count occurrences of the\ndelimiter delim. If count is positive, everything to the left of the\nfinal delimiter (counting from the left) is returned. If count is\nnegative, everything to the right of the final delimiter (counting from\nthe right) is returned. SUBSTRING_INDEX() performs a case-sensitive\nmatch when searching for delim.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT SUBSTRING_INDEX(\'www.mysql.com\', \'.\', 2);\n -> \'www.mysql\'\nmysql> SELECT SUBSTRING_INDEX(\'www.mysql.com\', \'.\', -2);\n -> \'mysql.com\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(343,'ENCODE',12,'Syntax:\nENCODE(str,pass_str)\n\nEncrypt str using pass_str as the password. To decrypt the result, use\nDECODE().\n\nThe result is a binary string of the same length as str.\n\nThe strength of the encryption is based on how good the random\ngenerator is. It should suffice for short strings.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(344,'LOOP',23,'Syntax:\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\nLOOP implements a simple loop construct, enabling repeated execution of\nthe statement list, which consists of one or more statements, each\nterminated by a semicolon (;) statement delimiter. The statements\nwithin the loop are repeated until the loop is terminated. Usually,\nthis is accomplished with a LEAVE statement. Within a stored function,\nRETURN can also be used, which exits the function entirely.\n\nNeglecting to include a loop-termination statement results in an\ninfinite loop.\n\nA LOOP statement can be labeled. For the rules regarding label use, see\n[HELP labels].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/loop.html\n\n','CREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN\n ITERATE label1;\n END IF;\n LEAVE label1;\n END LOOP label1;\n SET @x = p1;\nEND;\n','http://dev.mysql.com/doc/refman/5.5/en/loop.html'),(345,'TRUNCATE',4,'Syntax:\nTRUNCATE(X,D)\n\nReturns the number X, truncated to D decimal places. If D is 0, the\nresult has no decimal point or fractional part. D can be negative to\ncause D digits left of the decimal point of the value X to become zero.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT TRUNCATE(1.223,1);\n -> 1.2\nmysql> SELECT TRUNCATE(1.999,1);\n -> 1.9\nmysql> SELECT TRUNCATE(1.999,0);\n -> 1\nmysql> SELECT TRUNCATE(-1.999,1);\n -> -1.9\nmysql> SELECT TRUNCATE(122,-2);\n -> 100\nmysql> SELECT TRUNCATE(10.28*100,0);\n -> 1028\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(346,'TIMESTAMPADD',31,'Syntax:\nTIMESTAMPADD(unit,interval,datetime_expr)\n\nAdds the integer expression interval to the date or datetime expression\ndatetime_expr. The unit for interval is given by the unit argument,\nwhich should be one of the following values: MICROSECOND\n(microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or\nYEAR.\n\nIt is possible to use FRAC_SECOND in place of MICROSECOND, but\nFRAC_SECOND is deprecated. FRAC_SECOND was removed in MySQL 5.5.3.\n\nThe unit value may be specified using one of keywords as shown, or with\na prefix of SQL_TSI_. For example, DAY and SQL_TSI_DAY both are legal.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIMESTAMPADD(MINUTE,1,\'2003-01-02\');\n -> \'2003-01-02 00:01:00\'\nmysql> SELECT TIMESTAMPADD(WEEK,1,\'2003-01-02\');\n -> \'2003-01-09\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(347,'SHOW',26,'SHOW has many forms that provide information about databases, tables,\ncolumns, or status information about the server. This section describes\nthose following:\n\nSHOW AUTHORS\nSHOW {BINARY | MASTER} LOGS\nSHOW BINLOG EVENTS [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\nSHOW CHARACTER SET [like_or_where]\nSHOW COLLATION [like_or_where]\nSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [like_or_where]\nSHOW CONTRIBUTORS\nSHOW CREATE DATABASE db_name\nSHOW CREATE EVENT event_name\nSHOW CREATE FUNCTION func_name\nSHOW CREATE PROCEDURE proc_name\nSHOW CREATE TABLE tbl_name\nSHOW CREATE TRIGGER trigger_name\nSHOW CREATE VIEW view_name\nSHOW DATABASES [like_or_where]\nSHOW ENGINE engine_name {STATUS | MUTEX}\nSHOW [STORAGE] ENGINES\nSHOW ERRORS [LIMIT [offset,] row_count]\nSHOW EVENTS\nSHOW FUNCTION CODE func_name\nSHOW FUNCTION STATUS [like_or_where]\nSHOW GRANTS FOR user\nSHOW INDEX FROM tbl_name [FROM db_name]\nSHOW MASTER STATUS\nSHOW OPEN TABLES [FROM db_name] [like_or_where]\nSHOW PLUGINS\nSHOW PROCEDURE CODE proc_name\nSHOW PROCEDURE STATUS [like_or_where]\nSHOW PRIVILEGES\nSHOW [FULL] PROCESSLIST\nSHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n]\nSHOW PROFILES\nSHOW SLAVE HOSTS\nSHOW SLAVE STATUS\nSHOW [GLOBAL | SESSION] STATUS [like_or_where]\nSHOW TABLE STATUS [FROM db_name] [like_or_where]\nSHOW [FULL] TABLES [FROM db_name] [like_or_where]\nSHOW TRIGGERS [FROM db_name] [like_or_where]\nSHOW [GLOBAL | SESSION] VARIABLES [like_or_where]\nSHOW WARNINGS [LIMIT [offset,] row_count]\n\nlike_or_where:\n LIKE \'pattern\'\n | WHERE expr\n\nIf the syntax for a given SHOW statement includes a LIKE \'pattern\'\npart, \'pattern\' is a string that can contain the SQL \"%\" and \"_\"\nwildcard characters. The pattern is useful for restricting statement\noutput to matching values.\n\nSeveral SHOW statements also accept a WHERE clause that provides more\nflexibility in specifying which rows to display. See\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show.html'),(348,'GREATEST',18,'Syntax:\nGREATEST(value1,value2,...)\n\nWith two or more arguments, returns the largest (maximum-valued)\nargument. The arguments are compared using the same rules as for\nLEAST().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT GREATEST(2,0);\n -> 2\nmysql> SELECT GREATEST(34.0,3.0,5.0,767.0);\n -> 767.0\nmysql> SELECT GREATEST(\'B\',\'A\',\'C\');\n -> \'C\'\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(349,'SHOW VARIABLES',26,'Syntax:\nSHOW [GLOBAL | SESSION] VARIABLES\n [LIKE \'pattern\' | WHERE expr]\n\nSHOW VARIABLES shows the values of MySQL system variables. This\ninformation also can be obtained using the mysqladmin variables\ncommand. The LIKE clause, if present, indicates which variable names to\nmatch. The WHERE clause can be given to select rows using more general\nconditions, as discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html. This\nstatement does not require any privilege. It requires only the ability\nto connect to the server.\n\nWith the GLOBAL modifier, SHOW VARIABLES displays the values that are\nused for new connections to MySQL. As of MySQL 5.5.3, if a variable has\nno global value, no value is displayed. Before 5.5.3, the session value\nis displayed. With SESSION, SHOW VARIABLES displays the values that are\nin effect for the current connection. If no modifier is present, the\ndefault is SESSION. LOCAL is a synonym for SESSION.\nWith a LIKE clause, the statement displays only rows for those\nvariables with names that match the pattern. To obtain the row for a\nspecific variable, use a LIKE clause as shown:\n\nSHOW VARIABLES LIKE \'max_join_size\';\nSHOW SESSION VARIABLES LIKE \'max_join_size\';\n\nTo get a list of variables whose name match a pattern, use the \"%\"\nwildcard character in a LIKE clause:\n\nSHOW VARIABLES LIKE \'%size%\';\nSHOW GLOBAL VARIABLES LIKE \'%size%\';\n\nWildcard characters can be used in any position within the pattern to\nbe matched. Strictly speaking, because \"_\" is a wildcard that matches\nany single character, you should escape it as \"\\_\" to match it\nliterally. In practice, this is rarely necessary.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-variables.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-variables.html'),(350,'BINLOG',26,'Syntax:\nBINLOG \'str\'\n\nBINLOG is an internal-use statement. It is generated by the mysqlbinlog\nprogram as the printable representation of certain events in binary log\nfiles. (See http://dev.mysql.com/doc/refman/5.5/en/mysqlbinlog.html.)\nThe \'str\' value is a base 64-encoded string the that server decodes to\ndetermine the data change indicated by the corresponding event. This\nstatement requires the SUPER privilege.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/binlog.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/binlog.html'),(351,'BIT_AND',16,'Syntax:\nBIT_AND(expr)\n\nReturns the bitwise AND of all bits in expr. The calculation is\nperformed with 64-bit (BIGINT) precision.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(352,'SECOND',31,'Syntax:\nSECOND(time)\n\nReturns the second for time, in the range 0 to 59.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT SECOND(\'10:05:03\');\n -> 3\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(353,'ATAN2',4,'Syntax:\nATAN(Y,X), ATAN2(Y,X)\n\nReturns the arc tangent of the two variables X and Y. It is similar to\ncalculating the arc tangent of Y / X, except that the signs of both\narguments are used to determine the quadrant of the result.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ATAN(-2,2);\n -> -0.78539816339745\nmysql> SELECT ATAN2(PI(),0);\n -> 1.5707963267949\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(354,'MBRCONTAINS',6,'MBRContains(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\ncontains the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRWithin().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','mysql> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nmysql> SET @g2 = GeomFromText(\'Point(1 1)\');\nmysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);\n----------------------+----------------------+\n| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |\n+----------------------+----------------------+\n| 1 | 0 |\n+----------------------+----------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(355,'HOUR',31,'Syntax:\nHOUR(time)\n\nReturns the hour for time. The range of the return value is 0 to 23 for\ntime-of-day values. However, the range of TIME values actually is much\nlarger, so HOUR can return values greater than 23.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT HOUR(\'10:05:03\');\n -> 10\nmysql> SELECT HOUR(\'272:59:59\');\n -> 272\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(356,'SELECT',27,'Syntax:\nSELECT\n [ALL | DISTINCT | DISTINCTROW ]\n [HIGH_PRIORITY]\n [STRAIGHT_JOIN]\n [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]\n [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]\n select_expr [, select_expr ...]\n [FROM table_references\n [WHERE where_condition]\n [GROUP BY {col_name | expr | position}\n [ASC | DESC], ... [WITH ROLLUP]]\n [HAVING where_condition]\n [ORDER BY {col_name | expr | position}\n [ASC | DESC], ...]\n [LIMIT {[offset,] row_count | row_count OFFSET offset}]\n [PROCEDURE procedure_name(argument_list)]\n [INTO OUTFILE \'file_name\'\n [CHARACTER SET charset_name]\n export_options\n | INTO DUMPFILE \'file_name\'\n | INTO var_name [, var_name]]\n [FOR UPDATE | LOCK IN SHARE MODE]]\n\nSELECT is used to retrieve rows selected from one or more tables, and\ncan include UNION statements and subqueries. See [HELP UNION], and\nhttp://dev.mysql.com/doc/refman/5.5/en/subqueries.html.\n\nThe most commonly used clauses of SELECT statements are these:\n\no Each select_expr indicates a column that you want to retrieve. There\n must be at least one select_expr.\n\no table_references indicates the table or tables from which to retrieve\n rows. Its syntax is described in [HELP JOIN].\n\no The WHERE clause, if given, indicates the condition or conditions\n that rows must satisfy to be selected. where_condition is an\n expression that evaluates to true for each row to be selected. The\n statement selects all rows if there is no WHERE clause.\n\n In the WHERE expression, you can use any of the functions and\n operators that MySQL supports, except for aggregate (summary)\n functions. See\n http://dev.mysql.com/doc/refman/5.5/en/expressions.html, and\n http://dev.mysql.com/doc/refman/5.5/en/functions.html.\n\nSELECT can also be used to retrieve rows computed without reference to\nany table.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/select.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/select.html'),(357,'COT',4,'Syntax:\nCOT(X)\n\nReturns the cotangent of X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT COT(12);\n -> -1.5726734063977\nmysql> SELECT COT(0);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(358,'SHOW CREATE EVENT',26,'Syntax:\nSHOW CREATE EVENT event_name\n\nThis statement displays the CREATE EVENT statement needed to re-create\na given event. It requires the EVENT privilege for the database from\nwhich the event is to be shown. For example (using the same event\ne_daily defined and then altered in [HELP SHOW EVENTS]):\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-event.html\n\n','mysql> SHOW CREATE EVENT test.e_daily\\G\n*************************** 1. row ***************************\n Event: e_daily\n sql_mode:\n time_zone: SYSTEM\n Create Event: CREATE EVENT `e_daily`\n ON SCHEDULE EVERY 1 DAY\n STARTS CURRENT_TIMESTAMP + INTERVAL 6 HOUR\n ON COMPLETION NOT PRESERVE\n ENABLE\n COMMENT \'Saves total number of sessions then\n clears the table each day\'\n DO BEGIN\n INSERT INTO site_activity.totals (time, total)\n SELECT CURRENT_TIMESTAMP, COUNT(*)\n FROM site_activity.sessions;\n DELETE FROM site_activity.sessions;\n END\ncharacter_set_client: latin1\ncollation_connection: latin1_swedish_ci\n Database Collation: latin1_swedish_ci\n','http://dev.mysql.com/doc/refman/5.5/en/show-create-event.html'),(359,'LOAD_FILE',37,'Syntax:\nLOAD_FILE(file_name)\n\nReads the file and returns the file contents as a string. To use this\nfunction, the file must be located on the server host, you must specify\nthe full path name to the file, and you must have the FILE privilege.\nThe file must be readable by all and its size less than\nmax_allowed_packet bytes. If the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nIf the file does not exist or cannot be read because one of the\npreceding conditions is not satisfied, the function returns NULL.\n\nThe character_set_filesystem system variable controls interpretation of\nfile names that are given as literal strings.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> UPDATE t\n SET blob_col=LOAD_FILE(\'/tmp/picture\')\n WHERE id=1;\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(360,'POINTFROMTEXT',3,'PointFromText(wkt[,srid])\n\nConstructs a POINT value using its WKT representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(361,'GROUP_CONCAT',16,'Syntax:\nGROUP_CONCAT(expr)\n\nThis function returns a string result with the concatenated non-NULL\nvalues from a group. It returns NULL if there are no non-NULL values.\nThe full syntax is as follows:\n\nGROUP_CONCAT([DISTINCT] expr [,expr ...]\n [ORDER BY {unsigned_integer | col_name | expr}\n [ASC | DESC] [,col_name ...]]\n [SEPARATOR str_val])\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT student_name,\n -> GROUP_CONCAT(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(362,'DATE_FORMAT',31,'Syntax:\nDATE_FORMAT(date,format)\n\nFormats the date value according to the format string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DATE_FORMAT(\'2009-10-04 22:23:00\', \'%W %M %Y\');\n -> \'Sunday October 2009\'\nmysql> SELECT DATE_FORMAT(\'2007-10-04 22:23:00\', \'%H:%i:%s\');\n -> \'22:23:00\'\nmysql> SELECT DATE_FORMAT(\'1900-10-04 22:23:00\',\n -> \'%D %y %a %d %m %b %j\');\n -> \'4th 00 Thu 04 10 Oct 277\'\nmysql> SELECT DATE_FORMAT(\'1997-10-04 22:23:00\',\n -> \'%H %k %I %r %T %S %w\');\n -> \'22 22 10 10:23:00 PM 22:23:00 00 6\'\nmysql> SELECT DATE_FORMAT(\'1999-01-01\', \'%X %V\');\n -> \'1998 52\'\nmysql> SELECT DATE_FORMAT(\'2006-06-00\', \'%d\');\n -> \'00\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(363,'BENCHMARK',17,'Syntax:\nBENCHMARK(count,expr)\n\nThe BENCHMARK() function executes the expression expr repeatedly count\ntimes. It may be used to time how quickly MySQL processes the\nexpression. The result value is always 0. The intended use is from\nwithin the mysql client, which reports query execution times:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\'));\n+----------------------------------------------+\n| BENCHMARK(1000000,ENCODE(\'hello\',\'goodbye\')) |\n+----------------------------------------------+\n| 0 |\n+----------------------------------------------+\n1 row in set (4.74 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(364,'YEAR',31,'Syntax:\nYEAR(date)\n\nReturns the year for date, in the range 1000 to 9999, or 0 for the\n\"zero\" date.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT YEAR(\'1987-01-01\');\n -> 1987\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(365,'SHOW ENGINE',26,'Syntax:\nSHOW ENGINE engine_name {STATUS | MUTEX}\n\nSHOW ENGINE displays operational information about a storage engine.\nThe following statements currently are supported:\n\nSHOW ENGINE INNODB STATUS\nSHOW ENGINE INNODB MUTEX\nSHOW ENGINE {NDB | NDBCLUSTER} STATUS\nSHOW ENGINE PERFORMANCE_SCHEMA STATUS\n\nSHOW ENGINE INNODB STATUS displays extensive information from the\nstandard InnoDB Monitor about the state of the InnoDB storage engine.\nFor information about the standard monitor and other InnoDB Monitors\nthat provide information about InnoDB processing, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-monitors.html.\n\nSHOW ENGINE INNODB MUTEX displays InnoDB mutex statistics. The\nstatement displays the following fields:\n\no Type\n\n Always InnoDB.\n\no Name\n\n The source file where the mutex is implemented, and the line number\n in the file where the mutex is created. The line number may change\n depending on your version of MySQL.\n\no Status\n\n The mutex status. This field displays several values if UNIV_DEBUG\n was defined at MySQL compilation time (for example, in include/univ.i\n in the InnoDB part of the MySQL source tree). If UNIV_DEBUG was not\n defined, the statement displays only the os_waits value. In the\n latter case (without UNIV_DEBUG), the information on which the output\n is based is insufficient to distinguish regular mutexes and mutexes\n that protect rw-locks (which permit multiple readers or a single\n writer). Consequently, the output may appear to contain multiple rows\n for the same mutex.\n\n o count indicates how many times the mutex was requested.\n\n o spin_waits indicates how many times the spinlock had to run.\n\n o spin_rounds indicates the number of spinlock rounds. (spin_rounds\n divided by spin_waits provides the average round count.)\n\n o os_waits indicates the number of operating system waits. This\n occurs when the spinlock did not work (the mutex was not locked\n during the spinlock and it was necessary to yield to the operating\n system and wait).\n\n o os_yields indicates the number of times a the thread trying to lock\n a mutex gave up its timeslice and yielded to the operating system\n (on the presumption that permitting other threads to run will free\n the mutex so that it can be locked).\n\n o os_wait_times indicates the amount of time (in ms) spent in\n operating system waits, if the timed_mutexes system variable is 1\n (ON). If timed_mutexes is 0 (OFF), timing is disabled, so\n os_wait_times is 0. timed_mutexes is off by default.\n\nInformation from this statement can be used to diagnose system\nproblems. For example, large values of spin_waits and spin_rounds may\nindicate scalability problems.\n\nUse SHOW ENGINE PERFORMANCE_SCHEMA STATUS to inspect the internal\noperation of the Performance Schema code:\n\nmysql> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\\G\n...\n*************************** 3. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_size\nStatus: 76\n*************************** 4. row ***************************\n Type: performance_schema\n Name: events_waits_history.row_count\nStatus: 10000\n*************************** 5. row ***************************\n Type: performance_schema\n Name: events_waits_history.memory\nStatus: 760000\n...\n*************************** 57. row ***************************\n Type: performance_schema\n Name: performance_schema.memory\nStatus: 26459600\n...\n\nThe intent of this statement is to help the DBA to understand the\neffects that different options have on memory requirements.\n\nName values consist of two parts, which name an internal buffer and an\nattribute of the buffer, respectively:\n\no Internal buffers that are exposed as a table in the\n performance_schema database are named after the table. Examples:\n events_waits_history.row_size, mutex_instances.row_count.\n\no Internal buffers that are not exposed as a table are named within\n parentheses. Examples: (pfs_cond_class).row_size,\n (pfs_mutex_class).memory.\n\no Values that apply to the Performance Schema as a whole begin with\n performance_schema. Example: performance_schema.memory.\n\nAttributes have these meanings:\n\no row_size cannot be changed. It is the size of the internal record\n used by the implementation.\n\no row_count can be changed depending on the configuration options.\n\no For a table, tbl_name.memory is the product of row_size multiplied by\n row_count. For the Performance Schema as a whole,\n performance_schema.memory is the sum of all the memory used (the sum\n of all other memory values).\n\nIn some cases, there is a direct relationship between a configuration\nparameter and a SHOW ENGINE value. For example,\nevents_waits_history_long.row_count corresponds to\nperformance_schema_events_waits_history_long_size. In other cases, the\nrelationship is more complex. For example,\nevents_waits_history.row_count corresponds to\nperformance_schema_events_waits_history_size (the number of rows per\nthread) multiplied by performance_schema_max_thread_instances ( the\nnumber of threads).\n\nIf the server has the NDBCLUSTER storage engine enabled, SHOW ENGINE\nNDB STATUS displays cluster status information such as the number of\nconnected data nodes, the cluster connectstring, and cluster binlog\nepochs, as well as counts of various Cluster API objects created by the\nMySQL Server when connected to the cluster. Sample output from this\nstatement is shown here:\n\nmysql> SHOW ENGINE NDB STATUS;\n+------------+-----------------------+--------------------------------------------------+\n| Type | Name | Status |\n+------------+-----------------------+--------------------------------------------------+\n| ndbcluster | connection | cluster_node_id=7,\n connected_host=192.168.0.103, connected_port=1186, number_of_data_nodes=4,\n number_of_ready_data_nodes=3, connect_count=0 |\n| ndbcluster | NdbTransaction | created=6, free=0, sizeof=212 |\n| ndbcluster | NdbOperation | created=8, free=8, sizeof=660 |\n| ndbcluster | NdbIndexScanOperation | created=1, free=1, sizeof=744 |\n| ndbcluster | NdbIndexOperation | created=0, free=0, sizeof=664 |\n| ndbcluster | NdbRecAttr | created=1285, free=1285, sizeof=60 |\n| ndbcluster | NdbApiSignal | created=16, free=16, sizeof=136 |\n| ndbcluster | NdbLabel | created=0, free=0, sizeof=196 |\n| ndbcluster | NdbBranch | created=0, free=0, sizeof=24 |\n| ndbcluster | NdbSubroutine | created=0, free=0, sizeof=68 |\n| ndbcluster | NdbCall | created=0, free=0, sizeof=16 |\n| ndbcluster | NdbBlob | created=1, free=1, sizeof=264 |\n| ndbcluster | NdbReceiver | created=4, free=0, sizeof=68 |\n| ndbcluster | binlog | latest_epoch=155467, latest_trans_epoch=148126,\n latest_received_binlog_epoch=0, latest_handled_binlog_epoch=0,\n latest_applied_binlog_epoch=0 |\n+------------+-----------------------+--------------------------------------------------+\n\nThe rows with connection and binlog in the Name column were added to\nthe output of this statement in MySQL 5.1. The Status column in each of\nthese rows provides information about the MySQL server\'s connection to\nthe cluster and about the cluster binary log\'s status, respectively.\nThe Status information is in the form of comma-delimited set of\nname/value pairs.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-engine.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-engine.html'),(366,'NAME_CONST',14,'Syntax:\nNAME_CONST(name,value)\n\nReturns the given value. When used to produce a result set column,\nNAME_CONST() causes the column to have the given name. The arguments\nshould be constants.\n\nmysql> SELECT NAME_CONST(\'myname\', 14);\n+--------+\n| myname |\n+--------+\n| 14 |\n+--------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(367,'RELEASE_LOCK',14,'Syntax:\nRELEASE_LOCK(str)\n\nReleases the lock named by the string str that was obtained with\nGET_LOCK(). Returns 1 if the lock was released, 0 if the lock was not\nestablished by this thread (in which case the lock is not released),\nand NULL if the named lock did not exist. The lock does not exist if it\nwas never obtained by a call to GET_LOCK() or if it has previously been\nreleased.\n\nThe DO statement is convenient to use with RELEASE_LOCK(). See [HELP\nDO].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(368,'IS NULL',18,'Syntax:\nIS NULL\n\nTests whether a value is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;\n -> 0, 0, 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(369,'CONVERT_TZ',31,'Syntax:\nCONVERT_TZ(dt,from_tz,to_tz)\n\nCONVERT_TZ() converts a datetime value dt from the time zone given by\nfrom_tz to the time zone given by to_tz and returns the resulting\nvalue. Time zones are specified as described in\nhttp://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html. This\nfunction returns NULL if the arguments are invalid.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'GMT\',\'MET\');\n -> \'2004-01-01 13:00:00\'\nmysql> SELECT CONVERT_TZ(\'2004-01-01 12:00:00\',\'+00:00\',\'+10:00\');\n -> \'2004-01-01 22:00:00\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(370,'TIME_TO_SEC',31,'Syntax:\nTIME_TO_SEC(time)\n\nReturns the time argument, converted to seconds.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIME_TO_SEC(\'22:23:00\');\n -> 80580\nmysql> SELECT TIME_TO_SEC(\'00:39:38\');\n -> 2378\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(371,'WEEKDAY',31,'Syntax:\nWEEKDAY(date)\n\nReturns the weekday index for date (0 = Monday, 1 = Tuesday, ... 6 =\nSunday).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT WEEKDAY(\'2008-02-03 22:23:00\');\n -> 6\nmysql> SELECT WEEKDAY(\'2007-11-06\');\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(372,'EXPORT_SET',37,'Syntax:\nEXPORT_SET(bits,on,off[,separator[,number_of_bits]])\n\nReturns a string such that for every bit set in the value bits, you get\nan on string and for every bit not set in the value, you get an off\nstring. Bits in bits are examined from right to left (from low-order to\nhigh-order bits). Strings are added to the result from left to right,\nseparated by the separator string (the default being the comma\ncharacter \",\"). The number of bits examined is given by number_of_bits,\nwhich has a default of 64 if not specified. number_of_bits is silently\nclipped to 64 if larger than 64. It is treated as an unsigned integer,\nso a value of -1 is effectively the same as 64.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT EXPORT_SET(5,\'Y\',\'N\',\',\',4);\n -> \'Y,N,Y,N\'\nmysql> SELECT EXPORT_SET(6,\'1\',\'0\',\',\',10);\n -> \'0,1,1,0,0,0,0,0,0,0\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(373,'ALTER SERVER',39,'Syntax:\nALTER SERVER server_name\n OPTIONS (option [, option] ...)\n\nAlters the server information for server_name, adjusting any of the\noptions permitted in the CREATE SERVER statement. See [HELP CREATE\nSERVER]. The corresponding fields in the mysql.servers table are\nupdated accordingly. This statement requires the SUPER privilege.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-server.html\n\n','ALTER SERVER s OPTIONS (USER \'sally\');\n','http://dev.mysql.com/doc/refman/5.5/en/alter-server.html'),(374,'RESIGNAL',23,'Syntax:\nRESIGNAL [condition_value]\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nRESIGNAL passes on the error condition information that is available\nduring execution of a condition handler within a compound statement\ninside a stored procedure or function, trigger, or event. RESIGNAL may\nchange some or all information before passing it on. RESIGNAL is\nrelated to SIGNAL, but instead of originating a condition as SIGNAL\ndoes, RESIGNAL relays existing condition information, possibly after\nmodifying it.\n\nRESIGNAL makes it possible to both handle an error and return the error\ninformation. Otherwise, by executing an SQL statement within the\nhandler, information that caused the handler\'s activation is destroyed.\nRESIGNAL also can make some procedures shorter if a given handler can\nhandle part of a situation, then pass the condition \"up the line\" to\nanother handler.\n\nNo special privileges are required to execute the RESIGNAL statement.\n\nFor condition_value and signal_information_item, the definitions and\nrules are the same for RESIGNAL as for SIGNAL (see [HELP SIGNAL]).\n\nThe RESIGNAL statement takes condition_value and SET clauses, both of\nwhich are optional. This leads to several possible uses:\n\no RESIGNAL alone:\n\nRESIGNAL;\n\no RESIGNAL with new signal information:\n\nRESIGNAL SET signal_information_item [, signal_information_item] ...;\n\no RESIGNAL with a condition value and possibly new signal information:\n\nRESIGNAL condition_value\n [SET signal_information_item [, signal_information_item] ...];\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/resignal.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/resignal.html'),(375,'TIME FUNCTION',31,'Syntax:\nTIME(expr)\n\nExtracts the time part of the time or datetime expression expr and\nreturns it as a string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT TIME(\'2003-12-31 01:02:03\');\n -> \'01:02:03\'\nmysql> SELECT TIME(\'2003-12-31 01:02:03.000123\');\n -> \'01:02:03.000123\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(376,'DATE_ADD',31,'Syntax:\nDATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)\n\nThese functions perform date arithmetic. The date argument specifies\nthe starting date or datetime value. expr is an expression specifying\nthe interval value to be added or subtracted from the starting date.\nexpr is a string; it may start with a \"-\" for negative intervals. unit\nis a keyword indicating the units in which the expression should be\ninterpreted.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT \'2008-12-31 23:59:59\' + INTERVAL 1 SECOND;\n -> \'2009-01-01 00:00:00\'\nmysql> SELECT INTERVAL 1 DAY + \'2008-12-31\';\n -> \'2009-01-01\'\nmysql> SELECT \'2005-01-01\' - INTERVAL 1 SECOND;\n -> \'2004-12-31 23:59:59\'\nmysql> SELECT DATE_ADD(\'2000-12-31 23:59:59\',\n -> INTERVAL 1 SECOND);\n -> \'2001-01-01 00:00:00\'\nmysql> SELECT DATE_ADD(\'2010-12-31 23:59:59\',\n -> INTERVAL 1 DAY);\n -> \'2011-01-01 23:59:59\'\nmysql> SELECT DATE_ADD(\'2100-12-31 23:59:59\',\n -> INTERVAL \'1:1\' MINUTE_SECOND);\n -> \'2101-01-01 00:01:00\'\nmysql> SELECT DATE_SUB(\'2005-01-01 00:00:00\',\n -> INTERVAL \'1 1:1:1\' DAY_SECOND);\n -> \'2004-12-30 22:58:59\'\nmysql> SELECT DATE_ADD(\'1900-01-01 00:00:00\',\n -> INTERVAL \'-1 10\' DAY_HOUR);\n -> \'1899-12-30 14:00:00\'\nmysql> SELECT DATE_SUB(\'1998-01-02\', INTERVAL 31 DAY);\n -> \'1997-12-02\'\nmysql> SELECT DATE_ADD(\'1992-12-31 23:59:59.000002\',\n -> INTERVAL \'1.999999\' SECOND_MICROSECOND);\n -> \'1993-01-01 00:00:01.000001\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(377,'CAST',37,'Syntax:\nCAST(expr AS type)\n\nThe CAST() function takes an expression of any type and produces a\nresult value of a specified type, similar to CONVERT(). See the\ndescription of CONVERT() for more information.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html'),(378,'SOUNDS LIKE',37,'Syntax:\nexpr1 SOUNDS LIKE expr2\n\nThis is the same as SOUNDEX(expr1) = SOUNDEX(expr2).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(379,'PERIOD_DIFF',31,'Syntax:\nPERIOD_DIFF(P1,P2)\n\nReturns the number of months between periods P1 and P2. P1 and P2\nshould be in the format YYMM or YYYYMM. Note that the period arguments\nP1 and P2 are not date values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT PERIOD_DIFF(200802,200703);\n -> 11\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(380,'LIKE',37,'Syntax:\nexpr LIKE pat [ESCAPE \'escape_char\']\n\nPattern matching using SQL simple regular expression comparison.\nReturns 1 (TRUE) or 0 (FALSE). If either expr or pat is NULL, the\nresult is NULL.\n\nThe pattern need not be a literal string. For example, it can be\nspecified as a string expression or table column.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html\n\n','mysql> SELECT \'David!\' LIKE \'David_\';\n -> 1\nmysql> SELECT \'David!\' LIKE \'%D%v%\';\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html'),(381,'MULTIPOINT',24,'MultiPoint(pt1,pt2,...)\n\nConstructs a MultiPoint value using Point or WKB Point arguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(382,'>>',19,'Syntax:\n>>\n\nShifts a longlong (BIGINT) number to the right.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 4 >> 2;\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(383,'FETCH',23,'Syntax:\nFETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...\n\nThis statement fetches the next row for the SELECT statement associated\nwith the specified cursor (which must be open), and advances the cursor\npointer. If a row exists, the fetched columns are stored in the named\nvariables. The number of columns retrieved by the SELECT statement must\nmatch the number of output variables specified in the FETCH statement.\n\nIf no more rows are available, a No Data condition occurs with SQLSTATE\nvalue \'02000\'. To detect this condition, you can set up a handler for\nit (or for a NOT FOUND condition). For an example, see\nhttp://dev.mysql.com/doc/refman/5.5/en/cursors.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/fetch.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/fetch.html'),(384,'AVG',16,'Syntax:\nAVG([DISTINCT] expr)\n\nReturns the average value of expr. The DISTINCT option can be used to\nreturn the average of the distinct values of expr.\n\nAVG() returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT student_name, AVG(test_score)\n -> FROM student\n -> GROUP BY student_name;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(385,'TRUE FALSE',29,'The constants TRUE and FALSE evaluate to 1 and 0, respectively. The\nconstant names can be written in any lettercase.\n\nmysql> SELECT TRUE, true, FALSE, false;\n -> 1, 1, 0, 0\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/boolean-literals.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/boolean-literals.html'),(386,'MBRWITHIN',6,'MBRWithin(g1,g2)\n\nReturns 1 or 0 to indicate whether the Minimum Bounding Rectangle of g1\nis within the Minimum Bounding Rectangle of g2. This tests the opposite\nrelationship as MBRContains().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr\n\n','mysql> SET @g1 = GeomFromText(\'Polygon((0 0,0 3,3 3,3 0,0 0))\');\nmysql> SET @g2 = GeomFromText(\'Polygon((0 0,0 5,5 5,5 0,0 0))\');\nmysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);\n+--------------------+--------------------+\n| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |\n+--------------------+--------------------+\n| 1 | 0 |\n+--------------------+--------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#relations-on-geometry-mbr'),(387,'SESSION_USER',17,'Syntax:\nSESSION_USER()\n\nSESSION_USER() is a synonym for USER().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(388,'IN',18,'Syntax:\nexpr IN (value,...)\n\nReturns 1 if expr is equal to any of the values in the IN list, else\nreturns 0. If all values are constants, they are evaluated according to\nthe type of expr and sorted. The search for the item then is done using\na binary search. This means IN is very quick if the IN value list\nconsists entirely of constants. Otherwise, type conversion takes place\naccording to the rules described in\nhttp://dev.mysql.com/doc/refman/5.5/en/type-conversion.html, but\napplied to all the arguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 2 IN (0,3,5,7);\n -> 0\nmysql> SELECT \'wefwf\' IN (\'wee\',\'wefwf\',\'weg\');\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(389,'QUOTE',37,'Syntax:\nQUOTE(str)\n\nQuotes a string to produce a result that can be used as a properly\nescaped data value in an SQL statement. The string is returned enclosed\nby single quotation marks and with each instance of backslash (\"\\\"),\nsingle quote (\"\'\"), ASCII NUL, and Control+Z preceded by a backslash.\nIf the argument is NULL, the return value is the word \"NULL\" without\nenclosing single quotation marks.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT QUOTE(\'Don\\\'t!\');\n -> \'Don\\\'t!\'\nmysql> SELECT QUOTE(NULL);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(390,'HELP COMMAND',26,'Syntax:\nmysql> help search_string\n\nIf you provide an argument to the help command, mysql uses it as a\nsearch string to access server-side help from the contents of the MySQL\nReference Manual. The proper operation of this command requires that\nthe help tables in the mysql database be initialized with help topic\ninformation (see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-side-help-support.html).\n\nIf there is no match for the search string, the search fails:\n\nmysql> help me\n\nNothing found\nPlease try to run \'help contents\' for a list of all accessible topics\n\nUse help contents to see a list of the help categories:\n\nmysql> help contents\nYou asked for help about help category: \"Contents\"\nFor more information, type \'help \', where is one of the\nfollowing categories:\n Account Management\n Administration\n Data Definition\n Data Manipulation\n Data Types\n Functions\n Functions and Modifiers for Use with GROUP BY\n Geographic Features\n Language Structure\n Plugins\n Storage Engines\n Stored Routines\n Table Maintenance\n Transactions\n Triggers\n\nIf the search string matches multiple items, mysql shows a list of\nmatching topics:\n\nmysql> help logs\nMany help items for your request exist.\nTo make a more specific request, please type \'help \',\nwhere is one of the following topics:\n SHOW\n SHOW BINARY LOGS\n SHOW ENGINE\n SHOW LOGS\n\nUse a topic as the search string to see the help entry for that topic:\n\nmysql> help show binary logs\nName: \'SHOW BINARY LOGS\'\nDescription:\nSyntax:\nSHOW BINARY LOGS\nSHOW MASTER LOGS\n\nLists the binary log files on the server. This statement is used as\npart of the procedure described in [purge-binary-logs], that shows how\nto determine which logs can be purged.\n\nmysql> SHOW BINARY LOGS;\n+---------------+-----------+\n| Log_name | File_size |\n+---------------+-----------+\n| binlog.000015 | 724935 |\n| binlog.000016 | 733481 |\n+---------------+-----------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mysql-server-side-help.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/mysql-server-side-help.html'),(391,'QUARTER',31,'Syntax:\nQUARTER(date)\n\nReturns the quarter of the year for date, in the range 1 to 4.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT QUARTER(\'2008-04-01\');\n -> 2\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(392,'POSITION',37,'Syntax:\nPOSITION(substr IN str)\n\nPOSITION(substr IN str) is a synonym for LOCATE(substr,str).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(393,'SHOW CREATE FUNCTION',26,'Syntax:\nSHOW CREATE FUNCTION func_name\n\nThis statement is similar to SHOW CREATE PROCEDURE but for stored\nfunctions. See [HELP SHOW CREATE PROCEDURE].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-function.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-create-function.html'),(394,'IS_USED_LOCK',14,'Syntax:\nIS_USED_LOCK(str)\n\nChecks whether the lock named str is in use (that is, locked). If so,\nit returns the connection identifier of the client that holds the lock.\nOtherwise, it returns NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(395,'POLYFROMTEXT',3,'PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])\n\nConstructs a POLYGON value using its WKT representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(396,'DES_ENCRYPT',12,'Syntax:\nDES_ENCRYPT(str[,{key_num|key_str}])\n\nEncrypts the string with the given key using the Triple-DES algorithm.\n\nThis function works only if MySQL has been configured with SSL support.\nSee http://dev.mysql.com/doc/refman/5.5/en/ssl-connections.html.\n\nThe encryption key to use is chosen based on the second argument to\nDES_ENCRYPT(), if one was given. With no argument, the first key from\nthe DES key file is used. With a key_num argument, the given key number\n(0 to 9) from the DES key file is used. With a key_str argument, the\ngiven key string is used to encrypt str.\n\nThe key file can be specified with the --des-key-file server option.\n\nThe return string is a binary string where the first character is\nCHAR(128 | key_num). If an error occurs, DES_ENCRYPT() returns NULL.\n\nThe 128 is added to make it easier to recognize an encrypted key. If\nyou use a string key, key_num is 127.\n\nThe string length for the result is given by this formula:\n\nnew_len = orig_len + (8 - (orig_len % 8)) + 1\n\nEach line in the DES key file has the following format:\n\nkey_num des_key_str\n\nEach key_num value must be a number in the range from 0 to 9. Lines in\nthe file may be in any order. des_key_str is the string that is used to\nencrypt the message. There should be at least one space between the\nnumber and the key. The first key is the default key that is used if\nyou do not specify any key argument to DES_ENCRYPT().\n\nYou can tell MySQL to read new key values from the key file with the\nFLUSH DES_KEY_FILE statement. This requires the RELOAD privilege.\n\nOne benefit of having a set of default keys is that it gives\napplications a way to check for the existence of encrypted column\nvalues, without giving the end user the right to decrypt those values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT customer_address FROM customer_table \n > WHERE crypted_credit_card = DES_ENCRYPT(\'credit_card_number\');\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(397,'CEIL',4,'Syntax:\nCEIL(X)\n\nCEIL() is a synonym for CEILING().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(398,'LENGTH',37,'Syntax:\nLENGTH(str)\n\nReturns the length of the string str, measured in bytes. A multi-byte\ncharacter counts as multiple bytes. This means that for a string\ncontaining five 2-byte characters, LENGTH() returns 10, whereas\nCHAR_LENGTH() returns 5.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT LENGTH(\'text\');\n -> 4\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(399,'STR_TO_DATE',31,'Syntax:\nSTR_TO_DATE(str,format)\n\nThis is the inverse of the DATE_FORMAT() function. It takes a string\nstr and a format string format. STR_TO_DATE() returns a DATETIME value\nif the format string contains both date and time parts, or a DATE or\nTIME value if the string contains only date or time parts. If the date,\ntime, or datetime value extracted from str is illegal, STR_TO_DATE()\nreturns NULL and produces a warning.\n\nThe server scans str attempting to match format to it. The format\nstring can contain literal characters and format specifiers beginning\nwith %. Literal characters in format must match literally in str.\nFormat specifiers in format must match a date or time part in str. For\nthe specifiers that can be used in format, see the DATE_FORMAT()\nfunction description.\n\nmysql> SELECT STR_TO_DATE(\'01,5,2013\',\'%d,%m,%Y\');\n -> \'2013-05-01\'\nmysql> SELECT STR_TO_DATE(\'May 1, 2013\',\'%M %d,%Y\');\n -> \'2013-05-01\'\n\nScanning starts at the beginning of str and fails if format is found\nnot to match. Extra characters at the end of str are ignored.\n\nmysql> SELECT STR_TO_DATE(\'a09:30:17\',\'a%h:%i:%s\');\n -> \'09:30:17\'\nmysql> SELECT STR_TO_DATE(\'a09:30:17\',\'%h:%i:%s\');\n -> NULL\nmysql> SELECT STR_TO_DATE(\'09:30:17a\',\'%h:%i:%s\');\n -> \'09:30:17\'\n\nUnspecified date or time parts have a value of 0, so incompletely\nspecified values in str produce a result with some or all parts set to\n0:\n\nmysql> SELECT STR_TO_DATE(\'abc\',\'abc\');\n -> \'0000-00-00\'\nmysql> SELECT STR_TO_DATE(\'9\',\'%m\');\n -> \'0000-09-00\'\nmysql> SELECT STR_TO_DATE(\'9\',\'%s\');\n -> \'00:00:09\'\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(400,'Y',11,'Y(p)\n\nReturns the Y-coordinate value for the Point object p as a\ndouble-precision number.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#point-property-functions\n\n','mysql> SELECT Y(POINT(56.7, 53.34));\n+-----------------------+\n| Y(POINT(56.7, 53.34)) |\n+-----------------------+\n| 53.34 |\n+-----------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#point-property-functions'),(401,'CHECKSUM TABLE',20,'Syntax:\nCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]\n\nCHECKSUM TABLE reports a table checksum. This statement requires the\nSELECT privilege for the table.\n\nWith QUICK, the live table checksum is reported if it is available, or\nNULL otherwise. This is very fast. A live checksum is enabled by\nspecifying the CHECKSUM=1 table option when you create the table;\ncurrently, this is supported only for MyISAM tables. See [HELP CREATE\nTABLE].\n\nWith EXTENDED, the entire table is read row by row and the checksum is\ncalculated. This can be very slow for large tables.\n\nIf neither QUICK nor EXTENDED is specified, MySQL returns a live\nchecksum if the table storage engine supports it and scans the table\notherwise.\n\nFor a nonexistent table, CHECKSUM TABLE returns NULL and generates a\nwarning.\n\nIn MySQL 5.5, CHECKSUM TABLE returns 0 for partitioned tables unless\nyou include the EXTENDED option. This issue is resolved in MySQL 5.6.\n(Bug #11933226, Bug #60681)\n\nThe checksum value depends on the table row format. If the row format\nchanges, the checksum also changes. For example, the storage format for\nVARCHAR changed between MySQL 4.1 and 5.0, so if a 4.1 table is\nupgraded to MySQL 5.0, the checksum value may change.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/checksum-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/checksum-table.html'),(402,'NUMINTERIORRINGS',2,'NumInteriorRings(poly)\n\nReturns the number of interior rings in the Polygon value poly.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions\n\n','mysql> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nmysql> SELECT NumInteriorRings(GeomFromText(@poly));\n+---------------------------------------+\n| NumInteriorRings(GeomFromText(@poly)) |\n+---------------------------------------+\n| 1 |\n+---------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions'),(403,'INTERIORRINGN',2,'InteriorRingN(poly,N)\n\nReturns the N-th interior ring for the Polygon value poly as a\nLineString. Rings are numbered beginning with 1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions\n\n','mysql> SET @poly =\n -> \'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))\';\nmysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));\n+----------------------------------------------+\n| AsText(InteriorRingN(GeomFromText(@poly),1)) |\n+----------------------------------------------+\n| LINESTRING(1 1,1 2,2 2,2 1,1 1) |\n+----------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#polygon-property-functions'),(404,'UTC_TIME',31,'Syntax:\nUTC_TIME, UTC_TIME()\n\nReturns the current UTC time as a value in \'HH:MM:SS\' or HHMMSS.uuuuuu\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT UTC_TIME(), UTC_TIME() + 0;\n -> \'18:07:53\', 180753.000000\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(405,'DROP FUNCTION',39,'The DROP FUNCTION statement is used to drop stored functions and\nuser-defined functions (UDFs):\n\no For information about dropping stored functions, see [HELP DROP\n PROCEDURE].\n\no For information about dropping user-defined functions, see [HELP DROP\n FUNCTION UDF].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-function.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-function.html'),(406,'ALTER EVENT',39,'Syntax:\nALTER\n [DEFINER = { user | CURRENT_USER }]\n EVENT event_name\n [ON SCHEDULE schedule]\n [ON COMPLETION [NOT] PRESERVE]\n [RENAME TO new_event_name]\n [ENABLE | DISABLE | DISABLE ON SLAVE]\n [COMMENT \'comment\']\n [DO event_body]\n\nThe ALTER EVENT statement changes one or more of the characteristics of\nan existing event without the need to drop and recreate it. The syntax\nfor each of the DEFINER, ON SCHEDULE, ON COMPLETION, COMMENT, ENABLE /\nDISABLE, and DO clauses is exactly the same as when used with CREATE\nEVENT. (See [HELP CREATE EVENT].)\n\nAny user can alter an event defined on a database for which that user\nhas the EVENT privilege. When a user executes a successful ALTER EVENT\nstatement, that user becomes the definer for the affected event.\n\nALTER EVENT works only with an existing event:\n\nmysql> ALTER EVENT no_such_event \n > ON SCHEDULE \n > EVERY \'2:3\' DAY_HOUR;\nERROR 1517 (HY000): Unknown event \'no_such_event\'\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-event.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-event.html'),(407,'STDDEV',16,'Syntax:\nSTDDEV(expr)\n\nReturns the population standard deviation of expr. This function is\nprovided for compatibility with Oracle. The standard SQL function\nSTDDEV_POP() can be used instead.\n\nThis function returns NULL if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(408,'DATE_SUB',31,'Syntax:\nDATE_SUB(date,INTERVAL expr unit)\n\nSee the description for DATE_ADD().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(409,'PERIOD_ADD',31,'Syntax:\nPERIOD_ADD(P,N)\n\nAdds N months to period P (in the format YYMM or YYYYMM). Returns a\nvalue in the format YYYYMM. Note that the period argument P is not a\ndate value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT PERIOD_ADD(200801,2);\n -> 200803\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(410,'|',19,'Syntax:\n|\n\nBitwise OR:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT 29 | 15;\n -> 31\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(411,'GEOMFROMTEXT',3,'GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])\n\nConstructs a geometry value of any type using its WKT representation\nand SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(412,'UUID_SHORT',14,'Syntax:\nUUID_SHORT()\n\nReturns a \"short\" universal identifier as a 64-bit unsigned integer\n(rather than a string-form 128-bit identifier as returned by the UUID()\nfunction).\n\nThe value of UUID_SHORT() is guaranteed to be unique if the following\nconditions hold:\n\no The server_id of the current host is unique among your set of master\n and slave servers\n\no server_id is between 0 and 255\n\no You do not set back your system time for your server between mysqld\n restarts\n\no You do not invoke UUID_SHORT() on average more than 16 million times\n per second between mysqld restarts\n\nThe UUID_SHORT() return value is constructed this way:\n\n (server_id & 255) << 56\n+ (server_startup_time_in_seconds << 24)\n+ incremented_variable++;\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> SELECT UUID_SHORT();\n -> 92395783831158784\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(413,'RIGHT',37,'Syntax:\nRIGHT(str,len)\n\nReturns the rightmost len characters from the string str, or NULL if\nany argument is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT RIGHT(\'foobarbar\', 4);\n -> \'rbar\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(414,'DATEDIFF',31,'Syntax:\nDATEDIFF(expr1,expr2)\n\nDATEDIFF() returns expr1 - expr2 expressed as a value in days from one\ndate to the other. expr1 and expr2 are date or date-and-time\nexpressions. Only the date parts of the values are used in the\ncalculation.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DATEDIFF(\'2007-12-31 23:59:59\',\'2007-12-30\');\n -> 1\nmysql> SELECT DATEDIFF(\'2010-11-30 23:59:59\',\'2010-12-31\');\n -> -31\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(415,'DROP TABLESPACE',39,'Syntax:\nDROP TABLESPACE tablespace_name\n ENGINE [=] engine_name\n\nThis statement drops a tablespace that was previously created using\nCREATE TABLESPACE (see [HELP CREATE TABLESPACE]).\n\n*Important*: The tablespace to be dropped must not contain any data\nfiles; in other words, before you can drop a tablespace, you must first\ndrop each of its data files using ALTER TABLESPACE ... DROP DATAFILE\n(see [HELP ALTER TABLESPACE]).\n\nThe ENGINE clause (required) specifies the storage engine used by the\ntablespace. Currently, the only accepted values for engine_name are NDB\nand NDBCLUSTER.\n\nDROP TABLESPACE is useful only with Disk Data storage for MySQL\nCluster. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-cluster-disk-data.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-tablespace.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-tablespace.html'),(416,'DROP PROCEDURE',39,'Syntax:\nDROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name\n\nThis statement is used to drop a stored procedure or function. That is,\nthe specified routine is removed from the server. You must have the\nALTER ROUTINE privilege for the routine. (If the\nautomatic_sp_privileges system variable is enabled, that privilege and\nEXECUTE are granted automatically to the routine creator when the\nroutine is created and dropped from the creator when the routine is\ndropped. See\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-routines-privileges.html.\n)\n\nThe IF EXISTS clause is a MySQL extension. It prevents an error from\noccurring if the procedure or function does not exist. A warning is\nproduced that can be viewed with SHOW WARNINGS.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/drop-procedure.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/drop-procedure.html'),(417,'CHECK TABLE',20,'Syntax:\nCHECK TABLE tbl_name [, tbl_name] ... [option] ...\n\noption = {FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED}\n\nCHECK TABLE checks a table or tables for errors. CHECK TABLE works for\nInnoDB, MyISAM, ARCHIVE, and CSV tables. For MyISAM tables, the key\nstatistics are updated as well.\n\nTo check a table, you must have some privilege for it.\n\nCHECK TABLE can also check views for problems, such as tables that are\nreferenced in the view definition that no longer exist.\n\nCHECK TABLE is supported for partitioned tables, and you can use ALTER\nTABLE ... CHECK PARTITION to check one or more partitions; for more\ninformation, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/check-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/check-table.html'),(418,'BIN',37,'Syntax:\nBIN(N)\n\nReturns a string representation of the binary value of N, where N is a\nlonglong (BIGINT) number. This is equivalent to CONV(N,10,2). Returns\nNULL if N is NULL.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT BIN(12);\n -> \'1100\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(419,'INSTALL PLUGIN',5,'Syntax:\nINSTALL PLUGIN plugin_name SONAME \'shared_library_name\'\n\nThis statement installs a server plugin. It requires the INSERT\nprivilege for the mysql.plugin table.\n\nplugin_name is the name of the plugin as defined in the plugin\ndescriptor structure contained in the library file (see\nhttp://dev.mysql.com/doc/refman/5.5/en/plugin-data-structures.html).\nPlugin names are not case sensitive. For maximal compatibility, plugin\nnames should be limited to ASCII letters, digits, and underscore\nbecause they are used in C source files, shell command lines, M4 and\nBourne shell scripts, and SQL environments.\n\nshared_library_name is the name of the shared library that contains the\nplugin code. The name includes the file name extension (for example,\nlibmyplugin.so, libmyplugin.dll, or libmyplugin.dylib).\n\nThe shared library must be located in the plugin directory (the\ndirectory named by the plugin_dir system variable). The library must be\nin the plugin directory itself, not in a subdirectory. By default,\nplugin_dir is the plugin directory under the directory named by the\npkglibdir configuration variable, but it can be changed by setting the\nvalue of plugin_dir at server startup. For example, set its value in a\nmy.cnf file:\n\n[mysqld]\nplugin_dir=/path/to/plugin/directory\n\nIf the value of plugin_dir is a relative path name, it is taken to be\nrelative to the MySQL base directory (the value of the basedir system\nvariable).\n\nINSTALL PLUGIN loads and initializes the plugin code to make the plugin\navailable for use. A plugin is initialized by executing its\ninitialization function, which handles any setup that the plugin must\nperform before it can be used. When the server shuts down, it executes\nthe deinitialization function for each plugin that is loaded so that\nthe plugin has a change to perform any final cleanup.\n\nINSTALL PLUGIN also registers the plugin by adding a line that\nindicates the plugin name and library file name to the mysql.plugin\ntable. At server startup, the server loads and initializes any plugin\nthat is listed in the mysql.plugin table. This means that a plugin is\ninstalled with INSTALL PLUGIN only once, not every time the server\nstarts. Plugin loading at startup does not occur if the server is\nstarted with the --skip-grant-tables option.\n\nA plugin library can contain multiple plugins. For each of them to be\ninstalled, use a separate INSTALL PLUGIN statement. Each statement\nnames a different plugin, but all of them specify the same library\nname.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/install-plugin.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/install-plugin.html'),(420,'DECLARE CURSOR',23,'Syntax:\nDECLARE cursor_name CURSOR FOR select_statement\n\nThis statement declares a cursor and associates it with a SELECT\nstatement that retrieves the rows to be traversed by the cursor. To\nfetch the rows later, use a FETCH statement. The number of columns\nretrieved by the SELECT statement must match the number of output\nvariables specified in the FETCH statement.\n\nThe SELECT statement cannot have an INTO clause.\n\nCursor declarations must appear before handler declarations and after\nvariable and condition declarations.\n\nA stored program may contain multiple cursor declarations, but each\ncursor declared in a given block must have a unique name. For an\nexample, see http://dev.mysql.com/doc/refman/5.5/en/cursors.html.\n\nFor information available through SHOW statements, it is possible in\nmany cases to obtain equivalent information by using a cursor with an\nINFORMATION_SCHEMA table.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/declare-cursor.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/declare-cursor.html'),(421,'LOAD DATA',27,'Syntax:\nLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name\'\n [REPLACE | IGNORE]\n INTO TABLE tbl_name\n [CHARACTER SET charset_name]\n [{FIELDS | COLUMNS}\n [TERMINATED BY \'string\']\n [[OPTIONALLY] ENCLOSED BY \'char\']\n [ESCAPED BY \'char\']\n ]\n [LINES\n [STARTING BY \'string\']\n [TERMINATED BY \'string\']\n ]\n [IGNORE number {LINES | ROWS}]\n [(col_name_or_user_var,...)]\n [SET col_name = expr,...]\n\nThe LOAD DATA INFILE statement reads rows from a text file into a table\nat a very high speed. The file name must be given as a literal string.\n\nLOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. (See\nhttp://dev.mysql.com/doc/refman/5.5/en/select-into.html.) To write data\nfrom a table to a file, use SELECT ... INTO OUTFILE. To read the file\nback into a table, use LOAD DATA INFILE. The syntax of the FIELDS and\nLINES clauses is the same for both statements. Both clauses are\noptional, but FIELDS must precede LINES if both are specified.\n\nFor more information about the efficiency of INSERT versus LOAD DATA\nINFILE and speeding up LOAD DATA INFILE, see\nhttp://dev.mysql.com/doc/refman/5.5/en/insert-speed.html.\n\nThe character set indicated by the character_set_database system\nvariable is used to interpret the information in the file. SET NAMES\nand the setting of character_set_client do not affect interpretation of\ninput. If the contents of the input file use a character set that\ndiffers from the default, it is usually preferable to specify the\ncharacter set of the file by using the CHARACTER SET clause. A\ncharacter set of binary specifies \"no conversion.\"\n\nLOAD DATA INFILE interprets all fields in the file as having the same\ncharacter set, regardless of the data types of the columns into which\nfield values are loaded. For proper interpretation of file contents,\nyou must ensure that it was written with the correct character set. For\nexample, if you write a data file with mysqldump -T or by issuing a\nSELECT ... INTO OUTFILE statement in mysql, be sure to use a\n--default-character-set option with mysqldump or mysql so that output\nis written in the character set to be used when the file is loaded with\nLOAD DATA INFILE.\n\n*Note*: It is not possible to load data files that use the ucs2, utf16,\nor utf32 character set.\n\nThe character_set_filesystem system variable controls the\ninterpretation of the file name.\n\nYou can also load data files by using the mysqlimport utility; it\noperates by sending a LOAD DATA INFILE statement to the server. The\n--local option causes mysqlimport to read data files from the client\nhost. You can specify the --compress option to get better performance\nover slow networks if the client and server support the compressed\nprotocol. See http://dev.mysql.com/doc/refman/5.5/en/mysqlimport.html.\n\nIf you use LOW_PRIORITY, execution of the LOAD DATA statement is\ndelayed until no other clients are reading from the table. This affects\nonly storage engines that use only table-level locking (such as MyISAM,\nMEMORY, and MERGE).\n\nIf you specify CONCURRENT with a MyISAM table that satisfies the\ncondition for concurrent inserts (that is, it contains no free blocks\nin the middle), other threads can retrieve data from the table while\nLOAD DATA is executing. Using this option affects the performance of\nLOAD DATA a bit, even if no other thread is using the table at the same\ntime.\n\nPrior to MySQL 5.5.1, CONCURRENT was not replicated when using\nstatement-based replication (see Bug #34628). However, it is replicated\nwhen using row-based replication, regardless of the version. See\nhttp://dev.mysql.com/doc/refman/5.5/en/replication-features-load-data.h\ntml, for more information.\n\nThe LOCAL keyword, if specified, is interpreted with respect to the\nclient end of the connection:\n\no If LOCAL is specified, the file is read by the client program on the\n client host and sent to the server. The file can be given as a full\n path name to specify its exact location. If given as a relative path\n name, the name is interpreted relative to the directory in which the\n client program was started.\n\n When using LOCAL with LOAD DATA, a copy of the file is created in the\n server\'s temporary directory. This is not the directory determined by\n the value of tmpdir or slave_load_tmpdir, but rather the operating\n system\'s temporary directory, and is not configurable in the MySQL\n Server. (Typically the system temporary directory is /tmp on Linux\n systems and C:\\WINDOWS\\TEMP on Windows.) Lack of sufficient space for\n the copy in this directory can cause the LOAD DATA LOCAL statement to\n fail.\n\no If LOCAL is not specified, the file must be located on the server\n host and is read directly by the server. The server uses the\n following rules to locate the file:\n\n o If the file name is an absolute path name, the server uses it as\n given.\n\n o If the file name is a relative path name with one or more leading\n components, the server searches for the file relative to the\n server\'s data directory.\n\n o If a file name with no leading components is given, the server\n looks for the file in the database directory of the default\n database.\n\nNote that, in the non-LOCAL case, these rules mean that a file named as\n./myfile.txt is read from the server\'s data directory, whereas the file\nnamed as myfile.txt is read from the database directory of the default\ndatabase. For example, if db1 is the default database, the following\nLOAD DATA statement reads the file data.txt from the database directory\nfor db1, even though the statement explicitly loads the file into a\ntable in the db2 database:\n\nLOAD DATA INFILE \'data.txt\' INTO TABLE db2.my_table;\n\nWindows path names are specified using forward slashes rather than\nbackslashes. If you do use backslashes, you must double them.\n\nFor security reasons, when reading text files located on the server,\nthe files must either reside in the database directory or be readable\nby all. Also, to use LOAD DATA INFILE on server files, you must have\nthe FILE privilege. See\nhttp://dev.mysql.com/doc/refman/5.5/en/privileges-provided.html. For\nnon-LOCAL load operations, if the secure_file_priv system variable is\nset to a nonempty directory name, the file to be loaded must be located\nin that directory.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/load-data.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/load-data.html'),(422,'MULTILINESTRING',24,'MultiLineString(ls1,ls2,...)\n\nConstructs a MultiLineString value using LineString or WKB LineString\narguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-mysql-specific-functions'),(423,'LOCALTIME',31,'Syntax:\nLOCALTIME, LOCALTIME()\n\nLOCALTIME and LOCALTIME() are synonyms for NOW().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(424,'SHOW RELAYLOG EVENTS',26,'Syntax:\nSHOW RELAYLOG EVENTS\n [IN \'log_name\'] [FROM pos] [LIMIT [offset,] row_count]\n\nShows the events in the relay log of a replication slave. If you do not\nspecify \'log_name\', the first relay log is displayed. This statement\nhas no effect on the master.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-relaylog-events.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-relaylog-events.html'),(425,'MPOINTFROMTEXT',3,'MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])\n\nConstructs a MULTIPOINT value using its WKT representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkt-functions'),(426,'BLOB',22,'BLOB[(M)]\n\nA BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each\nBLOB value is stored using a 2-byte length prefix that indicates the\nnumber of bytes in the value.\n\nAn optional length M can be given for this type. If this is done, MySQL\ncreates the column as the smallest BLOB type large enough to hold\nvalues M bytes long.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(427,'SHA1',12,'Syntax:\nSHA1(str), SHA(str)\n\nCalculates an SHA-1 160-bit checksum for the string, as described in\nRFC 3174 (Secure Hash Algorithm). The value is returned as a string of\n40 hex digits, or NULL if the argument was NULL. One of the possible\nuses for this function is as a hash key. See the notes at the beginning\nof this section about storing hash values efficiently. You can also use\nSHA1() as a cryptographic function for storing passwords. SHA() is\nsynonymous with SHA1().\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring; see the notes at the beginning of this section about using the\nvalue as a nonbinary string.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SELECT SHA1(\'abc\');\n -> \'a9993e364706816aba3e25717850c26c9cd0d89d\'\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(428,'SUBSTR',37,'Syntax:\nSUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str\nFROM pos FOR len)\n\nSUBSTR() is a synonym for SUBSTRING().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(429,'PASSWORD',12,'Syntax:\nPASSWORD(str)\n\nCalculates and returns a hashed password string from the plaintext\npassword str and returns a nonbinary string in the connection character\nset (a binary string before MySQL 5.5.3), or NULL if the argument is\nNULL. This function is the SQL interface to the algorithm used by the\nserver to encrypt MySQL passwords for storage in the mysql.user grant\ntable.\n\nThe password hashing method used by PASSWORD() depends on the value of\nthe old_passwords system variable:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','mysql> SET old_passwords = 0;\nmysql> SELECT PASSWORD(\'mypass\');\n+-------------------------------------------+\n| PASSWORD(\'mypass\') |\n+-------------------------------------------+\n| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |\n+-------------------------------------------+\n\nmysql> SET old_passwords = 1;\nmysql> SELECT PASSWORD(\'mypass\');\n+--------------------+\n| PASSWORD(\'mypass\') |\n+--------------------+\n| 6f8c114b58f2ce9e |\n+--------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(430,'CHAR',22,'[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nA fixed-length string that is always right-padded with spaces to the\nspecified length when stored. M represents the column length in\ncharacters. The range of M is 0 to 255. If M is omitted, the length is\n1.\n\n*Note*: Trailing spaces are removed when CHAR values are retrieved\nunless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(431,'UTC_DATE',31,'Syntax:\nUTC_DATE, UTC_DATE()\n\nReturns the current UTC date as a value in \'YYYY-MM-DD\' or YYYYMMDD\nformat, depending on whether the function is used in a string or\nnumeric context.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT UTC_DATE(), UTC_DATE() + 0;\n -> \'2003-08-14\', 20030814\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(432,'DIMENSION',36,'Dimension(g)\n\nReturns the inherent dimension of the geometry value g. The result can\nbe -1, 0, 1, or 2. The meaning of these values is given in\nhttp://dev.mysql.com/doc/refman/5.5/en/gis-class-geometry.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','mysql> SELECT Dimension(GeomFromText(\'LineString(1 1,2 2)\'));\n+------------------------------------------------+\n| Dimension(GeomFromText(\'LineString(1 1,2 2)\')) |\n+------------------------------------------------+\n| 1 |\n+------------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(433,'COUNT DISTINCT',16,'Syntax:\nCOUNT(DISTINCT expr,[expr...])\n\nReturns a count of the number of rows with different non-NULL expr\nvalues.\n\nCOUNT(DISTINCT) returns 0 if there were no matching rows.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html\n\n','mysql> SELECT COUNT(DISTINCT results) FROM student;\n','http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html'),(434,'BIT',22,'BIT[(M)]\n\nA bit-field type. M indicates the number of bits per value, from 1 to\n64. The default is 1 if M is omitted.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(435,'EQUALS',30,'Equals(g1,g2)\n\nReturns 1 or 0 to indicate whether g1 is spatially equal to g2.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries\n\n','','http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html#functions-that-test-spatial-relationships-between-geometries'),(436,'SHOW CREATE VIEW',26,'Syntax:\nSHOW CREATE VIEW view_name\n\nThis statement shows a CREATE VIEW statement that creates the given\nview.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-create-view.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-create-view.html'),(437,'INTERVAL',18,'Syntax:\nINTERVAL(N,N1,N2,N3,...)\n\nReturns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All\narguments are treated as integers. It is required that N1 < N2 < N3 <\n... < Nn for this function to work correctly. This is because a binary\nsearch is used (very fast).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\n -> 3\nmysql> SELECT INTERVAL(10, 1, 10, 100, 1000);\n -> 2\nmysql> SELECT INTERVAL(22, 23, 30, 44, 200);\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(438,'FROM_DAYS',31,'Syntax:\nFROM_DAYS(N)\n\nGiven a day number N, returns a DATE value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT FROM_DAYS(730669);\n -> \'2007-07-03\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(439,'ALTER PROCEDURE',39,'Syntax:\nALTER PROCEDURE proc_name [characteristic ...]\n\ncharacteristic:\n COMMENT \'string\'\n | LANGUAGE SQL\n | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }\n | SQL SECURITY { DEFINER | INVOKER }\n\nThis statement can be used to change the characteristics of a stored\nprocedure. More than one change may be specified in an ALTER PROCEDURE\nstatement. However, you cannot change the parameters or body of a\nstored procedure using this statement; to make such changes, you must\ndrop and re-create the procedure using DROP PROCEDURE and CREATE\nPROCEDURE.\n\nYou must have the ALTER ROUTINE privilege for the procedure. By\ndefault, that privilege is granted automatically to the procedure\ncreator. This behavior can be changed by disabling the\nautomatic_sp_privileges system variable. See\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-routines-privileges.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-procedure.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-procedure.html'),(440,'BIT_COUNT',19,'Syntax:\nBIT_COUNT(N)\n\nReturns the number of bits that are set in the argument N.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html\n\n','mysql> SELECT BIT_COUNT(29), BIT_COUNT(b\'101010\');\n -> 4, 3\n','http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html'),(441,'OCTET_LENGTH',37,'Syntax:\nOCTET_LENGTH(str)\n\nOCTET_LENGTH() is a synonym for LENGTH().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(442,'UTC_TIMESTAMP',31,'Syntax:\nUTC_TIMESTAMP, UTC_TIMESTAMP()\n\nReturns the current UTC date and time as a value in \'YYYY-MM-DD\nHH:MM:SS\' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the\nfunction is used in a string or numeric context.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;\n -> \'2003-08-14 18:08:04\', 20030814180804.000000\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(443,'AES_ENCRYPT',12,'Syntax:\nAES_ENCRYPT(str,key_str)\n\nAES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of\ndata using the official AES (Advanced Encryption Standard) algorithm,\npreviously known as \"Rijndael.\" Encoding with a 128-bit key length is\nused, but you can extend it up to 256 bits by modifying the source. We\nchose 128 bits because it is much faster and it is secure enough for\nmost purposes.\n\nAES_ENCRYPT() encrypts a string and returns a binary string.\nAES_DECRYPT() decrypts the encrypted string and returns the original\nstring. The input arguments may be any length. If either argument is\nNULL, the result of this function is also NULL.\n\nBecause AES is a block-level algorithm, padding is used to encode\nuneven length strings and so the result string length may be calculated\nusing this formula:\n\n16 * (trunc(string_length / 16) + 1)\n\nIf AES_DECRYPT() detects invalid data or incorrect padding, it returns\nNULL. However, it is possible for AES_DECRYPT() to return a non-NULL\nvalue (possibly garbage) if the input data or the key is invalid.\n\nYou can use the AES functions to store data in an encrypted form by\nmodifying your queries:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','INSERT INTO t VALUES (1,AES_ENCRYPT(\'text\',\'password\'));\n','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(444,'+',4,'Syntax:\n+\n\nAddition:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html\n\n','mysql> SELECT 3+5;\n -> 8\n','http://dev.mysql.com/doc/refman/5.5/en/arithmetic-functions.html'),(445,'INET_NTOA',14,'Syntax:\nINET_NTOA(expr)\n\nGiven a numeric IPv4 network address in network byte order, returns the\ndotted-quad representation of the address as a string. INET_NTOA()\nreturns NULL if it does not understand its argument.\n\nAs of MySQL 5.5.3, the return value is a nonbinary string in the\nconnection character set. Before 5.5.3, the return value is a binary\nstring.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html\n\n','mysql> SELECT INET_NTOA(167773449);\n -> \'10.0.5.9\'\n','http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html'),(446,'ACOS',4,'Syntax:\nACOS(X)\n\nReturns the arc cosine of X, that is, the value whose cosine is X.\nReturns NULL if X is not in the range -1 to 1.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ACOS(1);\n -> 0\nmysql> SELECT ACOS(1.0001);\n -> NULL\nmysql> SELECT ACOS(0);\n -> 1.5707963267949\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(447,'ISOLATION',8,'Syntax:\nSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL\n {\n REPEATABLE READ\n | READ COMMITTED\n | READ UNCOMMITTED\n | SERIALIZABLE\n }\n\nThis statement sets the transaction isolation level, used for\noperations on InnoDB tables.\n\nScope of the Isolation Level\n\nYou can set the isolation level globally, for the current session, or\nfor the next transaction:\n\no With the GLOBAL keyword, the statement sets the default transaction\n level globally for all subsequent sessions. Existing sessions are\n unaffected.\n\no With the SESSION keyword, the statement sets the default transaction\n level for all subsequent transactions performed within the current\n session.\n\no Without any SESSION or GLOBAL keyword, the statement sets the\n isolation level for the next (not started) transaction performed\n within the current session.\n\nA change to the global default isolation level requires the SUPER\nprivilege. Any session is free to change its session isolation level\n(even in the middle of a transaction), or the isolation level for its\nnext transaction.\n\nSET TRANSACTION ISOLATION LEVEL without GLOBAL or SESSION is not\npermitted while there is an active transaction:\n\nmysql> START TRANSACTION;\nQuery OK, 0 rows affected (0.02 sec)\n\nmysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\nERROR 1568 (25001): Transaction isolation level can\'t be changed\nwhile a transaction is in progress\n\nTo set the global default isolation level at server startup, use the\n--transaction-isolation=level option to mysqld on the command line or\nin an option file. Values of level for this option use dashes rather\nthan spaces, so the permissible values are READ-UNCOMMITTED,\nREAD-COMMITTED, REPEATABLE-READ, or SERIALIZABLE. For example, to set\nthe default isolation level to REPEATABLE READ, use these lines in the\n[mysqld] section of an option file:\n\n[mysqld]\ntransaction-isolation = REPEATABLE-READ\n\nIt is possible to check or set the global and session transaction\nisolation levels at runtime by using the tx_isolation system variable:\n\nSELECT @@GLOBAL.tx_isolation, @@tx_isolation;\nSET GLOBAL tx_isolation=\'REPEATABLE-READ\';\nSET SESSION tx_isolation=\'SERIALIZABLE\';\n\nDetails and Usage of Isolation Levels\n\nInnoDB supports each of the transaction isolation levels described here\nusing different locking strategies. You can enforce a high degree of\nconsistency with the default REPEATABLE READ level, for operations on\ncrucial data where ACID compliance is important. Or you can relax the\nconsistency rules with READ COMMITTED or even READ UNCOMMITTED, in\nsituations such as bulk reporting where precise consistency and\nrepeatable results are less important than minimizing the amount of\noverhead for locking. SERIALIZABLE enforces even stricter rules than\nREPEATABLE READ, and is used mainly in specialized situations, such as\nwith XA transactions and for troubleshooting issues with concurrency\nand deadlocks.\n\nFor full information about how these isolation levels work with InnoDB\ntransactions, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-transaction-model.html.\nIn particular, for additional information about InnoDB record-level\nlocks and how it uses them to execute various types of statements, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html\nand http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html.\n\nThe following list describes how MySQL supports the different\ntransaction levels. The list goes from the most commonly used level to\nthe least used.\n\no REPEATABLE READ\n\n This is the default isolation level for InnoDB. For consistent reads,\n there is an important difference from the READ COMMITTED isolation\n level: All consistent reads within the same transaction read the\n snapshot established by the first read. This convention means that if\n you issue several plain (nonlocking) SELECT statements within the\n same transaction, these SELECT statements are consistent also with\n respect to each other. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n UPDATE, and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition, or a\n range-type search condition. For a unique index with a unique search\n condition, InnoDB locks only the index record found, not the gap\n before it. For other search conditions, InnoDB locks the index range\n scanned, using gap locks or next-key (gap plus index-record) locks to\n block insertions by other sessions into the gaps covered by the\n range.\n\no READ COMMITTED\n\n A somewhat Oracle-like isolation level with respect to consistent\n (nonlocking) reads: Each consistent read, even within the same\n transaction, sets and reads its own fresh snapshot. See\n http://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html.\n\n For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE),\n InnoDB locks only index records, not the gaps before them, and thus\n permits the free insertion of new records next to locked records. For\n UPDATE and DELETE statements, locking depends on whether the\n statement uses a unique index with a unique search condition (such as\n WHERE id = 100), or a range-type search condition (such as WHERE id >\n 100). For a unique index with a unique search condition, InnoDB locks\n only the index record found, not the gap before it. For range-type\n searches, InnoDB locks the index range scanned, using gap locks or\n next-key (gap plus index-record) locks to block insertions by other\n sessions into the gaps covered by the range. This is necessary\n because \"phantom rows\" must be blocked for MySQL replication and\n recovery to work.\n\n *Note*: In MySQL 5.5, if the READ COMMITTED isolation level is used\n or the innodb_locks_unsafe_for_binlog system variable is enabled,\n there is no InnoDB gap locking except for foreign-key constraint\n checking and duplicate-key checking. Also, record locks for\n nonmatching rows are released after MySQL has evaluated the WHERE\n condition. If you use READ COMMITTED or enable\n innodb_locks_unsafe_for_binlog, you must use row-based binary\n logging.\n\no READ UNCOMMITTED\n\n SELECT statements are performed in a nonlocking fashion, but a\n possible earlier version of a row might be used. Thus, using this\n isolation level, such reads are not consistent. This is also called a\n \"dirty read.\" Otherwise, this isolation level works like READ\n COMMITTED.\n\no SERIALIZABLE\n\n This level is like REPEATABLE READ, but InnoDB implicitly converts\n all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if\n autocommit is disabled. If autocommit is enabled, the SELECT is its\n own transaction. It therefore is known to be read only and can be\n serialized if performed as a consistent (nonlocking) read and need\n not block for other transactions. (To force a plain SELECT to block\n if other transactions have modified the selected rows, disable\n autocommit.)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html'),(448,'CEILING',4,'Syntax:\nCEILING(X)\n\nReturns the smallest integer value not less than X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT CEILING(1.23);\n -> 2\nmysql> SELECT CEILING(-1.23);\n -> -1\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(449,'SIN',4,'Syntax:\nSIN(X)\n\nReturns the sine of X, where X is given in radians.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT SIN(PI());\n -> 1.2246063538224e-16\nmysql> SELECT ROUND(SIN(PI()));\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(450,'DAYOFWEEK',31,'Syntax:\nDAYOFWEEK(date)\n\nReturns the weekday index for date (1 = Sunday, 2 = Monday, ..., 7 =\nSaturday). These index values correspond to the ODBC standard.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DAYOFWEEK(\'2007-02-03\');\n -> 7\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(451,'SHOW PROCESSLIST',26,'Syntax:\nSHOW [FULL] PROCESSLIST\n\nSHOW PROCESSLIST shows you which threads are running. You can also get\nthis information from the INFORMATION_SCHEMA PROCESSLIST table or the\nmysqladmin processlist command. If you have the PROCESS privilege, you\ncan see all threads. Otherwise, you can see only your own threads (that\nis, threads associated with the MySQL account that you are using). If\nyou do not use the FULL keyword, only the first 100 characters of each\nstatement are shown in the Info field.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-processlist.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-processlist.html'),(452,'LINEFROMWKB',32,'LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])\n\nConstructs a LINESTRING value using its WKB representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(453,'GEOMETRYTYPE',36,'GeometryType(g)\n\nReturns as a binary string the name of the geometry type of which the\ngeometry instance g is a member. The name corresponds to one of the\ninstantiable Geometry subclasses.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions\n\n','mysql> SELECT GeometryType(GeomFromText(\'POINT(1 1)\'));\n+------------------------------------------+\n| GeometryType(GeomFromText(\'POINT(1 1)\')) |\n+------------------------------------------+\n| POINT |\n+------------------------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#general-geometry-property-functions'),(454,'CREATE VIEW',39,'Syntax:\nCREATE\n [OR REPLACE]\n [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]\n [DEFINER = { user | CURRENT_USER }]\n [SQL SECURITY { DEFINER | INVOKER }]\n VIEW view_name [(column_list)]\n AS select_statement\n [WITH [CASCADED | LOCAL] CHECK OPTION]\n\nThe CREATE VIEW statement creates a new view, or replaces an existing\none if the OR REPLACE clause is given. If the view does not exist,\nCREATE OR REPLACE VIEW is the same as CREATE VIEW. If the view does\nexist, CREATE OR REPLACE VIEW is the same as ALTER VIEW.\n\nThe select_statement is a SELECT statement that provides the definition\nof the view. (When you select from the view, you select in effect using\nthe SELECT statement.) select_statement can select from base tables or\nother views.\n\nThe view definition is \"frozen\" at creation time, so changes to the\nunderlying tables afterward do not affect the view definition. For\nexample, if a view is defined as SELECT * on a table, new columns added\nto the table later do not become part of the view.\n\nThe ALGORITHM clause affects how MySQL processes the view. The DEFINER\nand SQL SECURITY clauses specify the security context to be used when\nchecking access privileges at view invocation time. The WITH CHECK\nOPTION clause can be given to constrain inserts or updates to rows in\ntables referenced by the view. These clauses are described later in\nthis section.\n\nThe CREATE VIEW statement requires the CREATE VIEW privilege for the\nview, and some privilege for each column selected by the SELECT\nstatement. For columns used elsewhere in the SELECT statement you must\nhave the SELECT privilege. If the OR REPLACE clause is present, you\nmust also have the DROP privilege for the view. CREATE VIEW might also\nrequire the SUPER privilege, depending on the DEFINER value, as\ndescribed later in this section.\n\nWhen a view is referenced, privilege checking occurs as described later\nin this section.\n\nA view belongs to a database. By default, a new view is created in the\ndefault database. To create the view explicitly in a given database,\nspecify the name as db_name.view_name when you create it:\n\nmysql> CREATE VIEW test.v AS SELECT * FROM t;\n\nWithin a database, base tables and views share the same namespace, so a\nbase table and a view cannot have the same name.\n\nColumns retrieved by the SELECT statement can be simple references to\ntable columns. They can also be expressions that use functions,\nconstant values, operators, and so forth.\n\nViews must have unique column names with no duplicates, just like base\ntables. By default, the names of the columns retrieved by the SELECT\nstatement are used for the view column names. To define explicit names\nfor the view columns, the optional column_list clause can be given as a\nlist of comma-separated identifiers. The number of names in column_list\nmust be the same as the number of columns retrieved by the SELECT\nstatement.\n\nUnqualified table or view names in the SELECT statement are interpreted\nwith respect to the default database. A view can refer to tables or\nviews in other databases by qualifying the table or view name with the\nproper database name.\n\nA view can be created from many kinds of SELECT statements. It can\nrefer to base tables or other views. It can use joins, UNION, and\nsubqueries. The SELECT need not even refer to any tables. The following\nexample defines a view that selects two columns from another table, as\nwell as an expression calculated from those columns:\n\nmysql> CREATE TABLE t (qty INT, price INT);\nmysql> INSERT INTO t VALUES(3, 50);\nmysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;\nmysql> SELECT * FROM v;\n+------+-------+-------+\n| qty | price | value |\n+------+-------+-------+\n| 3 | 50 | 150 |\n+------+-------+-------+\n\nA view definition is subject to the following restrictions:\n\no The SELECT statement cannot contain a subquery in the FROM clause.\n\no The SELECT statement cannot refer to system or user variables.\n\no Within a stored program, the definition cannot refer to program\n parameters or local variables.\n\no The SELECT statement cannot refer to prepared statement parameters.\n\no Any table or view referred to in the definition must exist. However,\n after a view has been created, it is possible to drop a table or view\n that the definition refers to. In this case, use of the view results\n in an error. To check a view definition for problems of this kind,\n use the CHECK TABLE statement.\n\no The definition cannot refer to a TEMPORARY table, and you cannot\n create a TEMPORARY view.\n\no Any tables named in the view definition must exist at definition\n time.\n\no You cannot associate a trigger with a view.\n\no Aliases for column names in the SELECT statement are checked against\n the maximum column length of 64 characters (not the maximum alias\n length of 256 characters).\n\nORDER BY is permitted in a view definition, but it is ignored if you\nselect from a view using a statement that has its own ORDER BY.\n\nFor other options or clauses in the definition, they are added to the\noptions or clauses of the statement that references the view, but the\neffect is undefined. For example, if a view definition includes a LIMIT\nclause, and you select from the view using a statement that has its own\nLIMIT clause, it is undefined which limit applies. This same principle\napplies to options such as ALL, DISTINCT, or SQL_SMALL_RESULT that\nfollow the SELECT keyword, and to clauses such as INTO, FOR UPDATE,\nLOCK IN SHARE MODE, and PROCEDURE.\n\nIf you create a view and then change the query processing environment\nby changing system variables, that may affect the results that you get\nfrom the view:\n\nmysql> CREATE VIEW v (mycol) AS SELECT \'abc\';\nQuery OK, 0 rows affected (0.01 sec)\n\nmysql> SET sql_mode = \'\';\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| mycol |\n+-------+\n1 row in set (0.01 sec)\n\nmysql> SET sql_mode = \'ANSI_QUOTES\';\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SELECT \"mycol\" FROM v;\n+-------+\n| mycol |\n+-------+\n| abc |\n+-------+\n1 row in set (0.00 sec)\n\nThe DEFINER and SQL SECURITY clauses determine which MySQL account to\nuse when checking access privileges for the view when a statement is\nexecuted that references the view. The valid SQL SECURITY\ncharacteristic values are DEFINER and INVOKER. These indicate that the\nrequired privileges must be held by the user who defined or invoked the\nview, respectively. The default SQL SECURITY value is DEFINER.\n\nIf a user value is given for the DEFINER clause, it should be a MySQL\naccount specified as \'user_name\'@\'host_name\' (the same format used in\nthe GRANT statement), CURRENT_USER, or CURRENT_USER(). The default\nDEFINER value is the user who executes the CREATE VIEW statement. This\nis the same as specifying DEFINER = CURRENT_USER explicitly.\n\nIf you specify the DEFINER clause, these rules determine the valid\nDEFINER user values:\n\no If you do not have the SUPER privilege, the only valid user value is\n your own account, either specified literally or by using\n CURRENT_USER. You cannot set the definer to some other account.\n\no If you have the SUPER privilege, you can specify any syntactically\n valid account name. If the account does not actually exist, a warning\n is generated.\n\no Although it is possible to create a view with a nonexistent DEFINER\n account, an error occurs when the view is referenced if the SQL\n SECURITY value is DEFINER but the definer account does not exist.\n\nFor more information about view security, see\nhttp://dev.mysql.com/doc/refman/5.5/en/stored-programs-security.html.\n\nWithin a view definition, CURRENT_USER returns the view\'s DEFINER value\nby default. For views defined with the SQL SECURITY INVOKER\ncharacteristic, CURRENT_USER returns the account for the view\'s\ninvoker. For information about user auditing within views, see\nhttp://dev.mysql.com/doc/refman/5.5/en/account-activity-auditing.html.\n\nWithin a stored routine that is defined with the SQL SECURITY DEFINER\ncharacteristic, CURRENT_USER returns the routine\'s DEFINER value. This\nalso affects a view defined within such a routine, if the view\ndefinition contains a DEFINER value of CURRENT_USER.\n\nView privileges are checked like this:\n\no At view definition time, the view creator must have the privileges\n needed to use the top-level objects accessed by the view. For\n example, if the view definition refers to table columns, the creator\n must have some privilege for each column in the select list of the\n definition, and the SELECT privilege for each column used elsewhere\n in the definition. If the definition refers to a stored function,\n only the privileges needed to invoke the function can be checked. The\n privileges required at function invocation time can be checked only\n as it executes: For different invocations, different execution paths\n within the function might be taken.\n\no The user who references a view must have appropriate privileges to\n access it (SELECT to select from it, INSERT to insert into it, and so\n forth.)\n\no When a view has been referenced, privileges for objects accessed by\n the view are checked against the privileges held by the view DEFINER\n account or invoker, depending on whether the SQL SECURITY\n characteristic is DEFINER or INVOKER, respectively.\n\no If reference to a view causes execution of a stored function,\n privilege checking for statements executed within the function depend\n on whether the function SQL SECURITY characteristic is DEFINER or\n INVOKER. If the security characteristic is DEFINER, the function runs\n with the privileges of the DEFINER account. If the characteristic is\n INVOKER, the function runs with the privileges determined by the\n view\'s SQL SECURITY characteristic.\n\nExample: A view might depend on a stored function, and that function\nmight invoke other stored routines. For example, the following view\ninvokes a stored function f():\n\nCREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);\n\nSuppose that f() contains a statement such as this:\n\nIF name IS NULL then\n CALL p1();\nELSE\n CALL p2();\nEND IF;\n\nThe privileges required for executing statements within f() need to be\nchecked when f() executes. This might mean that privileges are needed\nfor p1() or p2(), depending on the execution path within f(). Those\nprivileges must be checked at runtime, and the user who must possess\nthe privileges is determined by the SQL SECURITY values of the view v\nand the function f().\n\nThe DEFINER and SQL SECURITY clauses for views are extensions to\nstandard SQL. In standard SQL, views are handled using the rules for\nSQL SECURITY DEFINER. The standard says that the definer of the view,\nwhich is the same as the owner of the view\'s schema, gets applicable\nprivileges on the view (for example, SELECT) and may grant them. MySQL\nhas no concept of a schema \"owner\", so MySQL adds a clause to identify\nthe definer. The DEFINER clause is an extension where the intent is to\nhave what the standard has; that is, a permanent record of who defined\nthe view. This is why the default DEFINER value is the account of the\nview creator.\n\nThe optional ALGORITHM clause is a MySQL extension to standard SQL. It\naffects how MySQL processes the view. ALGORITHM takes three values:\nMERGE, TEMPTABLE, or UNDEFINED. The default algorithm is UNDEFINED if\nno ALGORITHM clause is present. For more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/view-algorithms.html.\n\nSome views are updatable. That is, you can use them in statements such\nas UPDATE, DELETE, or INSERT to update the contents of the underlying\ntable. For a view to be updatable, there must be a one-to-one\nrelationship between the rows in the view and the rows in the\nunderlying table. There are also certain other constructs that make a\nview nonupdatable.\n\nThe WITH CHECK OPTION clause can be given for an updatable view to\nprevent inserts or updates to rows except those for which the WHERE\nclause in the select_statement is true.\n\nIn a WITH CHECK OPTION clause for an updatable view, the LOCAL and\nCASCADED keywords determine the scope of check testing when the view is\ndefined in terms of another view. The LOCAL keyword restricts the CHECK\nOPTION only to the view being defined. CASCADED causes the checks for\nunderlying views to be evaluated as well. When neither keyword is\ngiven, the default is CASCADED.\n\nFor more information about updatable views and the WITH CHECK OPTION\nclause, see\nhttp://dev.mysql.com/doc/refman/5.5/en/view-updatability.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-view.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-view.html'),(455,'TRIM',37,'Syntax:\nTRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr\nFROM] str)\n\nReturns the string str with all remstr prefixes or suffixes removed. If\nnone of the specifiers BOTH, LEADING, or TRAILING is given, BOTH is\nassumed. remstr is optional and, if not specified, spaces are removed.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT TRIM(\' bar \');\n -> \'bar\'\nmysql> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');\n -> \'barxxx\'\nmysql> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');\n -> \'bar\'\nmysql> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');\n -> \'barx\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(456,'IS',18,'Syntax:\nIS boolean_value\n\nTests a value against a boolean value, where boolean_value can be TRUE,\nFALSE, or UNKNOWN.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;\n -> 1, 1, 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(457,'GET_FORMAT',31,'Syntax:\nGET_FORMAT({DATE|TIME|DATETIME}, {\'EUR\'|\'USA\'|\'JIS\'|\'ISO\'|\'INTERNAL\'})\n\nReturns a format string. This function is useful in combination with\nthe DATE_FORMAT() and the STR_TO_DATE() functions.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DATE_FORMAT(\'2003-10-03\',GET_FORMAT(DATE,\'EUR\'));\n -> \'03.10.2003\'\nmysql> SELECT STR_TO_DATE(\'10.31.2003\',GET_FORMAT(DATE,\'USA\'));\n -> \'2003-10-31\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(458,'TINYBLOB',22,'TINYBLOB\n\nA BLOB column with a maximum length of 255 (28 - 1) bytes. Each\nTINYBLOB value is stored using a 1-byte length prefix that indicates\nthe number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(459,'SIGNAL',23,'Syntax:\nSIGNAL condition_value\n [SET signal_information_item\n [, signal_information_item] ...]\n\ncondition_value:\n SQLSTATE [VALUE] sqlstate_value\n | condition_name\n\nsignal_information_item:\n condition_information_item_name = simple_value_specification\n\ncondition_information_item_name:\n CLASS_ORIGIN\n | SUBCLASS_ORIGIN\n | MESSAGE_TEXT\n | MYSQL_ERRNO\n | CONSTRAINT_CATALOG\n | CONSTRAINT_SCHEMA\n | CONSTRAINT_NAME\n | CATALOG_NAME\n | SCHEMA_NAME\n | TABLE_NAME\n | COLUMN_NAME\n | CURSOR_NAME\n\ncondition_name, simple_value_specification:\n (see following discussion)\n\nSIGNAL is the way to \"return\" an error. SIGNAL provides error\ninformation to a handler, to an outer portion of the application, or to\nthe client. Also, it provides control over the error\'s characteristics\n(error number, SQLSTATE value, message). Without SIGNAL, it is\nnecessary to resort to workarounds such as deliberately referring to a\nnonexistent table to cause a routine to return an error.\n\nNo special privileges are required to execute the SIGNAL statement.\n\nThe condition_value in a SIGNAL statement indicates the error value to\nbe returned. It can be an SQLSTATE value (a 5-character string literal)\nor a condition_name that refers to a named condition previously defined\nwith DECLARE ... CONDITION (see [HELP DECLARE CONDITION]).\n\nAn SQLSTATE value can indicate errors, warnings, or \"not found.\" The\nfirst two characters of the value indicate its error class, as\ndiscussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/signal.html#signal-condition-inf\normation-items. Some signal values cause statement termination; see\nhttp://dev.mysql.com/doc/refman/5.5/en/signal.html#signal-effects.\n\nThe SQLSTATE value for a SIGNAL statement should not start with \'00\'\nbecause such values indicate success and are not valid for signaling an\nerror. This is true whether the SQLSTATE value is specified directly in\nthe SIGNAL statement or in a named condition referred to in the\nstatement. If the value is invalid, a Bad SQLSTATE error occurs.\n\nTo signal a generic SQLSTATE value, use \'45000\', which means \"unhandled\nuser-defined exception.\"\n\nThe SIGNAL statement optionally includes a SET clause that contains\nmultiple signal items, in a comma-separated list of\ncondition_information_item_name = simple_value_specification\nassignments.\n\nEach condition_information_item_name may be specified only once in the\nSET clause. Otherwise, a Duplicate condition information item error\noccurs.\n\nValid simple_value_specification designators can be specified using\nstored procedure or function parameters, stored program local variables\ndeclared with DECLARE, user-defined variables, system variables, or\nliterals. A character literal may include a _charset introducer.\n\nFor information about permissible condition_information_item_name\nvalues, see\nhttp://dev.mysql.com/doc/refman/5.5/en/signal.html#signal-condition-inf\normation-items.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/signal.html\n\n','CREATE PROCEDURE p (pval INT)\nBEGIN\n DECLARE specialty CONDITION FOR SQLSTATE \'45000\';\n IF pval = 0 THEN\n SIGNAL SQLSTATE \'01000\';\n ELSEIF pval = 1 THEN\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSEIF pval = 2 THEN\n SIGNAL specialty\n SET MESSAGE_TEXT = \'An error occurred\';\n ELSE\n SIGNAL SQLSTATE \'01000\'\n SET MESSAGE_TEXT = \'A warning occurred\', MYSQL_ERRNO = 1000;\n SIGNAL SQLSTATE \'45000\'\n SET MESSAGE_TEXT = \'An error occurred\', MYSQL_ERRNO = 1001;\n END IF;\nEND;\n','http://dev.mysql.com/doc/refman/5.5/en/signal.html'),(460,'SAVEPOINT',8,'Syntax:\nSAVEPOINT identifier\nROLLBACK [WORK] TO [SAVEPOINT] identifier\nRELEASE SAVEPOINT identifier\n\nInnoDB supports the SQL statements SAVEPOINT, ROLLBACK TO SAVEPOINT,\nRELEASE SAVEPOINT and the optional WORK keyword for ROLLBACK.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/savepoint.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/savepoint.html'),(461,'USER',17,'Syntax:\nUSER()\n\nReturns the current MySQL user name and host name as a string in the\nutf8 character set.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT USER();\n -> \'davida@localhost\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(462,'LABELS',23,'Syntax:\n[begin_label:] BEGIN\n [statement_list]\nEND [end_label]\n\n[begin_label:] LOOP\n statement_list\nEND LOOP [end_label]\n\n[begin_label:] REPEAT\n statement_list\nUNTIL search_condition\nEND REPEAT [end_label]\n\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nLabels are permitted for BEGIN ... END blocks and for the LOOP, REPEAT,\nand WHILE statements. Label use for those statements follows these\nrules:\n\no begin_label must be followed by a colon.\n\no begin_label can be given without end_label. If end_label is present,\n it must be the same as begin_label.\n\no end_label cannot be given without begin_label.\n\no Labels at the same nesting level must be distinct.\n\no Labels can be up to 16 characters long.\n\nTo refer to a label within the labeled construct, use an ITERATE or\nLEAVE statement. The following example uses those statements to\ncontinue iterating or terminate the loop:\n\nCREATE PROCEDURE doiterate(p1 INT)\nBEGIN\n label1: LOOP\n SET p1 = p1 + 1;\n IF p1 < 10 THEN ITERATE label1; END IF;\n LEAVE label1;\n END LOOP label1;\nEND;\n\nThe scope of a block label does not include the code for handlers\ndeclared within the block. For details, see [HELP DECLARE HANDLER].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/statement-labels.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/statement-labels.html'),(463,'ALTER TABLE',39,'Syntax:\nALTER [ONLINE | OFFLINE] [IGNORE] TABLE tbl_name\n [alter_specification [, alter_specification] ...]\n [partition_options]\n\nalter_specification:\n table_options\n | ADD [COLUMN] col_name column_definition\n [FIRST | AFTER col_name ]\n | ADD [COLUMN] (col_name column_definition,...)\n | ADD {INDEX|KEY} [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]] PRIMARY KEY\n [index_type] (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n UNIQUE [INDEX|KEY] [index_name]\n [index_type] (index_col_name,...) [index_option] ...\n | ADD FULLTEXT [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD SPATIAL [INDEX|KEY] [index_name]\n (index_col_name,...) [index_option] ...\n | ADD [CONSTRAINT [symbol]]\n FOREIGN KEY [index_name] (index_col_name,...)\n reference_definition\n | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n | CHANGE [COLUMN] old_col_name new_col_name column_definition\n [FIRST|AFTER col_name]\n | MODIFY [COLUMN] col_name column_definition\n [FIRST | AFTER col_name]\n | DROP [COLUMN] col_name\n | DROP PRIMARY KEY\n | DROP {INDEX|KEY} index_name\n | DROP FOREIGN KEY fk_symbol\n | MAX_ROWS = rows\n | DISABLE KEYS\n | ENABLE KEYS\n | RENAME [TO|AS] new_tbl_name\n | ORDER BY col_name [, col_name] ...\n | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n | DISCARD TABLESPACE\n | IMPORT TABLESPACE\n | FORCE\n | ADD PARTITION (partition_definition)\n | DROP PARTITION partition_names\n | TRUNCATE PARTITION {partition_names | ALL}\n | COALESCE PARTITION number\n | REORGANIZE PARTITION [partition_names INTO (partition_definitions)]\n | ANALYZE PARTITION {partition_names | ALL}\n | CHECK PARTITION {partition_names | ALL}\n | OPTIMIZE PARTITION {partition_names | ALL}\n | REBUILD PARTITION {partition_names | ALL}\n | REPAIR PARTITION {partition_names | ALL}\n | PARTITION BY partitioning_expression\n | REMOVE PARTITIONING\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\ntable_options:\n table_option [[,] table_option] ... (see CREATE TABLE options)\n\npartition_options:\n (see CREATE TABLE options)\n\nALTER TABLE changes the structure of a table. For example, you can add\nor delete columns, create or destroy indexes, change the type of\nexisting columns, or rename columns or the table itself. You can also\nchange characteristics such as the storage engine used for the table or\nthe table comment.\n\nPartitioning-related clauses for ALTER TABLE can be used with\npartitioned tables for repartitioning, for adding, dropping, merging,\nand splitting partitions, and for performing partitioning maintenance.\nFor more information, see\nhttp://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations\n.html.\n\nFollowing the table name, specify the alterations to be made. If none\nare given, ALTER TABLE does nothing.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-table.html'),(464,'MPOINTFROMWKB',32,'MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])\n\nConstructs a MULTIPOINT value using its WKB representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(465,'CHAR BYTE',22,'The CHAR BYTE data type is an alias for the BINARY data type. This is a\ncompatibility feature.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(466,'REPAIR TABLE',20,'Syntax:\nREPAIR [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n [QUICK] [EXTENDED] [USE_FRM]\n\nREPAIR TABLE repairs a possibly corrupted table. By default, it has the\nsame effect as myisamchk --recover tbl_name. REPAIR TABLE works for\nMyISAM, ARCHIVE, and CSV tables. See\nhttp://dev.mysql.com/doc/refman/5.5/en/myisam-storage-engine.html, and\nhttp://dev.mysql.com/doc/refman/5.5/en/archive-storage-engine.html, and\nhttp://dev.mysql.com/doc/refman/5.5/en/csv-storage-engine.html\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nREPAIR TABLE is supported for partitioned tables. However, the USE_FRM\noption cannot be used with this statement on a partitioned table.\n\nYou can use ALTER TABLE ... REPAIR PARTITION to repair one or more\npartitions; for more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/repair-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/repair-table.html'),(467,'MERGE',39,'The MERGE storage engine, also known as the MRG_MyISAM engine, is a\ncollection of identical MyISAM tables that can be used as one.\n\"Identical\" means that all tables have identical column and index\ninformation. You cannot merge MyISAM tables in which the columns are\nlisted in a different order, do not have exactly the same columns, or\nhave the indexes in different order. However, any or all of the MyISAM\ntables can be compressed with myisampack. See\nhttp://dev.mysql.com/doc/refman/5.5/en/myisampack.html. Differences in\ntable options such as AVG_ROW_LENGTH, MAX_ROWS, or PACK_KEYS do not\nmatter.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/merge-storage-engine.html\n\n','mysql> CREATE TABLE t1 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nmysql> CREATE TABLE t2 (\n -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\n -> message CHAR(20)) ENGINE=MyISAM;\nmysql> INSERT INTO t1 (message) VALUES (\'Testing\'),(\'table\'),(\'t1\');\nmysql> INSERT INTO t2 (message) VALUES (\'Testing\'),(\'table\'),(\'t2\');\nmysql> CREATE TABLE total (\n -> a INT NOT NULL AUTO_INCREMENT,\n -> message CHAR(20), INDEX(a))\n -> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\n','http://dev.mysql.com/doc/refman/5.5/en/merge-storage-engine.html'),(468,'CREATE TABLE',39,'Syntax:\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n (create_definition,...)\n [table_options]\n [partition_options]\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n [(create_definition,...)]\n [table_options]\n [partition_options]\n select_statement\n\nOr:\n\nCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name\n { LIKE old_tbl_name | (LIKE old_tbl_name) }\n\ncreate_definition:\n col_name column_definition\n | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)\n [index_option] ...\n | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]\n [index_name] [index_type] (index_col_name,...)\n [index_option] ...\n | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)\n [index_option] ...\n | [CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name,...) reference_definition\n | CHECK (expr)\n\ncolumn_definition:\n data_type [NOT NULL | NULL] [DEFAULT default_value]\n [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]\n [COMMENT \'string\']\n [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n [STORAGE {DISK|MEMORY|DEFAULT}]\n [reference_definition]\n\ndata_type:\n BIT[(length)]\n | TINYINT[(length)] [UNSIGNED] [ZEROFILL]\n | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]\n | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]\n | INT[(length)] [UNSIGNED] [ZEROFILL]\n | INTEGER[(length)] [UNSIGNED] [ZEROFILL]\n | BIGINT[(length)] [UNSIGNED] [ZEROFILL]\n | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]\n | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL]\n | DATE\n | TIME\n | TIMESTAMP\n | DATETIME\n | YEAR\n | CHAR[(length)]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | VARCHAR(length)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | BINARY[(length)]\n | VARBINARY(length)\n | TINYBLOB\n | BLOB\n | MEDIUMBLOB\n | LONGBLOB\n | TINYTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | TEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | MEDIUMTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | LONGTEXT [BINARY]\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | ENUM(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | SET(value1,value2,value3,...)\n [CHARACTER SET charset_name] [COLLATE collation_name]\n | spatial_type\n\nindex_col_name:\n col_name [(length)] [ASC | DESC]\n\nindex_type:\n USING {BTREE | HASH}\n\nindex_option:\n KEY_BLOCK_SIZE [=] value\n | index_type\n | WITH PARSER parser_name\n | COMMENT \'string\'\n\nreference_definition:\n REFERENCES tbl_name (index_col_name,...)\n [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\ntable_options:\n table_option [[,] table_option] ...\n\ntable_option:\n ENGINE [=] engine_name\n | AUTO_INCREMENT [=] value\n | AVG_ROW_LENGTH [=] value\n | [DEFAULT] CHARACTER SET [=] charset_name\n | CHECKSUM [=] {0 | 1}\n | [DEFAULT] COLLATE [=] collation_name\n | COMMENT [=] \'string\'\n | CONNECTION [=] \'connect_string\'\n | DATA DIRECTORY [=] \'absolute path to directory\'\n | DELAY_KEY_WRITE [=] {0 | 1}\n | INDEX DIRECTORY [=] \'absolute path to directory\'\n | INSERT_METHOD [=] { NO | FIRST | LAST }\n | KEY_BLOCK_SIZE [=] value\n | MAX_ROWS [=] value\n | MIN_ROWS [=] value\n | PACK_KEYS [=] {0 | 1 | DEFAULT}\n | PASSWORD [=] \'string\'\n | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY|DEFAULT}]\n | UNION [=] (tbl_name[,tbl_name]...)\n\npartition_options:\n PARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list)\n | RANGE{(expr) | COLUMNS(column_list)}\n | LIST{(expr) | COLUMNS(column_list)} }\n [PARTITIONS num]\n [SUBPARTITION BY\n { [LINEAR] HASH(expr)\n | [LINEAR] KEY(column_list) }\n [SUBPARTITIONS num]\n ]\n [(partition_definition [, partition_definition] ...)]\n\npartition_definition:\n PARTITION partition_name\n [VALUES \n {LESS THAN {(expr | value_list) | MAXVALUE} \n | \n IN (value_list)}]\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n [(subpartition_definition [, subpartition_definition] ...)]\n\nsubpartition_definition:\n SUBPARTITION logical_name\n [[STORAGE] ENGINE [=] engine_name]\n [COMMENT [=] \'comment_text\' ]\n [DATA DIRECTORY [=] \'data_dir\']\n [INDEX DIRECTORY [=] \'index_dir\']\n [MAX_ROWS [=] max_number_of_rows]\n [MIN_ROWS [=] min_number_of_rows]\n [TABLESPACE [=] tablespace_name]\n [NODEGROUP [=] node_group_id]\n\nselect_statement:\n [IGNORE | REPLACE] [AS] SELECT ... (Some valid select statement)\n\nCREATE TABLE creates a table with the given name. You must have the\nCREATE privilege for the table.\n\nRules for permissible table names are given in\nhttp://dev.mysql.com/doc/refman/5.5/en/identifiers.html. By default,\nthe table is created in the default database, using the InnoDB storage\nengine. An error occurs if the table exists, if there is no default\ndatabase, or if the database does not exist.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/create-table.html'),(469,'>',18,'Syntax:\n>\n\nGreater than:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT 2 > 2;\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(470,'ANALYZE TABLE',20,'Syntax:\nANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE\n tbl_name [, tbl_name] ...\n\nANALYZE TABLE analyzes and stores the key distribution for a table.\nDuring the analysis, the table is locked with a read lock for InnoDB\nand MyISAM. This statement works with InnoDB, NDB, and MyISAM tables.\nFor MyISAM tables, this statement is equivalent to using myisamchk\n--analyze.\n\nFor more information on how the analysis works within InnoDB, see\nhttp://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html.\n\nMySQL uses the stored key distribution to decide the order in which\ntables should be joined when you perform a join on something other than\na constant. In addition, key distributions can be used when deciding\nwhich indexes to use for a specific table within a query.\n\nThis statement requires SELECT and INSERT privileges for the table.\n\nANALYZE TABLE is supported for partitioned tables, and you can use\nALTER TABLE ... ANALYZE PARTITION to analyze one or more partitions;\nfor more information, see [HELP ALTER TABLE], and\nhttp://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/analyze-table.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/analyze-table.html'),(471,'MICROSECOND',31,'Syntax:\nMICROSECOND(expr)\n\nReturns the microseconds from the time or datetime expression expr as a\nnumber in the range from 0 to 999999.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MICROSECOND(\'12:00:00.123456\');\n -> 123456\nmysql> SELECT MICROSECOND(\'2009-12-31 23:59:59.000010\');\n -> 10\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(472,'CONSTRAINT',39,'InnoDB supports foreign keys, which let you cross-reference related\ndata across tables, and foreign key constraints, which help keep this\nspread-out data consistent. The syntax for an InnoDB foreign key\nconstraint definition in the CREATE TABLE or ALTER TABLE statement\nlooks like this:\n\n[CONSTRAINT [symbol]] FOREIGN KEY\n [index_name] (index_col_name, ...)\n REFERENCES tbl_name (index_col_name,...)\n [ON DELETE reference_option]\n [ON UPDATE reference_option]\n\nreference_option:\n RESTRICT | CASCADE | SET NULL | NO ACTION\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html\n\n','CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,\n price DECIMAL,\n PRIMARY KEY(category, id)) ENGINE=INNODB;\nCREATE TABLE customer (id INT NOT NULL,\n PRIMARY KEY (id)) ENGINE=INNODB;\nCREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,\n product_category INT NOT NULL,\n product_id INT NOT NULL,\n customer_id INT NOT NULL,\n PRIMARY KEY(no),\n INDEX (product_category, product_id),\n FOREIGN KEY (product_category, product_id)\n REFERENCES product(category, id)\n ON UPDATE CASCADE ON DELETE RESTRICT,\n INDEX (customer_id),\n FOREIGN KEY (customer_id)\n REFERENCES customer(id)) ENGINE=INNODB;\n','http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html'),(473,'CREATE SERVER',39,'Syntax:\nCREATE SERVER server_name\n FOREIGN DATA WRAPPER wrapper_name\n OPTIONS (option [, option] ...)\n\noption:\n { HOST character-literal\n | DATABASE character-literal\n | USER character-literal\n | PASSWORD character-literal\n | SOCKET character-literal\n | OWNER character-literal\n | PORT numeric-literal }\n\nThis statement creates the definition of a server for use with the\nFEDERATED storage engine. The CREATE SERVER statement creates a new row\nwithin the servers table within the mysql database. This statement\nrequires the SUPER privilege.\n\nThe server_name should be a unique reference to the server. Server\ndefinitions are global within the scope of the server, it is not\npossible to qualify the server definition to a specific database.\nserver_name has a maximum length of 64 characters (names longer than 64\ncharacters are silently truncated), and is case insensitive. You may\nspecify the name as a quoted string.\n\nThe wrapper_name should be mysql, and may be quoted with single\nquotation marks. Other values for wrapper_name are not currently\nsupported.\n\nFor each option you must specify either a character literal or numeric\nliteral. Character literals are UTF-8, support a maximum length of 64\ncharacters and default to a blank (empty) string. String literals are\nsilently truncated to 64 characters. Numeric literals must be a number\nbetween 0 and 9999, default value is 0.\n\n*Note*: Note that the OWNER option is currently not applied, and has no\neffect on the ownership or operation of the server connection that is\ncreated.\n\nThe CREATE SERVER statement creates an entry in the mysql.servers table\nthat can later be used with the CREATE TABLE statement when creating a\nFEDERATED table. The options that you specify will be used to populate\nthe columns in the mysql.servers table. The table columns are\nServer_name, Host, Db, Username, Password, Port and Socket.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/create-server.html\n\n','CREATE SERVER s\nFOREIGN DATA WRAPPER mysql\nOPTIONS (USER \'Remote\', HOST \'192.168.1.106\', DATABASE \'test\');\n','http://dev.mysql.com/doc/refman/5.5/en/create-server.html'),(474,'FIELD',37,'Syntax:\nFIELD(str,str1,str2,str3,...)\n\nReturns the index (position) of str in the str1, str2, str3, ... list.\nReturns 0 if str is not found.\n\nIf all arguments to FIELD() are strings, all arguments are compared as\nstrings. If all arguments are numbers, they are compared as numbers.\nOtherwise, the arguments are compared as double.\n\nIf str is NULL, the return value is 0 because NULL fails equality\ncomparison with any value. FIELD() is the complement of ELT().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT FIELD(\'ej\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 2\nmysql> SELECT FIELD(\'fo\', \'Hej\', \'ej\', \'Heja\', \'hej\', \'foo\');\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(475,'MAKETIME',31,'Syntax:\nMAKETIME(hour,minute,second)\n\nReturns a time value calculated from the hour, minute, and second\narguments.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT MAKETIME(12,15,30);\n -> \'12:15:30\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(476,'CURDATE',31,'Syntax:\nCURDATE()\n\nReturns the current date as a value in \'YYYY-MM-DD\' or YYYYMMDD format,\ndepending on whether the function is used in a string or numeric\ncontext.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT CURDATE();\n -> \'2008-06-13\'\nmysql> SELECT CURDATE() + 0;\n -> 20080613\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(477,'SET PASSWORD',10,'Syntax:\nSET PASSWORD [FOR user] =\n {\n PASSWORD(\'cleartext password\')\n | OLD_PASSWORD(\'cleartext password\')\n | \'encrypted password\'\n }\n\nThe SET PASSWORD statement assigns a password to an existing MySQL user\naccount. When the read_only system variable is enabled, the SUPER\nprivilege is required to use SET PASSWORD, in addition to whatever\nother privileges might be required.\n\nIf the password is specified using the PASSWORD() or OLD_PASSWORD()\nfunction, the cleartext (unencrypted) password should be given as the\nargument to the function, which hashes the password and returns the\nencrypted password string. If the password is specified without using\neither function, it should be the already encrypted password value as a\nliteral string. In all cases, the encrypted password string must be in\nthe format required by the authentication method used for the account.\n\nThe old_passwords system variable value determines the hashing method\nused by PASSWORD(). If you specify the password using that function and\nSET PASSWORD rejects the password as not being in the correct format,\nit may be necessary to set old_passwords to change the hashing method.\nFor descriptions of the permitted values, see\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nWith no FOR user clause, this statement sets the password for the\ncurrent user. (To see which account the server authenticated you as,\ninvoke the CURRENT_USER() function.) Any client who successfully\nconnects to the server using a nonanonymous account can change the\npassword for that account.\n\nWith a FOR user clause, this statement sets the password for the named\nuser. You must have the UPDATE privilege for the mysql database to do\nthis. The user account name uses the format described in\nhttp://dev.mysql.com/doc/refman/5.5/en/account-names.html. The user\nvalue should be given as \'user_name\'@\'host_name\', where \'user_name\' and\n\'host_name\' are exactly as listed in the User and Host columns of the\nmysql.user table row. (If you specify only a user name, a host name of\n\'%\' is used.) For example, to set the password for an account with User\nand Host column values of \'bob\' and \'%.example.org\', write the\nstatement like this:\n\nSET PASSWORD FOR \'bob\'@\'%.example.org\' = PASSWORD(\'cleartext password\');\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/set-password.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/set-password.html'),(478,'ALTER TABLESPACE',39,'Syntax:\nALTER TABLESPACE tablespace_name\n {ADD|DROP} DATAFILE \'file_name\'\n [INITIAL_SIZE [=] size]\n [WAIT]\n ENGINE [=] engine_name\n\nThis statement can be used either to add a new data file, or to drop a\ndata file from a tablespace.\n\nThe ADD DATAFILE variant enables you to specify an initial size using\nan INITIAL_SIZE clause, where size is measured in bytes; the default\nvalue is 128M (128 megabytes). You may optionally follow this integer\nvalue with a one-letter abbreviation for an order of magnitude, similar\nto those used in my.cnf. Generally, this is one of the letters M (for\nmegabytes) or G (for gigabytes).\n\n*Note*: All MySQL Cluster Disk Data objects share the same namespace.\nThis means that each Disk Data object must be uniquely named (and not\nmerely each Disk Data object of a given type). For example, you cannot\nhave a tablespace and an data file with the same name, or an undo log\nfile and a tablespace with the same name.\n\nOn 32-bit systems, the maximum supported value for INITIAL_SIZE is 4G.\n(Bug #29186)\n\nINITIAL_SIZE is rounded, explicitly, as for CREATE TABLESPACE.\n\nOnce a data file has been created, its size cannot be changed; however,\nyou can add more data files to the tablespace using additional ALTER\nTABLESPACE ... ADD DATAFILE statements.\n\nUsing DROP DATAFILE with ALTER TABLESPACE drops the data file\n\'file_name\' from the tablespace. You cannot drop a data file from a\ntablespace which is in use by any table; in other words, the data file\nmust be empty (no extents used). See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-cluster-disk-data-objects.\nhtml. In addition, any data file to be dropped must previously have\nbeen added to the tablespace with CREATE TABLESPACE or ALTER\nTABLESPACE.\n\nBoth ALTER TABLESPACE ... ADD DATAFILE and ALTER TABLESPACE ... DROP\nDATAFILE require an ENGINE clause which specifies the storage engine\nused by the tablespace. Currently, the only accepted values for\nengine_name are NDB and NDBCLUSTER.\n\nWAIT is parsed but otherwise ignored, and so has no effect in MySQL\n5.5. It is intended for future expansion.\n\nWhen ALTER TABLESPACE ... ADD DATAFILE is used with ENGINE = NDB, a\ndata file is created on each Cluster data node. You can verify that the\ndata files were created and obtain information about them by querying\nthe INFORMATION_SCHEMA.FILES table. For example, the following query\nshows all data files belonging to the tablespace named newts:\n\nmysql> SELECT LOGFILE_GROUP_NAME, FILE_NAME, EXTRA\n -> FROM INFORMATION_SCHEMA.FILES\n -> WHERE TABLESPACE_NAME = \'newts\' AND FILE_TYPE = \'DATAFILE\';\n+--------------------+--------------+----------------+\n| LOGFILE_GROUP_NAME | FILE_NAME | EXTRA |\n+--------------------+--------------+----------------+\n| lg_3 | newdata.dat | CLUSTER_NODE=3 |\n| lg_3 | newdata.dat | CLUSTER_NODE=4 |\n| lg_3 | newdata2.dat | CLUSTER_NODE=3 |\n| lg_3 | newdata2.dat | CLUSTER_NODE=4 |\n+--------------------+--------------+----------------+\n2 rows in set (0.03 sec)\n\nSee http://dev.mysql.com/doc/refman/5.5/en/files-table.html.\n\nALTER TABLESPACE is useful only with Disk Data storage for MySQL\nCluster. See\nhttp://dev.mysql.com/doc/refman/5.5/en/mysql-cluster-disk-data.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/alter-tablespace.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/alter-tablespace.html'),(479,'IF FUNCTION',7,'Syntax:\nIF(expr1,expr2,expr3)\n\nIf expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns\nexpr2; otherwise it returns expr3. IF() returns a numeric or string\nvalue, depending on the context in which it is used.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html\n\n','mysql> SELECT IF(1>2,2,3);\n -> 3\nmysql> SELECT IF(1<2,\'yes\',\'no\');\n -> \'yes\'\nmysql> SELECT IF(STRCMP(\'test\',\'test1\'),\'no\',\'yes\');\n -> \'no\'\n','http://dev.mysql.com/doc/refman/5.5/en/control-flow-functions.html'),(480,'ENUM',22,'ENUM(\'value1\',\'value2\',...) [CHARACTER SET charset_name] [COLLATE\ncollation_name]\n\nAn enumeration. A string object that can have only one value, chosen\nfrom the list of values \'value1\', \'value2\', ..., NULL or the special \'\'\nerror value. An ENUM column can have a maximum of 65,535 distinct\nvalues. ENUM values are represented internally as integers.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(481,'DATABASE',17,'Syntax:\nDATABASE()\n\nReturns the default (current) database name as a string in the utf8\ncharacter set. If there is no default database, DATABASE() returns\nNULL. Within a stored routine, the default database is the database\nthat the routine is associated with, which is not necessarily the same\nas the database that is the default in the calling context.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT DATABASE();\n -> \'test\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(482,'POINTFROMWKB',32,'PointFromWKB(wkb[,srid])\n\nConstructs a POINT value using its WKB representation and SRID.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions\n\n','','http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#gis-wkb-functions'),(483,'POWER',4,'Syntax:\nPOWER(X,Y)\n\nThis is a synonym for POW().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(484,'ATAN',4,'Syntax:\nATAN(X)\n\nReturns the arc tangent of X, that is, the value whose tangent is X.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT ATAN(2);\n -> 1.1071487177941\nmysql> SELECT ATAN(-2);\n -> -1.1071487177941\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(485,'STRCMP',37,'Syntax:\nSTRCMP(expr1,expr2)\n\nSTRCMP() returns 0 if the strings are the same, -1 if the first\nargument is smaller than the second according to the current sort\norder, and 1 otherwise.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html\n\n','mysql> SELECT STRCMP(\'text\', \'text2\');\n -> -1\nmysql> SELECT STRCMP(\'text2\', \'text\');\n -> 1\nmysql> SELECT STRCMP(\'text\', \'text\');\n -> 0\n','http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html'),(486,'INSERT DELAYED',27,'Syntax:\nINSERT DELAYED ...\n\nThe DELAYED option for the INSERT statement is a MySQL extension to\nstandard SQL that is very useful if you have clients that cannot or\nneed not wait for the INSERT to complete. This is a common situation\nwhen you use MySQL for logging and you also periodically run SELECT and\nUPDATE statements that take a long time to complete.\n\nWhen a client uses INSERT DELAYED, it gets an okay from the server at\nonce, and the row is queued to be inserted when the table is not in use\nby any other thread.\n\nAnother major benefit of using INSERT DELAYED is that inserts from many\nclients are bundled together and written in one block. This is much\nfaster than performing many separate inserts.\n\nNote that INSERT DELAYED is slower than a normal INSERT if the table is\nnot otherwise in use. There is also the additional overhead for the\nserver to handle a separate thread for each table for which there are\ndelayed rows. This means that you should use INSERT DELAYED only when\nyou are really sure that you need it.\n\nThe queued rows are held only in memory until they are inserted into\nthe table. This means that if you terminate mysqld forcibly (for\nexample, with kill -9) or if mysqld dies unexpectedly, any queued rows\nthat have not been written to disk are lost.\n\nThere are some constraints on the use of DELAYED:\n\no INSERT DELAYED works only with MyISAM, MEMORY, ARCHIVE, and BLACKHOLE\n tables. For engines that do not support DELAYED, an error occurs.\n\no An error occurs for INSERT DELAYED if used with a table that has been\n locked with LOCK TABLES because the insert must be handled by a\n separate thread, not by the session that holds the lock.\n\no For MyISAM tables, if there are no free blocks in the middle of the\n data file, concurrent SELECT and INSERT statements are supported.\n Under these circumstances, you very seldom need to use INSERT DELAYED\n with MyISAM.\n\no INSERT DELAYED should be used only for INSERT statements that specify\n value lists. The server ignores DELAYED for INSERT ... SELECT or\n INSERT ... ON DUPLICATE KEY UPDATE statements.\n\no Because the INSERT DELAYED statement returns immediately, before the\n rows are inserted, you cannot use LAST_INSERT_ID() to get the\n AUTO_INCREMENT value that the statement might generate.\n\no DELAYED rows are not visible to SELECT statements until they actually\n have been inserted.\n\no Prior to MySQL 5.5.7, INSERT DELAYED was treated as a normal INSERT\n if the statement inserted multiple rows, binary logging was enabled,\n and the global logging format was statement-based (that is, whenever\n binlog_format was set to STATEMENT). Beginning with MySQL 5.5.7,\n INSERT DELAYED is always handled as a simple INSERT (that is, without\n the DELAYED option) whenever the value of binlog_format is STATEMENT\n or MIXED. (In the latter case, the statement no longer triggers a\n switch to row-based logging, and so is logged using the\n statement-based format.)\n\n This does not apply when using row-based binary logging mode\n (binlog_format set to ROW), in which INSERT DELAYED statements are\n always executed using the DELAYED option as specified, and logged as\n row-update events.\n\no DELAYED is ignored on slave replication servers, so that INSERT\n DELAYED is treated as a normal INSERT on slaves. This is because\n DELAYED could cause the slave to have different data than the master.\n\no Pending INSERT DELAYED statements are lost if a table is write locked\n and ALTER TABLE is used to modify the table structure.\n\no INSERT DELAYED is not supported for views.\n\no INSERT DELAYED is not supported for partitioned tables.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/insert-delayed.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/insert-delayed.html'),(487,'SHOW PROFILE',26,'Syntax:\nSHOW PROFILE [type [, type] ... ]\n [FOR QUERY n]\n [LIMIT row_count [OFFSET offset]]\n\ntype:\n ALL\n | BLOCK IO\n | CONTEXT SWITCHES\n | CPU\n | IPC\n | MEMORY\n | PAGE FAULTS\n | SOURCE\n | SWAPS\n\nThe SHOW PROFILE and SHOW PROFILES statements display profiling\ninformation that indicates resource usage for statements executed\nduring the course of the current session.\n\nProfiling is controlled by the profiling session variable, which has a\ndefault value of 0 (OFF). Profiling is enabled by setting profiling to\n1 or ON:\n\nmysql> SET profiling = 1;\n\nSHOW PROFILES displays a list of the most recent statements sent to the\nserver. The size of the list is controlled by the\nprofiling_history_size session variable, which has a default value of\n15. The maximum value is 100. Setting the value to 0 has the practical\neffect of disabling profiling.\n\nAll statements are profiled except SHOW PROFILE and SHOW PROFILES, so\nyou will find neither of those statements in the profile list.\nMalformed statements are profiled. For example, SHOW PROFILING is an\nillegal statement, and a syntax error occurs if you try to execute it,\nbut it will show up in the profiling list.\n\nSHOW PROFILE displays detailed information about a single statement.\nWithout the FOR QUERY n clause, the output pertains to the most\nrecently executed statement. If FOR QUERY n is included, SHOW PROFILE\ndisplays information for statement n. The values of n correspond to the\nQuery_ID values displayed by SHOW PROFILES.\n\nThe LIMIT row_count clause may be given to limit the output to\nrow_count rows. If LIMIT is given, OFFSET offset may be added to begin\nthe output offset rows into the full set of rows.\n\nBy default, SHOW PROFILE displays Status and Duration columns. The\nStatus values are like the State values displayed by SHOW PROCESSLIST,\nalthough there might be some minor differences in interpretion for the\ntwo statements for some status values (see\nhttp://dev.mysql.com/doc/refman/5.5/en/thread-information.html).\n\nOptional type values may be specified to display specific additional\ntypes of information:\n\no ALL displays all information\n\no BLOCK IO displays counts for block input and output operations\n\no CONTEXT SWITCHES displays counts for voluntary and involuntary\n context switches\n\no CPU displays user and system CPU usage times\n\no IPC displays counts for messages sent and received\n\no MEMORY is not currently implemented\n\no PAGE FAULTS displays counts for major and minor page faults\n\no SOURCE displays the names of functions from the source code, together\n with the name and line number of the file in which the function\n occurs\n\no SWAPS displays swap counts\n\nProfiling is enabled per session. When a session ends, its profiling\ninformation is lost.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-profile.html\n\n','mysql> SELECT @@profiling;\n+-------------+\n| @@profiling |\n+-------------+\n| 0 |\n+-------------+\n1 row in set (0.00 sec)\n\nmysql> SET profiling = 1;\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> DROP TABLE IF EXISTS t1;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nmysql> CREATE TABLE T1 (id INT);\nQuery OK, 0 rows affected (0.01 sec)\n\nmysql> SHOW PROFILES;\n+----------+----------+--------------------------+\n| Query_ID | Duration | Query |\n+----------+----------+--------------------------+\n| 0 | 0.000088 | SET PROFILING = 1 |\n| 1 | 0.000136 | DROP TABLE IF EXISTS t1 |\n| 2 | 0.011947 | CREATE TABLE t1 (id INT) |\n+----------+----------+--------------------------+\n3 rows in set (0.00 sec)\n\nmysql> SHOW PROFILE;\n+----------------------+----------+\n| Status | Duration |\n+----------------------+----------+\n| checking permissions | 0.000040 |\n| creating table | 0.000056 |\n| After create | 0.011363 |\n| query end | 0.000375 |\n| freeing items | 0.000089 |\n| logging slow query | 0.000019 |\n| cleaning up | 0.000005 |\n+----------------------+----------+\n7 rows in set (0.00 sec)\n\nmysql> SHOW PROFILE FOR QUERY 1;\n+--------------------+----------+\n| Status | Duration |\n+--------------------+----------+\n| query end | 0.000107 |\n| freeing items | 0.000008 |\n| logging slow query | 0.000015 |\n| cleaning up | 0.000006 |\n+--------------------+----------+\n4 rows in set (0.00 sec)\n\nmysql> SHOW PROFILE CPU FOR QUERY 2;\n+----------------------+----------+----------+------------+\n| Status | Duration | CPU_user | CPU_system |\n+----------------------+----------+----------+------------+\n| checking permissions | 0.000040 | 0.000038 | 0.000002 |\n| creating table | 0.000056 | 0.000028 | 0.000028 |\n| After create | 0.011363 | 0.000217 | 0.001571 |\n| query end | 0.000375 | 0.000013 | 0.000028 |\n| freeing items | 0.000089 | 0.000010 | 0.000014 |\n| logging slow query | 0.000019 | 0.000009 | 0.000010 |\n| cleaning up | 0.000005 | 0.000003 | 0.000002 |\n+----------------------+----------+----------+------------+\n7 rows in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/show-profile.html'),(488,'SHOW PROCEDURE CODE',26,'Syntax:\nSHOW PROCEDURE CODE proc_name\n\nThis statement is a MySQL extension that is available only for servers\nthat have been built with debugging support. It displays a\nrepresentation of the internal implementation of the named stored\nprocedure. A similar statement, SHOW FUNCTION CODE, displays\ninformation about stored functions (see [HELP SHOW FUNCTION CODE]).\n\nBoth statements require that you be the owner of the routine or have\nSELECT access to the mysql.proc table.\n\nIf the named routine is available, each statement produces a result\nset. Each row in the result set corresponds to one \"instruction\" in the\nroutine. The first column is Pos, which is an ordinal number beginning\nwith 0. The second column is Instruction, which contains an SQL\nstatement (usually changed from the original source), or a directive\nwhich has meaning only to the stored-routine handler.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-procedure-code.html\n\n','mysql> DELIMITER //\nmysql> CREATE PROCEDURE p1 ()\n -> BEGIN\n -> DECLARE fanta INT DEFAULT 55;\n -> DROP TABLE t2;\n -> LOOP\n -> INSERT INTO t3 VALUES (fanta);\n -> END LOOP;\n -> END//\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql> SHOW PROCEDURE CODE p1//\n+-----+----------------------------------------+\n| Pos | Instruction |\n+-----+----------------------------------------+\n| 0 | set fanta@0 55 |\n| 1 | stmt 9 \"DROP TABLE t2\" |\n| 2 | stmt 5 \"INSERT INTO t3 VALUES (fanta)\" |\n| 3 | jump 2 |\n+-----+----------------------------------------+\n4 rows in set (0.00 sec)\n','http://dev.mysql.com/doc/refman/5.5/en/show-procedure-code.html'),(489,'MEDIUMTEXT',22,'MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]\n\nA TEXT column with a maximum length of 16,777,215 (224 - 1) characters.\nThe effective maximum length is less if the value contains multi-byte\ncharacters. Each MEDIUMTEXT value is stored using a 3-byte length\nprefix that indicates the number of bytes in the value.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/string-type-overview.html'),(490,'LN',4,'Syntax:\nLN(X)\n\nReturns the natural logarithm of X; that is, the base-e logarithm of X.\nIf X is less than or equal to 0, then NULL is returned.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT LN(2);\n -> 0.69314718055995\nmysql> SELECT LN(-2);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(491,'RETURN',23,'Syntax:\nRETURN expr\n\nThe RETURN statement terminates execution of a stored function and\nreturns the value expr to the function caller. There must be at least\none RETURN statement in a stored function. There may be more than one\nif the function has multiple exit points.\n\nThis statement is not used in stored procedures, triggers, or events.\nThe LEAVE statement can be used to exit a stored program of those\ntypes.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/return.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/return.html'),(492,'SHOW COLLATION',26,'Syntax:\nSHOW COLLATION\n [LIKE \'pattern\' | WHERE expr]\n\nThis statement lists collations supported by the server. By default,\nthe output from SHOW COLLATION includes all available collations. The\nLIKE clause, if present, indicates which collation names to match. The\nWHERE clause can be given to select rows using more general conditions,\nas discussed in\nhttp://dev.mysql.com/doc/refman/5.5/en/extended-show.html. For example:\n\nmysql> SHOW COLLATION LIKE \'latin1%\';\n+-------------------+---------+----+---------+----------+---------+\n| Collation | Charset | Id | Default | Compiled | Sortlen |\n+-------------------+---------+----+---------+----------+---------+\n| latin1_german1_ci | latin1 | 5 | | | 0 |\n| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |\n| latin1_danish_ci | latin1 | 15 | | | 0 |\n| latin1_german2_ci | latin1 | 31 | | Yes | 2 |\n| latin1_bin | latin1 | 47 | | Yes | 0 |\n| latin1_general_ci | latin1 | 48 | | | 0 |\n| latin1_general_cs | latin1 | 49 | | | 0 |\n| latin1_spanish_ci | latin1 | 94 | | | 0 |\n+-------------------+---------+----+---------+----------+---------+\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/show-collation.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/show-collation.html'),(493,'LOG',4,'Syntax:\nLOG(X), LOG(B,X)\n\nIf called with one parameter, this function returns the natural\nlogarithm of X. If X is less than or equal to 0, then NULL is returned.\n\nThe inverse of this function (when called with a single argument) is\nthe EXP() function.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT LOG(2);\n -> 0.69314718055995\nmysql> SELECT LOG(-2);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(494,'SET SQL_LOG_BIN',8,'Syntax:\nSET sql_log_bin = {0|1}\n\nThe sql_log_bin variable controls whether logging to the binary log is\ndone. The default value is 1 (do logging). To change logging for the\ncurrent session, change the session value of this variable. The session\nuser must have the SUPER privilege to set this variable.\n\nBeginning with MySQL 5.5.5, it is no longer possible to set\n@@session.sql_log_bin within a transaction or subquery. (Bug #53437)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/set-sql-log-bin.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/set-sql-log-bin.html'),(495,'!=',18,'Syntax:\n<>, !=\n\nNot equal:\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT \'.01\' <> \'0.01\';\n -> 1\nmysql> SELECT .01 <> \'0.01\';\n -> 0\nmysql> SELECT \'zapp\' <> \'zappp\';\n -> 1\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(496,'WHILE',23,'Syntax:\n[begin_label:] WHILE search_condition DO\n statement_list\nEND WHILE [end_label]\n\nThe statement list within a WHILE statement is repeated as long as the\nsearch_condition expression is true. statement_list consists of one or\nmore SQL statements, each terminated by a semicolon (;) statement\ndelimiter.\n\nA WHILE statement can be labeled. For the rules regarding label use,\nsee [HELP labels].\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/while.html\n\n','CREATE PROCEDURE dowhile()\nBEGIN\n DECLARE v1 INT DEFAULT 5;\n\n WHILE v1 > 0 DO\n ...\n SET v1 = v1 - 1;\n END WHILE;\nEND;\n','http://dev.mysql.com/doc/refman/5.5/en/while.html'),(497,'AES_DECRYPT',12,'Syntax:\nAES_DECRYPT(crypt_str,key_str)\n\nThis function decrypts data using the official AES (Advanced Encryption\nStandard) algorithm. For more information, see the description of\nAES_ENCRYPT().\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html'),(498,'DAYNAME',31,'Syntax:\nDAYNAME(date)\n\nReturns the name of the weekday for date. The language used for the\nname is controlled by the value of the lc_time_names system variable\n(http://dev.mysql.com/doc/refman/5.5/en/locale-support.html).\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html\n\n','mysql> SELECT DAYNAME(\'2007-02-03\');\n -> \'Saturday\'\n','http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html'),(499,'COERCIBILITY',17,'Syntax:\nCOERCIBILITY(str)\n\nReturns the collation coercibility value of the string argument.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT COERCIBILITY(\'abc\' COLLATE latin1_swedish_ci);\n -> 0\nmysql> SELECT COERCIBILITY(USER());\n -> 3\nmysql> SELECT COERCIBILITY(\'abc\');\n -> 4\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(500,'INT',22,'INT[(M)] [UNSIGNED] [ZEROFILL]\n\nA normal-size integer. The signed range is -2147483648 to 2147483647.\nThe unsigned range is 0 to 4294967295.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html\n\n','','http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html'),(501,'GLENGTH',13,'GLength(ls)\n\nReturns as a double-precision number the length of the LineString value\nls in its associated spatial reference.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions\n\n','mysql> SET @ls = \'LineString(1 1,2 2,3 3)\';\nmysql> SELECT GLength(GeomFromText(@ls));\n+----------------------------+\n| GLength(GeomFromText(@ls)) |\n+----------------------------+\n| 2.8284271247462 |\n+----------------------------+\n','http://dev.mysql.com/doc/refman/5.5/en/geometry-property-functions.html#linestring-property-functions'),(502,'RADIANS',4,'Syntax:\nRADIANS(X)\n\nReturns the argument X, converted from degrees to radians. (Note that\nπ radians equals 180 degrees.)\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html\n\n','mysql> SELECT RADIANS(90);\n -> 1.5707963267949\n','http://dev.mysql.com/doc/refman/5.5/en/mathematical-functions.html'),(503,'COLLATION',17,'Syntax:\nCOLLATION(str)\n\nReturns the collation of the string argument.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT COLLATION(\'abc\');\n -> \'latin1_swedish_ci\'\nmysql> SELECT COLLATION(_utf8\'abc\');\n -> \'utf8_general_ci\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(504,'COALESCE',18,'Syntax:\nCOALESCE(value,...)\n\nReturns the first non-NULL value in the list, or NULL if there are no\nnon-NULL values.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html\n\n','mysql> SELECT COALESCE(NULL,1);\n -> 1\nmysql> SELECT COALESCE(NULL,NULL,NULL);\n -> NULL\n','http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html'),(505,'VERSION',17,'Syntax:\nVERSION()\n\nReturns a string that indicates the MySQL server version. The string\nuses the utf8 character set. The value might have a suffix in addition\nto the version number. See the description of the version system\nvariable in\nhttp://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html\n\n','mysql> SELECT VERSION();\n -> \'5.5.29-standard\'\n','http://dev.mysql.com/doc/refman/5.5/en/information-functions.html'),(506,'MAKE_SET',37,'Syntax:\nMAKE_SET(bits,str1,str2,...)\n\nReturns a set value (a string containing substrings separated by \",\"\ncharacters) consisting of the strings that have the corresponding bit\nin bits set. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL\nvalues in str1, str2, ... are not appended to the result.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT MAKE_SET(1,\'a\',\'b\',\'c\');\n -> \'a\'\nmysql> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',\'world\');\n -> \'hello,world\'\nmysql> SELECT MAKE_SET(1 | 4,\'hello\',\'nice\',NULL,\'world\');\n -> \'hello\'\nmysql> SELECT MAKE_SET(0,\'a\',\'b\',\'c\');\n -> \'\'\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'),(507,'FIND_IN_SET',37,'Syntax:\nFIND_IN_SET(str,strlist)\n\nReturns a value in the range of 1 to N if the string str is in the\nstring list strlist consisting of N substrings. A string list is a\nstring composed of substrings separated by \",\" characters. If the first\nargument is a constant string and the second is a column of type SET,\nthe FIND_IN_SET() function is optimized to use bit arithmetic. Returns\n0 if str is not in strlist or if strlist is the empty string. Returns\nNULL if either argument is NULL. This function does not work properly\nif the first argument contains a comma (\",\") character.\n\nURL: http://dev.mysql.com/doc/refman/5.5/en/string-functions.html\n\n','mysql> SELECT FIND_IN_SET(\'b\',\'a,b,c,d\');\n -> 2\n','http://dev.mysql.com/doc/refman/5.5/en/string-functions.html'); +/*!40000 ALTER TABLE `help_topic` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `host` +-- + +DROP TABLE IF EXISTS `host`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `host` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `host` +-- + +LOCK TABLES `host` WRITE; +/*!40000 ALTER TABLE `host` DISABLE KEYS */; +/*!40000 ALTER TABLE `host` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `ndb_binlog_index` +-- + +DROP TABLE IF EXISTS `ndb_binlog_index`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ndb_binlog_index` ( + `Position` bigint(20) unsigned NOT NULL, + `File` varchar(255) NOT NULL, + `epoch` bigint(20) unsigned NOT NULL, + `inserts` bigint(20) unsigned NOT NULL, + `updates` bigint(20) unsigned NOT NULL, + `deletes` bigint(20) unsigned NOT NULL, + `schemaops` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`epoch`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `ndb_binlog_index` +-- + +LOCK TABLES `ndb_binlog_index` WRITE; +/*!40000 ALTER TABLE `ndb_binlog_index` DISABLE KEYS */; +/*!40000 ALTER TABLE `ndb_binlog_index` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin` +-- + +DROP TABLE IF EXISTS `plugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin` ( + `name` varchar(64) NOT NULL DEFAULT '', + `dl` varchar(128) NOT NULL DEFAULT '', + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL plugins'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin` +-- + +LOCK TABLES `plugin` WRITE; +/*!40000 ALTER TABLE `plugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proc` +-- + +DROP TABLE IF EXISTS `proc`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proc` ( + `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `name` char(64) NOT NULL DEFAULT '', + `type` enum('FUNCTION','PROCEDURE') NOT NULL, + `specific_name` char(64) NOT NULL DEFAULT '', + `language` enum('SQL') NOT NULL DEFAULT 'SQL', + `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', + `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', + `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', + `param_list` blob NOT NULL, + `returns` longblob NOT NULL, + `body` longblob NOT NULL, + `definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', + `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `body_utf8` longblob, + PRIMARY KEY (`db`,`name`,`type`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proc` +-- + +LOCK TABLES `proc` WRITE; +/*!40000 ALTER TABLE `proc` DISABLE KEYS */; +/*!40000 ALTER TABLE `proc` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `procs_priv` +-- + +DROP TABLE IF EXISTS `procs_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `procs_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', + `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL, + `Grantor` char(77) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `procs_priv` +-- + +LOCK TABLES `procs_priv` WRITE; +/*!40000 ALTER TABLE `procs_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `proxies_priv` +-- + +DROP TABLE IF EXISTS `proxies_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `proxies_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Proxied_user` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `With_grant` tinyint(1) NOT NULL DEFAULT '0', + `Grantor` char(77) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `proxies_priv` +-- + +LOCK TABLES `proxies_priv` WRITE; +/*!40000 ALTER TABLE `proxies_priv` DISABLE KEYS */; +INSERT INTO `proxies_priv` VALUES ('localhost','root','','',1,'','2020-05-31 14:44:49'),('asus','root','','',1,'','2020-05-31 14:44:49'); +/*!40000 ALTER TABLE `proxies_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `servers` +-- + +DROP TABLE IF EXISTS `servers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `servers` ( + `Server_name` char(64) NOT NULL DEFAULT '', + `Host` char(64) NOT NULL DEFAULT '', + `Db` char(64) NOT NULL DEFAULT '', + `Username` char(64) NOT NULL DEFAULT '', + `Password` char(64) NOT NULL DEFAULT '', + `Port` int(4) NOT NULL DEFAULT '0', + `Socket` char(64) NOT NULL DEFAULT '', + `Wrapper` char(64) NOT NULL DEFAULT '', + `Owner` char(64) NOT NULL DEFAULT '', + PRIMARY KEY (`Server_name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `servers` +-- + +LOCK TABLES `servers` WRITE; +/*!40000 ALTER TABLE `servers` DISABLE KEYS */; +/*!40000 ALTER TABLE `servers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tables_priv` +-- + +DROP TABLE IF EXISTS `tables_priv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tables_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Grantor` char(77) COLLATE utf8_bin NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8 NOT NULL DEFAULT '', + `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', + PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), + KEY `Grantor` (`Grantor`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tables_priv` +-- + +LOCK TABLES `tables_priv` WRITE; +/*!40000 ALTER TABLE `tables_priv` DISABLE KEYS */; +/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone` +-- + +DROP TABLE IF EXISTS `time_zone`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone` ( + `Time_zone_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Use_leap_seconds` enum('Y','N') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Time_zone_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone` +-- + +LOCK TABLES `time_zone` WRITE; +/*!40000 ALTER TABLE `time_zone` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_leap_second` +-- + +DROP TABLE IF EXISTS `time_zone_leap_second`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_leap_second` ( + `Transition_time` bigint(20) NOT NULL, + `Correction` int(11) NOT NULL, + PRIMARY KEY (`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Leap seconds information for time zones'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_leap_second` +-- + +LOCK TABLES `time_zone_leap_second` WRITE; +/*!40000 ALTER TABLE `time_zone_leap_second` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_leap_second` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_name` +-- + +DROP TABLE IF EXISTS `time_zone_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_name` ( + `Name` char(64) NOT NULL, + `Time_zone_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone names'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_name` +-- + +LOCK TABLES `time_zone_name` WRITE; +/*!40000 ALTER TABLE `time_zone_name` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_name` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition` +-- + +DROP TABLE IF EXISTS `time_zone_transition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_time` bigint(20) NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`Time_zone_id`,`Transition_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transitions'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition` +-- + +LOCK TABLES `time_zone_transition` WRITE; +/*!40000 ALTER TABLE `time_zone_transition` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `time_zone_transition_type` +-- + +DROP TABLE IF EXISTS `time_zone_transition_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `time_zone_transition_type` ( + `Time_zone_id` int(10) unsigned NOT NULL, + `Transition_type_id` int(10) unsigned NOT NULL, + `Offset` int(11) NOT NULL DEFAULT '0', + `Is_DST` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Abbreviation` char(8) NOT NULL DEFAULT '', + PRIMARY KEY (`Time_zone_id`,`Transition_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Time zone transition types'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `time_zone_transition_type` +-- + +LOCK TABLES `time_zone_transition_type` WRITE; +/*!40000 ALTER TABLE `time_zone_transition_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `time_zone_transition_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', + `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', + `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', + `ssl_cipher` blob NOT NULL, + `x509_issuer` blob NOT NULL, + `x509_subject` blob NOT NULL, + `max_questions` int(11) unsigned NOT NULL DEFAULT '0', + `max_updates` int(11) unsigned NOT NULL DEFAULT '0', + `max_connections` int(11) unsigned NOT NULL DEFAULT '0', + `max_user_connections` int(11) NOT NULL DEFAULT '0', + `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', + `authentication_string` text COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`Host`,`User`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''),('asus','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''),('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''),('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''),('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'',''),('asus','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'',''); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `general_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `slow_log` +-- + +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-05-31 17:58:23 diff --git a/mysql-test/suite/binlog/include/binlog.test b/mysql-test/suite/binlog/include/binlog.test index e5d4efb183b..368dcebc5f1 100644 --- a/mysql-test/suite/binlog/include/binlog.test +++ b/mysql-test/suite/binlog/include/binlog.test @@ -391,7 +391,7 @@ SHOW SESSION VARIABLES LIKE "unique_checks"; --echo # INSERT INTO t1 VALUES(2) --echo # foreign_key_checks=1 and unique_checks=1 --echo # It should not change current session's variables, even error happens -call mtr.add_suppression("Slave SQL.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); +call mtr.add_suppression("BINLOG_BASE64_EVENT.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); --error 1062 BINLOG ' dfLtTBMBAAAAKQAAAKsBAAAAABcAAAAAAAEABHRlc3QAAnQxAAEDAAE= diff --git a/mysql-test/suite/binlog/r/binlog_base64_flag.result b/mysql-test/suite/binlog/r/binlog_base64_flag.result index a12e0d8eb31..a75164992d5 100644 --- a/mysql-test/suite/binlog/r/binlog_base64_flag.result +++ b/mysql-test/suite/binlog/r/binlog_base64_flag.result @@ -1,3 +1,5 @@ +call mtr.add_suppression("BINLOG_BASE64_EVENT: According to the master's version"); +call mtr.add_suppression("BINLOG_BASE64_EVENT: Column 1 of table 'test.char128_utf8' cannot be converted"); DROP TABLE IF EXISTS t1; ==== Test BUG#32407 ==== select * from t1; diff --git a/mysql-test/suite/binlog/r/binlog_drop_if_exists.result b/mysql-test/suite/binlog/r/binlog_drop_if_exists.result index 937662a7a49..c918de9a907 100644 --- a/mysql-test/suite/binlog/r/binlog_drop_if_exists.result +++ b/mysql-test/suite/binlog/r/binlog_drop_if_exists.result @@ -164,3 +164,47 @@ master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test`; CREATE TABLE t1(id int) master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS /* */ `t1` /* generated by server */ +# +# MDEV-22820 Bogus "Unknown table" warnings produced upon attempt to +# drop parent table referenced by FK +# +create table t1 (a int, key(a)) engine=InnoDB; +create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB; +drop table if exists t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table if exists t1,t0; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +show warnings; +Level Code Message +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails +Note 1051 Unknown table 'test.t0' +drop table t2,t1; +create table t3 (a int) engine=aria; +drop table t10,t20; +ERROR 42S02: Unknown table 'test.t10,test.t20' +drop table t10,t20,t3; +ERROR 42S02: Unknown table 'test.t10,test.t20' +drop table if exists t10,t20; +Warnings: +Note 1051 Unknown table 'test.t10,test.t20' +drop table if exists t10,t20,t3; +Warnings: +Note 1051 Unknown table 'test.t10,test.t20,test.t3' +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create table t1 (a int, key(a)) engine=InnoDB +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t0` /* generated by server */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE `t2`,`t1` /* generated by server */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create table t3 (a int) engine=aria +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE `t10`,`t20`,`t3` /* generated by server */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t10`,`t20` /* generated by server */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t10`,`t20`,`t3` /* generated by server */ diff --git a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result new file mode 100644 index 00000000000..eb96f7bb984 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result @@ -0,0 +1,31 @@ +CREATE TEMPORARY SEQUENCE seq_1; +XA START '3'; +CREATE TEMPORARY TABLE tmp_1(c INT); +XA END '3'; +XA PREPARE '3'; +DROP TEMPORARY TABLE tmp_1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +ALTER TABLE tmp_1 DROP COLUMN c; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +DROP TEMPORARY SEQUENCE seq_1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +ALTER SEQUENCE seq_1 INCREMENT BY 1; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +CREATE TEMPORARY TABLE tmp_2(c INT); +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +CREATE TEMPORARY SEQUENCE seq_2; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +XA ROLLBACK '3'; +# Proof of correct logging incl empty XA-PREPARE +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY SEQUENCE seq_1 +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp_1(c INT) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # XA START X'33',X'',1 GTID #-#-# +master-bin.000001 # Query # # XA END X'33',X'',1 +master-bin.000001 # XA_prepare # # XA PREPARE X'33',X'',1 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # XA ROLLBACK X'33',X'',1 diff --git a/mysql-test/suite/binlog/r/binlog_mixed.result b/mysql-test/suite/binlog/r/binlog_mixed.result new file mode 100644 index 00000000000..1f30f21a9b4 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_mixed.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 (a) VALUES (1),(2); +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @a = 0; +CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM t1 LIMIT 1; +SET AUTOCOMMIT= OFF; +LOCK TABLES t2 WRITE; +DELETE FROM t1 LIMIT 1; +SAVEPOINT A; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_frag.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_frag.result index 5f685dfa785..5c880cd5db1 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_frag.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_frag.result @@ -20,5 +20,8 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SET @binlog_fragment_0='012345'; BINLOG @binlog_fragment_0, @binlog_fragment_not_exist; ERROR 42000: Incorrect argument type to variable 'binlog_fragment_not_exist' +SET @a= '42'; +BINLOG @a, @a; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use # Cleanup DROP TABLE t; diff --git a/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result b/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result new file mode 100644 index 00000000000..88ed236a528 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result @@ -0,0 +1,45 @@ +call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0"); +call mtr.add_suppression("Log filename extension number exhausted:."); +call mtr.add_suppression("Can't generate a unique log-filename"); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name."); +call mtr.add_suppression("Could not use master-bin for logging"); +"Test case verifies creation of binary log with max entension value." +RESET MASTER TO 2147483647; +show binary logs; +Log_name File_size +master-bin.2147483647 # +FOUND 1 /Next log extension: 2147483647. Remaining log filename extensions: 0./ in mysqld.1.err +CREATE DATABASE db1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.2147483647 # Gtid # # GTID #-#-# +master-bin.2147483647 # Query # # CREATE DATABASE db1 +RESET MASTER TO 2147483648; +ERROR HY000: Can't generate a unique log-filename master-bin.(1-999) + +FOUND 1 /Turning logging off for the whole duration of the MariaDB server process/ in mysqld.1.err +"Following CREATE DATABSE db2 command will not be present in binary log" +"as binary log got closed due to ER_NO_UNIQUE_LOGFILE error." +CREATE DATABASE db2; +"RESET MASTER command fails to generate a new binary log" +"log-bin will be disabled and server needs to be restarted to" +"re-enable the binary log." +SHOW BINARY LOGS; +ERROR HY000: You are not using binary logging +# restart +show binary logs; +Log_name File_size +master-bin.000001 # +SHOW DATABASES LIKE 'db%'; +Database (db%) +db1 +db2 +include/show_binlog_events.inc +DROP DATABASE db1; +DROP DATABASE db2; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # DROP DATABASE db1 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # DROP DATABASE db2 diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index 2d79de6960a..7715d0e0325 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -1054,7 +1054,7 @@ unique_checks OFF # INSERT INTO t1 VALUES(2) # foreign_key_checks=1 and unique_checks=1 # It should not change current session's variables, even error happens -call mtr.add_suppression("Slave SQL.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); +call mtr.add_suppression("BINLOG_BASE64_EVENT.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); BINLOG ' dfLtTBMBAAAAKQAAAKsBAAAAABcAAAAAAAEABHRlc3QAAnQxAAEDAAE= dfLtTBcBAAAAIgAAAM0BAAAAABcAAAAAAAEAAf/+AgAAAA== diff --git a/mysql-test/suite/binlog/r/binlog_stm_binlog.result b/mysql-test/suite/binlog/r/binlog_stm_binlog.result index ccc3db2ba7e..ad14a31381d 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_stm_binlog.result @@ -650,7 +650,7 @@ unique_checks OFF # INSERT INTO t1 VALUES(2) # foreign_key_checks=1 and unique_checks=1 # It should not change current session's variables, even error happens -call mtr.add_suppression("Slave SQL.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); +call mtr.add_suppression("BINLOG_BASE64_EVENT.*Could not execute Write_rows_v1 event on table test.t1; Duplicate entry .2. for key .PRIMARY., Error_code: 1062"); BINLOG ' dfLtTBMBAAAAKQAAAKsBAAAAABcAAAAAAAEABHRlc3QAAnQxAAEDAAE= dfLtTBcBAAAAIgAAAM0BAAAAABcAAAAAAAEAAf/+AgAAAA== diff --git a/mysql-test/suite/binlog/t/binlog_base64_flag.test b/mysql-test/suite/binlog/t/binlog_base64_flag.test index e1187cd895c..5311da54f5f 100644 --- a/mysql-test/suite/binlog/t/binlog_base64_flag.test +++ b/mysql-test/suite/binlog/t/binlog_base64_flag.test @@ -9,10 +9,12 @@ # BINLOG statement does not work in embedded mode. source include/not_embedded.inc; +call mtr.add_suppression("BINLOG_BASE64_EVENT: According to the master's version"); +call mtr.add_suppression("BINLOG_BASE64_EVENT: Column 1 of table 'test.char128_utf8' cannot be converted"); + disable_warnings; DROP TABLE IF EXISTS t1; enable_warnings; - # Test to show BUG#32407. This reads a binlog created with the # mysql-5.1-telco-6.1 tree, specifically at the tag # mysql-5.1.15-ndb-6.1.23, and applies it to the database. The test diff --git a/mysql-test/suite/binlog/t/binlog_drop_if_exists.test b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test index 26910432428..b565104ce3a 100644 --- a/mysql-test/suite/binlog/t/binlog_drop_if_exists.test +++ b/mysql-test/suite/binlog/t/binlog_drop_if_exists.test @@ -1,3 +1,5 @@ +--source include/have_innodb.inc + # BUG#13684: # SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine # does not exist @@ -128,3 +130,33 @@ DROP TABLE IF EXISTS /* */ t1; --source include/show_binlog_events.inc +--echo # +--echo # MDEV-22820 Bogus "Unknown table" warnings produced upon attempt to +--echo # drop parent table referenced by FK +--echo # + +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +create table t1 (a int, key(a)) engine=InnoDB; +create table t2 (b int, foreign key(b) references t1(a)) engine=InnoDB; +--error ER_ROW_IS_REFERENCED_2 +drop table if exists t1; +--error ER_ROW_IS_REFERENCED_2 +drop table if exists t1,t0; +show warnings; +drop table t2,t1; + +create table t3 (a int) engine=aria; + +# This is not logged +--error ER_BAD_TABLE_ERROR +drop table t10,t20; +# This is logged +--error ER_BAD_TABLE_ERROR +drop table t10,t20,t3; + +# These are both logged +drop table if exists t10,t20; +drop table if exists t10,t20,t3; + +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test new file mode 100644 index 00000000000..7f923f71f81 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test @@ -0,0 +1,35 @@ +# The test verifies execution and binary logging of user XA that produce empty +# XA-PREPARE group of events. + +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc + + +# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state + +# Temporary sequnce may not be created within a transaction +CREATE TEMPORARY SEQUENCE seq_1; + +XA START '3'; +CREATE TEMPORARY TABLE tmp_1(c INT); +XA END '3'; +XA PREPARE '3'; +--error ER_XAER_RMFAIL +DROP TEMPORARY TABLE tmp_1; +--error ER_XAER_RMFAIL +ALTER TABLE tmp_1 DROP COLUMN c; +--error ER_XAER_RMFAIL +DROP TEMPORARY SEQUENCE seq_1; +--error ER_XAER_RMFAIL +ALTER SEQUENCE seq_1 INCREMENT BY 1; + +--error ER_XAER_RMFAIL +CREATE TEMPORARY TABLE tmp_2(c INT); +--error ER_XAER_RMFAIL +CREATE TEMPORARY SEQUENCE seq_2; + +# Cleanup +XA ROLLBACK '3'; + +--echo # Proof of correct logging incl empty XA-PREPARE +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_mixed.test b/mysql-test/suite/binlog/t/binlog_mixed.test new file mode 100644 index 00000000000..fa1b2ca3a85 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mixed.test @@ -0,0 +1,23 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_row.inc + +# +# MDEV-22048 Assertion `binlog_table_maps == 0 || +# locked_tables_mode == LTM_LOCK_TABLES' failed in +# THD::reset_for_next_command +# + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 (a) VALUES (1),(2); + +CREATE TABLE t2 (b INT) ENGINE=InnoDB; + +CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @a = 0; +CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM t1 LIMIT 1; + +SET AUTOCOMMIT= OFF; +LOCK TABLES t2 WRITE; +DELETE FROM t1 LIMIT 1; +SAVEPOINT A; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test index 6765b26f3da..9f0d0f2588b 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row_frag.test @@ -41,6 +41,11 @@ SET @binlog_fragment_0='012345'; --error ER_WRONG_TYPE_FOR_VAR BINLOG @binlog_fragment_0, @binlog_fragment_not_exist; +# MDEV-22520 +SET @a= '42'; +--error ER_SYNTAX_ERROR +BINLOG @a, @a; + --echo # Cleanup --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql DROP TABLE t; diff --git a/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test new file mode 100644 index 00000000000..cb8b1078bdd --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test @@ -0,0 +1,83 @@ +# ==== Purpose ==== +# +# Test verifies that when RESET MASTER TO # command is supplied with binlog +# extension number greater than 2147483647 the command should report +# appropriate error and binary log should be disabled. It should not result in +# a crash. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Verify case with max binary log extension. Max value is '2147483647' +# 1 - Confirm that SHOW BINARY LOGS displays a binary log with '2147483647' +# 2 - Verify that events are successfully written into max extension file. +# 3 - Try to create a binary log with extension greater than max allowed +# value '2147483648', verify ER_NO_UNIQUE_LOGFILE error is reported. +# 4 - Execute CREATE DATABASE db2 statement and verify server dosn't crash. +# 5 - Execute SHOW BINARY LOG command and verify that it reports +# ER_NO_BINARY_LOGGING error. +# 6 - Restart the server and verify that databse 'db2' exists and it it not +# present in the binary log. +# +# ==== References ==== +# +# MDEV-22451: SIGSEGV in __memmove_avx_unaligned_erms/memcpy from +# _my_b_write on CREATE after RESET MASTER +# +--source include/have_log_bin.inc + +call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0"); +call mtr.add_suppression("Log filename extension number exhausted:."); +call mtr.add_suppression("Can't generate a unique log-filename"); +call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name."); +call mtr.add_suppression("Could not use master-bin for logging"); + + +--echo "Test case verifies creation of binary log with max entension value." +RESET MASTER TO 2147483647; +--source include/show_binary_logs.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Next log extension: 2147483647. Remaining log filename extensions: 0. +--source include/search_pattern_in_file.inc + +CREATE DATABASE db1; +--source include/show_binlog_events.inc + +--error ER_NO_UNIQUE_LOGFILE +RESET MASTER TO 2147483648; + +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Turning logging off for the whole duration of the MariaDB server process +--source include/search_pattern_in_file.inc + +--echo "Following CREATE DATABSE db2 command will not be present in binary log" +--echo "as binary log got closed due to ER_NO_UNIQUE_LOGFILE error." +CREATE DATABASE db2; + + +--echo "RESET MASTER command fails to generate a new binary log" +--echo "log-bin will be disabled and server needs to be restarted to" +--echo "re-enable the binary log." +--error ER_NO_BINARY_LOGGING +SHOW BINARY LOGS; + +--source include/restart_mysqld.inc + +--source include/show_binary_logs.inc +SHOW DATABASES LIKE 'db%'; +--source include/show_binlog_events.inc + +# Cleanup +DROP DATABASE db1; +DROP DATABASE db2; +--source include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result b/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result index c8a10577517..4c667bd7f5a 100644 --- a/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result +++ b/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result @@ -9,6 +9,7 @@ connection master; call mtr.add_suppression("Can't generate a unique log-filename"); call mtr.add_suppression("Writing one row to the row-based binary log failed.*"); call mtr.add_suppression("Error writing file .*"); +call mtr.add_suppression("Could not use master-bin for logging"); SET @old_debug= @@global.debug_dbug; SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data'; SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data'; diff --git a/mysql-test/suite/compat/oracle/r/exception.result b/mysql-test/suite/compat/oracle/r/exception.result index b61d25f36ee..3bd239808bc 100644 --- a/mysql-test/suite/compat/oracle/r/exception.result +++ b/mysql-test/suite/compat/oracle/r/exception.result @@ -106,7 +106,7 @@ RAISE dup_val_on_index; END; $$ CALL p1(); -ERROR 23000: Duplicate entry '%-.192s' for key %d +ERROR 23000: Duplicate entry '%-.192T' for key %d DROP PROCEDURE p1; CREATE PROCEDURE p1 AS diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result index a1a92b13aa3..c5810c7c1d5 100644 --- a/mysql-test/suite/compat/oracle/r/parser.result +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -607,6 +607,40 @@ ERROR HY000: Unknown system variable 'password' SELECT @@GLOBAL.role; ERROR HY000: Unknown system variable 'role' # +# MDEV-22822 sql_mode="oracle" cannot declare without variable errors +# +# It's OK to have no declarations between DECLARE and BEGIN. +# +BEGIN +DECLARE +BEGIN +NULL; +END; +EXCEPTION +WHEN OTHERS THEN +NULL; +END; +// +DECLARE +BEGIN +NULL; +EXCEPTION +WHEN OTHERS THEN +NULL; +END; +// +BEGIN +<> +DECLARE +BEGIN +NULL; +END; +EXCEPTION +WHEN OTHERS THEN +NULL; +END; +// +# # End of 10.3 tests # # diff --git a/mysql-test/suite/compat/oracle/t/parser.test b/mysql-test/suite/compat/oracle/t/parser.test index 091307d37bf..99355c57dc3 100644 --- a/mysql-test/suite/compat/oracle/t/parser.test +++ b/mysql-test/suite/compat/oracle/t/parser.test @@ -409,6 +409,53 @@ SELECT @@GLOBAL.password; SELECT @@GLOBAL.role; +--echo # +--echo # MDEV-22822 sql_mode="oracle" cannot declare without variable errors +--echo # +--echo # It's OK to have no declarations between DECLARE and BEGIN. +--echo # + +DELIMITER //; +BEGIN + DECLARE + BEGIN + NULL; + END; +EXCEPTION +WHEN OTHERS THEN + NULL; +END; +// +DELIMITER ;// + + +DELIMITER //; +DECLARE +BEGIN + NULL; +EXCEPTION +WHEN OTHERS THEN + NULL; +END; +// +DELIMITER ;// + + +DELIMITER //; +BEGIN +<> + DECLARE + BEGIN + NULL; + END; +EXCEPTION +WHEN OTHERS THEN + NULL; +END; +// +DELIMITER ;// + + --echo # --echo # End of 10.3 tests --echo # diff --git a/mysql-test/suite/csv/csv.result b/mysql-test/suite/csv/csv.result index 220b84b222e..de5025be0ea 100644 --- a/mysql-test/suite/csv/csv.result +++ b/mysql-test/suite/csv/csv.result @@ -4928,9 +4928,7 @@ period 9410 drop table if exists t1,t2,t3,t4; Warnings: -Note 1051 Unknown table 'test.t2' -Note 1051 Unknown table 'test.t3' -Note 1051 Unknown table 'test.t4' +Note 1051 Unknown table 'test.t2,test.t3,test.t4' DROP TABLE IF EXISTS bug13894; CREATE TABLE bug13894 ( val integer not null ) ENGINE = CSV; INSERT INTO bug13894 VALUES (5); diff --git a/mysql-test/suite/encryption/disabled.def b/mysql-test/suite/encryption/disabled.def deleted file mode 100644 index d92d3495cb8..00000000000 --- a/mysql-test/suite/encryption/disabled.def +++ /dev/null @@ -1,14 +0,0 @@ -############################################################################## -# -# List the test cases that are to be disabled temporarily. -# -# Separate the test case name and the comment with ':'. -# -# : BUG# -# -# Do not use any TAB characters for whitespace. -# -############################################################################## - -innodb_scrub : MDEV-8139 scrubbing does not work reliably -innodb_scrub_background : MDEV-8139 scrubbing does not work reliably diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result index f90e7aeb780..87377a01479 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result +++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result @@ -1,10 +1,10 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); -call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'"); +call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); diff --git a/mysql-test/suite/encryption/r/innodb_scrub.result b/mysql-test/suite/encryption/r/innodb_scrub.result deleted file mode 100644 index 6e8febc762d..00000000000 --- a/mysql-test/suite/encryption/r/innodb_scrub.result +++ /dev/null @@ -1,138 +0,0 @@ -create table snapshot_status engine = myisam -select * from information_schema.global_status -where variable_name like 'innodb_scrub%'; -# MDEV-8139 Fix scrubbing tests -# FIXME: Add index(b) to each table; ensure that undo logs are scrubbed. -create table delete_3 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -delete from delete_3; -create table delete_rollback_delete_3 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -begin; -delete from delete_rollback_delete_3; -rollback; -delete from delete_rollback_delete_3; -create table insert_rollback_3 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -begin; -rollback; -create table delete_2 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compact; -delete from delete_2; -create table delete_rollback_delete_2 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compact; -begin; -delete from delete_rollback_delete_2; -rollback; -delete from delete_rollback_delete_2; -create table insert_rollback_2 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compact; -begin; -rollback; -create table delete_1 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=redundant; -delete from delete_1; -create table delete_rollback_delete_1 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=redundant; -begin; -delete from delete_rollback_delete_1; -rollback; -delete from delete_rollback_delete_1; -create table insert_rollback_1 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=redundant; -begin; -rollback; -create table delete_0 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=dynamic; -delete from delete_0; -create table delete_rollback_delete_0 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=dynamic; -begin; -delete from delete_rollback_delete_0; -rollback; -delete from delete_rollback_delete_0; -create table insert_rollback_0 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=dynamic; -begin; -rollback; -SET GLOBAL innodb_fast_shutdown=0; -# delete_3.ibd -# delete_rollback_delete_3.ibd -# insert_rollback_3.ibd -# delete_2.ibd -# delete_rollback_delete_2.ibd -# insert_rollback_2.ibd -# delete_1.ibd -# delete_rollback_delete_1.ibd -# insert_rollback_1.ibd -# delete_0.ibd -# delete_rollback_delete_0.ibd -# insert_rollback_0.ibd -check table delete_3, delete_rollback_delete_3, insert_rollback_3; -Table Op Msg_type Msg_text -test.delete_3 check status OK -test.delete_rollback_delete_3 check status OK -test.insert_rollback_3 check status OK -drop table delete_3, delete_rollback_delete_3, insert_rollback_3; -check table delete_2, delete_rollback_delete_2, insert_rollback_2; -Table Op Msg_type Msg_text -test.delete_2 check status OK -test.delete_rollback_delete_2 check status OK -test.insert_rollback_2 check status OK -drop table delete_2, delete_rollback_delete_2, insert_rollback_2; -check table delete_1, delete_rollback_delete_1, insert_rollback_1; -Table Op Msg_type Msg_text -test.delete_1 check status OK -test.delete_rollback_delete_1 check status OK -test.insert_rollback_1 check status OK -drop table delete_1, delete_rollback_delete_1, insert_rollback_1; -check table delete_0, delete_rollback_delete_0, insert_rollback_0; -Table Op Msg_type Msg_text -test.delete_0 check status OK -test.delete_rollback_delete_0 check status OK -test.insert_rollback_0 check status OK -drop table delete_0, delete_rollback_delete_0, insert_rollback_0; -show variables like 'innodb_%scrub_data%'; -Variable_name Value -innodb_background_scrub_data_check_interval 3600 -innodb_background_scrub_data_compressed OFF -innodb_background_scrub_data_interval 604800 -innodb_background_scrub_data_uncompressed OFF -innodb_immediate_scrub_data_uncompressed ON -# verify that this test have not caused any background scrubbing -select ss.variable_name, gs.variable_value - ss.variable_value as variable_value -from snapshot_status ss, -information_schema.global_status gs -where ss.variable_name = gs.variable_name; -variable_name variable_value -INNODB_SCRUB_BACKGROUND_PAGE_REORGANIZATIONS 0 -INNODB_SCRUB_BACKGROUND_PAGE_SPLITS 0 -INNODB_SCRUB_BACKGROUND_PAGE_SPLIT_FAILURES_MISSING_INDEX 0 -INNODB_SCRUB_BACKGROUND_PAGE_SPLIT_FAILURES_OUT_OF_FILESPACE 0 -INNODB_SCRUB_BACKGROUND_PAGE_SPLIT_FAILURES_UNDERFLOW 0 -INNODB_SCRUB_BACKGROUND_PAGE_SPLIT_FAILURES_UNKNOWN 0 -drop table snapshot_status; diff --git a/mysql-test/suite/encryption/r/innodb_scrub_background.result b/mysql-test/suite/encryption/r/innodb_scrub_background.result deleted file mode 100644 index 6a2f263d0a1..00000000000 --- a/mysql-test/suite/encryption/r/innodb_scrub_background.result +++ /dev/null @@ -1,160 +0,0 @@ -# -# immediate scrubbing is off -# background scrubbing is on -# -show variables like 'innodb_%scrub_data%'; -Variable_name Value -innodb_background_scrub_data_check_interval 3600 -innodb_background_scrub_data_compressed ON -innodb_background_scrub_data_interval 604800 -innodb_background_scrub_data_uncompressed ON -innodb_immediate_scrub_data_uncompressed OFF -# make sure spaces are checked quickly -SET GLOBAL innodb_background_scrub_data_check_interval=1; -create table delete_3 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compressed; -# Populate table with rows -delete from delete_3; -create table delete_rollback_delete_3 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compressed; -# Populate table with rows -begin; -delete from delete_rollback_delete_3; -rollback; -delete from delete_rollback_delete_3; -create table insert_rollback_3 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compressed; -# Populate table with rows -begin; -rollback; -create table delete_2 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compact; -# Populate table with rows -delete from delete_2; -create table delete_rollback_delete_2 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compact; -# Populate table with rows -begin; -delete from delete_rollback_delete_2; -rollback; -delete from delete_rollback_delete_2; -create table insert_rollback_2 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=compact; -# Populate table with rows -begin; -rollback; -create table delete_1 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=redundant; -# Populate table with rows -delete from delete_1; -create table delete_rollback_delete_1 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=redundant; -# Populate table with rows -begin; -delete from delete_rollback_delete_1; -rollback; -delete from delete_rollback_delete_1; -create table insert_rollback_1 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=redundant; -# Populate table with rows -begin; -rollback; -create table delete_0 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=dynamic; -# Populate table with rows -delete from delete_0; -create table delete_rollback_delete_0 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=dynamic; -# Populate table with rows -begin; -delete from delete_rollback_delete_0; -rollback; -delete from delete_rollback_delete_0; -create table insert_rollback_0 ( -a int auto_increment primary key, -b varchar(256), -c text, -index(b)) engine = innodb row_format=dynamic; -# Populate table with rows -begin; -rollback; -# start scrubbing threads -SET GLOBAL innodb_encryption_threads=5; -# Wait max 10 min for scrubbing -SET GLOBAL innodb_fast_shutdown=0; -# delete_3.ibd -# delete_rollback_delete_3.ibd -# insert_rollback_3.ibd -# delete_2.ibd -# delete_rollback_delete_2.ibd -# insert_rollback_2.ibd -# delete_1.ibd -# delete_rollback_delete_1.ibd -# insert_rollback_1.ibd -# delete_0.ibd -# delete_rollback_delete_0.ibd -# insert_rollback_0.ibd -check table delete_3, delete_rollback_delete_3, insert_rollback_3; -Table Op Msg_type Msg_text -test.delete_3 check status OK -test.delete_rollback_delete_3 check status OK -test.insert_rollback_3 check status OK -drop table delete_3, delete_rollback_delete_3, insert_rollback_3; -check table delete_2, delete_rollback_delete_2, insert_rollback_2; -Table Op Msg_type Msg_text -test.delete_2 check status OK -test.delete_rollback_delete_2 check status OK -test.insert_rollback_2 check status OK -drop table delete_2, delete_rollback_delete_2, insert_rollback_2; -check table delete_1, delete_rollback_delete_1, insert_rollback_1; -Table Op Msg_type Msg_text -test.delete_1 check status OK -test.delete_rollback_delete_1 check status OK -test.insert_rollback_1 check status OK -drop table delete_1, delete_rollback_delete_1, insert_rollback_1; -check table delete_0, delete_rollback_delete_0, insert_rollback_0; -Table Op Msg_type Msg_text -test.delete_0 check status OK -test.delete_rollback_delete_0 check status OK -test.insert_rollback_0 check status OK -drop table delete_0, delete_rollback_delete_0, insert_rollback_0; -show variables like 'innodb_%scrub_data%'; -Variable_name Value -innodb_background_scrub_data_check_interval 3600 -innodb_background_scrub_data_compressed ON -innodb_background_scrub_data_interval 604800 -innodb_background_scrub_data_uncompressed ON -innodb_immediate_scrub_data_uncompressed OFF diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result new file mode 100644 index 00000000000..d08cb33e0fc --- /dev/null +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -0,0 +1,18 @@ +# +# Tests when the temporary files are encrypted +# +select @@encrypt_tmp_files; +@@encrypt_tmp_files +1 +# +# MDEV-22556: Incorrect result for window function when using encrypt-tmp-files=ON +# +set @save_sort_buffer_size=@@sort_buffer_size; +set sort_buffer_size= 2000; +create table t1( a DECIMAL(12,0) DEFAULT NULL, b VARCHAR(20) DEFAULT NULL, c DECIMAL(12,0) DEFAULT NULL)engine=INNODB; +insert into t1 select seq, seq, seq from seq_1_to_5000; +select count(*) from (select a, b, c, ROW_NUMBER() OVER (PARTITION BY a) FROM t1)q; +count(*) +5000 +set @@sort_buffer_size=@save_sort_buffer_size; +drop table t1; diff --git a/mysql-test/suite/encryption/t/corrupted_during_recovery.test b/mysql-test/suite/encryption/t/corrupted_during_recovery.test index 7e13168e759..48445ccb08b 100644 --- a/mysql-test/suite/encryption/t/corrupted_during_recovery.test +++ b/mysql-test/suite/encryption/t/corrupted_during_recovery.test @@ -5,8 +5,8 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page"); -call mtr.add_suppression("InnoDB: Failed to read file '.*test.t1\\.ibd' at offset 3: Table is encrypted but decrypt failed"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); +call mtr.add_suppression("InnoDB: Failed to read page [123] from file '.*test.t1\\.ibd': Table is encrypted but decrypt failed"); call mtr.add_suppression("InnoDB: The page \\[page id: space=\\d+, page number=3\\] in file '.*test.t1\\.ibd' cannot be decrypted"); call mtr.add_suppression("InnoDB: Table in tablespace \\d+ encrypted. However key management plugin or used key_version \\d+ is not found or used encryption algorithm or method does not match. Can't continue opening the table."); --enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test index 50f81deb462..09ad7a7d5a3 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test @@ -9,11 +9,11 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); -call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'"); +call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); # for innodb_checksum_algorithm=full_crc32 only diff --git a/mysql-test/suite/encryption/t/innodb_encryption_tables.test b/mysql-test/suite/encryption/t/innodb_encryption_tables.test index bc762faf12e..d03bc890ba4 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_tables.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_tables.test @@ -1,6 +1,8 @@ -- source include/have_innodb.inc -- source include/have_example_key_management_plugin.inc -- source include/not_embedded.inc +# We can't run this test under valgrind as it 'takes forever' +-- source include/not_valgrind.inc create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact; diff --git a/mysql-test/suite/encryption/t/innodb_scrub.opt b/mysql-test/suite/encryption/t/innodb_scrub.opt deleted file mode 100644 index ef43b2a20a8..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub.opt +++ /dev/null @@ -1,7 +0,0 @@ ---innodb-background-scrub-data-compressed=OFF ---innodb-background-scrub-data-uncompressed=OFF ---innodb-encrypt-tables=OFF ---innodb-encryption-threads=0 ---innodb-immediate-scrub-data-uncompressed=ON ---loose-innodb-debug-force-scrubbing=ON ---innodb-tablespaces-scrubbing diff --git a/mysql-test/suite/encryption/t/innodb_scrub.test b/mysql-test/suite/encryption/t/innodb_scrub.test deleted file mode 100644 index 3288ae9ce1c..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub.test +++ /dev/null @@ -1,147 +0,0 @@ --- source include/have_innodb.inc --- source include/not_embedded.inc --- source include/have_example_key_management_plugin.inc - -let $MYSQLD_DATADIR=`select @@datadir`; -let INNODB_PAGE_SIZE= `select @@innodb_page_size`; - -create table snapshot_status engine = myisam -select * from information_schema.global_status -where variable_name like 'innodb_scrub_background%'; - -let $rowcount=500; -let $maxformatno= 4; -let $formatno= $maxformatno; - ---echo # MDEV-8139 Fix scrubbing tests ---echo # FIXME: Add index(b) to each table; ensure that undo logs are scrubbed. -let $tableformat= ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format; - -while ($formatno) -{ -dec $formatno; -let $format = `select case $formatno - when 0 then 'dynamic' - when 1 then 'redundant' - when 2 then 'compact' - when 3 then 'compressed' - end`; - -let $t= delete_$formatno; -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; ---disable_query_log -begin; -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('repairman', repeat('unicycle', 1000)); -} -commit; ---enable_query_log - -eval delete from $t; - -let $t= delete_rollback_delete_$formatno; -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; ---disable_query_log -begin; -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('breakhuman', repeat('bicycle', 1000)); -} -commit; ---enable_query_log - -begin; -eval delete from $t; -rollback; -eval delete from $t; - -let $t= insert_rollback_$formatno; - -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; -begin; ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('wonderwoman', repeat('tricycle', 1000)); -} ---enable_query_log - -rollback; -} - -SET GLOBAL innodb_fast_shutdown=0; --- source include/shutdown_mysqld.inc - -let SEARCH_ABORT= FOUND; -let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man; -let SEARCH_RANGE= 12582912; -let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1; - -# We may randomly find copies of unscrubbed pages in the doublewrite buffer. -# Let us scrub the doublewrite buffer ourselves. -perl; -use Fcntl 'SEEK_SET'; -my $page_size = $ENV{INNODB_PAGE_SIZE}; -open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n"; -seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n"; -print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n"; -close FILE or die "cannot close: $!\n";; -EOF - --- source include/search_pattern_in_file.inc - -let $formatno= $maxformatno; -while ($formatno) -{ -dec $formatno; - -let $t= delete_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -let $t= delete_rollback_delete_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -let $t= insert_rollback_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -} - --- source include/start_mysqld.inc - -let $formatno= $maxformatno; -while ($formatno) -{ -dec $formatno; - -let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno; - -eval check table $t; -eval drop table $t; -} - -show variables like 'innodb_%scrub_data%'; - ---echo # verify that this test have not caused any background scrubbing ---sorted_result -select ss.variable_name, gs.variable_value - ss.variable_value as variable_value -from snapshot_status ss, - information_schema.global_status gs -where ss.variable_name = gs.variable_name; - -drop table snapshot_status; diff --git a/mysql-test/suite/encryption/t/innodb_scrub_background.opt b/mysql-test/suite/encryption/t/innodb_scrub_background.opt deleted file mode 100644 index 04987f4a3ad..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub_background.opt +++ /dev/null @@ -1,7 +0,0 @@ ---innodb-immediate-scrub-data-uncompressed=OFF ---innodb-background-scrub-data-uncompressed=ON ---innodb-background-scrub-data-compressed=ON ---loose-innodb-debug-force-scrubbing=ON ---innodb-encryption-threads=0 ---innodb-encrypt-tables=OFF ---innodb-tablespaces-scrubbing diff --git a/mysql-test/suite/encryption/t/innodb_scrub_background.test b/mysql-test/suite/encryption/t/innodb_scrub_background.test deleted file mode 100644 index 3843e9d16eb..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub_background.test +++ /dev/null @@ -1,170 +0,0 @@ --- source include/have_innodb.inc --- source include/not_embedded.inc --- source include/have_example_key_management_plugin.inc - -let $MYSQLD_DATADIR=`select @@datadir`; -let INNODB_PAGE_SIZE= `select @@innodb_page_size`; - ---echo # ---echo # immediate scrubbing is off ---echo # background scrubbing is on ---echo # -show variables like 'innodb_%scrub_data%'; - --- echo # make sure spaces are checked quickly -SET GLOBAL innodb_background_scrub_data_check_interval=1; - -let $rowcount=500; -let $maxformatno= 4; -let $formatno= $maxformatno; - -let $tableformat= ( - a int auto_increment primary key, - b varchar(256), - c text, - index(b)) engine = innodb row_format; - -while ($formatno) -{ -dec $formatno; -let $format = `select case $formatno - when 0 then 'dynamic' - when 1 then 'redundant' - when 2 then 'compact' - when 3 then 'compressed' - end`; - -let $t= delete_$formatno; -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -begin; -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('unicycle', repeat('wonderwoman', 1000)); -} -commit; ---enable_query_log - -eval delete from $t; - -let $t= delete_rollback_delete_$formatno; - -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -begin; -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('bicycle', repeat('repairman', 1000)); -} -commit; ---enable_query_log - -begin; -eval delete from $t; -rollback; -eval delete from $t; - -let $t= insert_rollback_$formatno; - -eval create table $t $tableformat=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows -begin; ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - eval insert into $t(b,c) values ('tricycle', repeat('superhuman', 1000)); -} ---enable_query_log - -rollback; -} - --- echo # start scrubbing threads -SET GLOBAL innodb_encryption_threads=5; --- echo # Wait max 10 min for scrubbing -let $cnt=600; -while ($cnt) -{ - let $success=`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING WHERE LAST_SCRUB_COMPLETED IS NULL AND (NAME LIKE 'test/%' OR SPACE = 0)`; - if ($success) - { - let $cnt=0; - } - if (!$success) - { - real_sleep 1; - dec $cnt; - } -} -if (!$success) -{ - SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING; - SHOW STATUS LIKE 'innodb_%scrub%'; - -- die Timeout waiting for background threads -} - -SET GLOBAL innodb_fast_shutdown=0; --- source include/shutdown_mysqld.inc - -let SEARCH_ABORT= FOUND; -let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man; -let SEARCH_RANGE= 12582912; -let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1; - -# We may randomly find copies of unscrubbed pages in the doublewrite buffer. -# Let us scrub the doublewrite buffer ourselves. -perl; -use Fcntl 'SEEK_SET'; -my $page_size = $ENV{INNODB_PAGE_SIZE}; -open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n"; -seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n"; -print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n"; -close FILE or die "cannot close: $!\n";; -EOF - --- source include/search_pattern_in_file.inc - -let $formatno= $maxformatno; -while ($formatno) -{ -dec $formatno; - -let $t= delete_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -let $t= delete_rollback_delete_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -let $t= insert_rollback_$formatno.ibd; -let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; --- echo # $t --- source include/search_pattern_in_file.inc -} - --- source include/start_mysqld.inc - -let $formatno= $maxformatno; -while ($formatno) -{ -dec $formatno; - -let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno; - -eval check table $t; -eval drop table $t; -} - -show variables like 'innodb_%scrub_data%'; diff --git a/mysql-test/suite/encryption/t/tempfiles_encrypted.opt b/mysql-test/suite/encryption/t/tempfiles_encrypted.opt new file mode 100644 index 00000000000..81877a8d1c5 --- /dev/null +++ b/mysql-test/suite/encryption/t/tempfiles_encrypted.opt @@ -0,0 +1 @@ +--encrypt-tmp_files=ON diff --git a/mysql-test/suite/encryption/t/tempfiles_encrypted.test b/mysql-test/suite/encryption/t/tempfiles_encrypted.test new file mode 100644 index 00000000000..96b981c1c06 --- /dev/null +++ b/mysql-test/suite/encryption/t/tempfiles_encrypted.test @@ -0,0 +1,23 @@ +--echo # +--echo # Tests when the temporary files are encrypted +--echo # + +source include/have_file_key_management_plugin.inc; +source include/have_sequence.inc; +source include/have_innodb.inc; + +select @@encrypt_tmp_files; + +--echo # +--echo # MDEV-22556: Incorrect result for window function when using encrypt-tmp-files=ON +--echo # + +set @save_sort_buffer_size=@@sort_buffer_size; +set sort_buffer_size= 2000; +create table t1( a DECIMAL(12,0) DEFAULT NULL, b VARCHAR(20) DEFAULT NULL, c DECIMAL(12,0) DEFAULT NULL)engine=INNODB; +insert into t1 select seq, seq, seq from seq_1_to_5000; +select count(*) from (select a, b, c, ROW_NUMBER() OVER (PARTITION BY a) FROM t1)q; + +set @@sort_buffer_size=@save_sort_buffer_size; + +drop table t1; diff --git a/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result b/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result index fdd1a4be290..4b1ffc9045b 100644 Binary files a/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result and b/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result differ diff --git a/mysql-test/suite/engines/iuds/r/strings_update_delete.result b/mysql-test/suite/engines/iuds/r/strings_update_delete.result index 56dd0cf4d12..708d2811bf8 100644 --- a/mysql-test/suite/engines/iuds/r/strings_update_delete.result +++ b/mysql-test/suite/engines/iuds/r/strings_update_delete.result @@ -70472,17 +70472,4 @@ SIZE DROP TABLE t17,t18; DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18; Warnings: -Note 1051 Unknown table 'test.t3' -Note 1051 Unknown table 'test.t4' -Note 1051 Unknown table 'test.t5' -Note 1051 Unknown table 'test.t6' -Note 1051 Unknown table 'test.t7' -Note 1051 Unknown table 'test.t8' -Note 1051 Unknown table 'test.t9' -Note 1051 Unknown table 'test.t10' -Note 1051 Unknown table 'test.t11' -Note 1051 Unknown table 'test.t13' -Note 1051 Unknown table 'test.t14' -Note 1051 Unknown table 'test.t15' -Note 1051 Unknown table 'test.t17' -Note 1051 Unknown table 'test.t18' +Note 1051 Unknown table 'test.t3,test.t4,test.t5,test.t6,test.t7,test.t8,test.t9,test.t10,test.t11,test.t13,test.t14,test....' diff --git a/mysql-test/suite/engines/iuds/r/type_bit_iuds.result b/mysql-test/suite/engines/iuds/r/type_bit_iuds.result index 2c84abfd49d..93ed7a9f162 100644 --- a/mysql-test/suite/engines/iuds/r/type_bit_iuds.result +++ b/mysql-test/suite/engines/iuds/r/type_bit_iuds.result @@ -56209,9 +56209,9 @@ SELECT 0 + b'101010101010101010101010101010'; 715827882 SELECT 0 + (101010101010101010101010101010<<0); 0 + (101010101010101010101010101010<<0) -9223372036854775807 +18446744073709551615 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(0)); CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0)); INSERT IGNORE INTO t1 VALUES (b'101010101010101010101010101010'); @@ -57001,7 +57001,7 @@ SELECT 0 + (101010101010101010101010101010<<1); 0 + (101010101010101010101010101010<<1) 18446744073709551614 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(1)); CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1)); set @v1=1; @@ -57840,7 +57840,7 @@ SELECT 0 + (101010101010101010101010101010<<2); 0 + (101010101010101010101010101010<<2) 18446744073709551612 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(2)); CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2)); set @v1=2; @@ -58698,7 +58698,7 @@ SELECT 0 + (101010101010101010101010101010<<4); 0 + (101010101010101010101010101010<<4) 18446744073709551600 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(4)); CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4)); set @v1=4; @@ -59620,7 +59620,7 @@ SELECT 0 + (101010101010101010101010101010<<8); 0 + (101010101010101010101010101010<<8) 18446744073709551360 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(8)); CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8)); set @v1=8; @@ -60827,7 +60827,7 @@ SELECT 0 + (101010101010101010101010101010<<16); 0 + (101010101010101010101010101010<<16) 18446744073709486080 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(16)); CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16)); set @v1=16; @@ -62239,7 +62239,7 @@ SELECT 0 + (101010101010101010101010101010<<32); 0 + (101010101010101010101010101010<<32) 18446744069414584320 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(32)); CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32)); set @v1=32; @@ -64312,7 +64312,7 @@ SELECT 0 + (101010101010101010101010101010<<64); 0 + (101010101010101010101010101010<<64) 0 Warnings: -Warning 1916 Got overflow when converting '101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(64)); CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64)); set @v1=64; @@ -67487,9 +67487,9 @@ Warnings: Note 1051 Unknown table 'test.t3' SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<0); 0 + (1010101010101010101010101010101010101010101010101010101010101010<<0) -9223372036854775807 +18446744073709551615 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(0)); CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0)); INSERT IGNORE INTO t1 VALUES (b'1010101010101010101010101010101010101010101010101010101010101010'); @@ -68276,7 +68276,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<1) 0 + (1010101010101010101010101010101010101010101010101010101010101010<<1) 18446744073709551614 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(1)); CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1)); set @v1=1; @@ -69112,7 +69112,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<2) 0 + (1010101010101010101010101010101010101010101010101010101010101010<<2) 18446744073709551612 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(2)); CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2)); set @v1=2; @@ -69967,7 +69967,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<4) 0 + (1010101010101010101010101010101010101010101010101010101010101010<<4) 18446744073709551600 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(4)); CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4)); set @v1=4; @@ -70886,7 +70886,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<8) 0 + (1010101010101010101010101010101010101010101010101010101010101010<<8) 18446744073709551360 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(8)); CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8)); set @v1=8; @@ -72090,7 +72090,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<16 0 + (1010101010101010101010101010101010101010101010101010101010101010<<16) 18446744073709486080 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(16)); CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16)); set @v1=16; @@ -73499,7 +73499,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<32 0 + (1010101010101010101010101010101010101010101010101010101010101010<<32) 18446744069414584320 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(32)); CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32)); set @v1=32; @@ -75575,7 +75575,7 @@ SELECT 0 + (1010101010101010101010101010101010101010101010101010101010101010<<64 0 + (1010101010101010101010101010101010101010101010101010101010101010<<64) 0 Warnings: -Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to INT. Value truncated +Warning 1916 Got overflow when converting '1010101010101010101010101010101010101010101010101010101010101010' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(64)); CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64)); set @v1=64; @@ -78750,9 +78750,9 @@ Warnings: Note 1051 Unknown table 'test.t3' SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<0); 0 + (10101010101010101010101010101010101010101010101010101010101010101<<0) -9223372036854775807 +18446744073709551615 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(0)); CREATE TABLE t2(c1 BIT(0), c2 BIT(0), c3 BIT(0)); INSERT IGNORE INTO t1 VALUES (b'10101010101010101010101010101010101010101010101010101010101010101'); @@ -79539,7 +79539,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<1 0 + (10101010101010101010101010101010101010101010101010101010101010101<<1) 18446744073709551614 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(1)); CREATE TABLE t2(c1 BIT(1), c2 BIT(1), c3 BIT(1)); set @v1=1; @@ -80375,7 +80375,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<2 0 + (10101010101010101010101010101010101010101010101010101010101010101<<2) 18446744073709551612 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(2)); CREATE TABLE t2(c1 BIT(2), c2 BIT(2), c3 BIT(2)); set @v1=2; @@ -81230,7 +81230,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<4 0 + (10101010101010101010101010101010101010101010101010101010101010101<<4) 18446744073709551600 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(4)); CREATE TABLE t2(c1 BIT(4), c2 BIT(4), c3 BIT(4)); set @v1=4; @@ -82149,7 +82149,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<8 0 + (10101010101010101010101010101010101010101010101010101010101010101<<8) 18446744073709551360 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(8)); CREATE TABLE t2(c1 BIT(8), c2 BIT(8), c3 BIT(8)); set @v1=8; @@ -83353,7 +83353,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<1 0 + (10101010101010101010101010101010101010101010101010101010101010101<<16) 18446744073709486080 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(16)); CREATE TABLE t2(c1 BIT(16), c2 BIT(16), c3 BIT(16)); set @v1=16; @@ -84762,7 +84762,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<3 0 + (10101010101010101010101010101010101010101010101010101010101010101<<32) 18446744069414584320 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(32)); CREATE TABLE t2(c1 BIT(32), c2 BIT(32), c3 BIT(32)); set @v1=32; @@ -86838,7 +86838,7 @@ SELECT 0 + (10101010101010101010101010101010101010101010101010101010101010101<<6 0 + (10101010101010101010101010101010101010101010101010101010101010101<<64) 0 Warnings: -Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to INT. Value truncated +Warning 1916 Got overflow when converting '10101010101010101010101010101010101010101010101010101010101010101' to UNSIGNED INT. Value truncated CREATE TABLE t1(c1 BIT(64)); CREATE TABLE t2(c1 BIT(64), c2 BIT(64), c3 BIT(64)); set @v1=64; diff --git a/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl b/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl index f277bce018e..e997f479466 100755 --- a/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl +++ b/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ################################################################################ # # This script runs the transactional stress test "stress_tx_rr" against the diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index 90a5234a02f..7a407d8aeef 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -209,7 +209,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 7 1 PRIMARY ref key0 key0 18 federated.t3.name 2 2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL -3 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 Using temporary ANALYZE FORMAT=JSON SELECT * FROM federated.t3, (SELECT t1.name FROM federated.t1 @@ -253,25 +252,7 @@ ANALYZE "select_id": 2, "table": { "message": "Pushed derived" - }, - "subqueries": [ - { - "query_block": { - "select_id": 3, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "r_loops": 0, - "rows": 7, - "r_rows": null, - "filtered": 100, - "r_filtered": null - } - } - } - } - ] + } } } } @@ -321,6 +302,78 @@ select @var; @var xxx select name into outfile 'tmp.txt' from federated.t1; +# +# MDEV-22993: Crash on EXPLAIN with PUSHED DOWN SELECT and subquery +# +explain +select * from federated.t1 +where name in (select name from federated.t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL +explain format=json +select * from federated.t1 +where name in (select name from federated.t2); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Pushed select" + } + } +} +# +# MDEV-22993, testcase #2: EXPLAIN output doesn't make sense when +# derived table pushdown is used. +# +create table t5 (a int) engine=myisam; +insert into t5 values (1),(2); +# Must not show lines with id=3 +explain +select * from t5, +(select id from federated.t1 +where name in (select name from federated.t2) or name like 'foo%') as TQ; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t5 ALL NULL NULL NULL NULL 2 +1 PRIMARY ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join) +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL +# Must not show elements with select_id=3 +explain format=json +select * from t5, +(select id from federated.t1 +where name in (select name from federated.t2) or name like 'foo%') as TQ; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t5", + "access_type": "ALL", + "rows": 2, + "filtered": 100 + }, + "block-nl-join": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + }, + "buffer_type": "flat", + "buffer_size": "65", + "join_type": "BNL", + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "message": "Pushed derived" + } + } + } + } + } +} +drop table t5; DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4; connection slave; DROP TABLE federated.t1, federated.t2; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index 42a03e60d67..d765588b79b 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -167,6 +167,40 @@ select name into outfile 'tmp.txt' from federated.t1; let $path=`select concat(@@datadir, 'test/tmp.txt')`; remove_file $path; +--echo # +--echo # MDEV-22993: Crash on EXPLAIN with PUSHED DOWN SELECT and subquery +--echo # + +explain +select * from federated.t1 +where name in (select name from federated.t2); + +explain format=json +select * from federated.t1 +where name in (select name from federated.t2); + +--echo # +--echo # MDEV-22993, testcase #2: EXPLAIN output doesn't make sense when +--echo # derived table pushdown is used. +--echo # + +create table t5 (a int) engine=myisam; +insert into t5 values (1),(2); + +--echo # Must not show lines with id=3 +explain +select * from t5, +(select id from federated.t1 + where name in (select name from federated.t2) or name like 'foo%') as TQ; + +--echo # Must not show elements with select_id=3 +explain format=json +select * from t5, +(select id from federated.t1 + where name in (select name from federated.t2) or name like 'foo%') as TQ; + +drop table t5; + DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4; connection slave; diff --git a/mysql-test/suite/federated/federatedx_versioning.result b/mysql-test/suite/federated/federatedx_versioning.result index abf2658d2e2..be3b578e839 100644 --- a/mysql-test/suite/federated/federatedx_versioning.result +++ b/mysql-test/suite/federated/federatedx_versioning.result @@ -9,8 +9,8 @@ show create table tf; Table Create Table tf CREATE TABLE `tf` ( `x` int(11) DEFAULT NULL, - `row_start` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0, - `row_end` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0 + `row_start` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000', + `row_end` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000' ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:MASTER_MYPORT/test/t1' # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/federated/federatedx_versioning.test b/mysql-test/suite/federated/federatedx_versioning.test index e8db8ef9e2a..6c3247cea55 100644 --- a/mysql-test/suite/federated/federatedx_versioning.test +++ b/mysql-test/suite/federated/federatedx_versioning.test @@ -12,7 +12,7 @@ eval create or replace table t1 ( with system versioning; --replace_result $MASTER_MYPORT MASTER_MYPORT eval create or replace table tf engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1'; ---replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE "'0000-00-00 00:00:00.000000'" 0 +--replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE 19710101000000 "'1971-01-01 00:00:00.000000'" " NOT NULL" "" show create table tf; --echo # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/funcs_1/lib/DataGen_local.pl b/mysql-test/suite/funcs_1/lib/DataGen_local.pl index 738a73e0fd5..8ca74407141 100755 --- a/mysql-test/suite/funcs_1/lib/DataGen_local.pl +++ b/mysql-test/suite/funcs_1/lib/DataGen_local.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl if ( (scalar(@ARGV) != 1 ) || ($ARGV[0] =~ /[^0-9]/i ) ) diff --git a/mysql-test/suite/funcs_1/lib/DataGen_modify.pl b/mysql-test/suite/funcs_1/lib/DataGen_modify.pl index 4675049ff0d..8ad8e619a20 100755 --- a/mysql-test/suite/funcs_1/lib/DataGen_modify.pl +++ b/mysql-test/suite/funcs_1/lib/DataGen_modify.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl if ( (scalar(@ARGV) != 2 ) || ($ARGV[0] =~ /[^0-9]/i ) ) diff --git a/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl b/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl index 3b85ed02f5b..c0973a10950 100755 --- a/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl +++ b/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ################################################################################# # Author: Serge Kozlov # diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index e1868260af1..e4244c63297 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -15,8 +15,6 @@ GCF-939 : MDEV-21520 galera.GCF-939 MDEV-16509 : MDEV-21523 galera.MDEV-16509 MDEV-20225 : MDEV-20886 galera.MDEV-20225 MW-286 : MDEV-18464 Killing thread can cause mutex deadlock if done concurrently with Galera/replication victim kill -MW-328A : MDEV-21483 galera.MW-328A galera.MW-328B -MW-328B : MDEV-21483 galera.MW-328A galera.MW-328B MW-329 : MDEV-19962 Galera test failure on MW-329 galera.galera_defaults : MDEV-21494 Galera test sporadic failure on galera.galera_defaults galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() @@ -39,7 +37,7 @@ galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and ga galera_ssl_upgrade : MDEV-19950 Galera test failure on galera_ssl_upgrade galera_sst_mariabackup_encrypt_with_key : MDEV-21484 galera_sst_mariabackup_encrypt_with_key galera_toi_ddl_nonconflicting : MDEV-21518 galera.galera_toi_ddl_nonconflicting -galera_var_innodb_disallow_writes : MDEV-20928 galera.galera_var_innodb_disallow_writes +galera_toi_truncate : MDEV-22996 Hang on galera_toi_truncate test case galera_var_node_address : MDEV-20485 Galera test failure galera_var_notify_cmd : MDEV-21905 Galera test galera_var_notify_cmd causes hang galera_var_reject_queries : assertion in inline_mysql_socket_send diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf index c84c4b25d2a..4181ee13ebc 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -19,6 +19,7 @@ innodb_lock_schedule_algorithm=FCFS wsrep-on=1 log-slave-updates +wsrep-on=1 innodb-autoinc-lock-mode=2 default-storage-engine=innodb @@ -44,6 +45,7 @@ innodb_lock_schedule_algorithm=FCFS wsrep-on=1 log-slave-updates +wsrep-on=1 innodb-autoinc-lock-mode=2 default-storage-engine=innodb @@ -69,6 +71,7 @@ innodb_lock_schedule_algorithm=FCFS wsrep-on=1 log-slave-updates +wsrep-on=1 innodb-autoinc-lock-mode=2 default-storage-engine=innodb diff --git a/mysql-test/suite/galera/r/MW-328C.result b/mysql-test/suite/galera/r/MW-328C.result new file mode 100644 index 00000000000..7a00bb718de --- /dev/null +++ b/mysql-test/suite/galera/r/MW-328C.result @@ -0,0 +1,25 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; +INSERT INTO t1 (f1) VALUES (1); +CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; +CREATE PROCEDURE proc_update () +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; +SET SESSION wsrep_sync_wait = 0; +WHILE 1 DO +UPDATE t1 SET f2 = LEFT(MD5(RAND()), 4); +END WHILE; +END| +connect node_1X, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1X; +CALL proc_update();; +connection node_2; +SET SESSION wsrep_retry_autocommit = 10000; +connection node_1; +connection node_1X; +Got one of the listed errors +connection node_1; +DROP PROCEDURE proc_update; +DROP TABLE t1, t2; +CALL mtr.add_suppression("conflict state ABORTED after post commit"); diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid.result b/mysql-test/suite/galera/r/galera_as_slave_gtid.result index 3f4137a3b28..41d9085ccac 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result @@ -9,6 +9,7 @@ INSERT INTO t1 VALUES(1); SELECT LENGTH(@@global.gtid_binlog_state) > 1; LENGTH(@@global.gtid_binlog_state) > 1 1 +connection node_1; connection node_2; gtid_binlog_state_equal 1 diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_auto_engine.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_auto_engine.result index 6c84c1ecd31..cff5bb0a5d0 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid_auto_engine.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_auto_engine.result @@ -9,6 +9,7 @@ INSERT INTO t1 VALUES(1); SELECT LENGTH(@@global.gtid_binlog_state) > 1; LENGTH(@@global.gtid_binlog_state) > 1 1 +connection node_1; connection node_2; gtid_binlog_state_equal 1 diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result index 7e8da675ad4..b498f334bf8 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result @@ -31,7 +31,6 @@ DROP TABLE t1; connection node_1; connection node_2; connection node_3; -connection node_3; RESET MASTER; connection node_1; STOP SLAVE; @@ -43,3 +42,5 @@ connection node_2; SET GLOBAL WSREP_ON=OFF; reset master; SET GLOBAL WSREP_ON=ON; +connection node_3; +RESET MASTER; diff --git a/mysql-test/suite/galera/r/galera_bf_kill.result b/mysql-test/suite/galera/r/galera_bf_kill.result new file mode 100644 index 00000000000..2a7bc9eac29 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_kill.result @@ -0,0 +1,89 @@ +connection node_2; +connection node_1; +connection node_2; +CREATE TABLE t1(a int not null primary key auto_increment,b int) engine=InnoDB; +insert into t1 values (NULL,1); +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +begin; +update t1 set a = 5; +connection node_2; +select * from t1; +a b +2 1 +disconnect node_2a; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +begin; +update t1 set a =5; +connection node_2; +select * from t1; +a b +2 1 +disconnect node_2a; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +begin; +update t1 set a =5, b=2; +connection node_2; +ALTER TABLE t1 ADD UNIQUE KEY b1(b); +ALTER TABLE t1 DROP KEY b1; +select * from t1; +a b +2 1 +disconnect node_2a; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +begin; +update t1 set a =5, b=2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2b; +begin; +update t1 set a =6, b=7; +connection node_2; +ALTER TABLE t1 ADD UNIQUE KEY b2(b); +ALTER TABLE t1 DROP KEY b2; +select * from t1; +a b +2 1 +disconnect node_2a; +disconnect node_2b; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +SET SESSION wsrep_on=OFF; +begin; +update t1 set a =5, b=2; +connection node_2; +ALTER TABLE t1 ADD UNIQUE KEY b3(b); +select * from t1; +a b +2 1 +disconnect node_2a; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +SET SESSION wsrep_on=OFF; +begin; +update t1 set a =5, b=2; +connection node_2; +select * from t1; +a b +2 1 +disconnect node_2a; +drop table t1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +CREATE TABLE t1 (i int primary key); +SET DEBUG_SYNC = "before_wsrep_ordered_commit SIGNAL bwoc_reached WAIT_FOR bwoc_continue"; +INSERT INTO t1 VALUES (1); +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR bwoc_reached"; +SET DEBUG_SYNC = "now SIGNAL bwoc_continue"; +SET DEBUG_SYNC='RESET'; +connection node_2a; +connection node_2; +select * from t1; +i +1 +disconnect node_2a; +connection node_2; +drop table t1; diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result index f893848a72d..71627d11a4e 100644 --- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result +++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result @@ -1,5 +1,7 @@ connection node_2; connection node_1; +connection node_1; +call mtr.add_suppression("WSREP: Trying to continue unpaused monitor"); CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2; ALTER TABLE t1 add primary key(a); CREATE PROCEDURE p1() @@ -19,7 +21,7 @@ connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2; call p1; connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2; call p1; -connection default; +connection node_1; checking error log for 'BF lock wait long' message for 10 times every 10 seconds ... drop table t1; drop procedure p1; diff --git a/mysql-test/suite/galera/r/galera_drop_database.result b/mysql-test/suite/galera/r/galera_drop_database.result index ac76683cb25..6ab4b3d0c7b 100644 --- a/mysql-test/suite/galera/r/galera_drop_database.result +++ b/mysql-test/suite/galera/r/galera_drop_database.result @@ -13,9 +13,33 @@ INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; DROP TABLE ten; UPDATE fts_t1 SET f2 = 'abcd'; UPDATE fts_t2 SET f2 = 'efjh'; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1 where f2 = 'abcd'; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2 where f2 = 'efjh'; +EXPECT_1000 +1000 connection node_2; connection node_1; connection node_2; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1 where f2 = 'abcd'; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2 where f2 = 'efjh'; +EXPECT_1000 +1000 connection node_1; USE fts; DROP TABLE fts_t1; @@ -23,3 +47,4 @@ DROP TABLE fts_t2; SHOW TABLES; Tables_in_fts DROP DATABASE fts; +connection node_2; diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result index 88cb6cacc07..e09e34274dd 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result @@ -18,6 +18,8 @@ COMMIT; SET current_num = current_num + 1; END WHILE; END| +call p1(1000); +connection node_1; connection node_1a; connection node_1b; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_slave_replay.result b/mysql-test/suite/galera/r/galera_slave_replay.result index e8dd6ae87b1..0b0199c4a02 100644 --- a/mysql-test/suite/galera/r/galera_slave_replay.result +++ b/mysql-test/suite/galera/r/galera_slave_replay.result @@ -4,9 +4,7 @@ connection node_2; connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; -SET GLOBAL wsrep_on=OFF; RESET MASTER; -SET GLOBAL wsrep_on=ON; connection node_2a; START SLAVE; connection node_3; @@ -72,20 +70,17 @@ SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE t1 SET f2 = 'd' WHERE f1 = 3; connection node_2a; -SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; -connection node_3; +connection node_1; UPDATE test.t1 SET f2 = 'e' WHERE f1 = 3; +connection node_2a; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_3; COMMIT; connection node_2a; SET GLOBAL debug_dbug = ""; SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; connection node_2a; -SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; -SET DEBUG_SYNC = "RESET"; -connection node_2a; set session wsrep_sync_wait=15; SELECT COUNT(*) = 1 FROM test.t1 WHERE f2 = 'e'; COUNT(*) = 1 @@ -93,9 +88,8 @@ COUNT(*) = 1 set session wsrep_sync_wait=0; STOP SLAVE; RESET SLAVE; +SET DEBUG_SYNC = "RESET"; DROP TABLE t1; connection node_3; DROP TABLE t1; -SET GLOBAL wsrep_on=OFF; RESET MASTER; -SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result index 081a82e6e7d..7db0f8abdb8 100644 --- a/mysql-test/suite/galera/r/galera_toi_truncate.result +++ b/mysql-test/suite/galera/r/galera_toi_truncate.result @@ -1,26 +1,24 @@ connection node_2; connection node_1; connection node_1; -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; connection node_2; SET SESSION wsrep_retry_autocommit = 0; -INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; -set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go'; -INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;; +INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8; connection node_1; TRUNCATE TABLE t1;; -connection node_1; connection node_2; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -connection node_2; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 connection node_1; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 +connection node_2; +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 +0 +connection node_1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 +0 DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result index f5ec473fea4..3eb56d1a48d 100644 --- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result +++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result @@ -1,5 +1,6 @@ connection node_2; connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; SET SESSION wsrep_sync_wait = 0; connection node_1; @@ -7,19 +8,20 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; SET GLOBAL innodb_disallow_writes=ON; INSERT INTO t1 VALUES (1);; connection node_1a; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 0 -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 0 SET GLOBAL innodb_disallow_writes=OFF; connection node_1; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 connection node_2; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; +disconnect node_1a; diff --git a/mysql-test/suite/galera/r/galera_vote_rejoin_ddl.result b/mysql-test/suite/galera/r/galera_vote_rejoin_ddl.result index fe98d403e13..6ad7ac75314 100644 --- a/mysql-test/suite/galera/r/galera_vote_rejoin_ddl.result +++ b/mysql-test/suite/galera/r/galera_vote_rejoin_ddl.result @@ -1,5 +1,7 @@ connection node_2; connection node_1; +connection node_1; +connection node_2; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; diff --git a/mysql-test/suite/galera/r/mysql-wsrep-bugs-607.result b/mysql-test/suite/galera/r/mysql-wsrep-bugs-607.result new file mode 100644 index 00000000000..9d9614ffefe --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep-bugs-607.result @@ -0,0 +1,31 @@ +connection node_2; +connection node_1; +# +# test the order of wsrep XID storage after certifiation failure +# +connection node_1; +set session wsrep_sync_wait=0; +create table t1 (i int primary key, j int); +insert into t1 values (4, 0); +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2b; +set session wsrep_sync_wait=0; +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; +connection node_1; +UPDATE test.t1 set j=1 where i=4; +connection node_2b; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_2; +set session wsrep_sync_wait=0; +set session wsrep_retry_autocommit=0; +UPDATE test.t1 SET j=2 WHERE i=4; +connection node_2b; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; +connection node_2; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +select * from t1; +i j +4 1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 4dd11f5d7a4..671fd1688c9 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -62,7 +62,8 @@ push @::global_suppressions, qr(WSREP: Ignoring error*), qr(WSREP: Failed to remove page file .*), qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), - qr(WSREP: .*Transport endpoint is not connected.*), + qr|WSREP: Sending JOIN failed: -107 \(Transport endpoint is not connected\). Will retry in new primary component.|, + qr|WSREP: Trying to continue unpaused monitor|, ); sub skip_combinations { diff --git a/mysql-test/suite/galera/t/MW-328A.cnf b/mysql-test/suite/galera/t/MW-328A.cnf index a10ea88bdf2..e68f891792c 100644 --- a/mysql-test/suite/galera/t/MW-328A.cnf +++ b/mysql-test/suite/galera/t/MW-328A.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld.1] -wsrep-debug=ON +wsrep-debug=SERVER [mysqld.2] -wsrep-debug=ON +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328B.cnf b/mysql-test/suite/galera/t/MW-328B.cnf index a10ea88bdf2..e68f891792c 100644 --- a/mysql-test/suite/galera/t/MW-328B.cnf +++ b/mysql-test/suite/galera/t/MW-328B.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld.1] -wsrep-debug=ON +wsrep-debug=SERVER [mysqld.2] -wsrep-debug=ON +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328C.cnf b/mysql-test/suite/galera/t/MW-328C.cnf new file mode 100644 index 00000000000..e68f891792c --- /dev/null +++ b/mysql-test/suite/galera/t/MW-328C.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=SERVER + +[mysqld.2] +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328C.test b/mysql-test/suite/galera/t/MW-328C.test new file mode 100644 index 00000000000..7241dfbdbca --- /dev/null +++ b/mysql-test/suite/galera/t/MW-328C.test @@ -0,0 +1,35 @@ +# +# MW-328 Fix unnecessary/silent BF aborts +# + +# +# Make sure that a high value of wsrep_retry_autocommit +# masks all deadlock errors +# + +--source include/galera_cluster.inc +--source suite/galera/t/MW-328-header.inc + +--connection node_2 +--let $count = 100 + +SET SESSION wsrep_retry_autocommit = 10000; + +--disable_query_log + +while ($count) +{ + --error 0 + INSERT IGNORE INTO t2 SELECT f2 FROM t1; + + --disable_result_log + --error 0 + SELECT 1 FROM DUAL; + --enable_result_log + + --dec $count +} + +--enable_query_log + +--source suite/galera/t/MW-328-footer.inc diff --git a/mysql-test/suite/galera/t/MW-328D.cnf b/mysql-test/suite/galera/t/MW-328D.cnf new file mode 100644 index 00000000000..e68f891792c --- /dev/null +++ b/mysql-test/suite/galera/t/MW-328D.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=SERVER + +[mysqld.2] +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328E.cnf b/mysql-test/suite/galera/t/MW-328E.cnf new file mode 100644 index 00000000000..e68f891792c --- /dev/null +++ b/mysql-test/suite/galera/t/MW-328E.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=SERVER + +[mysqld.2] +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-388.test b/mysql-test/suite/galera/t/MW-388.test index 09fc8a8bfc9..b88f53ca8d9 100644 --- a/mysql-test/suite/galera/t/MW-388.test +++ b/mysql-test/suite/galera/t/MW-388.test @@ -1,5 +1,7 @@ --source include/galera_cluster.inc +--source include/have_debug.inc --source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc --connection node_1 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB; diff --git a/mysql-test/suite/galera/t/MW-86-wait1.test b/mysql-test/suite/galera/t/MW-86-wait1.test index 4e99872bf4d..7ebd3ba95a0 100644 --- a/mysql-test/suite/galera/t/MW-86-wait1.test +++ b/mysql-test/suite/galera/t/MW-86-wait1.test @@ -7,6 +7,8 @@ --source include/have_binlog_format_row.inc --source include/have_debug.inc --source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + SET @orig_debug=@@debug_dbug; --connection node_2 diff --git a/mysql-test/suite/galera/t/MW-86-wait8.test b/mysql-test/suite/galera/t/MW-86-wait8.test index 7d9e54a16ba..1b3f355eb25 100644 --- a/mysql-test/suite/galera/t/MW-86-wait8.test +++ b/mysql-test/suite/galera/t/MW-86-wait8.test @@ -3,7 +3,10 @@ # --source include/galera_cluster.inc --source include/have_binlog_format_row.inc +--source include/have_debug.inc --source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + SET @orig_debug=@@debug_dbug; --connection node_2 diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid.inc b/mysql-test/suite/galera/t/galera_as_slave_gtid.inc index f5222b4322b..ca6cce52497 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid.inc +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.inc @@ -8,6 +8,7 @@ # --source include/have_innodb.inc +--source include/have_log_bin.inc --source include/galera_cluster.inc # As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it @@ -27,6 +28,13 @@ INSERT INTO t1 VALUES(1); SELECT LENGTH(@@global.gtid_binlog_state) > 1; --let $gtid_binlog_state_node1 = `SELECT @@global.gtid_binlog_state;` +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + --connection node_2 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.cnf index adcba9b6069..efabe4161aa 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.cnf +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.cnf @@ -5,4 +5,4 @@ log-bin=mysqld-bin log-slave-updates binlog-format=ROW -gtid_pos_auto_engines=InnoDB \ No newline at end of file +gtid_pos_auto_engines=InnoDB diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.test index 990dd35f40e..5ef98573660 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.test +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_auto_engine.test @@ -11,4 +11,4 @@ --connection node_2 DROP TABLE mysql.gtid_slave_pos_InnoDB; -CALL mtr.add_suppression("The automatically created table"); \ No newline at end of file +CALL mtr.add_suppression("The automatically created table"); diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test index 004f5c825bb..8787f864a99 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test @@ -59,6 +59,8 @@ SELECT COUNT(*) AS EXPECT_0 FROM t1; --connection node_3 DROP TABLE t1; +--sleep 1 + --connection node_1 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc @@ -70,8 +72,6 @@ DROP TABLE t1; --connection node_3 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc - ---connection node_3 RESET MASTER; --connection node_1 @@ -85,3 +85,6 @@ SET GLOBAL WSREP_ON=ON; SET GLOBAL WSREP_ON=OFF; reset master; SET GLOBAL WSREP_ON=ON; + +--connection node_3 +RESET MASTER; diff --git a/mysql-test/suite/galera/t/galera_bf_kill.cnf b/mysql-test/suite/galera/t/galera_bf_kill.cnf new file mode 100644 index 00000000000..e68f891792c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_kill.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=SERVER + +[mysqld.2] +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/galera_bf_kill.test b/mysql-test/suite/galera/t/galera_bf_kill.test new file mode 100644 index 00000000000..3eb3ddc32b5 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_kill.test @@ -0,0 +1,190 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# +# Test case 1: Start a transaction on node_2a and kill it +# from other connection on same node +# + +--connection node_2 +CREATE TABLE t1(a int not null primary key auto_increment,b int) engine=InnoDB; +insert into t1 values (NULL,1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +begin; +update t1 set a = 5; + +--connection node_2 + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1 +--source include/wait_condition.inc + +--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1` + +--disable_query_log +--eval KILL $k_thread +--enable_query_log + +select * from t1; +--disconnect node_2a + +# +# Test case 2: Start a transaction on node_2a and use +# kill query from other connection on same node +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +begin; +update t1 set a =5; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1 +--source include/wait_condition.inc + +--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1` + +--disable_query_log +--eval KILL QUERY $k_thread +--enable_query_log + +select * from t1; +--disconnect node_2a +# +# Test case 3: Start a transaction on node_2a and start a DDL on other transaction +# that will then abort node_2a transaction +# +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +begin; +update t1 set a =5, b=2; + +--connection node_2 +ALTER TABLE t1 ADD UNIQUE KEY b1(b); +ALTER TABLE t1 DROP KEY b1; + +select * from t1; + +--disconnect node_2a + +# +# Test case 4: Start a transaction on node_2a and conflicting transaction on node_2b +# and start a DDL on other transaction that will then abort node_2a and node_2b +# transactions +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +begin; +update t1 set a =5, b=2; + +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2b +begin; +send update t1 set a =6, b=7; + +--connection node_2 +ALTER TABLE t1 ADD UNIQUE KEY b2(b); +ALTER TABLE t1 DROP KEY b2; + +select * from t1; + +--disconnect node_2a +--disconnect node_2b + +# +# Test case 5: Start a transaction on node_2a with wsrep disabled +# and start a DDL on other transaction that will then abort node_2a +# transactions +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION wsrep_on=OFF; +begin; +update t1 set a =5, b=2; + +--connection node_2 +ALTER TABLE t1 ADD UNIQUE KEY b3(b); + +select * from t1; + +--disconnect node_2a + +# +# Test case 6: Start a transaction on node_2a with wsrep disabled +# and kill it from other connection on same node +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION wsrep_on=OFF; +begin; +update t1 set a =5, b=2; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1 +--source include/wait_condition.inc + +--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1` + +--disable_query_log +--eval KILL $k_thread +--enable_query_log + + +select * from t1; + +--disconnect node_2a + +drop table t1; + + +# +# Test case 7: +# run a transaction in node 2, and set a sync point to pause the transaction +# in commit phase. +# Through another connection to node 2, kill the committing transaction by +# KILL QUERY command +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +--let $connection_id = `SELECT CONNECTION_ID()` + +CREATE TABLE t1 (i int primary key); + +# Set up sync point +SET DEBUG_SYNC = "before_wsrep_ordered_commit SIGNAL bwoc_reached WAIT_FOR bwoc_continue"; + +# Send insert which will block in the sync point above +--send INSERT INTO t1 VALUES (1) + +--connection node_2 +SET DEBUG_SYNC = "now WAIT_FOR bwoc_reached"; + +--disable_query_log +--disable_result_log +# victim has passed the point of no return, kill is not possible anymore +--eval KILL QUERY $connection_id +--enable_result_log +--enable_query_log + +SET DEBUG_SYNC = "now SIGNAL bwoc_continue"; +SET DEBUG_SYNC='RESET'; +--connection node_2a +--error 0,1213 +--reap + +--connection node_2 +# victim was able to complete the INSERT +select * from t1; + +--disconnect node_2a + +--connection node_2 +drop table t1; + diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf b/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf new file mode 100644 index 00000000000..e68f891792c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=SERVER + +[mysqld.2] +wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.test b/mysql-test/suite/galera/t/galera_bf_lock_wait.test index e3a9077a888..97d3b8e0710 100644 --- a/mysql-test/suite/galera/t/galera_bf_lock_wait.test +++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.test @@ -1,6 +1,11 @@ --source include/galera_cluster.inc +--source include/have_innodb.inc --source include/big_test.inc - + +--connection node_1 + +call mtr.add_suppression("WSREP: Trying to continue unpaused monitor"); + CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2; ALTER TABLE t1 add primary key(a); @@ -28,7 +33,7 @@ send call p1; --connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2 send call p1; -connection default; +connection node_1; let $counter=10; let $sleep_period=10; diff --git a/mysql-test/suite/galera/t/galera_drop_database.test b/mysql-test/suite/galera/t/galera_drop_database.test index 12d9efea2f9..8dc73c1ce38 100644 --- a/mysql-test/suite/galera/t/galera_drop_database.test +++ b/mysql-test/suite/galera/t/galera_drop_database.test @@ -23,6 +23,10 @@ INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; DROP TABLE ten; UPDATE fts_t1 SET f2 = 'abcd'; UPDATE fts_t2 SET f2 = 'efjh'; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1 where f2 = 'abcd'; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2 where f2 = 'efjh'; # Restart the second node: --connection node_2 @@ -34,6 +38,14 @@ UPDATE fts_t2 SET f2 = 'efjh'; --connection node_2 --source include/wait_until_ready.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM fts_t1 where f2 = 'abcd'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM fts_t2 where f2 = 'efjh'; +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t1 where f2 = 'abcd'; +SELECT COUNT(*) AS EXPECT_1000 FROM fts_t2 where f2 = 'efjh'; # Drop the tables and database after nodes restarted: --connection node_1 @@ -43,5 +55,13 @@ DROP TABLE fts_t2; SHOW TABLES; DROP DATABASE fts; +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'fts_t1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'fts_t2'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'fts'; +--source include/wait_condition.inc + # Restore original auto_increment_offset values. --source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test index ee64e147f65..c8cdda5d624 100644 --- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test +++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test @@ -39,7 +39,7 @@ SELECT COUNT(*) = 0 FROM t1; --connection node_2 --sleep 1 ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Init' AND INFO = 'FLUSH TABLES WITH READ LOCK' +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE (STATE = 'Init' OR STATE = 'starting') AND INFO = 'FLUSH TABLES WITH READ LOCK' --source include/wait_condition.inc --source include/galera_clear_sync_point.inc diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test index b82a160657d..587fbe10fe4 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test @@ -57,6 +57,8 @@ send call p1(1000); --connection node_2 --disable_query_log +--let $wait_condition = select count(*)=1 from information_schema.routines WHERE routine_name='p1'; +--source include/wait_condition.inc send call p1(1000); --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test index e13e7f1f748..6d1e21fd94d 100644 --- a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test @@ -1,6 +1,8 @@ --source include/galera_cluster.inc +--source include/have_debug.inc --source include/have_debug_sync.inc --source include/have_query_cache.inc +--source include/galera_have_debug_sync.inc CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); diff --git a/mysql-test/suite/galera/t/galera_slave_replay.cnf b/mysql-test/suite/galera/t/galera_slave_replay.cnf new file mode 100644 index 00000000000..9449ec9cf40 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_slave_replay.cnf @@ -0,0 +1 @@ +!include ../galera_2nodes_as_slave.cnf diff --git a/mysql-test/suite/galera/t/galera_slave_replay.test b/mysql-test/suite/galera/t/galera_slave_replay.test index 37c4cbd5b43..f1500eeaeaa 100644 --- a/mysql-test/suite/galera/t/galera_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_slave_replay.test @@ -7,6 +7,7 @@ # --source include/have_innodb.inc +--source include/have_log_bin.inc --source include/have_debug.inc --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc @@ -21,9 +22,7 @@ # --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 -SET GLOBAL wsrep_on=OFF; RESET MASTER; -SET GLOBAL wsrep_on=ON; --connection node_2a # @@ -33,10 +32,10 @@ SET GLOBAL wsrep_on=ON; # -# nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB naster in node 3 +# nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB master in node 3 # --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; @@ -156,35 +155,31 @@ UPDATE t1 SET f2 = 'd' WHERE f1 = 3; --let $wait_condition = SELECT COUNT(*) = 4 FROM test.t1; --source include/wait_condition.inc -# Block the commit ---let $galera_sync_point = commit_monitor_master_enter_sync ---source include/galera_set_sync_point.inc - # block applier SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; -# Inject a conflicting update from node 3 ---connection node_3 +# Inject a conflicting update from node 1 +--connection node_1 UPDATE test.t1 SET f2 = 'e' WHERE f1 = 3; +--connection node_2a +# wait until applier has reached the sync point +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + # send the update from master --connection node_3 --error 0 COMMIT; --connection node_2a +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc -# release the applier +# release the applier from node 1 SET GLOBAL debug_dbug = ""; SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; - -# Unblock the async slave commit ---connection node_2a ---source include/galera_clear_sync_point.inc ---source include/galera_signal_sync_point.inc -SET DEBUG_SYNC = "RESET"; - --connection node_2a set session wsrep_sync_wait=15; @@ -193,11 +188,10 @@ set session wsrep_sync_wait=0; STOP SLAVE; RESET SLAVE; +SET DEBUG_SYNC = "RESET"; DROP TABLE t1; --connection node_3 DROP TABLE t1; -SET GLOBAL wsrep_on=OFF; RESET MASTER; -SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_toi_truncate.test b/mysql-test/suite/galera/t/galera_toi_truncate.test index 0c1d0e45e41..30e0e802816 100644 --- a/mysql-test/suite/galera/t/galera_toi_truncate.test +++ b/mysql-test/suite/galera/t/galera_toi_truncate.test @@ -4,50 +4,42 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc --source include/have_debug_sync.inc ---source include/not_embedded.inc +--source include/have_debug.inc # # INSERT and TRUNCATE on different nodes # --connection node_1 -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -# Insert 1m rows --connection node_2 --let $wait_condition = SELECT COUNT(*) = 10 FROM ten; --source include/wait_condition.inc # Prevent autocommit retring from masking the deadlock error we expect to get SET SESSION wsrep_retry_autocommit = 0; -INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; - -set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go'; ---send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6; +--send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8 --connection node_1 -# Wait for a above insert to start ---let $wait_condition = SELECT COUNT(*) >= 100 from t1; ---source include/wait_condition.inc - --send TRUNCATE TABLE t1; ---connection node_1 ---reap - --connection node_2 --error ER_LOCK_DEADLOCK --reap +--connection node_1 +--reap + --connection node_2 -SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; --connection node_1 -SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; + DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_var_cluster_conf_id.test b/mysql-test/suite/galera/t/galera_var_cluster_conf_id.test index c569634823f..dd4a630035d 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_conf_id.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_conf_id.test @@ -1,9 +1,9 @@ --source include/galera_cluster.inc --connection node_1 ---replace_regex /18446744073709551/ERROR/ /[0-9]/#/ +--replace_regex /18446744073709551/ERROR/ /[0-9+]/#/ show status like 'wsrep_cluster_conf_id'; --connection node_2 ---replace_regex /18446744073709551/ERROR/ /[0-9]/#/ +--replace_regex /18446744073709551/ERROR/ /[0-9+]/#/ show status like 'wsrep_cluster_conf_id'; diff --git a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test index 9ccecc5a61d..37469d8a5fb 100644 --- a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test +++ b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test @@ -11,13 +11,10 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc --source include/have_log_bin.inc # Open a separate connection to be used to run SHOW PROCESSLIST ---let $galera_connection_name = node_1a ---let $galera_server_number = 1 ---source include/galera_connect.inc +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a SET SESSION wsrep_sync_wait = 0; @@ -27,18 +24,27 @@ SET GLOBAL innodb_disallow_writes=ON; --send INSERT INTO t1 VALUES (1); --connection node_1a -SELECT COUNT(*) = 1 FROM t1; -let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t1 VALUES (1)' AND State = 'Commit'; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; +let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t1 VALUES (1)'; +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_0 FROM t1; SET GLOBAL innodb_disallow_writes=OFF; --connection node_1 --reap -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; --connection node_2 -SELECT COUNT(*) = 1 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; + +--disconnect node_1a + diff --git a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test index df541b774a4..6bed1b0120f 100644 --- a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test +++ b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test @@ -4,7 +4,9 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/have_debug.inc --source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 diff --git a/mysql-test/suite/galera/t/galera_vote_rejoin_ddl.test b/mysql-test/suite/galera/t/galera_vote_rejoin_ddl.test index ce87c728b8c..ca75d33b7d7 100644 --- a/mysql-test/suite/galera/t/galera_vote_rejoin_ddl.test +++ b/mysql-test/suite/galera/t/galera_vote_rejoin_ddl.test @@ -6,6 +6,17 @@ --source include/galera_cluster.inc --source include/big_test.inc +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc +# The following has to be set hard as these connection doesn't yet exists and +# the auto_increment_offset value changes during the lifetime of the servers. +--let $node_3=node_3 +--let $auto_increment_offset_node_3 = 3; +--let $node_4=node_4 +--let $auto_increment_offset_node_4 = 4; + # Isolate node #3 --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 @@ -81,3 +92,5 @@ SELECT COUNT(*) AS expect_1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't CALL mtr.add_suppression("WSREP: Vote 0 \\(success\\) on .* is inconsistent with group. Leaving cluster."); DROP TABLE t2; + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/mysql-wsrep-bugs-607.test b/mysql-test/suite/galera/t/mysql-wsrep-bugs-607.test new file mode 100644 index 00000000000..c24ec7911e2 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep-bugs-607.test @@ -0,0 +1,70 @@ +--source include/galera_cluster.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc +--source include/have_log_bin.inc + +# +# Test case to stress the order of wsrep XID checkpointing. +# +# In buggy version, the transaction which failed certification can +# rush to record wsrep XID checkpoint before the offending applier, +# causing assert in innodb sys header update routine +# + +--echo # +--echo # test the order of wsrep XID storage after certifiation failure +--echo # + +--connection node_1 +set session wsrep_sync_wait=0; + +create table t1 (i int primary key, j int); + +insert into t1 values (4, 0); + +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2b +set session wsrep_sync_wait=0; +# wait for the last insert to be replicated from node 1 +--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t1; +--source include/wait_condition.inc + +# block applier before applying +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; + +# send update from node 1, it will pause in the sync point +--connection node_1 +UPDATE test.t1 set j=1 where i=4; + +--connection node_2b +# wait until applier has reached the sync point +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + +# look number of cert failures so far, and expect one more to happen +--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + +# Inject a conflicting update in node 2, it should fail in certification +--connection node_2 +set session wsrep_sync_wait=0; +set session wsrep_retry_autocommit=0; +--send UPDATE test.t1 SET j=2 WHERE i=4 + +--connection node_2b +# wait until the update has hit certification failure + +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc + +# release the applier +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; + +--connection node_2 +--error ER_LOCK_DEADLOCK +--reap +select * from t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result new file mode 100644 index 00000000000..0461f1f1feb --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result @@ -0,0 +1,40 @@ +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (2, 3); +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (3, 2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (4, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (5, 2); +SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (6, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (7, 2); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (8, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; +SET GLOBAL wsrep_provider_options = 'signal=before_send_state_request'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +INSERT INTO t1 VALUES (9, 2); +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET GLOBAL wsrep_provider_options = 'dbug='; +DROP TABLE t1; +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result new file mode 100644 index 00000000000..d878f60ca6b --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result @@ -0,0 +1,50 @@ +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (2, 3); +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (3, 2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (4, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (5, 2); +SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=before_send_state_request'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DEBUG_SYNC_WAITERS after_shift_to_joining +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (6, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (7, 2); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (8, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +INSERT INTO t1 VALUES (9, 2); +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DEBUG_SYNC_WAITERS process_primary_configuration +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET GLOBAL wsrep_provider_options = 'dbug='; +DROP TABLE t1; +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result new file mode 100644 index 00000000000..df0a924029c --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_C.result @@ -0,0 +1,55 @@ +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (2, 3); +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (3, 2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (4, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (5, 2); +SET GLOBAL wsrep_provider_options = 'dbug=d,before_send_state_request'; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_shift_to_joining'; +SET GLOBAL wsrep_provider_options = 'signal=before_send_state_request'; +4 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DEBUG_SYNC_WAITERS +INSERT INTO t1 VALUES (6, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO t1 VALUES (7, 2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,process_primary_configuration'; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (8, 3); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +INSERT INTO t1 VALUES (9, 2); +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=process_primary_configuration'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 0; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=after_shift_to_joining'; +DROP TABLE t1; +call mtr.add_suppression("WSREP: Send action {\(.*\), STATE_REQUEST} returned -107 \\(Transport endpoint is not connected\\)"); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test index 7f73e36c0b8..d6b97f939f2 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test @@ -1,7 +1,7 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc --source include/have_innodb.inc ---source include/have_mariabackup.inc +--source ../galera/include/have_mariabackup.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test index fd76c3586ca..e9425bcffdf 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test @@ -1,7 +1,7 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc --source include/have_innodb.inc ---source include/have_mariabackup.inc +--source ../galera/include/have_mariabackup.inc # Confirm that initial handshake happened over ipv6 diff --git a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test new file mode 100644 index 00000000000..2248ff5014a --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test @@ -0,0 +1,262 @@ +# +# Tests handling of several configuration changes while a joiner gets +# state transfer +# +# Variant A: sending of state transfer request delayed until two more +# primary configuration changes happen +# +# Refs codersihp/galera-bugs#454 +# +--source include/have_innodb.inc +--source include/galera_cluster.inc +--source include/galera_have_debug_sync.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +# +# Isolate node_1 and update cluster state to force node 1 into joiner mode +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (2, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +# +# Now reconnect node_1 but first make it block before sending state transfer +# request +# +# THIS IS PC1 +# +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +--let $galera_sync_point = after_shift_to_joining +--source include/galera_set_sync_point.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (3, 2); + +--connection node_1a +--source include/galera_wait_sync_point.inc +# +# At this point every node thinks that node_1 is in a JOINER state +# + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Now that node_1 sent state request and became JOINER isolate node_1 again +# and commit one more action, so that node_1 loses JOINER state +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (4, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 4 FROM t1; +--source include/wait_condition.inc + +# +# Reconnect node_1 again +# +# THIS IS PC2 +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# After this point node_1 is no longer JOINER and is required to start the +# whole procedure over because it missed some actions (4th insert into t1) +# + +INSERT INTO t1 VALUES (5, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +# +# Now let node_1 continue with IST and finish processing PC1, but make it +# block when processing PC2 just before sending state transfer request +# +--connection node_1a +--let $galera_sync_point = before_send_state_request +--source include/galera_set_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = before_send_state_request +--source include/galera_wait_sync_point.inc + +# since PC1 has been processed node_1 must have 3 rows in t1 +# 2 were there before PC1 and one was added while in PC1 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Now disconnect and reconnect node_1 again to get PC3 +# It still is blocked before sending state transfer request in PC2. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (6, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC3 +# + +INSERT INTO t1 VALUES (7, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 7 FROM t1; +--source include/wait_condition.inc + +# +# Now disconnect and reconnect node_1 again to get PC4 and allow node_1 +# to send state transfer request to be delivered in PC4 (and thus get +# updated to PC4 seqno in state transfer. +# Note that node_1 still processes PC2. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (8, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC4. node_1 is still processing PC2, waiting to send state trasfer +# request +# +--connection node_1a +--let $galera_sync_point = process_primary_configuration +--source include/galera_set_sync_point.inc +--let $galera_sync_point = before_send_state_request +--source include/galera_signal_sync_point.inc +# sent STR from PC2 into PC4 + +--let $galera_sync_point = process_primary_configuration +--source include/galera_wait_sync_point.inc +# +# Now node_1 is processing PC3, but should have completed state transfer from +# PC4 and thus must have 8 rows in t1 +# +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +--connection node_2 +INSERT INTO t1 VALUES (9, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1a +#--let $galera_sync_point = process_primary_configuration +--source include/galera_signal_sync_point.inc +--source include/galera_wait_sync_point.inc +# +# Now node_1 is processing PC4, still must have 8 rows in t1 +# +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +#--let $galera_sync_point = process_primary_configuration +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc + +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +DROP TABLE t1; + +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_2 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_3 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test new file mode 100644 index 00000000000..2fb0e78c759 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test @@ -0,0 +1,273 @@ +# +# Tests handling of several configuration changes while a joiner gets +# state transfer +# +# Variant B: sending of state transfer request is immediate but completion +# of IST delayed until two more primary configuration changes happen +# +# Refs codersihp/galera-bugs#454 +# +--source include/have_innodb.inc +--source include/galera_cluster.inc +--source include/galera_have_debug_sync.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +# +# Isolate node_1 and update cluster state to force node 1 into joiner mode +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (2, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +# +# Now reconnect node_1 but first make it block before sending state transfer +# request +# +# THIS IS PC1 +# +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +--let $galera_sync_point = after_shift_to_joining +--source include/galera_set_sync_point.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (3, 2); + +--connection node_1a +--source include/galera_wait_sync_point.inc +# +# At this point every node thinks that node_1 is in a JOINER state +# + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Now that node_1 sent state request and became JOINER isolate node_1 again +# and commit one more action, so that node_1 loses JOINER state +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (4, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 4 FROM t1; +--source include/wait_condition.inc + +# +# Reconnect node_1 again +# +# THIS IS PC2 +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# After this point node_1 is no longer JOINER and is required to start the +# whole procedure over because it missed some actions (4th insert into t1) +# + +INSERT INTO t1 VALUES (5, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +# +# Now let node_1 continue with IST and finish processing PC1, but make it +# block when processing PC2 right after progressing to JOINER state and +# before IST happens. +# +--connection node_1a +--let $galera_sync_point = before_send_state_request +--source include/galera_set_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = before_send_state_request +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +# Here node_1 is processing PC2 just before sending state request + +# since PC1 has been processed node_1 must have 3 rows in t1 +# 2 were there before PC1 and one was added while in PC1 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# Proceed to sending state transfer request and block right after +--source include/galera_signal_sync_point.inc # before_send_state_request +--let $galera_sync_point = after_shift_to_joining +--source include/galera_wait_sync_point.inc +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; + +# +# Now disconnect and reconnect node_1 again to get PC3 +# It is blocked right after shifting to JOINING state. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (6, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC3 +# + +INSERT INTO t1 VALUES (7, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 7 FROM t1; +--source include/wait_condition.inc + +# +# Now disconnect and reconnect node_1 again to get PC4 and allow node_1 +# to continue with IST. +# Note that node_1 still processes PC2 and is joining. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (8, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC4. node_1 is still processing PC2, waiting to send state trasfer +# request +# +--connection node_1a +--let $galera_sync_point = process_primary_configuration +--source include/galera_set_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_signal_sync_point.inc +# continue with IST prepared for in PC2 + +--let $galera_sync_point = process_primary_configuration +--source include/galera_wait_sync_point.inc +# +# Now node_1 is processing PC3, and should have finished state transfer +# State tranfer request was dilivered before PC3, so node_1 should have +# received IST up to 4 rows in t1 (what was there before PC2) plus one more +# INSERT while in PC2. +# +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +--connection node_2 +INSERT INTO t1 VALUES (9, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1a +#--let $galera_sync_point = process_primary_configuration +--source include/galera_signal_sync_point.inc +--source include/galera_wait_sync_point.inc +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; +# +# Now node_1 is processing PC4, still must have 8 rows in t1 +# +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +#--let $galera_sync_point = process_primary_configuration +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc + +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +DROP TABLE t1; + +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_2 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_3 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_C.test b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_C.test new file mode 100644 index 00000000000..133903d7cbf --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_C.test @@ -0,0 +1,299 @@ +# +# Tests handling of several configuration changes while a joiner gets +# state transfer +# +# Variant C: sending of state transfer request is scheduled while in non-PRIM +# +# Refs codersihp/galera-bugs#454 +# +--source include/have_innodb.inc +--source include/galera_cluster.inc +--source include/galera_have_debug_sync.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1, 1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +# +# Isolate node_1 and update cluster state to force node 1 into joiner mode +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (2, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +# +# Now reconnect node_1 but first make it block before sending state transfer +# request +# +# THIS IS PC1 +# +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET wsrep_sync_wait = 0; +SET wsrep_on = OFF; +--let $galera_sync_point = after_shift_to_joining +--source include/galera_set_sync_point.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (3, 2); + +--connection node_1a +--source include/galera_wait_sync_point.inc +# +# At this point every node thinks that node_1 is in a JOINER state +# + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Now that node_1 sent state request and became JOINER isolate node_1 again +# and commit one more action, so that node_1 loses JOINER state +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (4, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 4 FROM t1; +--source include/wait_condition.inc + +# +# Reconnect node_1 again +# +# THIS IS PC2 +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# After this point node_1 is no longer JOINER and is required to start the +# whole procedure over because it missed some actions (4th insert into t1) +# + +INSERT INTO t1 VALUES (5, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +# +# Now let node_1 continue with IST and finish processing PC1, but make it +# block when processing PC2 right after progressing to JOINER state and +# before IST happens. +# +--connection node_1a +--let $galera_sync_point = before_send_state_request +--source include/galera_set_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = before_send_state_request +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +# Here we are processing PC2 just before sending state request + +# since PC1 has been processed node_1 must have 3 rows in t1 +# 2 were there before PC1 and one was added while in PC1 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Now disconnect and reconnect node_1 again to get PC3 +# It still is blocked before sending state transfer request in PC2. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Proceed to sending state transfer request +--connection node_1a +--let $galera_sync_point = after_shift_to_joining +--source include/galera_set_sync_point.inc +--let $galera_sync_point = before_send_state_request +--source include/galera_signal_sync_point.inc # before_send_state_request +# +# node_1 proceeds to sending state transfer request, it will be delivered only +# in the next PC which is PC3. Only then the node will shift to JOINING +# +--echo 4 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'; + +--connection node_3 +INSERT INTO t1 VALUES (6, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC3 +# + +INSERT INTO t1 VALUES (7, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 7 FROM t1; +--source include/wait_condition.inc + +# node_1 is stiil processing PC2, it was let to send state transfer request +# while in non-PRIM. Now it should be able to complete it and shift to +# JOINING. Make it block on next PC(3) and continue to receive IST +--connection node_1a +--let $galera_sync_point = after_shift_to_joining +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc # won't need it any more +--let $galera_sync_point = process_primary_configuration +--source include/galera_set_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_signal_sync_point.inc +# continue with IST while still processing PC2 + +# +# Now disconnect and reconnect node_1 again to generate PC4. +# +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (8, 3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 8 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +# +# This is PC4. node_1 should complete IST, complete PC2, and continue +# with the next item in queue +# +--connection node_1a +--let $galera_sync_point = process_primary_configuration +--source include/galera_wait_sync_point.inc + +# +# Now node_1 is blocked before processing PC3, and should have finished state +# transfer started while in PC2. +# State tranfer request was dilivered in PC3 to donor, so node_1 should have +# received IST up to 6 rows in t1 (what was there before PC3). +# +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--source include/wait_condition.inc + +--connection node_2 +INSERT INTO t1 VALUES (9, 2); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1a +# continue with processing PC3 +--let $galera_sync_point = process_primary_configuration +--source include/galera_signal_sync_point.inc + +# wait for row that follows PC3 +--let $wait_condition = SELECT COUNT(*) = 7 FROM t1; +--source include/wait_condition.inc + +# wait till PC4 +--let $galera_sync_point = process_primary_configuration +--source include/galera_wait_sync_point.inc +# +# Now node_1 is processing PC4, still must have 7 rows in t1 +# +--let $wait_condition = SELECT COUNT(*) = 7 FROM t1; +--source include/wait_condition.inc + +# Continue with PC4 +--let $galera_sync_point = process_primary_configuration +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = after_shift_to_joining +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc + +--let $wait_condition = SELECT COUNT(*) = 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +DROP TABLE t1; + +call mtr.add_suppression("WSREP: Send action {\(.*\), STATE_REQUEST} returned -107 \\(Transport endpoint is not connected\\)"); +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_2 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--connection node_3 +call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); diff --git a/mysql-test/suite/galera_sr/r/MDEV-22616.result b/mysql-test/suite/galera_sr/r/MDEV-22616.result new file mode 100644 index 00000000000..0c3847bd9b9 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MDEV-22616.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +START TRANSACTION; +INSERT INTO t1 VALUES (1); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/MDEV-22616.test b/mysql-test/suite/galera_sr/t/MDEV-22616.test new file mode 100644 index 00000000000..818d787703f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MDEV-22616.test @@ -0,0 +1,18 @@ +# +# MDEV-22616 +# +# CHECK TABLE fails with wsrep_trx_fragment_size > 0 +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +CHECK TABLE t1; + +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +CHECK TABLE t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/gcol/r/gcol_purge.result b/mysql-test/suite/gcol/r/gcol_purge.result new file mode 100644 index 00000000000..ea8369ad8e5 --- /dev/null +++ b/mysql-test/suite/gcol/r/gcol_purge.result @@ -0,0 +1,22 @@ +CREATE TABLE t1(f1 INT NOT NULL, f2 int not null, +f3 int generated always as (f2 * 2) VIRTUAL, +primary key(f1), INDEX (f3))ENGINE=InnoDB; +connect con1,localhost,root,,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +INSERT INTO t1(f1, f2) VALUES(1,2); +DELETE from t1 where f1 = 1; +connect con2,localhost,root,,,; +begin; +INSERT INTO t1 (f1, f2) VALUES(1,2); +set global debug_dbug="+d,ib_purge_virtual_index_callback"; +connection con1; +COMMIT; +InnoDB 0 transactions not purged +connection con2; +commit; +disconnect con1; +disconnect con2; +connection default; +set global debug_dbug=default; +DROP TABLE t1; diff --git a/mysql-test/suite/gcol/t/gcol_purge.test b/mysql-test/suite/gcol/t/gcol_purge.test new file mode 100644 index 00000000000..3696b41b3d8 --- /dev/null +++ b/mysql-test/suite/gcol/t/gcol_purge.test @@ -0,0 +1,30 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +CREATE TABLE t1(f1 INT NOT NULL, f2 int not null, + f3 int generated always as (f2 * 2) VIRTUAL, + primary key(f1), INDEX (f3))ENGINE=InnoDB; +connect(con1,localhost,root,,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +INSERT INTO t1(f1, f2) VALUES(1,2); +DELETE from t1 where f1 = 1; + +connect(con2,localhost,root,,,); +begin; +INSERT INTO t1 (f1, f2) VALUES(1,2); + +set global debug_dbug="+d,ib_purge_virtual_index_callback"; +connection con1; +COMMIT; + +--source ../innodb/include/wait_all_purged.inc + +connection con2; +commit; + +disconnect con1; +disconnect con2; +connection default; +set global debug_dbug=default; +DROP TABLE t1; diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result index 51283022588..e34164957a3 100644 --- a/mysql-test/suite/handler/aria.result +++ b/mysql-test/suite/handler/aria.result @@ -1132,166 +1132,7 @@ connection default; # Reaping 'select * from t2' ERROR 42S02: Table 'test.t2' doesn't exist handler t1 close; -# -# ROLLBACK TO SAVEPOINT releases transactional locks, -# but has no effect on open HANDLERs -# -create table t2 like t1; -create table t3 like t1; -begin; -# Have something before the savepoint -select * from t3; -a -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -drop table t3; -# -# A few special cases when using SAVEPOINT/ROLLBACK TO -# SAVEPOINT and HANDLER. -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction doesn't release mdl lock on -# the HANDLER that was opened later. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -begin; -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: -drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction works properly (no valgrind warnins, etc), -# even though it's done after the HANDLER mdl lock that was there -# at the beginning is released and added again. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -create table t3 like t1; -insert into t3 (a) select a from t1; -begin; -handler t1 open; -savepoint sv; -handler t1 read a first; -a -1 -select * from t2; -a -handler t1 close; -handler t3 open; -handler t3 read a first; -a -1 -rollback to savepoint sv; -connection con1; -drop table t1, t2; -# Sending: -drop table t3; -# Let DROP TABLE statement sync in. -connection con2; -# Waiting for 'drop table t3' to get blocked... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t3 read a next; -a -2 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t3 close; -connection con1; -# Reaping 'drop table t3'... -connection default; -commit; # # If we have to wait on an exclusive locks while having # an open HANDLER, ER_LOCK_DEADLOCK is reported. diff --git a/mysql-test/suite/handler/handler.inc b/mysql-test/suite/handler/handler.inc index c29ee0c693d..f4c677adc90 100644 --- a/mysql-test/suite/handler/handler.inc +++ b/mysql-test/suite/handler/handler.inc @@ -890,166 +890,7 @@ connection default; --error ER_NO_SUCH_TABLE reap; handler t1 close; - ---echo # ---echo # ROLLBACK TO SAVEPOINT releases transactional locks, ---echo # but has no effect on open HANDLERs ---echo # -create table t2 like t1; -create table t3 like t1; -begin; ---echo # Have something before the savepoint -select * from t3; -savepoint sv; -handler t1 open; -handler t1 read a first; -handler t1 read a next; -select * from t2; -connection con1; ---echo # Sending: ---send drop table t1 -connection con2; ---echo # Sending: ---send drop table t2 -connection default; ---echo # Let DROP TABLE statements sync in. We must use ---echo # a separate connection for that, because otherwise SELECT ---echo # will auto-close the HANDLERs, becaues there are pending ---echo # exclusive locks against them. -connection con3; ---echo # Waiting for 'drop table t1' to get blocked... -let $wait_condition=select count(*)=1 from information_schema.processlist - where state='Waiting for table metadata lock' and - info='drop table t1'; ---source include/wait_condition.inc ---echo # Waiting for 'drop table t2' to get blocked... -let $wait_condition=select count(*)=1 from information_schema.processlist - where state='Waiting for table metadata lock' and - info='drop table t2'; ---source include/wait_condition.inc ---echo # Demonstrate that t2 lock was released and t2 was dropped ---echo # after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; ---echo # Reaping 'drop table t2'... ---reap ---echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler ---echo # lock. -connection default; -handler t1 read a next; -handler t1 read a next; ---echo # Demonstrate that the drop will go through as soon as we close the ---echo # HANDLER -handler t1 close; -connection con1; ---echo # Reaping 'drop table t1'... ---reap -connection default; -commit; -drop table t3; ---echo # ---echo # A few special cases when using SAVEPOINT/ROLLBACK TO ---echo # SAVEPOINT and HANDLER. ---echo # ---echo # Show that rollback to the savepoint taken in the beginning ---echo # of the transaction doesn't release mdl lock on ---echo # the HANDLER that was opened later. ---echo # -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -begin; -savepoint sv; -handler t1 open; -handler t1 read a first; -handler t1 read a next; -select * from t2; -connection con1; ---echo # Sending: ---send drop table t1 -connection con2; ---echo # Sending: ---send drop table t2 -connection default; ---echo # Let DROP TABLE statements sync in. We must use ---echo # a separate connection for that, because otherwise SELECT ---echo # will auto-close the HANDLERs, becaues there are pending ---echo # exclusive locks against them. -connection con3; ---echo # Waiting for 'drop table t1' to get blocked... -let $wait_condition=select count(*)=1 from information_schema.processlist - where state='Waiting for table metadata lock' and - info='drop table t1'; ---source include/wait_condition.inc ---echo # Waiting for 'drop table t2' to get blocked... -let $wait_condition=select count(*)=1 from information_schema.processlist - where state='Waiting for table metadata lock' and - info='drop table t2'; ---source include/wait_condition.inc ---echo # Demonstrate that t2 lock was released and t2 was dropped ---echo # after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; ---echo # Reaping 'drop table t2'... ---reap ---echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler ---echo # lock. -connection default; -handler t1 read a next; -handler t1 read a next; ---echo # Demonstrate that the drop will go through as soon as we close the ---echo # HANDLER -handler t1 close; -connection con1; ---echo # Reaping 'drop table t1'... ---reap -connection default; -commit; ---echo # ---echo # Show that rollback to the savepoint taken in the beginning ---echo # of the transaction works properly (no valgrind warnins, etc), ---echo # even though it's done after the HANDLER mdl lock that was there ---echo # at the beginning is released and added again. ---echo # -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -create table t3 like t1; -insert into t3 (a) select a from t1; -begin; -handler t1 open; -savepoint sv; -handler t1 read a first; -select * from t2; -handler t1 close; -handler t3 open; -handler t3 read a first; -rollback to savepoint sv; -connection con1; -drop table t1, t2; ---echo # Sending: ---send drop table t3 ---echo # Let DROP TABLE statement sync in. -connection con2; ---echo # Waiting for 'drop table t3' to get blocked... -let $wait_condition=select count(*)=1 from information_schema.processlist - where state='Waiting for table metadata lock' and - info='drop table t3'; ---source include/wait_condition.inc ---echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler ---echo # lock. -connection default; -handler t3 read a next; ---echo # Demonstrate that the drop will go through as soon as we close the ---echo # HANDLER -handler t3 close; -connection con1; ---echo # Reaping 'drop table t3'... ---reap -connection default; -commit; +drop table t1; --echo # --echo # If we have to wait on an exclusive locks while having diff --git a/mysql-test/suite/handler/heap.result b/mysql-test/suite/handler/heap.result index bd8aff906fd..e66bccb1341 100644 --- a/mysql-test/suite/handler/heap.result +++ b/mysql-test/suite/handler/heap.result @@ -1131,166 +1131,7 @@ connection default; # Reaping 'select * from t2' ERROR 42S02: Table 'test.t2' doesn't exist handler t1 close; -# -# ROLLBACK TO SAVEPOINT releases transactional locks, -# but has no effect on open HANDLERs -# -create table t2 like t1; -create table t3 like t1; -begin; -# Have something before the savepoint -select * from t3; -a -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -drop table t3; -# -# A few special cases when using SAVEPOINT/ROLLBACK TO -# SAVEPOINT and HANDLER. -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction doesn't release mdl lock on -# the HANDLER that was opened later. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -begin; -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: -drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction works properly (no valgrind warnins, etc), -# even though it's done after the HANDLER mdl lock that was there -# at the beginning is released and added again. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -create table t3 like t1; -insert into t3 (a) select a from t1; -begin; -handler t1 open; -savepoint sv; -handler t1 read a first; -a -1 -select * from t2; -a -handler t1 close; -handler t3 open; -handler t3 read a first; -a -1 -rollback to savepoint sv; -connection con1; -drop table t1, t2; -# Sending: -drop table t3; -# Let DROP TABLE statement sync in. -connection con2; -# Waiting for 'drop table t3' to get blocked... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t3 read a next; -a -2 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t3 close; -connection con1; -# Reaping 'drop table t3'... -connection default; -commit; # # If we have to wait on an exclusive locks while having # an open HANDLER, ER_LOCK_DEADLOCK is reported. diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result index 9026f917245..dac6b2e997b 100644 --- a/mysql-test/suite/handler/innodb.result +++ b/mysql-test/suite/handler/innodb.result @@ -1136,166 +1136,7 @@ connection default; # Reaping 'select * from t2' ERROR 42S02: Table 'test.t2' doesn't exist handler t1 close; -# -# ROLLBACK TO SAVEPOINT releases transactional locks, -# but has no effect on open HANDLERs -# -create table t2 like t1; -create table t3 like t1; -begin; -# Have something before the savepoint -select * from t3; -a -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -drop table t3; -# -# A few special cases when using SAVEPOINT/ROLLBACK TO -# SAVEPOINT and HANDLER. -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction doesn't release mdl lock on -# the HANDLER that was opened later. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -begin; -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: -drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction works properly (no valgrind warnins, etc), -# even though it's done after the HANDLER mdl lock that was there -# at the beginning is released and added again. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -create table t3 like t1; -insert into t3 (a) select a from t1; -begin; -handler t1 open; -savepoint sv; -handler t1 read a first; -a -1 -select * from t2; -a -handler t1 close; -handler t3 open; -handler t3 read a first; -a -1 -rollback to savepoint sv; -connection con1; -drop table t1, t2; -# Sending: -drop table t3; -# Let DROP TABLE statement sync in. -connection con2; -# Waiting for 'drop table t3' to get blocked... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t3 read a next; -a -2 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t3 close; -connection con1; -# Reaping 'drop table t3'... -connection default; -commit; # # If we have to wait on an exclusive locks while having # an open HANDLER, ER_LOCK_DEADLOCK is reported. @@ -1742,6 +1583,185 @@ HANDLER t1 READ a NEXT; a HANDLER t1 CLOSE; DROP TABLE t1; +# +# Testing savepoints with handlers that supports it +# +connect con1, localhost, root,,; +connect con2, localhost, root,,; +connect con3, localhost, root,,; +connection default; +# +# ROLLBACK TO SAVEPOINT releases transactional locks, +# but has no effect on open HANDLERs +# +create table t1 (a int, key a (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +create table t3 like t1; +begin; +# Have something before the savepoint +select * from t3; +a +savepoint sv; +handler t1 open; +handler t1 read a first; +a +1 +handler t1 read a next; +a +2 +select * from t2; +a +connection con1; +# Sending: +drop table t1; +connection con2; +# Sending: +drop table t2; +connection default; +# Let DROP TABLE statements sync in. We must use +# a separate connection for that, because otherwise SELECT +# will auto-close the HANDLERs, becaues there are pending +# exclusive locks against them. +connection con3; +# Waiting for 'drop table t1' to get blocked... +# Waiting for 'drop table t2' to get blocked... +# Demonstrate that t2 lock was released and t2 was dropped +# after ROLLBACK TO SAVEPOINT +connection default; +rollback to savepoint sv; +connection con2; +# Reaping 'drop table t2'... +# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +# lock. +connection default; +handler t1 read a next; +a +3 +handler t1 read a next; +a +4 +# Demonstrate that the drop will go through as soon as we close the +# HANDLER +handler t1 close; +connection con1; +# Reaping 'drop table t1'... +connection default; +commit; +drop table t3; +# +# A few special cases when using SAVEPOINT/ROLLBACK TO +# SAVEPOINT and HANDLER. +# +# Show that rollback to the savepoint taken in the beginning +# of the transaction doesn't release mdl lock on +# the HANDLER that was opened later. +# +create table t1 (a int, key using btree (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +begin; +savepoint sv; +handler t1 open; +handler t1 read a first; +a +1 +handler t1 read a next; +a +2 +select * from t2; +a +connection con1; +# Sending: +drop table t1; +connection con2; +# Sending: +drop table t2; +connection default; +# Let DROP TABLE statements sync in. We must use +# a separate connection for that, because otherwise SELECT +# will auto-close the HANDLERs, becaues there are pending +# exclusive locks against them. +connection con3; +# Waiting for 'drop table t1' to get blocked... +# Waiting for 'drop table t2' to get blocked... +# Demonstrate that t2 lock was released and t2 was dropped +# after ROLLBACK TO SAVEPOINT +connection default; +rollback to savepoint sv; +connection con2; +# Reaping 'drop table t2'... +# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +# lock. +connection default; +handler t1 read a next; +a +3 +handler t1 read a next; +a +4 +# Demonstrate that the drop will go through as soon as we close the +# HANDLER +handler t1 close; +connection con1; +# Reaping 'drop table t1'... +connection default; +commit; +# +# Show that rollback to the savepoint taken in the beginning +# of the transaction works properly (no valgrind warnins, etc), +# even though it's done after the HANDLER mdl lock that was there +# at the beginning is released and added again. +# +create table t1 (a int, key using btree (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +create table t3 like t1; +insert into t3 (a) select a from t1; +begin; +handler t1 open; +savepoint sv; +handler t1 read a first; +a +1 +select * from t2; +a +handler t1 close; +handler t3 open; +handler t3 read a first; +a +1 +rollback to savepoint sv; +connection con1; +drop table t1, t2; +# Sending: +drop table t3; +# Let DROP TABLE statement sync in. +connection con2; +# Waiting for 'drop table t3' to get blocked... +# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +# lock. +connection default; +handler t3 read a next; +a +2 +# Demonstrate that the drop will go through as soon as we close the +# HANDLER +handler t3 close; +connection con1; +# Reaping 'drop table t3'... +connection default; +commit; +# +# Cleanup for savepoint.inc +# +connection con1; +disconnect con1; +connection con2; +disconnect con2; +connection con3; +disconnect con3; +connection default; CREATE TABLE t1 (f1 integer, f2 integer, primary key (f1), key (f2)) engine=innodb; INSERT INTO t1 VALUES (1,1),(2,2),(3,3); HANDLER t1 OPEN; diff --git a/mysql-test/suite/handler/innodb.test b/mysql-test/suite/handler/innodb.test index 6527c4bb8bb..5c2dae8a146 100644 --- a/mysql-test/suite/handler/innodb.test +++ b/mysql-test/suite/handler/innodb.test @@ -15,6 +15,7 @@ let $engine_type= InnoDB; --source init.inc --source handler.inc +--source savepoint.inc # # LP#697610 ha_index_prev(uchar*): Assertion `inited==INDEX' diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result index 4fb600050ee..896908e1602 100644 --- a/mysql-test/suite/handler/myisam.result +++ b/mysql-test/suite/handler/myisam.result @@ -1132,166 +1132,7 @@ connection default; # Reaping 'select * from t2' ERROR 42S02: Table 'test.t2' doesn't exist handler t1 close; -# -# ROLLBACK TO SAVEPOINT releases transactional locks, -# but has no effect on open HANDLERs -# -create table t2 like t1; -create table t3 like t1; -begin; -# Have something before the savepoint -select * from t3; -a -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -drop table t3; -# -# A few special cases when using SAVEPOINT/ROLLBACK TO -# SAVEPOINT and HANDLER. -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction doesn't release mdl lock on -# the HANDLER that was opened later. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -begin; -savepoint sv; -handler t1 open; -handler t1 read a first; -a -1 -handler t1 read a next; -a -2 -select * from t2; -a -connection con1; -# Sending: -drop table t1; -connection con2; -# Sending: -drop table t2; -connection default; -# Let DROP TABLE statements sync in. We must use -# a separate connection for that, because otherwise SELECT -# will auto-close the HANDLERs, becaues there are pending -# exclusive locks against them. -connection con3; -# Waiting for 'drop table t1' to get blocked... -# Waiting for 'drop table t2' to get blocked... -# Demonstrate that t2 lock was released and t2 was dropped -# after ROLLBACK TO SAVEPOINT -connection default; -rollback to savepoint sv; -connection con2; -# Reaping 'drop table t2'... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t1 read a next; -a -3 -handler t1 read a next; -a -4 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t1 close; -connection con1; -# Reaping 'drop table t1'... -connection default; -commit; -# -# Show that rollback to the savepoint taken in the beginning -# of the transaction works properly (no valgrind warnins, etc), -# even though it's done after the HANDLER mdl lock that was there -# at the beginning is released and added again. -# -create table t1 (a int, key using btree (a)); -insert into t1 (a) values (1), (2), (3), (4), (5); -create table t2 like t1; -create table t3 like t1; -insert into t3 (a) select a from t1; -begin; -handler t1 open; -savepoint sv; -handler t1 read a first; -a -1 -select * from t2; -a -handler t1 close; -handler t3 open; -handler t3 read a first; -a -1 -rollback to savepoint sv; -connection con1; -drop table t1, t2; -# Sending: -drop table t3; -# Let DROP TABLE statement sync in. -connection con2; -# Waiting for 'drop table t3' to get blocked... -# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler -# lock. -connection default; -handler t3 read a next; -a -2 -# Demonstrate that the drop will go through as soon as we close the -# HANDLER -handler t3 close; -connection con1; -# Reaping 'drop table t3'... -connection default; -commit; # # If we have to wait on an exclusive locks while having # an open HANDLER, ER_LOCK_DEADLOCK is reported. diff --git a/mysql-test/suite/handler/savepoint.inc b/mysql-test/suite/handler/savepoint.inc new file mode 100644 index 00000000000..a237183ef11 --- /dev/null +++ b/mysql-test/suite/handler/savepoint.inc @@ -0,0 +1,182 @@ +--echo # +--echo # Testing savepoints with handlers that supports it +--echo # +connect(con1, localhost, root,,); +connect(con2, localhost, root,,); +connect(con3, localhost, root,,); +connection default; +--echo # +--echo # ROLLBACK TO SAVEPOINT releases transactional locks, +--echo # but has no effect on open HANDLERs +--echo # +create table t1 (a int, key a (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +create table t3 like t1; +begin; +--echo # Have something before the savepoint +select * from t3; +savepoint sv; +handler t1 open; +handler t1 read a first; +handler t1 read a next; +select * from t2; +connection con1; +--echo # Sending: +--send drop table t1 +connection con2; +--echo # Sending: +--send drop table t2 +connection default; +--echo # Let DROP TABLE statements sync in. We must use +--echo # a separate connection for that, because otherwise SELECT +--echo # will auto-close the HANDLERs, becaues there are pending +--echo # exclusive locks against them. +connection con3; +--echo # Waiting for 'drop table t1' to get blocked... +let $wait_condition=select count(*)=1 from information_schema.processlist + where state='Waiting for table metadata lock' and + info='drop table t1'; +--source include/wait_condition.inc +--echo # Waiting for 'drop table t2' to get blocked... +let $wait_condition=select count(*)=1 from information_schema.processlist + where state='Waiting for table metadata lock' and + info='drop table t2'; +--source include/wait_condition.inc +--echo # Demonstrate that t2 lock was released and t2 was dropped +--echo # after ROLLBACK TO SAVEPOINT +connection default; +rollback to savepoint sv; +connection con2; +--echo # Reaping 'drop table t2'... +--reap +--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +--echo # lock. +connection default; +handler t1 read a next; +handler t1 read a next; +--echo # Demonstrate that the drop will go through as soon as we close the +--echo # HANDLER +handler t1 close; +connection con1; +--echo # Reaping 'drop table t1'... +--reap +connection default; +commit; +drop table t3; +--echo # +--echo # A few special cases when using SAVEPOINT/ROLLBACK TO +--echo # SAVEPOINT and HANDLER. +--echo # +--echo # Show that rollback to the savepoint taken in the beginning +--echo # of the transaction doesn't release mdl lock on +--echo # the HANDLER that was opened later. +--echo # +create table t1 (a int, key using btree (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +begin; +savepoint sv; +handler t1 open; +handler t1 read a first; +handler t1 read a next; +select * from t2; +connection con1; +--echo # Sending: +--send drop table t1 +connection con2; +--echo # Sending: +--send drop table t2 +connection default; +--echo # Let DROP TABLE statements sync in. We must use +--echo # a separate connection for that, because otherwise SELECT +--echo # will auto-close the HANDLERs, becaues there are pending +--echo # exclusive locks against them. +connection con3; +--echo # Waiting for 'drop table t1' to get blocked... +let $wait_condition=select count(*)=1 from information_schema.processlist + where state='Waiting for table metadata lock' and + info='drop table t1'; +--source include/wait_condition.inc +--echo # Waiting for 'drop table t2' to get blocked... +let $wait_condition=select count(*)=1 from information_schema.processlist + where state='Waiting for table metadata lock' and + info='drop table t2'; +--source include/wait_condition.inc +--echo # Demonstrate that t2 lock was released and t2 was dropped +--echo # after ROLLBACK TO SAVEPOINT +connection default; +rollback to savepoint sv; +connection con2; +--echo # Reaping 'drop table t2'... +--reap +--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +--echo # lock. +connection default; +handler t1 read a next; +handler t1 read a next; +--echo # Demonstrate that the drop will go through as soon as we close the +--echo # HANDLER +handler t1 close; +connection con1; +--echo # Reaping 'drop table t1'... +--reap +connection default; +commit; +--echo # +--echo # Show that rollback to the savepoint taken in the beginning +--echo # of the transaction works properly (no valgrind warnins, etc), +--echo # even though it's done after the HANDLER mdl lock that was there +--echo # at the beginning is released and added again. +--echo # +create table t1 (a int, key using btree (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +create table t2 like t1; +create table t3 like t1; +insert into t3 (a) select a from t1; +begin; +handler t1 open; +savepoint sv; +handler t1 read a first; +select * from t2; +handler t1 close; +handler t3 open; +handler t3 read a first; +rollback to savepoint sv; +connection con1; +drop table t1, t2; +--echo # Sending: +--send drop table t3 +--echo # Let DROP TABLE statement sync in. +connection con2; +--echo # Waiting for 'drop table t3' to get blocked... +let $wait_condition=select count(*)=1 from information_schema.processlist + where state='Waiting for table metadata lock' and + info='drop table t3'; +--source include/wait_condition.inc +--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler +--echo # lock. +connection default; +handler t3 read a next; +--echo # Demonstrate that the drop will go through as soon as we close the +--echo # HANDLER +handler t3 close; +connection con1; +--echo # Reaping 'drop table t3'... +--reap +connection default; +commit; + +--echo # +--echo # Cleanup for savepoint.inc +--echo # +connection con1; +disconnect con1; +--source include/wait_until_disconnected.inc +connection con2; +disconnect con2; +--source include/wait_until_disconnected.inc +connection con3; +disconnect con3; +--source include/wait_until_disconnected.inc +connection default; diff --git a/mysql-test/suite/innodb/disabled.def b/mysql-test/suite/innodb/disabled.def index 35c941f8af7..fd5a8ab6d39 100644 --- a/mysql-test/suite/innodb/disabled.def +++ b/mysql-test/suite/innodb/disabled.def @@ -11,3 +11,5 @@ ############################################################################## create-index-debug : MDEV-13680 InnoDB may crash when btr_page_alloc() fails +innodb_force_recovery_rollback : MDEV-22889 InnoDB occasionally breaks ACID +innodb_scrub : MDEV-8139/MDEV-22970 Fix scrubbing diff --git a/mysql-test/suite/innodb/r/alter_crash.result b/mysql-test/suite/innodb/r/alter_crash.result index 322caa66b07..bf593c6acca 100644 --- a/mysql-test/suite/innodb/r/alter_crash.result +++ b/mysql-test/suite/innodb/r/alter_crash.result @@ -152,3 +152,41 @@ SELECT * FROM t1; a b d 1 NULL NULL DROP TABLE t1; +# +# MDEV-22637 Rollback of insert fails when column reorder happens +# +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_TRANS_TABLES', ''); +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_ALL_TABLES', ''); +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100), +f3 CHAR(100), f4 CHAR(100))ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, "This is column2", "This is column3", +"This is column4"); +set DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; +ALTER TABLE t1 ADD COLUMN f6 int after f3, add primary key(f6, f4(3), f3(3)); +connect con1,localhost,root,,; +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +BEGIN; +INSERT INTO t1(f1, f2) VALUES(2, "This is column2 value"); +ROLLBACK; +set DEBUG_SYNC = 'now SIGNAL insert_done'; +connection default; +Warnings: +Warning 1265 Data truncated for column 'f3' at row 3 +Warning 1265 Data truncated for column 'f4' at row 3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` char(100) DEFAULT NULL, + `f3` char(100) NOT NULL, + `f6` int(11) NOT NULL, + `f4` char(100) NOT NULL, + PRIMARY KEY (`f6`,`f4`(3),`f3`(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +disconnect con1; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; +SET SQL_MODE=DEFAULT; diff --git a/mysql-test/suite/innodb/r/analyze_table.result b/mysql-test/suite/innodb/r/analyze_table.result index 57095b725eb..830130821da 100644 --- a/mysql-test/suite/innodb/r/analyze_table.result +++ b/mysql-test/suite/innodb/r/analyze_table.result @@ -1,26 +1,16 @@ -CREATE PROCEDURE populate_t1() -BEGIN -DECLARE i int DEFAULT 1; -START TRANSACTION; -WHILE (i <= 1000000) DO -INSERT INTO t1 VALUES (i, i, CONCAT('a', i)); -SET i = i + 1; -END WHILE; -COMMIT; -END| +set use_stat_tables='preferably'; CREATE TABLE t1( class INT, id INT, title VARCHAR(100) ) ENGINE=InnoDB; +insert into t1 select seq, seq, concat('a', seq) from seq_1_to_500; SELECT COUNT(*) FROM t1; COUNT(*) -1000000 -SET GLOBAL innodb_stats_persistent_sample_pages=2000; +500 +set @@max_heap_table_size=16384; ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; -DROP PROCEDURE populate_t1; -SET GLOBAL innodb_stats_persistent_sample_pages=default; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 0f85b88483f..00563d397f3 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -766,3 +766,21 @@ ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (b); ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") DROP TABLE t1; # End of 10.5 tests +# +# MDEV-22602 Disable UPDATE CASCADE for SQL constraints +# +# TODO: enable them after MDEV-16417 is finished +create or replace table t1 (a int primary key) engine=innodb; +create or replace table t2 (a int, check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb; +ERROR HY000: Function or expression 'a' cannot be used in the CHECK clause of `CONSTRAINT_1` +create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb; +create or replace table t2 ( +a int, s date, e date, +period for p (s, e), +primary key (a, p without overlaps), +foreign key (a, e, s) references t1 (f1, f3, f2) on delete cascade on update cascade) engine=innodb; +ERROR HY000: Key `PRIMARY` cannot have WITHOUT OVERLAPS +create or replace table t1 (a varchar(4096) unique) engine=innodb; +create or replace table t2 (pk int primary key, a varchar(4096) unique, foreign key(a) references t1(a) on update cascade) engine=innodb; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +drop table t1; diff --git a/mysql-test/suite/innodb/r/information_schema_grants.result b/mysql-test/suite/innodb/r/information_schema_grants.result index 25eb1c632bd..622faa2920a 100644 --- a/mysql-test/suite/innodb/r/information_schema_grants.result +++ b/mysql-test/suite/innodb/r/information_schema_grants.result @@ -276,9 +276,9 @@ select count(*) > -1 from d_sys_virtual; count(*) > -1 1 select count(*) > -1 from information_schema.innodb_tablespaces_encryption; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation +ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation select count(*) > -1 from i_tablespaces_encryption; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation +ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation select count(*) > -1 from d_tablespaces_encryption; count(*) > -1 1 diff --git a/mysql-test/suite/innodb/r/innodb-alter-debug.result b/mysql-test/suite/innodb/r/innodb-alter-debug.result index 48722bbea44..4644c124a45 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-debug.result +++ b/mysql-test/suite/innodb/r/innodb-alter-debug.result @@ -105,5 +105,5 @@ CREATE TABLE t (c1 INT, c2 INT, KEY i2 (c2)) ENGINE=INNODB; SET DEBUG_DBUG= '+d,ib_rename_index_fail1'; ALTER TABLE t RENAME INDEX i2 to x, ALGORITHM=INPLACE; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SET DEBUG_DBUG= '-d,ib_rename_index_fail1'; +SET DEBUG_DBUG = @saved_debug_dbug; DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result index b6e164a33f0..d3c1aa77eaf 100644 --- a/mysql-test/suite/innodb/r/innodb-fk.result +++ b/mysql-test/suite/innodb/r/innodb-fk.result @@ -199,3 +199,10 @@ b char(255), FOREIGN KEY ( a012345678901234567890123456789012345678901, b ) REFERENCES tx (ax, bx) ) ENGINE=InnoDB; ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +CREATE TABLE t1 ( +a012345678901234567 int, +b int, +c0123456789012345678 int, +FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3) +) ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 76dedbf2495..1cd62911e81 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -3130,8 +3130,7 @@ SET TX_ISOLATION='read-committed'; SET AUTOCOMMIT=0; DROP TABLE IF EXISTS t1, t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' CREATE TABLE t1 ( a int ) ENGINE=InnoDB; CREATE TABLE t2 LIKE t1; SELECT * FROM t2; diff --git a/mysql-test/suite/innodb/r/innodb_bug34053.result b/mysql-test/suite/innodb/r/innodb_bug34053.result deleted file mode 100644 index 23c5b0cc2f7..00000000000 --- a/mysql-test/suite/innodb/r/innodb_bug34053.result +++ /dev/null @@ -1 +0,0 @@ -SET default_storage_engine=InnoDB; diff --git a/mysql-test/suite/innodb/r/innodb_force_recovery.result b/mysql-test/suite/innodb/r/innodb_force_recovery.result index 9d537126216..029a6f71fa3 100644 --- a/mysql-test/suite/innodb/r/innodb_force_recovery.result +++ b/mysql-test/suite/innodb/r/innodb_force_recovery.result @@ -40,7 +40,7 @@ ERROR HY000: Running in read-only mode create table t3(f1 int not null)engine=innodb; ERROR HY000: Can't create table `test`.`t3` (errno: 165 "Table is read only") drop table t3; -ERROR 42S02: Unknown table 'test.t3' +ERROR HY000: Table 't3' is read only rename table t2 to t3; ERROR HY000: Error on rename of './test/t2' to './test/t3' (errno: 165 "Table is read only") truncate table t2; diff --git a/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result b/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result new file mode 100644 index 00000000000..81fa2448e3d --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_force_recovery_rollback.result @@ -0,0 +1,18 @@ +FLUSH TABLES; +# +# MDEV-21217 innodb_force_recovery=2 may wrongly abort the rollback +# of recovered transactions +# +connect con0,localhost,root; +CREATE TABLE t0 (a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t0 SELECT * FROM seq_1_to_1000; +connection default; +SET GLOBAL innodb_flush_log_at_trx_commit=1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +# restart: --innodb-force-recovery=2 +disconnect con0; +connection default; +SELECT * FROM t0 LOCK IN SHARE MODE; +a +DROP TABLE t0,t1; diff --git a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result index 6328458d46e..46372cd85f2 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result @@ -1,35 +1,24 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; -SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; -SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; +POOL_ID POOL_SIZE FREE_BUFFERS DATABASE_PAGES OLD_DATABASE_PAGES MODIFIED_DATABASE_PAGES PENDING_DECOMPRESS PENDING_READS PENDING_FLUSH_LRU PENDING_FLUSH_LIST PAGES_MADE_YOUNG PAGES_NOT_MADE_YOUNG PAGES_MADE_YOUNG_RATE PAGES_MADE_NOT_YOUNG_RATE NUMBER_PAGES_READ NUMBER_PAGES_CREATED NUMBER_PAGES_WRITTEN PAGES_READ_RATE PAGES_CREATE_RATE PAGES_WRITTEN_RATE NUMBER_PAGES_GET HIT_RATE YOUNG_MAKE_PER_THOUSAND_GETS NOT_YOUNG_MAKE_PER_THOUSAND_GETS NUMBER_PAGES_READ_AHEAD NUMBER_READ_AHEAD_EVICTED READ_AHEAD_RATE READ_AHEAD_EVICTED_RATE LRU_IO_TOTAL LRU_IO_CURRENT UNCOMPRESS_TOTAL UNCOMPRESS_CURRENT +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; INSERT INTO infoschema_buffer_test VALUES(9); -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" - and PAGE_STATE="file_page" and PAGE_TYPE="index"; -TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE -`test`.`infoschema_buffer_test` GEN_CLUST_INDEX 1 29 FILE_PAGE INDEX +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; +POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK +0 # # 3 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` GEN_CLUST_INDEX 1 29 0 FILE_PAGE IO_FIX OLD # INSERT INTO infoschema_buffer_test VALUES(19); -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" -and PAGE_STATE="file_page" and PAGE_TYPE="index"; -TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE -`test`.`infoschema_buffer_test` GEN_CLUST_INDEX 2 58 FILE_PAGE INDEX CREATE INDEX idx ON infoschema_buffer_test(col1); -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" -and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; -TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE -`test`.`infoschema_buffer_test` idx 2 32 FILE_PAGE INDEX -`test`.`infoschema_buffer_test` idx 2 32 FILE_PAGE INDEX +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; +POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK +0 # # 3 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` GEN_CLUST_INDEX 2 58 0 FILE_PAGE IO_FIX OLD # +0 # # 4 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # +0 # # 5 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # DROP TABLE infoschema_buffer_test; -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%"; -TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%'; +POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), @@ -37,11 +26,10 @@ FOREIGN KEY (parent_id) REFERENCES infoschema_parent(id) ON DELETE CASCADE) ENGINE=INNODB; -SELECT count(*) -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_child%" and PAGE_STATE="file_page" -and PAGE_TYPE="index"; -count(*) -2 +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_child%'; +POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK +0 # # 3 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_child` GEN_CLUST_INDEX 0 0 0 FILE_PAGE IO_FIX OLD # +0 # # 4 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_child` par_ind 0 0 0 FILE_PAGE IO_FIX OLD # DROP TABLE infoschema_child; DROP TABLE infoschema_parent; diff --git a/mysql-test/suite/innodb/r/innodb_scrub.result b/mysql-test/suite/innodb/r/innodb_scrub.result new file mode 100644 index 00000000000..f783b9f167c --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_scrub.result @@ -0,0 +1,10 @@ +CREATE TABLE t1(f1 int auto_increment primary key, +f2 varchar(256), +f3 text) engine = innodb; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +FOUND 500500 /unicycle|repairman/ in t1.ibd +DELETE FROM t1; +InnoDB 0 transactions not purged +NOT FOUND /unicycle|repairman/ in t1.ibd +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 264968e4365..9ab72408274 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -249,8 +249,6 @@ innodb_master_active_loops server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NU innodb_master_idle_loops server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times master thread performs its tasks when server is idle innodb_background_drop_table_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to process drop table list innodb_log_flush_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to flush log records -innodb_mem_validate_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to do memory validation -innodb_master_purge_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent by master thread to purge records innodb_dict_lru_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to process DICT LRU list innodb_dict_lru_count_active server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of tables evicted from DICT LRU list in the active loop innodb_dict_lru_count_idle server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of tables evicted from DICT LRU list in the idle loop diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 9fcb8b05a34..50b69801043 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -370,3 +370,36 @@ b SET DEBUG_SYNC='RESET'; disconnect con2; DROP TABLE t1; +# +# MDEV-22867 Assertion instant.n_core_fields == n_core_fields +# in dict_index_t::instant_add_field +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SET a=1; +connect prevent_purge,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +ALTER TABLE t1 ADD COLUMN c INT; +DELETE FROM t1; +connect con2,localhost,root,,test; +ALTER TABLE t1 DROP b, ADD INDEX(c), ALGORITHM=NOCOPY; +ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL ddl WAIT_FOR emptied'; +ALTER TABLE t1 DROP b; +connection default; +SET DEBUG_SYNC='now WAIT_FOR ddl'; +BEGIN; +INSERT INTO t1 SET a=1; +connection prevent_purge; +COMMIT; +disconnect prevent_purge; +connection default; +ROLLBACK; +SELECT * FROM t1; +a b c +SET DEBUG_SYNC='now SIGNAL emptied'; +connection con2; +disconnect con2; +connection default; +DROP TABLE t1; +SET DEBUG_SYNC=RESET; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff new file mode 100644 index 00000000000..57d87f7172f --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_limit,16k.rdiff @@ -0,0 +1,13 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,16k.reject 2020-05-26 20:14:38.452463919 +0530 +@@ -45,3 +45,10 @@ + instants + 502 + DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff index 5e46c66ce73..8f8cf64b7fc 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff @@ -1,9 +1,16 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result -@@ -42,5 +42,5 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,32k.reject 2020-05-26 19:59:19.743877366 +0530 +@@ -43,5 +43,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +506 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff index b40c6482d22..dad28218a02 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff @@ -1,5 +1,5 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,4k.reject 2020-05-26 20:17:53.314736548 +0530 @@ -5,6 +5,276 @@ ENGINE=InnoDB; INSERT INTO t VALUES(1,2,3,4,5); @@ -295,10 +295,19 @@ ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE SELECT variable_value-@old_instant instants -@@ -43,5 +319,5 @@ +@@ -43,5 +319,14 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +474 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++Warnings: ++Warning 139 Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline. ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff index 5e46c66ce73..d7479dbba40 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff @@ -1,9 +1,16 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result -@@ -42,5 +42,5 @@ +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,64k.reject 2020-05-26 20:00:22.499711222 +0530 +@@ -43,5 +43,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +506 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff index f7cb7238ae3..1fe3e1a56eb 100644 --- a/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff @@ -1,5 +1,5 @@ ---- instant_alter_limit.result -+++ instant_alter_limit.result +--- instant_alter_limit.result 2020-05-26 18:01:27.377946439 +0530 ++++ instant_alter_limit,8k.reject 2020-05-26 20:19:50.881869095 +0530 @@ -5,6 +5,28 @@ ENGINE=InnoDB; INSERT INTO t VALUES(1,2,3,4,5); @@ -47,10 +47,17 @@ ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE SELECT variable_value-@old_instant instants -@@ -43,5 +71,5 @@ +@@ -43,5 +71,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -502 +492 DROP TABLE t; ++# ++# MDEV-21787 Alter table failure tries to access uninitialized column ++# ++CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; ++ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); ++ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; ++DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result index c382c1e8507..0c0168fb266 100644 --- a/mysql-test/suite/innodb/r/monitor.result +++ b/mysql-test/suite/innodb/r/monitor.result @@ -215,8 +215,6 @@ innodb_master_active_loops disabled innodb_master_idle_loops disabled innodb_background_drop_table_usec disabled innodb_log_flush_usec disabled -innodb_mem_validate_usec disabled -innodb_master_purge_usec disabled innodb_dict_lru_usec disabled innodb_dict_lru_count_active disabled innodb_dict_lru_count_idle disabled diff --git a/mysql-test/suite/innodb/r/temp_table_savepoint.result b/mysql-test/suite/innodb/r/temp_table_savepoint.result index c2bf70ca9ee..44c8db04c43 100644 --- a/mysql-test/suite/innodb/r/temp_table_savepoint.result +++ b/mysql-test/suite/innodb/r/temp_table_savepoint.result @@ -2,45 +2,6 @@ create procedure populate_tables() begin declare n int default 20; declare inner_loop int default 100; -create temporary table t1(c1 int not null, -c2 int not null, -c3 char(255) not null, -c4 text(6000) not null, -c5 blob(6000) not null, -c6 varchar(2000) not null, -c7 varchar(2000) not null, -c8 datetime, -c9 decimal(6,3), -primary key (c1), -index (c3,c4(50),c5(50)), -index (c2)) -engine=innodb row_format=redundant; -create temporary table t2(c1 int not null, -c2 int not null, -c3 char(255) not null, -c4 text(6000) not null, -c5 blob(6000) not null, -c6 varchar(2000) not null, -c7 varchar(2000) not null, -c8 datetime, -c9 decimal(6,3), -primary key (c1), -index (c3,c4(50),c5(50)), -index (c2)) -engine=innodb row_format=compact; -create temporary table t4(c1 int not null, -c2 int not null, -c3 char(255) not null, -c4 text(6000) not null, -c5 blob(6000) not null, -c6 varchar(2000) not null, -c7 varchar(2000) not null, -c8 datetime, -c9 decimal(6,3), -primary key (c1), -index (c3,c4(50),c5(50)), -index (c2)) -engine=innodb row_format=dynamic; create temporary table t5(c1 int not null, c2 int not null, c3 char(255) not null, @@ -58,18 +19,6 @@ create temporary table t6 ( a int ) engine = innodb; insert into t6 values (50),(100),(150),(190); while (n > 0) do start transaction; -insert into t1 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), -repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), -now(),(100.55+n)); -insert into t2 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), -repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), -now(),(100.55+n)); -insert ignore into t4 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), -repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), -now(),(100.55+n)); insert ignore into t5 values(n,n,repeat(concat(' tc3_',n),30), repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), @@ -77,73 +26,25 @@ now(),(100.55+n)); if (n > 10) then commit; else -delete from t1 where c1 > 10 ; -delete from t2 where c1 > 10 ; -delete from t4 where c1 > 10 ; delete from t5 where c1 > 10 ; rollback; start transaction; -update t1 set c1 = c1 + 1000 where c1 > 10; -update t2 set c1 = c1 + 1000 where c1 > 10; -update t4 set c1 = c1 + 1000 where c1 > 10; update t5 set c1 = c1 + 1000 where c1 > 10; rollback; end if; start transaction; -insert into t1 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert into t2 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert ignore into t4 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); insert ignore into t5 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), now(),(100.55+n+inner_loop)); -delete from t1 where c1 between 100 and 110; -delete from t2 where c1 between 100 and 110; -delete from t4 where c1 between 100 and 110; delete from t5 where c1 between 100 and 110; -update t1 set c1 = c1+1 where c1>110; -update t2 set c1 = c1+1 where c1>110; -update t4 set c1 = c1+1 where c1>110; update t5 set c1 = c1+1 where c1>110; savepoint a; -insert into t1 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert into t2 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert ignore into t4 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); insert ignore into t5 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), now(),(100.55+n+inner_loop)); savepoint b; -insert into t1 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert into t2 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), -repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), -now(),(100.55+n+inner_loop)); -insert into t4 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); insert into t5 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), @@ -162,84 +63,6 @@ call populate_tables();; connect con2,localhost,root,,; call populate_tables();; connection con1; -select count(*) from t1; -count(*) -20 -select count(*) from t2; -count(*) -20 -select count(*) from t4; -count(*) -20 -select count(*) from t5; -count(*) -20 -select c1 from t1; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -select c1 from t2; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -select c1 from t4; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 select c1 from t5; c1 11 @@ -263,84 +86,6 @@ c1 138 140 connection con2; -select count(*) from t1; -count(*) -20 -select count(*) from t2; -count(*) -20 -select count(*) from t4; -count(*) -20 -select count(*) from t5; -count(*) -20 -select c1 from t1; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -select c1 from t2; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -select c1 from t4; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 select c1 from t5; c1 11 @@ -365,89 +110,32 @@ c1 140 connection con1; set autocommit = 0; -insert into t1 values (20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t1 values (20,1,'a','a','a','a','a',now(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -insert into t2 values (20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t2 values (20,1,'a','a','a','a','a',now(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -insert into t4 values (20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t4 values (20,1,'a','a','a','a','a',now(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' insert into t5 values (20,1,'a','a','a','a','a',now(),100.55); ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert ignore into t5 values (20,1,'a','a','a','a','a',now(),100.55); Warnings: Warning 1062 Duplicate entry '20' for key 'PRIMARY' -insert into t1 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert into t2 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert into t4 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert into t5 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); ERROR 23000: Duplicate entry '20' for key 'PRIMARY' set autocommit = 1; -select c1,c2 from t1 where c1 in (20,1); -c1 c2 -20 20 -select c1,c2 from t2 where c1 in (20,1); -c1 c2 -20 20 -select c1,c2 from t4 where c1 in (20,1); -c1 c2 -20 20 select c1,c2 from t5 where c1 in (20,1); c1 c2 20 20 -replace into t1 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t2 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t4 values (20,1,'a','a','a','a','a',now(),100.55); replace into t5 values (20,1,'a','a','a','a','a',now(),100.55); -select c1,c2,c3,c4,c5,c6,c7,c9 from t1 where c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -select c1,c2,c3,c4,c5,c6,c7,c9 from t2 where c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -select c1,c2,c3,c4,c5,c6,c7,c9 from t4 where c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 select c1,c2,c3,c4,c5,c6,c7,c9 from t5 where c1 = 20; c1 c2 c3 c4 c5 c6 c7 c9 20 1 a a a a a 100.550 -update ignore t1 set c1 = 20 where c1 = 140 ; -update ignore t2 set c1 = 20 where c1 = 140 ; -update ignore t4 set c1 = 20 where c1 = 140 ; update ignore t5 set c1 = 20 where c1 = 140 ; -select count(*) from t1 where c1 = 140; -count(*) -1 -select count(*) from t2 where c1 = 140; -count(*) -1 -select count(*) from t4 where c1 = 140; -count(*) -1 select count(*) from t5 where c1 = 140; count(*) 1 -select * into outfile "VARDIR/tmp/t1.outfile" from t1; -create temporary table temp_1 engine = innodb as select * from t1 where 1=2; +select * into outfile "VARDIR/tmp/t5.outfile" from t5; +create temporary table temp_1 engine = innodb as select * from t5 where 1=2; select count(*) from temp_1; count(*) 0 -load data infile 'VARDIR/tmp/t1.outfile' into table temp_1; +load data infile 'VARDIR/tmp/t5.outfile' into table temp_1; select count(*) from temp_1; count(*) 20 diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result index b559de388e2..ed9f19b7eb3 100644 --- a/mysql-test/suite/innodb/r/xa_recovery.result +++ b/mysql-test/suite/innodb/r/xa_recovery.result @@ -5,12 +5,20 @@ XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; +connect con2,localhost,root; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +XA START 'y'; +INSERT INTO t2 VALUES (1); +XA END 'y'; +XA PREPARE 'y'; connection default; # restart: --innodb-force-recovery=2 disconnect con1; +disconnect con2; connect con1,localhost,root; SELECT * FROM t1 LOCK IN SHARE MODE; connection default; +DROP TABLE t2; # restart disconnect con1; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; @@ -22,3 +30,6 @@ SELECT * FROM t1; a 1 DROP TABLE t1; +SET GLOBAL innodb_fast_shutdown=0; +# restart +XA ROLLBACK 'y'; diff --git a/mysql-test/suite/innodb/t/alter_crash.test b/mysql-test/suite/innodb/t/alter_crash.test index c7cd1bcfe66..72116b0ca9d 100644 --- a/mysql-test/suite/innodb/t/alter_crash.test +++ b/mysql-test/suite/innodb/t/alter_crash.test @@ -196,3 +196,30 @@ SHOW CREATE TABLE t1; UPDATE t1 SET d=NULL; SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-22637 Rollback of insert fails when column reorder happens +--echo # +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_TRANS_TABLES', ''); +SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'STRICT_ALL_TABLES', ''); +CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100), + f3 CHAR(100), f4 CHAR(100))ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, "This is column2", "This is column3", + "This is column4"); +set DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done'; +--send ALTER TABLE t1 ADD COLUMN f6 int after f3, add primary key(f6, f4(3), f3(3)) +connect(con1,localhost,root,,); +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +BEGIN; +INSERT INTO t1(f1, f2) VALUES(2, "This is column2 value"); +ROLLBACK; +set DEBUG_SYNC = 'now SIGNAL insert_done'; + +connection default; +reap; +SHOW CREATE TABLE t1; +SELECT COUNT(*) FROM t1; +disconnect con1; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; +SET SQL_MODE=DEFAULT; diff --git a/mysql-test/suite/innodb/t/analyze_table.test b/mysql-test/suite/innodb/t/analyze_table.test index e9db3668f02..538eed04ba4 100644 --- a/mysql-test/suite/innodb/t/analyze_table.test +++ b/mysql-test/suite/innodb/t/analyze_table.test @@ -1,23 +1,11 @@ -# -# BUG#22385442 - INNODB: DIFFICULT TO FIND FREE BLOCKS IN THE BUFFER POOL -# - --source include/have_innodb.inc ---source include/big_test.inc +--source include/have_sequence.inc -DELIMITER |; -CREATE PROCEDURE populate_t1() -BEGIN - DECLARE i int DEFAULT 1; +# +# MDEV-22073 MSAN use-of-uninitialized-value in collect_statistics_for_table() +# - START TRANSACTION; - WHILE (i <= 1000000) DO - INSERT INTO t1 VALUES (i, i, CONCAT('a', i)); - SET i = i + 1; - END WHILE; - COMMIT; -END| -DELIMITER ;| +set use_stat_tables='preferably'; CREATE TABLE t1( class INT, @@ -25,18 +13,11 @@ CREATE TABLE t1( title VARCHAR(100) ) ENGINE=InnoDB; --- disable_query_log -CALL populate_t1(); --- enable_query_log +insert into t1 select seq, seq, concat('a', seq) from seq_1_to_500; SELECT COUNT(*) FROM t1; -SET GLOBAL innodb_stats_persistent_sample_pages=2000; - +set @@max_heap_table_size=16384; ANALYZE TABLE t1; DROP TABLE t1; - -DROP PROCEDURE populate_t1; - -SET GLOBAL innodb_stats_persistent_sample_pages=default; diff --git a/mysql-test/suite/innodb/t/corrupted_during_recovery.test b/mysql-test/suite/innodb/t/corrupted_during_recovery.test index 5f1de1bedf9..31fd1f18b8a 100644 --- a/mysql-test/suite/innodb/t/corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/corrupted_during_recovery.test @@ -4,8 +4,8 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page"); -call mtr.add_suppression("InnoDB: Failed to read file '.*test.t1\\.ibd' at offset 3: Page read from tablespace is corrupted."); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); +call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted."); call mtr.add_suppression("InnoDB: Background Page read failed to read or decrypt \\[page id: space=\\d+, page number=3\\]"); call mtr.add_suppression("InnoDB: Table `test`.`t1` is corrupted. Please drop the table and recreate."); --enable_query_log diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index c75206981af..4719384cd65 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -741,4 +741,27 @@ DROP TABLE t1; --echo # End of 10.5 tests +--echo # +--echo # MDEV-22602 Disable UPDATE CASCADE for SQL constraints +--echo # +--echo # TODO: enable them after MDEV-16417 is finished +create or replace table t1 (a int primary key) engine=innodb; +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +create or replace table t2 (a int, check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb; + +create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb; +--error ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS +create or replace table t2 ( + a int, s date, e date, + period for p (s, e), + primary key (a, p without overlaps), + foreign key (a, e, s) references t1 (f1, f3, f2) on delete cascade on update cascade) engine=innodb; + +# FK on long unique is already disabled +create or replace table t1 (a varchar(4096) unique) engine=innodb; +--error ER_CANT_CREATE_TABLE +create or replace table t2 (pk int primary key, a varchar(4096) unique, foreign key(a) references t1(a) on update cascade) engine=innodb; + +drop table t1; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-alter-debug.test b/mysql-test/suite/innodb/t/innodb-alter-debug.test index 792716aeb4e..7fbbb3159ee 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-debug.test +++ b/mysql-test/suite/innodb/t/innodb-alter-debug.test @@ -130,9 +130,6 @@ reap; UNLOCK TABLES; DROP TABLE t1; -# Wait till all disconnects are completed ---source include/wait_until_count_sessions.inc - --echo # --echo # MDEV-7318 RENAME INDEX --echo # @@ -141,6 +138,9 @@ CREATE TABLE t (c1 INT, c2 INT, KEY i2 (c2)) ENGINE=INNODB; SET DEBUG_DBUG= '+d,ib_rename_index_fail1'; -- error ER_LOCK_DEADLOCK ALTER TABLE t RENAME INDEX i2 to x, ALGORITHM=INPLACE; -SET DEBUG_DBUG= '-d,ib_rename_index_fail1'; +SET DEBUG_DBUG = @saved_debug_dbug; DROP TABLE t; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test index 4069e02d9b7..fcab4b22eb1 100644 --- a/mysql-test/suite/innodb/t/innodb-fk.test +++ b/mysql-test/suite/innodb/t/innodb-fk.test @@ -236,3 +236,11 @@ CREATE TABLE t1 ( b char(255), FOREIGN KEY ( a012345678901234567890123456789012345678901, b ) REFERENCES tx (ax, bx) ) ENGINE=InnoDB; + +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1 ( + a012345678901234567 int, + b int, + c0123456789012345678 int, + FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3) +) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/t/innodb_bug14147491.test b/mysql-test/suite/innodb/t/innodb_bug14147491.test index 44b9d16ca78..c6e4f01a642 100644 --- a/mysql-test/suite/innodb/t/innodb_bug14147491.test +++ b/mysql-test/suite/innodb/t/innodb_bug14147491.test @@ -9,7 +9,7 @@ --disable_query_log call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted\\. Please drop the table and recreate\\."); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); call mtr.add_suppression("InnoDB: We detected index corruption in an InnoDB type table"); call mtr.add_suppression("Index for table 't1' is corrupt; try to repair it"); --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb_bug34053.test b/mysql-test/suite/innodb/t/innodb_bug34053.test deleted file mode 100644 index d93d5100d81..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug34053.test +++ /dev/null @@ -1,57 +0,0 @@ -# -# Make sure http://bugs.mysql.com/34053 remains fixed. -# - --- source include/not_embedded.inc --- source include/have_innodb.inc - -SET default_storage_engine=InnoDB; - -# we do not really care about what gets printed, we are only -# interested in getting success or failure according to our -# expectations --- disable_query_log --- disable_result_log - -GRANT USAGE ON *.* TO 'shane'@'localhost' IDENTIFIED BY '12345'; -FLUSH PRIVILEGES; - --- connect (con1,localhost,shane,12345,) - --- connection con1 --- error ER_SPECIFIC_ACCESS_DENIED_ERROR -SET GLOBAL innodb_status_output=ON; --- error ER_SPECIFIC_ACCESS_DENIED_ERROR -SET GLOBAL innodb_status_output_locks=ON; - -CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB; -DROP TABLE innodb_monitor; -CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB; -DROP TABLE innodb_mem_validate; -CREATE TABLE innodb_sql (a INT) ENGINE=INNODB; -DROP TABLE innodb_sql; -CREATE TABLE innodb_monitorx (a INT) ENGINE=INNODB; -DROP TABLE innodb_monitorx; -CREATE TABLE innodb_monito (a INT) ENGINE=INNODB; -DROP TABLE innodb_monito; -CREATE TABLE xinnodb_monitor (a INT) ENGINE=INNODB; -DROP TABLE xinnodb_monitor; -CREATE TABLE nnodb_monitor (a INT) ENGINE=INNODB; -DROP TABLE nnodb_monitor; - --- connection default -SET GLOBAL innodb_status_output=ON; -SET GLOBAL innodb_status_output_locks=ON; - --- connection con1 --- error ER_SPECIFIC_ACCESS_DENIED_ERROR -SET GLOBAL innodb_status_output=OFF; --- error ER_SPECIFIC_ACCESS_DENIED_ERROR -SET GLOBAL innodb_status_output_locks=OFF; - --- connection default -SET GLOBAL innodb_status_output=OFF; -SET GLOBAL innodb_status_output_locks=OFF; -DROP USER 'shane'@'localhost'; - --- disconnect con1 diff --git a/mysql-test/suite/innodb/t/innodb_force_recovery.test b/mysql-test/suite/innodb/t/innodb_force_recovery.test index bd9554e6b6e..76baf55af83 100644 --- a/mysql-test/suite/innodb/t/innodb_force_recovery.test +++ b/mysql-test/suite/innodb/t/innodb_force_recovery.test @@ -68,7 +68,7 @@ update t2 set f1=3 where f2=2; --error ER_CANT_CREATE_TABLE create table t3(f1 int not null)engine=innodb; ---error ER_BAD_TABLE_ERROR +--error ER_OPEN_AS_READONLY drop table t3; --error ER_ERROR_ON_RENAME diff --git a/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test b/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test new file mode 100644 index 00000000000..ad234eba72e --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_force_recovery_rollback.test @@ -0,0 +1,34 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc + +# We will kill and restart the server. +--source include/not_embedded.inc +FLUSH TABLES; + +--echo # +--echo # MDEV-21217 innodb_force_recovery=2 may wrongly abort the rollback +--echo # of recovered transactions +--echo # + +connect (con0,localhost,root); +CREATE TABLE t0 (a INT PRIMARY KEY) ENGINE=InnoDB; +# Create enough undo log so that the rollback may take enough time. +BEGIN; +INSERT INTO t0 SELECT * FROM seq_1_to_1000; + +connection default; +# Persist the above incomplete transaction. +SET GLOBAL innodb_flush_log_at_trx_commit=1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; + +--let $restart_parameters= --innodb-force-recovery=2 +--let $shutdown_timeout=0 +--source include/restart_mysqld.inc +--let $restart_parameters= +--let $shutdown_timeout= + +disconnect con0; +connection default; +# If the rollback was aborted, we would end up in a lock wait here. +SELECT * FROM t0 LOCK IN SHARE MODE; +DROP TABLE t0,t1; diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test index 5bfac22ec39..7f0d4f0a737 100644 --- a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test +++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test @@ -8,19 +8,9 @@ -- source include/have_innodb.inc --- disable_result_log +--replace_regex /([0-9]*\.)?[0-9]+/#/ SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; -# How many buffer pools we have -SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; - -SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; - -# This gives the over all buffer pool size -SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; - --- enable_result_log - # Create a table and check its page info behave correctly in the pool CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; @@ -28,36 +18,27 @@ INSERT INTO infoschema_buffer_test VALUES(9); # We should be able to see this table in the buffer pool if we check # right away -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" - and PAGE_STATE="file_page" and PAGE_TYPE="index"; +--sorted_result +--replace_column 2 # 3 # 7 FIX 8 AHI 9 LSN 10 LSN 11 TIME 18 IO_FIX 19 OLD 20 # +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; # The NUMBER_RECORDS and DATA_SIZE should check with each insertion INSERT INTO infoschema_buffer_test VALUES(19); -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" -and PAGE_STATE="file_page" and PAGE_TYPE="index"; - CREATE INDEX idx ON infoschema_buffer_test(col1); -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%" -and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; - +--sorted_result +--replace_column 2 # 3 # 7 FIX 8 AHI 9 LSN 10 LSN 11 TIME 18 IO_FIX 19 OLD 20 # +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; # Check the buffer after dropping the table DROP TABLE infoschema_buffer_test; -SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_buffer_test%"; +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_buffer_test%'; -# Do one more test -#--replace_regex /'*[0-9]*'/'NUM'/ CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; @@ -67,11 +48,10 @@ CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), ON DELETE CASCADE) ENGINE=INNODB; -SELECT count(*) -FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE -WHERE TABLE_NAME like "%infoschema_child%" and PAGE_STATE="file_page" -and PAGE_TYPE="index"; +--sorted_result +--replace_column 2 # 3 # 7 FIX 8 AHI 9 LSN 10 LSN 11 TIME 18 IO_FIX 19 OLD 20 # +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME LIKE '%infoschema_child%'; DROP TABLE infoschema_child; DROP TABLE infoschema_parent; - diff --git a/mysql-test/suite/innodb/t/innodb_scrub.opt b/mysql-test/suite/innodb/t/innodb_scrub.opt new file mode 100644 index 00000000000..f9984508bde --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_scrub.opt @@ -0,0 +1 @@ +--innodb-immediate-scrub-data-uncompressed=ON diff --git a/mysql-test/suite/innodb/t/innodb_scrub.test b/mysql-test/suite/innodb/t/innodb_scrub.test new file mode 100644 index 00000000000..c1b7fb4df1d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_scrub.test @@ -0,0 +1,26 @@ +-- source include/have_innodb.inc + +let $MYSQLD_DATADIR=`select @@datadir`; +CREATE TABLE t1(f1 int auto_increment primary key, + f2 varchar(256), + f3 text) engine = innodb; +let $numinserts = 500; +--disable_query_log +begin; +while ($numinserts) +{ + dec $numinserts; + eval INSERT INTO t1(f2,f3) VALUES ('repairman', repeat('unicycle', 1000)); +} +commit; +--enable_query_log +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; + +let SEARCH_PATTERN= unicycle|repairman; +let SEARCH_FILE= $MYSQLD_DATADIR/test/t1.ibd; +-- source include/search_pattern_in_file.inc +DELETE FROM t1; +-- source include/wait_all_purged.inc +-- source include/search_pattern_in_file.inc +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index fe80de2ca51..b71e52a5f80 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -414,3 +414,46 @@ SELECT * FROM t1; SET DEBUG_SYNC='RESET'; --disconnect con2 DROP TABLE t1; + +--echo # +--echo # MDEV-22867 Assertion instant.n_core_fields == n_core_fields +--echo # in dict_index_t::instant_add_field +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SET a=1; + +connect (prevent_purge,localhost,root,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +ALTER TABLE t1 ADD COLUMN c INT; +DELETE FROM t1; + +connect (con2,localhost,root,,test); +# FIXME: If this is implemented then also i->online_log must be checked in +# dict_index_t::must_avoid_clear_instant_add(). See the comment there. +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 DROP b, ADD INDEX(c), ALGORITHM=NOCOPY; +SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL ddl WAIT_FOR emptied'; +send ALTER TABLE t1 DROP b; + +connection default; +SET DEBUG_SYNC='now WAIT_FOR ddl'; +BEGIN; +INSERT INTO t1 SET a=1; + +connection prevent_purge; +COMMIT; +disconnect prevent_purge; + +connection default; +ROLLBACK; +SELECT * FROM t1; +SET DEBUG_SYNC='now SIGNAL emptied'; + +connection con2; +reap; +disconnect con2; +connection default; +DROP TABLE t1; +SET DEBUG_SYNC=RESET; diff --git a/mysql-test/suite/innodb/t/instant_alter_limit.test b/mysql-test/suite/innodb/t/instant_alter_limit.test index e84885f88e7..b7fb3ee55c1 100644 --- a/mysql-test/suite/innodb/t/instant_alter_limit.test +++ b/mysql-test/suite/innodb/t/instant_alter_limit.test @@ -60,3 +60,17 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; DROP TABLE t; + +--echo # +--echo # MDEV-21787 Alter table failure tries to access uninitialized column +--echo # +CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT GENERATED ALWAYS AS (SUBSTR(f4, 1, 400)), f3 VARCHAR(500), f4 TEXT)ENGINE=InnoDB ROW_FORMAT=Compact; +ALTER TABLE t1 ADD UNIQUE KEY (f2(9)); +let $error_code = 0; +let $innodb_page_size = `SELECT @@INNODB_PAGE_SIZE`; +if ($innodb_page_size == 4k) { + let $error_code= ER_TOO_BIG_ROWSIZE; +} +--error $error_code +ALTER TABLE t1 ADD COLUMN f5 TEXT, ALGORITHM=INPLACE; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test index 7ffb9bb6596..b7fff30dca2 100644 --- a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test @@ -2,14 +2,14 @@ --source include/have_debug.inc --disable_query_log -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page "); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); call mtr.add_suppression("InnoDB: Background Page read failed to read or decrypt \\[page id: space=\\d+, page number=19\\]"); -call mtr.add_suppression("\\[ERROR\\] InnoDB: Failed to read file '.*test.t1\\.ibd' at offset 19: Page read from tablespace is corrupted\\."); +call mtr.add_suppression("\\[ERROR\\] InnoDB: Failed to read page 19 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted\\."); call mtr.add_suppression("\\[ERROR\\] InnoDB: Plugin initialization aborted at srv0start\\.cc.* with error Data structure corruption"); call mtr.add_suppression("\\[ERROR\\] Plugin 'InnoDB' (init function|registration)"); call mtr.add_suppression("\\[ERROR\\] InnoDB: We detected index corruption"); call mtr.add_suppression("\\[ERROR\\] (mysqld|mariadbd).*: Index for table 't1' is corrupt; try to repair it"); -call mtr.add_suppression("InnoDB: Error code: [0-9][0-9][0-9]* btr_pcur_open_low level: 0 called from file: "); +call mtr.add_suppression("InnoDB: btr_pcur_open_low level: 0 called from file: "); --enable_query_log CREATE TABLE t1 (pk INT PRIMARY KEY, c CHAR(255))ENGINE=InnoDB STATS_PERSISTENT=0; diff --git a/mysql-test/suite/innodb/t/temp_table_savepoint.test b/mysql-test/suite/innodb/t/temp_table_savepoint.test index c8a4bc870a7..ffac771ded9 100644 --- a/mysql-test/suite/innodb/t/temp_table_savepoint.test +++ b/mysql-test/suite/innodb/t/temp_table_savepoint.test @@ -1,5 +1,5 @@ --source include/have_innodb.inc ---source include/no_valgrind_without_big.inc +--source include/innodb_row_format.inc #################################################################### # TC to test temp-table DML optimization changes for correctness # @@ -28,48 +28,6 @@ create procedure populate_tables() declare n int default 20; declare inner_loop int default 100; - create temporary table t1(c1 int not null, - c2 int not null, - c3 char(255) not null, - c4 text(6000) not null, - c5 blob(6000) not null, - c6 varchar(2000) not null, - c7 varchar(2000) not null, - c8 datetime, - c9 decimal(6,3), - primary key (c1), - index (c3,c4(50),c5(50)), - index (c2)) - engine=innodb row_format=redundant; - - create temporary table t2(c1 int not null, - c2 int not null, - c3 char(255) not null, - c4 text(6000) not null, - c5 blob(6000) not null, - c6 varchar(2000) not null, - c7 varchar(2000) not null, - c8 datetime, - c9 decimal(6,3), - primary key (c1), - index (c3,c4(50),c5(50)), - index (c2)) - engine=innodb row_format=compact; - - create temporary table t4(c1 int not null, - c2 int not null, - c3 char(255) not null, - c4 text(6000) not null, - c5 blob(6000) not null, - c6 varchar(2000) not null, - c7 varchar(2000) not null, - c8 datetime, - c9 decimal(6,3), - primary key (c1), - index (c3,c4(50),c5(50)), - index (c2)) - engine=innodb row_format=dynamic; - create temporary table t5(c1 int not null, c2 int not null, c3 char(255) not null, @@ -89,18 +47,6 @@ create procedure populate_tables() while (n > 0) do start transaction; - insert into t1 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), - repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), - now(),(100.55+n)); - insert into t2 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), - repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), - now(),(100.55+n)); - insert ignore into t4 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), - repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), - now(),(100.55+n)); insert ignore into t5 values(n,n,repeat(concat(' tc3_',n),30), repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), @@ -109,80 +55,32 @@ create procedure populate_tables() if (n > 10) then commit; else - delete from t1 where c1 > 10 ; - delete from t2 where c1 > 10 ; - delete from t4 where c1 > 10 ; delete from t5 where c1 > 10 ; rollback; start transaction; - update t1 set c1 = c1 + 1000 where c1 > 10; - update t2 set c1 = c1 + 1000 where c1 > 10; - update t4 set c1 = c1 + 1000 where c1 > 10; update t5 set c1 = c1 + 1000 where c1 > 10; rollback; end if; start transaction; - insert into t1 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert into t2 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert ignore into t4 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); insert ignore into t5 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), now(),(100.55+n+inner_loop)); - delete from t1 where c1 between 100 and 110; - delete from t2 where c1 between 100 and 110; - delete from t4 where c1 between 100 and 110; delete from t5 where c1 between 100 and 110; - update t1 set c1 = c1+1 where c1>110; - update t2 set c1 = c1+1 where c1>110; - update t4 set c1 = c1+1 where c1>110; update t5 set c1 = c1+1 where c1>110; savepoint a; - insert into t1 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert into t2 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert ignore into t4 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); insert ignore into t5 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), now(),(100.55+n+inner_loop)); savepoint b; - insert into t1 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert into t2 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), - repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), - now(),(100.55+n+inner_loop)); - insert into t4 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); insert into t5 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), @@ -208,25 +106,11 @@ connect (con2,localhost,root,,); connection con1; --reap # 20 rows expected -select count(*) from t1; -select count(*) from t2; -select count(*) from t4; -select count(*) from t5; -select c1 from t1; -select c1 from t2; -select c1 from t4; select c1 from t5; connection con2; --reap # 20 rows expected -select count(*) from t1; -select count(*) from t2; -select count(*) from t4; -select count(*) from t5; -select c1 from t1; -select c1 from t2; -select c1 from t4; select c1 from t5; connection con1; @@ -234,71 +118,38 @@ connection con1; set autocommit = 0; # Check duplicate key constraint + insert ignore --error ER_DUP_ENTRY -insert into t1 values (20,1,'a','a','a','a','a',now(),100.55); -insert ignore into t1 values (20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY -insert into t2 values (20,1,'a','a','a','a','a',now(),100.55); -insert ignore into t2 values (20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY -insert into t4 values (20,1,'a','a','a','a','a',now(),100.55); -insert ignore into t4 values (20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY insert into t5 values (20,1,'a','a','a','a','a',now(),100.55); insert ignore into t5 values (20,1,'a','a','a','a','a',now(),100.55); # check rollback due to duplicate value in second record of insert --error ER_DUP_ENTRY -insert into t1 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY -insert into t2 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY -insert into t4 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY insert into t5 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); set autocommit = 1; -select c1,c2 from t1 where c1 in (20,1); -select c1,c2 from t2 where c1 in (20,1); -select c1,c2 from t4 where c1 in (20,1); select c1,c2 from t5 where c1 in (20,1); #replace statement -replace into t1 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t2 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t4 values (20,1,'a','a','a','a','a',now(),100.55); replace into t5 values (20,1,'a','a','a','a','a',now(),100.55); # verify row is replaced from (20,20) to (20,1) -select c1,c2,c3,c4,c5,c6,c7,c9 from t1 where c1 = 20; -select c1,c2,c3,c4,c5,c6,c7,c9 from t2 where c1 = 20; -select c1,c2,c3,c4,c5,c6,c7,c9 from t4 where c1 = 20; select c1,c2,c3,c4,c5,c6,c7,c9 from t5 where c1 = 20; # Update ignore. statement is ignored as 20 value exists -update ignore t1 set c1 = 20 where c1 = 140 ; -update ignore t2 set c1 = 20 where c1 = 140 ; -update ignore t4 set c1 = 20 where c1 = 140 ; update ignore t5 set c1 = 20 where c1 = 140 ; # see record 140 is present as last update ignored -select count(*) from t1 where c1 = 140; -select count(*) from t2 where c1 = 140; -select count(*) from t4 where c1 = 140; select count(*) from t5 where c1 = 140; --replace_result $MYSQLTEST_VARDIR VARDIR -eval select * into outfile "$MYSQLTEST_VARDIR/tmp/t1.outfile" from t1; +eval select * into outfile "$MYSQLTEST_VARDIR/tmp/t5.outfile" from t5; -create temporary table temp_1 engine = innodb as select * from t1 where 1=2; +create temporary table temp_1 engine = innodb as select * from t5 where 1=2; select count(*) from temp_1; --replace_result $MYSQLTEST_VARDIR VARDIR -eval load data infile '$MYSQLTEST_VARDIR/tmp/t1.outfile' into table temp_1; +eval load data infile '$MYSQLTEST_VARDIR/tmp/t5.outfile' into table temp_1; select count(*) from temp_1; ---remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile +--remove_file $MYSQLTEST_VARDIR/tmp/t5.outfile # Alter table to add column and primary key alter table temp_1 add column c10 int default 99 , diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test index 20bb52c22f2..bb8e3316860 100644 --- a/mysql-test/suite/innodb/t/xa_recovery.test +++ b/mysql-test/suite/innodb/t/xa_recovery.test @@ -5,7 +5,7 @@ # MDEV-8841 - close tables opened by previous tests, # so they don't get marked crashed when the server gets crashed --disable_query_log -call mtr.add_suppression("Found 1 prepared XA transactions"); +call mtr.add_suppression("Found [12] prepared XA transactions"); FLUSH TABLES; --enable_query_log @@ -13,6 +13,9 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connect (con1,localhost,root); XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; +connect (con2,localhost,root); +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +XA START 'y'; INSERT INTO t2 VALUES (1); XA END 'y'; XA PREPARE 'y'; connection default; # innodb_force_recovery=2 prevents the purge and tests that the fix of @@ -25,6 +28,7 @@ connection default; --let $shutdown_timeout= disconnect con1; +disconnect con2; connect (con1,localhost,root); --send SELECT * FROM t1 LOCK IN SHARE MODE @@ -35,6 +39,8 @@ let $wait_condition= info = 'SELECT * FROM t1 LOCK IN SHARE MODE'; --source include/wait_condition.inc +DROP TABLE t2; + --source include/restart_mysqld.inc disconnect con1; @@ -45,3 +51,8 @@ XA ROLLBACK 'x'; SELECT * FROM t1; DROP TABLE t1; + +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc + +XA ROLLBACK 'y'; diff --git a/mysql-test/suite/innodb/t/xa_recovery_debug.test b/mysql-test/suite/innodb/t/xa_recovery_debug.test index 21a38854adb..ada2940ed9c 100644 --- a/mysql-test/suite/innodb/t/xa_recovery_debug.test +++ b/mysql-test/suite/innodb/t/xa_recovery_debug.test @@ -4,6 +4,10 @@ # Embedded server does not support restarting --source include/not_embedded.inc +--disable_query_log +FLUSH TABLES; +--enable_query_log + --echo # --echo # Bug#20872655 XA ROLLBACK IS NOT CRASH-SAFE --echo # diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result index 1382457debf..7d98aba7fc3 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result @@ -225,6 +225,13 @@ id title body 1 MySQL Tutorial DBMS stands for DataBase ... 3 Optimizing MySQL In this tutorial we will show ... DROP TABLE articles; +# +# MDEV-22811 DDL fails to drop and re-create FTS index +# +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY, +f1 VARCHAR(200),FULLTEXT fidx(f1))engine=innodb; +ALTER TABLE t1 DROP index fidx, ADD FULLTEXT INDEX(f1); +DROP TABLE t1; CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB; ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b); DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index c81ec18a4e6..cca110f3550 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -270,6 +270,14 @@ SELECT * FROM articles WHERE MATCH (title, body) DROP TABLE articles; +--echo # +--echo # MDEV-22811 DDL fails to drop and re-create FTS index +--echo # +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY, + f1 VARCHAR(200),FULLTEXT fidx(f1))engine=innodb; +ALTER TABLE t1 DROP index fidx, ADD FULLTEXT INDEX(f1); +DROP TABLE t1; + # Add more than one FTS index CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB; ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b); diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result index 3ef5608e155..9d4c43b1a8f 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result @@ -17,7 +17,7 @@ INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` ( `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT 0, `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, - `PAGE_STATE` enum('NOT_USED','READY_FOR_USE','FILE_PAGE','MEMORY','REMOVE_HASH') NOT NULL, + `PAGE_STATE` enum('NOT_USED','MEMORY','REMOVE_HASH','FILE_PAGE') NOT NULL, `IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE','IO_PIN') NOT NULL, `IS_OLD` int(1) NOT NULL DEFAULT 0, `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0 diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result b/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result index 73871eb2eda..42d33fdbeac 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_page_lru.result @@ -6,7 +6,7 @@ INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` ( `SPACE` int(11) unsigned NOT NULL DEFAULT 0, `PAGE_NUMBER` int(11) unsigned NOT NULL DEFAULT 0, `PAGE_TYPE` varchar(64) DEFAULT NULL, - `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT 0, + `FLUSH_TYPE` int(11) unsigned NOT NULL DEFAULT 0, `FIX_COUNT` int(11) unsigned NOT NULL DEFAULT 0, `IS_HASHED` int(1) NOT NULL DEFAULT 0, `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT 0, diff --git a/mysql-test/suite/maria/bulk_insert_crash.opt b/mysql-test/suite/maria/bulk_insert_crash.opt new file mode 100644 index 00000000000..f85a8d9c973 --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.opt @@ -0,0 +1,2 @@ +--skip-stack-trace --skip-core-file +--default-storage-engine=Aria diff --git a/mysql-test/suite/maria/bulk_insert_crash.result b/mysql-test/suite/maria/bulk_insert_crash.result new file mode 100644 index 00000000000..fc28bf325ba --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.result @@ -0,0 +1,13 @@ +create table t1 (a int primary key, b int, c int, unique key(b), key(c)) engine=aria transactional=1; +insert into t1 values (1000,1000,1000); +insert into t1 select seq,seq+100, seq+200 from seq_1_to_10; +SET GLOBAL debug_dbug="+d,crash_end_bulk_insert"; +REPLACE into t1 select seq+20,seq+95, seq + 300 from seq_1_to_10; +ERROR HY000: Lost connection to MySQL server during query +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select sum(a),sum(b),sum(c) from t1; +sum(a) sum(b) sum(c) +1055 2055 3055 +drop table t1; diff --git a/mysql-test/suite/maria/bulk_insert_crash.test b/mysql-test/suite/maria/bulk_insert_crash.test new file mode 100644 index 00000000000..d9167c3f0d7 --- /dev/null +++ b/mysql-test/suite/maria/bulk_insert_crash.test @@ -0,0 +1,36 @@ +--source include/not_embedded.inc +--source include/not_valgrind.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc +# Binary must be compiled with debug for crash to occur +--source include/have_debug.inc +--source include/have_sequence.inc + +# +# MDEV-20578 Got error 126 when executing undo undo_key_delete upon Aria crash +# recovery +# + +# Write file to make mysql-test-run.pl expect crash and restart +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +create table t1 (a int primary key, b int, c int, unique key(b), key(c)) engine=aria transactional=1; +insert into t1 values (1000,1000,1000); +insert into t1 select seq,seq+100, seq+200 from seq_1_to_10; + +# Insert into t1 with batch insert where we get a rows replaced after +# a few sucessful inserts + +SET GLOBAL debug_dbug="+d,crash_end_bulk_insert"; + +--error 2013 +REPLACE into t1 select seq+20,seq+95, seq + 300 from seq_1_to_10; + +# Wait until restarted +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect + +check table t1; +select sum(a),sum(b),sum(c) from t1; +drop table t1; diff --git a/mysql-test/suite/maria/create.result b/mysql-test/suite/maria/create.result index 82c6b8c9871..cf79542731b 100644 --- a/mysql-test/suite/maria/create.result +++ b/mysql-test/suite/maria/create.result @@ -31,3 +31,32 @@ select * from t2; f1 f2 3 qux DROP TABLE t1, t2; +CREATE TABLE t1 (a INT) ENGINE=Aria; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (b INT); +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t1; +a +1 +SELECT * from t2; +a +1 +BEGIN; +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t2; +a +1 +COMMIT; +LOCK TABLES t1 read, t2 write; +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t2; +a +1 +UNLOCK TABLES; +CREATE TABLE t3 (a INT) engine=Aria; +INSERT INTO t3 values(2); +CREATE OR REPLACE TABLE t2 AS SELECT t1.a,t3.a as b FROM t1,t3; +SELECT * from t2; +a b +1 2 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/maria/create.test b/mysql-test/suite/maria/create.test index 8f2ffd7492f..d33dd71df35 100644 --- a/mysql-test/suite/maria/create.test +++ b/mysql-test/suite/maria/create.test @@ -40,3 +40,38 @@ INSERT IGNORE INTO t1 VALUES (1),(2); CREATE OR REPLACE TABLE t2 ENGINE=Aria AS SELECT SUM(a) AS f1, IFNULL( 'qux', ExtractValue( 'foo', 'bar' ) ) AS f2 FROM t1; select * from t2; DROP TABLE t1, t2; + +# +# MDEV-22686 # Assertion `trn' failed in ha_maria::start_stmt +# ASAN heap-after-free in maria_status +# + +CREATE TABLE t1 (a INT) ENGINE=Aria; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (b INT); +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t1; +SELECT * from t2; + +# Check also BEGIN/COMMIT + +BEGIN; +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t2; +COMMIT; + +# Check also LOCK TABLES + +LOCK TABLES t1 read, t2 write; +CREATE OR REPLACE TABLE t2 AS SELECT * FROM t1; +SELECT * from t2; +UNLOCK TABLES; + +# Check with 3 tables +CREATE TABLE t3 (a INT) engine=Aria; +INSERT INTO t3 values(2); + +CREATE OR REPLACE TABLE t2 AS SELECT t1.a,t3.a as b FROM t1,t3; +SELECT * from t2; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/maria/lock.result b/mysql-test/suite/maria/lock.result index de24b987524..0891e8ad249 100644 --- a/mysql-test/suite/maria/lock.result +++ b/mysql-test/suite/maria/lock.result @@ -1,7 +1,6 @@ drop table if exists t1,t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' CREATE TABLE t1 (i INT) ENGINE=Aria; CREATE TABLE t2 (i INT) ENGINE=Aria; LOCK TABLE t1 WRITE, t2 WRITE; @@ -167,3 +166,14 @@ test.t1 optimize status Table is already up to date disconnect con1; connection default; DROP TABLE t1, t2; +# +# MDEV-22829 SIGSEGV in _ma_reset_history on LOCK +# +CREATE TABLE t1 (f1 INT) ENGINE=Aria; +CREATE TABLE t2 (f2 INT) ENGINE=Aria; +LOCK TABLES t2 WRITE, t1 WRITE; +INSERT INTO t1 VALUES (1); +CREATE TRIGGER ai AFTER INSERT ON t1 FOR EACH ROW UPDATE t1 SET v=1 WHERE b=new.a; +ERROR 42S22: Unknown column 'a' in 'NEW' +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/maria/lock.test b/mysql-test/suite/maria/lock.test index bb709f8a69c..017bd025ac1 100644 --- a/mysql-test/suite/maria/lock.test +++ b/mysql-test/suite/maria/lock.test @@ -185,3 +185,16 @@ OPTIMIZE TABLE t1; --disconnect con1 --connection default DROP TABLE t1, t2; + +--echo # +--echo # MDEV-22829 SIGSEGV in _ma_reset_history on LOCK +--echo # + +CREATE TABLE t1 (f1 INT) ENGINE=Aria; +CREATE TABLE t2 (f2 INT) ENGINE=Aria; +LOCK TABLES t2 WRITE, t1 WRITE; +INSERT INTO t1 VALUES (1); +--error ER_BAD_FIELD_ERROR +CREATE TRIGGER ai AFTER INSERT ON t1 FOR EACH ROW UPDATE t1 SET v=1 WHERE b=new.a; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/maria/maria-connect.result b/mysql-test/suite/maria/maria-connect.result index 1d9cf2ab97b..76e30d7d136 100644 --- a/mysql-test/suite/maria/maria-connect.result +++ b/mysql-test/suite/maria/maria-connect.result @@ -8,6 +8,11 @@ CREATE TABLE t1 (a int primary key); insert t1 values (1),(2),(3); insert t1 values (4),(2),(5); ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show warnings; +Level Code Message +Error 1062 Duplicate entry '2' for key 'PRIMARY' +Note 4173 Engine Aria does not support rollback. Changes where commited during rollback call +Warning 1196 Some non-transactional changed tables couldn't be rolled back select * from t1; a 1 diff --git a/mysql-test/suite/maria/maria-connect.test b/mysql-test/suite/maria/maria-connect.test index 8df305d47eb..ac7e9589285 100644 --- a/mysql-test/suite/maria/maria-connect.test +++ b/mysql-test/suite/maria/maria-connect.test @@ -29,6 +29,7 @@ CREATE TABLE t1 (a int primary key); insert t1 values (1),(2),(3); --error ER_DUP_ENTRY insert t1 values (4),(2),(5); +show warnings; select * from t1; --replace_result $start_pos --replace_column 2 # 5 # diff --git a/mysql-test/suite/maria/maria-partitioning.result b/mysql-test/suite/maria/maria-partitioning.result index 1ef54bde3c8..35b7da489fa 100644 --- a/mysql-test/suite/maria/maria-partitioning.result +++ b/mysql-test/suite/maria/maria-partitioning.result @@ -2,8 +2,7 @@ set global default_storage_engine=aria; set session default_storage_engine=aria; DROP TABLE if exists t1,t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' create table t2(a blob) engine=aria; create table t1(a int primary key) engine=aria; insert into t2 values ('foo'),('bar'); diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index eaa4fa568a5..9f4835a63a2 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -935,7 +935,7 @@ _id DELETE FROM t1 WHERE _id < 8; SELECT table_name, engine, version, row_format, Table_rows, Data_free, create_options, table_comment FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' and TABLE_NAME='t1'; table_name engine version row_format Table_rows Data_free create_options table_comment -t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC +t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC transactional=0 CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text test.t1 check status OK @@ -947,7 +947,7 @@ Table Op Msg_type Msg_text test.t1 check status OK SELECT table_name, engine, version, row_format, Table_rows, Data_free, create_options, table_comment FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' and TABLE_NAME='t1'; table_name engine version row_format Table_rows Data_free create_options table_comment -t1 Aria 10 Dynamic 2 0 row_format=DYNAMIC +t1 Aria 10 Dynamic 2 0 row_format=DYNAMIC transactional=0 SELECT _id FROM t1; _id 8 @@ -994,7 +994,7 @@ _id DELETE FROM t1 WHERE _id < 8; SELECT table_name, engine, version, row_format, Table_rows, Data_free, create_options, table_comment FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' and TABLE_NAME='t1'; table_name engine version row_format Table_rows Data_free create_options table_comment -t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC +t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC transactional=0 CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text test.t1 check status OK @@ -1006,7 +1006,7 @@ Table Op Msg_type Msg_text test.t1 check status OK SELECT table_name, engine, version, row_format, Table_rows, Data_free, create_options, table_comment FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' and TABLE_NAME='t1'; table_name engine version row_format Table_rows Data_free create_options table_comment -t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC +t1 Aria 10 Dynamic 2 140 row_format=DYNAMIC transactional=0 SELECT _id FROM t1; _id 8 @@ -1773,27 +1773,27 @@ DROP TABLE t1; CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)); SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 0 # # # 8192 # # # # # # # # N +t1 Aria 10 Page 0 # # # 8192 # # # # # # # transactional=1 # N INSERT INTO t1 VALUES (1,1); SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 1 # # # 24576 # # # # # # # # N +t1 Aria 10 Page 1 # # # 24576 # # # # # # # transactional=1 # N ALTER TABLE t1 DISABLE KEYS; SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 1 # # # 24576 # # # # # # # # N +t1 Aria 10 Page 1 # # # 24576 # # # # # # # transactional=1 # N ALTER TABLE t1 ENABLE KEYS; SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 1 # # # 24576 # # # # # # # # N +t1 Aria 10 Page 1 # # # 24576 # # # # # # # transactional=1 # N ALTER TABLE t1 DISABLE KEYS; SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 1 # # # 24576 # # # # # # # # N +t1 Aria 10 Page 1 # # # 24576 # # # # # # # transactional=1 # N ALTER TABLE t1 ENABLE KEYS; SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 1 # # # 24576 # # # # # # # # N +t1 Aria 10 Page 1 # # # 24576 # # # # # # # transactional=1 # N # Enable keys with parallel repair SET @@aria_repair_threads=2; ALTER TABLE t1 DISABLE KEYS; diff --git a/mysql-test/suite/maria/max_length.result b/mysql-test/suite/maria/max_length.result index b4ca61392cc..4403ce5d0d2 100644 --- a/mysql-test/suite/maria/max_length.result +++ b/mysql-test/suite/maria/max_length.result @@ -1,7 +1,6 @@ drop table if exists t1,t2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' create table t1 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob) row_format=page max_rows=2 engine=aria; create table t2 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob, key(v)) row_format=page max_rows=20000000 engine=aria; show create table t1; @@ -24,8 +23,8 @@ t2 CREATE TABLE `t2` ( lock tables t1 write,t2 write; show table status like "t_"; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 0 0 8192 268320768 8192 0 1 # # # latin1_swedish_ci NULL max_rows=2 row_format=PAGE 536862720 N -t2 Aria 10 Page 0 0 8192 17592186011648 8192 0 1 # # # latin1_swedish_ci NULL max_rows=20000000 row_format=PAGE 137438945280 N +t1 Aria 10 Page 0 0 8192 268320768 8192 0 1 # # # latin1_swedish_ci NULL max_rows=2 row_format=PAGE transactional=1 536862720 N +t2 Aria 10 Page 0 0 8192 17592186011648 8192 0 1 # # # latin1_swedish_ci NULL max_rows=20000000 row_format=PAGE transactional=1 137438945280 N insert into t1 values(null, repeat("ab",100),repeat("def",1000)); insert into t1 values(null, repeat("de",200),repeat("ghi",2000)); insert into t1 values(null, repeat("fe",300),repeat("ghi",3000)); @@ -177,9 +176,9 @@ test.t1 check warning Datafile is almost full, 268320768 of 268320768 used test.t1 check status OK show table status like "t1"; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 6189940 43 268320768 268320768 8192 0 NULL # # # latin1_swedish_ci NULL max_rows=10 row_format=PAGE 137438945280 N +t1 Aria 10 Page 6189940 43 268320768 268320768 8192 0 NULL # # # latin1_swedish_ci NULL max_rows=10 row_format=PAGE transactional=1 137438945280 N create index seq on t1(c1); show table status like "t1"; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 Aria 10 Page 6189940 43 268320768 268320768 49750016 0 NULL # # # latin1_swedish_ci NULL max_rows=10 page_checksum=1 row_format=PAGE 536862720 N +t1 Aria 10 Page 6189940 43 268320768 268320768 49750016 0 NULL # # # latin1_swedish_ci NULL max_rows=10 page_checksum=1 row_format=PAGE transactional=1 536862720 N drop table t1; diff --git a/mysql-test/suite/maria/rollback.result b/mysql-test/suite/maria/rollback.result new file mode 100644 index 00000000000..fd2e012805a --- /dev/null +++ b/mysql-test/suite/maria/rollback.result @@ -0,0 +1,186 @@ +call mtr.add_suppression("Table '.*' is marked as crashed and should be repaired"); +call mtr.add_suppression("Checking table: .*"); +create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1; +create table t2 (a int primary key auto_increment, b int) engine=aria transactional= 0; +create sequence s1 cache=2 engine=aria; +insert into t1 (b) values (1),(2),(3),(4); +insert into t2 (b) values (1),(2),(3),(4); +select NEXT VALUE for s1,seq from seq_1_to_4; +NEXT VALUE for s1 seq +1 1 +2 2 +3 3 +4 4 +begin; +insert into t1 (b) values (5),(6); +insert into t1 (b) values (7),(8); +insert into t2 (b) values (5),(6); +insert into t2 (b) values (7),(8); +commit; +begin; +insert into t1 (b) values (10),(11),(12); +update t1 set b=100 where a=2; +delete from t1 where a between 3 and 4; +insert into t2 (b) values (10),(11),(12); +update t2 set b=100 where a=2; +delete from t2 where a between 3 and 4; +select NEXT VALUE for s1,seq from seq_1_to_4; +NEXT VALUE for s1 seq +5 1 +6 2 +7 3 +8 4 +# Kill and restart +select * from t1 order by a; +a b +1 1 +2 100 +5 5 +6 6 +7 7 +8 8 +9 10 +10 11 +11 12 +select * from t2 order by a; +a b +1 1 +2 100 +5 5 +6 6 +7 7 +8 8 +9 10 +10 11 +11 12 +Warnings: +Error 145 Table './test/t2' is marked as crashed and should be repaired +Warning 1034 1 client is using or hasn't closed the table properly +Note 1034 Table is fixed +insert into t1 (b) values (100),(200); +insert into t2 (b) values (100),(200); +select * from t1 order by a; +a b +1 1 +2 100 +5 5 +6 6 +7 7 +8 8 +9 10 +10 11 +11 12 +12 100 +13 200 +select * from t2 order by a; +a b +1 1 +2 100 +5 5 +6 6 +7 7 +8 8 +9 10 +10 11 +11 12 +12 100 +13 200 +select NEXT VALUE for s1,seq from seq_1_to_4; +NEXT VALUE for s1 seq +9 1 +10 2 +11 3 +12 4 +Warnings: +Error 145 Table './test/s1' is marked as crashed and should be repaired +Warning 1034 1 client is using or hasn't closed the table properly +Note 1034 Table is fixed +drop table t1,t2; +drop sequence s1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern) VALUES ( NAME_CONST('pattern',_latin1'Table \'.*\' is marked as crashed and should be repaired' COLLATE 'latin1_swedish_ci')) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern) VALUES ( NAME_CONST('pattern',_latin1'Checking table: .*' COLLATE 'latin1_swedish_ci')) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create table t2 (a int primary key auto_increment, b int) engine=aria transactional= 0 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; create sequence s1 cache=2 engine=aria +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=1 +master-bin.000001 # Query # # use `test`; insert into t1 (b) values (1),(2),(3),(4) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=1 +master-bin.000001 # Query # # use `test`; insert into t2 (b) values (1),(2),(3),(4) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Annotate_rows # # select NEXT VALUE for s1,seq from seq_1_to_4 +master-bin.000001 # Table_map # # table_id: # (test.s1) +master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=5 +master-bin.000001 # Query # # use `test`; insert into t1 (b) values (5),(6) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=7 +master-bin.000001 # Query # # use `test`; insert into t1 (b) values (7),(8) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=5 +master-bin.000001 # Query # # use `test`; insert into t2 (b) values (5),(6) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=7 +master-bin.000001 # Query # # use `test`; insert into t2 (b) values (7),(8) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=9 +master-bin.000001 # Query # # use `test`; insert into t1 (b) values (10),(11),(12) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; update t1 set b=100 where a=2 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; delete from t1 where a between 3 and 4 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Intvar # # INSERT_ID=9 +master-bin.000001 # Query # # use `test`; insert into t2 (b) values (10),(11),(12) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; update t2 set b=100 where a=2 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; delete from t2 where a between 3 and 4 +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Annotate_rows # # select NEXT VALUE for s1,seq from seq_1_to_4 +master-bin.000001 # Table_map # # table_id: # (test.s1) +master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=12 +master-bin.000002 # Query # # use `test`; insert into t1 (b) values (100),(200) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Intvar # # INSERT_ID=12 +master-bin.000002 # Query # # use `test`; insert into t2 (b) values (100),(200) +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Annotate_rows # # select NEXT VALUE for s1,seq from seq_1_to_4 +master-bin.000002 # Table_map # # table_id: # (test.s1) +master-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # GTID #-#-# +master-bin.000002 # Query # # use `test`; DROP TABLE `t1`,`t2` /* generated by server */ +master-bin.000002 # Gtid # # GTID #-#-# +master-bin.000002 # Query # # use `test`; DROP SEQUENCE `s1` /* generated by server */ diff --git a/mysql-test/suite/maria/rollback.test b/mysql-test/suite/maria/rollback.test new file mode 100644 index 00000000000..40a96b9b05b --- /dev/null +++ b/mysql-test/suite/maria/rollback.test @@ -0,0 +1,51 @@ +--source include/have_binlog_format_mixed_or_statement.inc +--source include/have_sequence.inc +# no-protocol doesn't print warnings about repaired tables +--source include/no_protocol.inc + +call mtr.add_suppression("Table '.*' is marked as crashed and should be repaired"); +call mtr.add_suppression("Checking table: .*"); + +# +# Testing rollback after crash +# + +create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1; +create table t2 (a int primary key auto_increment, b int) engine=aria transactional= 0; +create sequence s1 cache=2 engine=aria; + +insert into t1 (b) values (1),(2),(3),(4); +insert into t2 (b) values (1),(2),(3),(4); +select NEXT VALUE for s1,seq from seq_1_to_4; + +begin; +insert into t1 (b) values (5),(6); +insert into t1 (b) values (7),(8); +insert into t2 (b) values (5),(6); +insert into t2 (b) values (7),(8); +commit; +begin; +insert into t1 (b) values (10),(11),(12); +update t1 set b=100 where a=2; +delete from t1 where a between 3 and 4; + +insert into t2 (b) values (10),(11),(12); +update t2 set b=100 where a=2; +delete from t2 where a between 3 and 4; +select NEXT VALUE for s1,seq from seq_1_to_4; + +--source include/kill_and_restart_mysqld.inc + +select * from t1 order by a; +select * from t2 order by a; +insert into t1 (b) values (100),(200); +insert into t2 (b) values (100),(200); +select * from t1 order by a; +select * from t2 order by a; +select NEXT VALUE for s1,seq from seq_1_to_4; +drop table t1,t2; +drop sequence s1; + +source include/show_binlog_events.inc; +--let $binlog_file=master-bin.000002 +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/maria/transaction.result b/mysql-test/suite/maria/transaction.result new file mode 100644 index 00000000000..369d3728839 --- /dev/null +++ b/mysql-test/suite/maria/transaction.result @@ -0,0 +1,19 @@ +connect con1, localhost, root,,; +connection default; +CREATE TABLE t1 (c1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (c1)) +ENGINE = aria; +START TRANSACTION; +INSERT INTO t1 (c1) VALUES (2); +INSERT INTO t1 (c1) VALUES (4); +connection con1; +START TRANSACTION; +select * from t1; +c1 +2 +4 +select * from t1 where c1=2; +c1 +2 +disconnect con1; +connection default; +drop table t1; diff --git a/mysql-test/suite/maria/transaction.test b/mysql-test/suite/maria/transaction.test new file mode 100644 index 00000000000..6cf4590cdbd --- /dev/null +++ b/mysql-test/suite/maria/transaction.test @@ -0,0 +1,26 @@ +# +# Test that checks transactions and MVCC +# + +# +# This is a taken from parts.partition_auto_increment_maria. It originally +# crashde because con1 could read the first record from t1, which confused +# the optimizer. +# + +connect(con1, localhost, root,,); +connection default; +CREATE TABLE t1 (c1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (c1)) + ENGINE = aria; +START TRANSACTION; +INSERT INTO t1 (c1) VALUES (2); +INSERT INTO t1 (c1) VALUES (4); +connection con1; +START TRANSACTION; +# When Aria proparly supports MVCC, the following two queries will not see +# any rows +select * from t1; +select * from t1 where c1=2; +disconnect con1; +connection default; +drop table t1; diff --git a/mysql-test/suite/mariabackup/apply-log-only-incr.test b/mysql-test/suite/mariabackup/apply-log-only-incr.test index 74ab680d840..c2d23c88a3e 100644 --- a/mysql-test/suite/mariabackup/apply-log-only-incr.test +++ b/mysql-test/suite/mariabackup/apply-log-only-incr.test @@ -36,7 +36,7 @@ connection default; --disable_result_log exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --ftwrl-wait-timeout=5 --ftwrl-wait-threshold=300 --ftwrl-wait-query-type=all --target-dir=$incremental_dir --incremental-basedir=$basedir ; -exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir ; +exec $XTRABACKUP --prepare --verbose --target-dir=$basedir ; --enable_result_log let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; @@ -44,7 +44,7 @@ let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; --source include/search_pattern_in_file.inc --echo # expect NOT FOUND -exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir --incremental-dir=$incremental_dir ; +exec $XTRABACKUP --prepare --verbose --target-dir=$basedir --incremental-dir=$incremental_dir ; --source include/search_pattern_in_file.inc --echo # expect NOT FOUND diff --git a/mysql-test/suite/mariabackup/apply-log-only.test b/mysql-test/suite/mariabackup/apply-log-only.test index 5a3c45f2914..7ffed0719f0 100644 --- a/mysql-test/suite/mariabackup/apply-log-only.test +++ b/mysql-test/suite/mariabackup/apply-log-only.test @@ -11,7 +11,7 @@ INSERT INTO t VALUES(1); exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; --enable_result_log -exec $XTRABACKUP --prepare --apply-log-only --target-dir=$basedir ; +exec $XTRABACKUP --prepare --target-dir=$basedir ; let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; --let SEARCH_PATTERN= Rolled back recovered transaction diff --git a/mysql-test/suite/mariabackup/binlog.test b/mysql-test/suite/mariabackup/binlog.test index 998397bb495..b2f08c2d7bb 100644 --- a/mysql-test/suite/mariabackup/binlog.test +++ b/mysql-test/suite/mariabackup/binlog.test @@ -12,7 +12,7 @@ SHOW VARIABLES like 'log_bin'; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; --enable_result_log -exec $XTRABACKUP --prepare --binlog-info=1 --apply-log-only --target-dir=$basedir ; +exec $XTRABACKUP --prepare --binlog-info=1 --target-dir=$basedir ; let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; --let SEARCH_PATTERN= Last binlog file .*, position .* diff --git a/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test index 2136771b97e..f243ac1acd9 100644 --- a/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test +++ b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test @@ -33,7 +33,7 @@ select count(*) from t7; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir; --echo # XTRABACKUP PREPARE -exec $XTRABACKUP --apply-log-only --prepare --target-dir=$basedir; +exec $XTRABACKUP --prepare --target-dir=$basedir; --echo # XTRABACKUP INCREMENTAL PREPARE exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir; diff --git a/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test index 60780b13920..fdae90132cc 100644 --- a/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test +++ b/mysql-test/suite/mariabackup/incremental_ddl_during_backup.test @@ -25,7 +25,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir --let after_load_tablespaces= --disable_result_log echo # Prepare full backup, apply incremental one; -exec $XTRABACKUP --apply-log-only --prepare --target-dir=$basedir; +exec $XTRABACKUP --prepare --target-dir=$basedir; exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir ; echo # Restore and check results; diff --git a/mysql-test/suite/mariabackup/mdev-14447.test b/mysql-test/suite/mariabackup/mdev-14447.test index 17f78b4d1c9..7877a7805e1 100644 --- a/mysql-test/suite/mariabackup/mdev-14447.test +++ b/mysql-test/suite/mariabackup/mdev-14447.test @@ -30,9 +30,9 @@ remove_file $backuplog; --disable_result_log echo # Prepare full backup, apply incremental one; -exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir; +exec $XTRABACKUP --prepare --verbose --target-dir=$basedir; -exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir --incremental-dir=$incremental_dir ; +exec $XTRABACKUP --prepare --verbose --target-dir=$basedir --incremental-dir=$incremental_dir ; echo # Restore and check results; let $targetdir=$basedir; diff --git a/mysql-test/suite/mariabackup/options_check.result b/mysql-test/suite/mariabackup/options_check.result new file mode 100644 index 00000000000..59666754f04 --- /dev/null +++ b/mysql-test/suite/mariabackup/options_check.result @@ -0,0 +1,8 @@ +# Check for unknown options in command-line +# Check for unknown options in "mariabackup" group +# Check for unknown options in "xtrabackup" group +# Check for unknown options in "mariadb-backup" group +# Check for options overwriting +# Check if uknown options that follow --mysqld-args are ingored +# Check if [mariadb-client] group is not loaded (MDEV-22894) +# Check if --help presents diff --git a/mysql-test/suite/mariabackup/options_check.test b/mysql-test/suite/mariabackup/options_check.test new file mode 100644 index 00000000000..022bcbd5d10 --- /dev/null +++ b/mysql-test/suite/mariabackup/options_check.test @@ -0,0 +1,69 @@ +--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup +--let $custom_cnf=$MYSQLTEST_VARDIR/tmp/custom_my.cnf + +--echo # Check for unknown options in command-line +--disable_result_log +--error 7 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --unknown-option=xxx --target-dir=$targetdir; +--error 2 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --unknown-option --target-dir=$targetdir; + +--echo # Check for unknown options in "mariabackup" group +--write_file $custom_cnf +[mariabackup] +unknown-option=XXX +EOF +--error 7 +exec $XTRABACKUP --defaults-file=$custom_cnf --backup --target-dir=$targetdir; +--remove_file $custom_cnf + +--echo # Check for unknown options in "xtrabackup" group +--write_file $custom_cnf +[xtrabackup] +unknown-option=XXX +EOF +--error 7 +exec $XTRABACKUP --defaults-file=$custom_cnf --backup --target-dir=$targetdir; +--remove_file $custom_cnf + +--echo # Check for unknown options in "mariadb-backup" group +--write_file $custom_cnf +[mariadb-backup] +unknown-option=XXX +EOF +--error 7 +exec $XTRABACKUP --defaults-file=$custom_cnf --backup --target-dir=$targetdir; +--remove_file $custom_cnf + +--echo # Check for options overwriting +--write_file $custom_cnf +[mariadbd] +innodb-flush-method=O_DIRECT + +[mariabackup] +innodb-flush-method=blablabla +EOF +--error 13 +exec $XTRABACKUP --defaults-file=$custom_cnf --backup --target-dir=$targetdir; +--remove_file $custom_cnf + +--echo # Check if uknown options that follow --mysqld-args are ingored +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --mysqld-args --unknown-option; +--rmdir $targetdir + +--echo # Check if [mariadb-client] group is not loaded (MDEV-22894) +--copy_file $MYSQLTEST_VARDIR/my.cnf $custom_cnf +--append_file $custom_cnf +[mariadb-client] +user=bla +password=bla +EOF +exec $XTRABACKUP --defaults-file=$custom_cnf --backup --target-dir=$targetdir; +--remove_file $custom_cnf +--rmdir $targetdir + +--echo # Check if --help presents +exec $XTRABACKUP --help; +exec $XTRABACKUP -?; +--enable_result_log + diff --git a/mysql-test/suite/mariabackup/undo_space_id.test b/mysql-test/suite/mariabackup/undo_space_id.test index b582554b28a..2c56492fd8e 100644 --- a/mysql-test/suite/mariabackup/undo_space_id.test +++ b/mysql-test/suite/mariabackup/undo_space_id.test @@ -17,7 +17,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir list_files $basedir undo*; --echo # xtrabackup prepare -exec $XTRABACKUP --prepare --apply-log-only --target-dir=$basedir; +exec $XTRABACKUP --prepare --target-dir=$basedir; --echo # Display undo log files from targer directory list_files $basedir undo*; diff --git a/mysql-test/suite/mariabackup/xb_fulltext_encrypted.test b/mysql-test/suite/mariabackup/xb_fulltext_encrypted.test index d5a5003c11a..f7b72b5ccea 100644 --- a/mysql-test/suite/mariabackup/xb_fulltext_encrypted.test +++ b/mysql-test/suite/mariabackup/xb_fulltext_encrypted.test @@ -16,7 +16,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; --disable_result_log exec $INNOBACKUPEX --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; -exec $INNOBACKUPEX --apply-log --rebuild-indexes --rebuild-threads=2 $targetdir; +exec $INNOBACKUPEX --apply-log $targetdir; --source include/restart_and_restore.inc --enable_result_log diff --git a/mysql-test/suite/mariabackup/xb_partition.test b/mysql-test/suite/mariabackup/xb_partition.test index e6f8c5d996f..3d027b67fc1 100644 --- a/mysql-test/suite/mariabackup/xb_partition.test +++ b/mysql-test/suite/mariabackup/xb_partition.test @@ -38,7 +38,7 @@ INSERT INTO isam_p VALUES (1), (101), (201), (301); let $targetdir=$MYSQLTEST_VARDIR/tmp; --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp --backup --target-dir=$targetdir/full; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir/full; --enable_result_log DROP TABLE t1; diff --git a/mysql-test/suite/parts/inc/partition_auto_increment.inc b/mysql-test/suite/parts/inc/partition_auto_increment.inc index 199c8680864..4392d04db8a 100644 --- a/mysql-test/suite/parts/inc/partition_auto_increment.inc +++ b/mysql-test/suite/parts/inc/partition_auto_increment.inc @@ -861,6 +861,17 @@ SELECT * FROM t1; DROP TABLE t1; } +if (!$skip_update) +{ +--echo # +--echo # MDEV-19622 Assertion failures in +--echo # ha_partition::set_auto_increment_if_higher upon UPDATE on Aria table +--echo # +CREATE OR REPLACE TABLE t1 (pk INT AUTO_INCREMENT, a INT, KEY(pk)) ENGINE=myisam PARTITION BY HASH(a); +INSERT INTO t1 VALUES (1,1),(2,2); +UPDATE t1 SET pk = 0; +DROP TABLE t1; +} --echo ############################################################################## } diff --git a/mysql-test/suite/parts/r/alter_table.result b/mysql-test/suite/parts/r/alter_table.result new file mode 100644 index 00000000000..fc508663204 --- /dev/null +++ b/mysql-test/suite/parts/r/alter_table.result @@ -0,0 +1,23 @@ +set @save_alter_algorithm= @@session.alter_algorithm; +SET SESSION alter_algorithm=4; +CREATE TABLE t1(a INT) engine=myisam PARTITION BY RANGE(a) SUBPARTITION BY KEY(a) (PARTITION p0 VALUES LESS THAN (10) (SUBPARTITION s0,SUBPARTITION s1), PARTITION p1 VALUES LESS THAN (20) (SUBPARTITION s2,SUBPARTITION s3)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`a`) +SUBPARTITION BY KEY (`a`) +(PARTITION `p0` VALUES LESS THAN (10) + (SUBPARTITION `s0` ENGINE = MyISAM, + SUBPARTITION `s1` ENGINE = MyISAM), + PARTITION `p1` VALUES LESS THAN (20) + (SUBPARTITION `s2` ENGINE = MyISAM, + SUBPARTITION `s3` ENGINE = MyISAM)) +ALTER TABLE t1 ADD COLUMN c INT; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY +DROP table if exists t1; +set @@session.alter_algorithm= @save_alter_algorithm; +CREATE TABLE t1 (a INT) PARTITION BY RANGE(a) SUBPARTITION BY HASH(a) (PARTITION p VALUES LESS THAN (5) (SUBPARTITION sp, SUBPARTITION sp1), PARTITION p1 VALUES LESS THAN MAXVALUE (SUBPARTITION sp2, SUBPARTITION sp3)); +ALTER TABLE t1 DROP PARTITION p; +DROP TABLE if exists t1; diff --git a/mysql-test/suite/parts/r/longname.result b/mysql-test/suite/parts/r/longname.result index 2d2802d8b38..1b8f823c98f 100644 --- a/mysql-test/suite/parts/r/longname.result +++ b/mysql-test/suite/parts/r/longname.result @@ -25,4 +25,45 @@ SUBPARTITIONS 2 ( PARTITION çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç VALUES LESS THAN (1000) ENGINE = InnoDB, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); ERROR HY000: The path specified for @0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@... is too long +SET @file_per_table=@@GLOBAL.innodb_file_per_table; +SET GLOBAL innodb_file_per_table=0; +CREATE TABLE mysqltest1.t1 (a INT) ENGINE=INNODB +PARTITION BY RANGE (a) SUBPARTITION BY HASH(a) +(PARTITION `$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$` + VALUES LESS THAN (10) +(SUBPARTITION +`--------------------------abcdef0123456789abcdef0123456789abcdef`, +SUBPARTITION +`0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`) +); +SET GLOBAL innodb_file_per_table=@file_per_table; +SHOW CREATE TABLE mysqltest1.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`a`) +SUBPARTITION BY HASH (`a`) +(PARTITION `$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$` VALUES LESS THAN (10) + (SUBPARTITION `--------------------------abcdef0123456789abcdef0123456789abcdef` ENGINE = InnoDB, + SUBPARTITION `0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef` ENGINE = InnoDB)) +INSERT INTO mysqltest1.t1 VALUES(1); +DROP TABLE mysqltest1.`#mysql50#t1#P#@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024#SP#0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`; +ERROR 42000: Incorrect table name '#mysql50#t1#P#@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@' +ALTER TABLE mysqltest1.t1 ADD FOREIGN KEY (a) REFERENCES +mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890; +ERROR HY000: Partitioned tables do not support FOREIGN KEY +ALTER TABLE +mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890 +ADD FOREIGN KEY (a) REFERENCES mysqltest1.t1; +ERROR HY000: Partitioned tables do not support FOREIGN KEY +SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES +WHERE NAME LIKE 'mysqltest1%'; +NAME +mysqltest1/t1#P#@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024#SP#0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +mysqltest1/t1#P#@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024#SP#@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002d@002dabcdef0123456789abcdef0123456789abcdef +mysqltest1/test_jfg_table_name_with_64_chars_123456789012345678901234567890#P#pmax#SP#pmaxsp0 +mysqltest1/test_jfg_table_name_with_64_chars_123456789012345678901234567890#P#pmax#SP#pmaxsp1 +mysqltest1/test_jfg_table_name_with_64_chars_123456789012345678901234567890#P#test_jfg_partition_name_with_60_chars_1234567890123456789012#SP#test_jfg_partition_name_with_60_chars_1234567890123456789012sp0 +mysqltest1/test_jfg_table_name_with_64_chars_123456789012345678901234567890#P#test_jfg_partition_name_with_60_chars_1234567890123456789012#SP#test_jfg_partition_name_with_60_chars_1234567890123456789012sp1 drop database mysqltest1; diff --git a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result index 6250f28eb00..76f1ddfceae 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result @@ -1101,4 +1101,12 @@ SELECT * FROM t1; a 0 DROP TABLE t1; +# +# MDEV-19622 Assertion failures in +# ha_partition::set_auto_increment_if_higher upon UPDATE on Aria table +# +CREATE OR REPLACE TABLE t1 (pk INT AUTO_INCREMENT, a INT, KEY(pk)) ENGINE=myisam PARTITION BY HASH(a); +INSERT INTO t1 VALUES (1,1),(2,2); +UPDATE t1 SET pk = 0; +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/partition_auto_increment_maria.result b/mysql-test/suite/parts/r/partition_auto_increment_maria.result index 5acce3e9492..5a3902475a9 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_maria.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_maria.result @@ -1148,4 +1148,12 @@ SELECT * FROM t1; a 0 DROP TABLE t1; +# +# MDEV-19622 Assertion failures in +# ha_partition::set_auto_increment_if_higher upon UPDATE on Aria table +# +CREATE OR REPLACE TABLE t1 (pk INT AUTO_INCREMENT, a INT, KEY(pk)) ENGINE=myisam PARTITION BY HASH(a); +INSERT INTO t1 VALUES (1,1),(2,2); +UPDATE t1 SET pk = 0; +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/partition_auto_increment_memory.result b/mysql-test/suite/parts/r/partition_auto_increment_memory.result index e622ddaa259..c395f8ed0c9 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_memory.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_memory.result @@ -1129,4 +1129,12 @@ SELECT * FROM t1; a 0 DROP TABLE t1; +# +# MDEV-19622 Assertion failures in +# ha_partition::set_auto_increment_if_higher upon UPDATE on Aria table +# +CREATE OR REPLACE TABLE t1 (pk INT AUTO_INCREMENT, a INT, KEY(pk)) ENGINE=myisam PARTITION BY HASH(a); +INSERT INTO t1 VALUES (1,1),(2,2); +UPDATE t1 SET pk = 0; +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result index 4e67094b327..792423096b5 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result @@ -1148,4 +1148,12 @@ SELECT * FROM t1; a 0 DROP TABLE t1; +# +# MDEV-19622 Assertion failures in +# ha_partition::set_auto_increment_if_higher upon UPDATE on Aria table +# +CREATE OR REPLACE TABLE t1 (pk INT AUTO_INCREMENT, a INT, KEY(pk)) ENGINE=myisam PARTITION BY HASH(a); +INSERT INTO t1 VALUES (1,1),(2,2); +UPDATE t1 SET pk = 0; +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/percona_nonflushing_analyze_debug.result b/mysql-test/suite/parts/r/percona_nonflushing_analyze_debug.result new file mode 100644 index 00000000000..070d5e8d79f --- /dev/null +++ b/mysql-test/suite/parts/r/percona_nonflushing_analyze_debug.result @@ -0,0 +1,68 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t1 VALUES (1), (2), (3), (4); +connect con1,localhost,root; +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +connection default; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +set @tmp=@@use_stat_tables; +set use_stat_tables='preferably_for_queries'; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +set use_stat_tables=@tmp; +SELECT * FROM t1; +a +1 +2 +3 +4 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +connection con1; +a +1 +2 +3 +4 +disconnect con1; +connection default; +SET DEBUG_SYNC='reset'; +DROP TABLE t1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (A) +SUBPARTITIONS 2 ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t2 VALUES (1), (2), (3), (4); +connect con1,localhost,root; +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t2; +connection default; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +set @tmp=@@use_stat_tables; +set use_stat_tables='preferably_for_queries'; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +set use_stat_tables=@tmp; +SELECT * FROM t2; +a +1 +2 +3 +4 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +connection con1; +a +1 +2 +3 +4 +disconnect con1; +connection default; +SET DEBUG_SYNC='reset'; +DROP TABLE t2; diff --git a/mysql-test/suite/parts/t/alter_table.test b/mysql-test/suite/parts/t/alter_table.test new file mode 100644 index 00000000000..6c4d83f9eed --- /dev/null +++ b/mysql-test/suite/parts/t/alter_table.test @@ -0,0 +1,29 @@ +# +# General errors with ALTER TABLE and partitions that doesn't have to be run +# on all engines +# + +--source include/have_partition.inc + +# +# MDEV-22649 SIGSEGV in ha_partition::create_partitioning_metadata on ALTER +# + +set @save_alter_algorithm= @@session.alter_algorithm; +SET SESSION alter_algorithm=4; +CREATE TABLE t1(a INT) engine=myisam PARTITION BY RANGE(a) SUBPARTITION BY KEY(a) (PARTITION p0 VALUES LESS THAN (10) (SUBPARTITION s0,SUBPARTITION s1), PARTITION p1 VALUES LESS THAN (20) (SUBPARTITION s2,SUBPARTITION s3)); +show create table t1; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD COLUMN c INT; +DROP table if exists t1; +set @@session.alter_algorithm= @save_alter_algorithm; + + +# +# MDEV-22804 SIGSEGV in ha_partition::create_partitioning_metadata | +# ERROR 1507 (HY000): Error in list of partitions to DROP +# + +CREATE TABLE t1 (a INT) PARTITION BY RANGE(a) SUBPARTITION BY HASH(a) (PARTITION p VALUES LESS THAN (5) (SUBPARTITION sp, SUBPARTITION sp1), PARTITION p1 VALUES LESS THAN MAXVALUE (SUBPARTITION sp2, SUBPARTITION sp3)); +ALTER TABLE t1 DROP PARTITION p; +DROP TABLE if exists t1; diff --git a/mysql-test/suite/parts/t/longname.test b/mysql-test/suite/parts/t/longname.test index 0f7378ef8e3..ab6137d56dd 100644 --- a/mysql-test/suite/parts/t/longname.test +++ b/mysql-test/suite/parts/t/longname.test @@ -1,5 +1,7 @@ source include/have_innodb.inc; source include/have_partition.inc; +# The absolute path names in the embedded server hit the limit earlier. +source include/not_embedded.inc; set names utf8; create database mysqltest1; @@ -29,4 +31,36 @@ PARTITION BY RANGE ( id ) PARTITION çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç VALUES LESS THAN (1000) ENGINE = InnoDB, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); +SET @file_per_table=@@GLOBAL.innodb_file_per_table; +SET GLOBAL innodb_file_per_table=0; + +CREATE TABLE mysqltest1.t1 (a INT) ENGINE=INNODB +PARTITION BY RANGE (a) SUBPARTITION BY HASH(a) +(PARTITION `$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$` + VALUES LESS THAN (10) + (SUBPARTITION + `--------------------------abcdef0123456789abcdef0123456789abcdef`, + SUBPARTITION + `0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`) +); + +SET GLOBAL innodb_file_per_table=@file_per_table; + +SHOW CREATE TABLE mysqltest1.t1; +INSERT INTO mysqltest1.t1 VALUES(1); + +--error ER_WRONG_TABLE_NAME +DROP TABLE mysqltest1.`#mysql50#t1#P#@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024@0024#SP#0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`; + +--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING +ALTER TABLE mysqltest1.t1 ADD FOREIGN KEY (a) REFERENCES +mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890; +--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING +ALTER TABLE +mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890 +ADD FOREIGN KEY (a) REFERENCES mysqltest1.t1; + +SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES +WHERE NAME LIKE 'mysqltest1%'; + drop database mysqltest1; diff --git a/mysql-test/suite/parts/t/percona_nonflushing_analyze_debug.test b/mysql-test/suite/parts/t/percona_nonflushing_analyze_debug.test new file mode 100644 index 00000000000..61c0a278ebb --- /dev/null +++ b/mysql-test/suite/parts/t/percona_nonflushing_analyze_debug.test @@ -0,0 +1,29 @@ +--source include/have_debug_sync.inc +--source include/have_innodb.inc +--source include/have_partition.inc + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t1 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; + +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB + PARTITION BY RANGE (a) + SUBPARTITION BY HASH (A) + SUBPARTITIONS 2 ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t2 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t2 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t2; diff --git a/mysql-test/suite/perfschema/r/event_aggregate.result b/mysql-test/suite/perfschema/r/event_aggregate.result index 2582262c8c4..4ad4c773941 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate.result +++ b/mysql-test/suite/perfschema/r/event_aggregate.result @@ -248,35 +248,35 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -315,19 +315,19 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -380,7 +380,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -392,7 +392,7 @@ user2 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -404,21 +404,21 @@ user2 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -467,21 +467,21 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 user2 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 user2 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -548,45 +548,45 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -635,21 +635,21 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -709,12 +709,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -726,12 +726,12 @@ user3 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -743,21 +743,21 @@ user3 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -816,23 +816,23 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 user3 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 user3 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -906,55 +906,55 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -1013,23 +1013,23 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1096,17 +1096,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -1118,17 +1118,17 @@ user4 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -1140,21 +1140,21 @@ user4 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -1223,25 +1223,25 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 user4 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1322,65 +1322,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 24 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1449,25 +1449,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1535,65 +1535,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 25 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1663,25 +1663,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1748,65 +1748,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 26 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1876,25 +1876,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1960,65 +1960,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 27 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -2088,25 +2088,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2171,65 +2171,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2299,25 +2299,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2383,65 +2383,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2511,25 +2511,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2594,65 +2594,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2722,25 +2722,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2805,65 +2805,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2933,25 +2933,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3016,65 +3016,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3144,25 +3144,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3227,65 +3227,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3355,25 +3355,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3438,65 +3438,65 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3566,25 +3566,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3671,43 +3671,43 @@ user4 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3777,25 +3777,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3904,21 +3904,21 @@ user4 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3988,25 +3988,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4122,14 +4122,14 @@ localhost stage/sql/starting 0 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4199,25 +4199,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4340,7 +4340,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4410,25 +4410,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4551,7 +4551,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4621,25 +4621,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4762,7 +4762,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4832,25 +4832,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4973,7 +4973,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5043,25 +5043,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5184,7 +5184,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5254,25 +5254,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5395,7 +5395,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5465,25 +5465,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5606,7 +5606,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5676,25 +5676,25 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5817,7 +5817,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5893,19 +5893,19 @@ user3 localhost transaction 0 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6028,7 +6028,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6110,13 +6110,13 @@ user3 transaction 0 user4 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6239,7 +6239,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6324,10 +6324,10 @@ host event_name count_star localhost transaction 0 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6450,7 +6450,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6538,7 +6538,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6633,7 +6633,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6697,7 +6697,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6760,7 +6760,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6800,7 +6800,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6859,7 +6859,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6899,7 +6899,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result index b67cd3ee31c..9ce3bb7efe8 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result @@ -232,28 +232,28 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -289,16 +289,16 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -347,7 +347,7 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -359,21 +359,21 @@ user2 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -414,17 +414,17 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 user2 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -486,33 +486,33 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -553,17 +553,17 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -616,12 +616,12 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -633,21 +633,21 @@ user3 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -693,18 +693,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 user3 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -770,38 +770,38 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -847,18 +847,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -915,17 +915,17 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -937,21 +937,21 @@ user4 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -1002,19 +1002,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 user4 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1084,43 +1084,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 24 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1171,19 +1171,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1240,43 +1240,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 25 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1328,19 +1328,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1396,43 +1396,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 26 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1484,19 +1484,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1551,43 +1551,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 27 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1639,19 +1639,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1705,43 +1705,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1793,19 +1793,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1860,43 +1860,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1948,19 +1948,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2014,43 +2014,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2102,19 +2102,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2168,43 +2168,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2256,19 +2256,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2322,43 +2322,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2410,19 +2410,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2476,43 +2476,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2564,19 +2564,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2630,43 +2630,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2718,19 +2718,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2784,43 +2784,43 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2872,19 +2872,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2960,21 +2960,21 @@ user4 stage/sql/starting 0 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3026,19 +3026,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3121,14 +3121,14 @@ localhost stage/sql/starting 0 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3180,19 +3180,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3282,7 +3282,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3334,19 +3334,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3436,7 +3436,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3488,19 +3488,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3590,7 +3590,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3642,19 +3642,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3744,7 +3744,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3796,19 +3796,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3898,7 +3898,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3950,19 +3950,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4052,7 +4052,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4104,19 +4104,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4206,7 +4206,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4258,19 +4258,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4360,7 +4360,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4412,19 +4412,19 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4514,7 +4514,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4572,13 +4572,13 @@ user3 transaction 0 user4 transaction 0 execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4668,7 +4668,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4729,10 +4729,10 @@ host event_name count_star localhost transaction 0 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4822,7 +4822,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4886,7 +4886,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4976,7 +4976,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5040,7 +5040,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -5102,7 +5102,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5142,7 +5142,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -5200,7 +5200,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5240,7 +5240,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result index 76f183fa43d..6590c162dda 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result @@ -202,7 +202,7 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -211,14 +211,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -249,15 +249,15 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -303,7 +303,7 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -317,14 +317,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -360,16 +360,16 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 user2 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -428,12 +428,12 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -442,14 +442,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -485,16 +485,16 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -544,12 +544,12 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -563,14 +563,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -611,17 +611,17 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 user3 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -684,17 +684,17 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -703,14 +703,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -751,17 +751,17 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -815,17 +815,17 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -839,14 +839,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -892,18 +892,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 user4 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -970,22 +970,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -994,14 +994,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1047,18 +1047,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1112,22 +1112,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1136,14 +1136,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1190,18 +1190,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1254,22 +1254,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1278,14 +1278,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1332,18 +1332,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1395,22 +1395,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1419,14 +1419,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1473,18 +1473,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1535,22 +1535,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -1559,14 +1559,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1613,18 +1613,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1676,22 +1676,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -1700,14 +1700,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1754,18 +1754,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1816,22 +1816,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -1840,14 +1840,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1894,18 +1894,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1956,22 +1956,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -1980,14 +1980,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2034,18 +2034,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2096,22 +2096,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2120,14 +2120,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2174,18 +2174,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2236,22 +2236,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2260,14 +2260,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2314,18 +2314,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2376,22 +2376,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2400,14 +2400,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2454,18 +2454,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2516,22 +2516,22 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2540,14 +2540,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2594,18 +2594,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2680,14 +2680,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2734,18 +2734,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2820,14 +2820,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2874,18 +2874,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2967,7 +2967,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3014,18 +3014,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3107,7 +3107,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3154,18 +3154,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3247,7 +3247,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3294,18 +3294,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3387,7 +3387,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3434,18 +3434,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3527,7 +3527,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3574,18 +3574,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3667,7 +3667,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3714,18 +3714,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3807,7 +3807,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3854,18 +3854,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3947,7 +3947,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3994,18 +3994,18 @@ execute dump_transactions_account; user host event_name count_star execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4087,7 +4087,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4142,10 +4142,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4227,7 +4227,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4282,10 +4282,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4367,7 +4367,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4425,7 +4425,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4507,7 +4507,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4565,7 +4565,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4619,7 +4619,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4653,7 +4653,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -4703,7 +4703,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4737,7 +4737,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result index d5d8e96dd64..b7cf3b8a5ce 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result @@ -216,21 +216,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -263,13 +263,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -314,21 +314,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -361,13 +361,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -424,21 +424,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -471,13 +471,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -523,21 +523,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -570,13 +570,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -634,21 +634,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -681,13 +681,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -734,21 +734,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -781,13 +781,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -846,21 +846,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 24 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -893,13 +893,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -945,21 +945,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 25 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -993,13 +993,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1044,21 +1044,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 26 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1092,13 +1092,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1142,21 +1142,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 27 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1190,13 +1190,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1239,21 +1239,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1287,13 +1287,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1337,21 +1337,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1385,13 +1385,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1434,21 +1434,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1482,13 +1482,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1531,21 +1531,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1579,13 +1579,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1628,21 +1628,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1676,13 +1676,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1725,21 +1725,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1773,13 +1773,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1822,21 +1822,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1870,13 +1870,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1919,21 +1919,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1967,13 +1967,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2016,21 +2016,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2064,13 +2064,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2120,14 +2120,14 @@ localhost stage/sql/starting 0 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2161,13 +2161,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2224,7 +2224,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2258,13 +2258,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2321,7 +2321,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2355,13 +2355,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2418,7 +2418,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2452,13 +2452,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2515,7 +2515,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2549,13 +2549,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2612,7 +2612,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2646,13 +2646,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2709,7 +2709,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2743,13 +2743,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2806,7 +2806,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2840,13 +2840,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2903,7 +2903,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2937,13 +2937,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3000,7 +3000,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3034,13 +3034,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3097,7 +3097,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3134,10 +3134,10 @@ host event_name count_star localhost transaction 0 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3194,7 +3194,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3234,7 +3234,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3291,7 +3291,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3331,7 +3331,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3388,7 +3388,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3428,7 +3428,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -3485,7 +3485,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3525,7 +3525,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result index ce23077d4bd..24de36da22b 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result @@ -188,14 +188,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -225,10 +225,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -272,14 +272,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -309,10 +309,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -368,14 +368,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -405,10 +405,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -453,14 +453,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -490,10 +490,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -550,14 +550,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -587,10 +587,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -636,14 +636,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -673,10 +673,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -734,14 +734,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -771,10 +771,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -819,14 +819,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -857,10 +857,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -904,14 +904,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -942,10 +942,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -988,14 +988,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1026,10 +1026,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1071,14 +1071,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1109,10 +1109,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1155,14 +1155,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1193,10 +1193,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1238,14 +1238,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1276,10 +1276,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1321,14 +1321,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1359,10 +1359,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1404,14 +1404,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1442,10 +1442,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1487,14 +1487,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1525,10 +1525,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1570,14 +1570,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1608,10 +1608,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1653,14 +1653,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1691,10 +1691,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1736,14 +1736,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1774,10 +1774,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1819,14 +1819,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1857,10 +1857,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1909,7 +1909,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1940,10 +1940,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -1992,7 +1992,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2023,10 +2023,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2075,7 +2075,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2106,10 +2106,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2158,7 +2158,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2189,10 +2189,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2241,7 +2241,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2272,10 +2272,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2324,7 +2324,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2355,10 +2355,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2407,7 +2407,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2438,10 +2438,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2490,7 +2490,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2521,10 +2521,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2573,7 +2573,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2604,10 +2604,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2656,7 +2656,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2687,10 +2687,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2739,7 +2739,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2773,7 +2773,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2822,7 +2822,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2856,7 +2856,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2905,7 +2905,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2939,7 +2939,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; @@ -2988,7 +2988,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3022,7 +3022,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_users; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result index a74b0288cd7..2f0c96d7234 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result @@ -218,14 +218,14 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -234,14 +234,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -275,18 +275,18 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -336,7 +336,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -348,7 +348,7 @@ user2 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 @@ -362,14 +362,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -413,20 +413,20 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 user2 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 +user1 transaction 2 user2 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -490,24 +490,24 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -516,14 +516,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -567,20 +567,20 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -637,12 +637,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -654,12 +654,12 @@ user3 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 @@ -673,14 +673,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -734,22 +734,22 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 user3 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 +user1 transaction 2 +user2 transaction 2 user3 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -820,34 +820,34 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -856,14 +856,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -917,22 +917,22 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -996,17 +996,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -1018,17 +1018,17 @@ user4 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 @@ -1042,14 +1042,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -1113,24 +1113,24 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 user4 transaction 0 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1208,44 +1208,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 6 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1254,14 +1254,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1325,24 +1325,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1407,44 +1407,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 6 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1453,14 +1453,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1525,24 +1525,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1606,44 +1606,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 6 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1652,14 +1652,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1724,24 +1724,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1804,44 +1804,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 6 @@ -1850,14 +1850,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1922,24 +1922,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2001,44 +2001,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2047,14 +2047,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2119,24 +2119,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2199,44 +2199,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2245,14 +2245,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2317,24 +2317,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2396,44 +2396,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2442,14 +2442,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2514,24 +2514,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2593,44 +2593,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2639,14 +2639,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2711,24 +2711,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2790,44 +2790,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -2836,14 +2836,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2908,24 +2908,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2987,44 +2987,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -3033,14 +3033,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3105,24 +3105,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3184,44 +3184,44 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -3230,14 +3230,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3302,24 +3302,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3403,22 +3403,22 @@ user4 localhost stage/sql/starting 0 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 -user1 stage/sql/closing tables 13 +user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 -user2 stage/sql/closing tables 11 +user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 -user3 stage/sql/closing tables 11 +user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 -user4 stage/sql/closing tables 11 +user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 user4 stage/sql/starting 7 @@ -3427,14 +3427,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3499,24 +3499,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3624,14 +3624,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3696,24 +3696,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3821,14 +3821,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3893,24 +3893,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4025,7 +4025,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4090,24 +4090,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4222,7 +4222,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4287,24 +4287,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4419,7 +4419,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4484,24 +4484,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4616,7 +4616,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4681,24 +4681,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4813,7 +4813,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4878,24 +4878,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5010,7 +5010,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5075,24 +5075,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5207,7 +5207,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5272,24 +5272,24 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5404,7 +5404,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5475,18 +5475,18 @@ user3 localhost transaction 0 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star -user1 transaction 1 -user2 transaction 1 -user3 transaction 1 -user4 transaction 1 +user1 transaction 2 +user2 transaction 2 +user3 transaction 2 +user4 transaction 2 execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5601,7 +5601,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5680,10 +5680,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5798,7 +5798,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5877,10 +5877,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5995,7 +5995,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6077,7 +6077,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6164,7 +6164,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6222,7 +6222,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6277,7 +6277,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6311,7 +6311,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -6362,7 +6362,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -6396,7 +6396,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result index c9c5ed2aebd..618201d9b85 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result @@ -230,7 +230,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -239,21 +239,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -287,18 +287,18 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -345,7 +345,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -359,21 +359,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 -localhost stage/sql/closing tables 13 +localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 localhost stage/sql/starting 6 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -412,19 +412,19 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 user2 localhost transaction 0 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 1 +localhost transaction 2 execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -484,12 +484,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -498,21 +498,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -551,19 +551,19 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -614,12 +614,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -633,21 +633,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 -localhost stage/sql/closing tables 24 +localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 localhost stage/sql/starting 12 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -691,20 +691,20 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 user3 localhost transaction 0 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 2 +localhost transaction 4 execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -768,17 +768,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -787,21 +787,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -845,20 +845,20 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -913,17 +913,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -937,21 +937,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 -localhost stage/sql/closing tables 35 +localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 localhost stage/sql/starting 18 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -1000,21 +1000,21 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 3 +localhost transaction 6 execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1082,22 +1082,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1106,21 +1106,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 24 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1169,21 +1169,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1238,22 +1238,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1262,21 +1262,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 25 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1326,21 +1326,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1394,22 +1394,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1418,21 +1418,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 26 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1482,21 +1482,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1549,22 +1549,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1573,21 +1573,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 27 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1637,21 +1637,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1703,22 +1703,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1727,21 +1727,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1791,21 +1791,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1858,22 +1858,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1882,21 +1882,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1946,21 +1946,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2012,22 +2012,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2036,21 +2036,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2100,21 +2100,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2166,22 +2166,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2190,21 +2190,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2254,21 +2254,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2320,22 +2320,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2344,21 +2344,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2408,21 +2408,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2474,22 +2474,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2498,21 +2498,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2562,21 +2562,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2628,22 +2628,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2652,21 +2652,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2716,21 +2716,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2806,21 +2806,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2870,21 +2870,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2960,21 +2960,21 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 -localhost stage/sql/closing tables 46 +localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3024,21 +3024,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3121,14 +3121,14 @@ localhost stage/sql/starting 0 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3178,21 +3178,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3282,7 +3282,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3332,21 +3332,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3436,7 +3436,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3486,21 +3486,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3590,7 +3590,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3640,21 +3640,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3744,7 +3744,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3794,21 +3794,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3898,7 +3898,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3948,21 +3948,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4052,7 +4052,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4102,21 +4102,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4206,7 +4206,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4256,21 +4256,21 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4360,7 +4360,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4418,13 +4418,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4514,7 +4514,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4572,13 +4572,13 @@ execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star -localhost transaction 4 +localhost transaction 8 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4668,7 +4668,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4729,10 +4729,10 @@ host event_name count_star localhost transaction 0 execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4822,7 +4822,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4886,7 +4886,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4948,7 +4948,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4988,7 +4988,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5046,7 +5046,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5086,7 +5086,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -5144,7 +5144,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -5184,7 +5184,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result index 671125191f8..d6dd322a70c 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result @@ -200,7 +200,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -211,14 +211,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -247,17 +247,17 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -301,7 +301,7 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 @@ -317,14 +317,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 -stage/sql/closing tables 13 +stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 stage/sql/starting 6 @@ -358,7 +358,7 @@ statement/sql/insert 1 statement/sql/select 3 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 +user1 localhost transaction 2 user2 localhost transaction 0 execute dump_transactions_user; user event_name count_star @@ -366,10 +366,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 1 +transaction 2 execute dump_transactions_history; event_name count(event_name) -transaction 1 +transaction 2 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -426,12 +426,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -442,14 +442,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -483,18 +483,18 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -542,12 +542,12 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 @@ -563,14 +563,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 -stage/sql/closing tables 24 +stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 stage/sql/starting 12 @@ -609,8 +609,8 @@ statement/sql/insert 2 statement/sql/select 6 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 user3 localhost transaction 0 execute dump_transactions_user; user event_name count_star @@ -618,10 +618,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 2 +transaction 4 execute dump_transactions_history; event_name count(event_name) -transaction 2 +transaction 4 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -682,17 +682,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -703,14 +703,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -749,19 +749,19 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -813,17 +813,17 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 @@ -839,14 +839,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 -stage/sql/closing tables 35 +stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 stage/sql/starting 18 @@ -890,9 +890,9 @@ statement/sql/insert 3 statement/sql/select 9 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 user4 localhost transaction 0 execute dump_transactions_user; user event_name count_star @@ -900,10 +900,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 3 +transaction 6 execute dump_transactions_history; event_name count(event_name) -transaction 3 +transaction 6 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -968,22 +968,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 6 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -994,14 +994,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 24 @@ -1045,20 +1045,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1110,22 +1110,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 6 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1136,14 +1136,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 25 @@ -1188,20 +1188,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1252,22 +1252,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 6 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1278,14 +1278,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 26 @@ -1330,20 +1330,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1393,22 +1393,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 6 @@ -1419,14 +1419,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 27 @@ -1471,20 +1471,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1533,22 +1533,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1559,14 +1559,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1611,20 +1611,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1674,22 +1674,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1700,14 +1700,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1752,20 +1752,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1814,22 +1814,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1840,14 +1840,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -1892,20 +1892,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -1954,22 +1954,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -1980,14 +1980,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2032,20 +2032,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2094,22 +2094,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2120,14 +2120,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2172,20 +2172,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2234,22 +2234,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2260,14 +2260,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2312,20 +2312,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2374,22 +2374,22 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/checking permissions 4 -user1 localhost stage/sql/closing tables 13 +user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 -user2 localhost stage/sql/closing tables 11 +user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 -user3 localhost stage/sql/closing tables 11 +user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 -user4 localhost stage/sql/closing tables 11 +user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 user4 localhost stage/sql/starting 7 @@ -2400,14 +2400,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2452,20 +2452,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2540,14 +2540,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2592,20 +2592,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2680,14 +2680,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2732,20 +2732,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2820,14 +2820,14 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -2872,20 +2872,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -2967,7 +2967,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3012,20 +3012,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3107,7 +3107,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3152,20 +3152,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3247,7 +3247,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3292,20 +3292,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3387,7 +3387,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3432,20 +3432,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3527,7 +3527,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3572,20 +3572,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3667,7 +3667,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3712,20 +3712,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3807,7 +3807,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -3852,20 +3852,20 @@ statement/sql/insert 4 statement/sql/select 12 execute dump_transactions_account; user host event_name count_star -user1 localhost transaction 1 -user2 localhost transaction 1 -user3 localhost transaction 1 -user4 localhost transaction 1 +user1 localhost transaction 2 +user2 localhost transaction 2 +user3 localhost transaction 2 +user4 localhost transaction 2 execute dump_transactions_user; user event_name count_star execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -3947,7 +3947,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4002,10 +4002,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4087,7 +4087,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4142,10 +4142,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4227,7 +4227,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4282,10 +4282,10 @@ execute dump_transactions_host; host event_name count_star execute dump_transactions_global; event_name count_star -transaction 4 +transaction 8 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4367,7 +4367,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4425,7 +4425,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4479,7 +4479,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4513,7 +4513,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4563,7 +4563,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4597,7 +4597,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 @@ -4647,7 +4647,7 @@ stage/sql/starting 0 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 -stage/sql/closing tables 46 +stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 stage/sql/starting 28 @@ -4681,7 +4681,7 @@ event_name count_star transaction 0 execute dump_transactions_history; event_name count(event_name) -transaction 4 +transaction 8 execute dump_accounts; USER HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS root localhost 1 1 diff --git a/mysql-test/suite/perfschema/r/grant.result b/mysql-test/suite/perfschema/r/grant.result new file mode 100644 index 00000000000..4679499279f --- /dev/null +++ b/mysql-test/suite/perfschema/r/grant.result @@ -0,0 +1,7 @@ +create user a@localhost; +connect a,localhost,a; +select * from performance_schema.global_status where variable_name='b'; +VARIABLE_NAME VARIABLE_VALUE +connection default; +disconnect a; +drop user a@localhost; diff --git a/mysql-test/suite/perfschema/r/sxlock_func.result b/mysql-test/suite/perfschema/r/sxlock_func.result index 21ecd5eee0b..04db3a42dd0 100644 --- a/mysql-test/suite/perfschema/r/sxlock_func.result +++ b/mysql-test/suite/perfschema/r/sxlock_func.result @@ -17,7 +17,6 @@ wait/synch/sxlock/innodb/dict_table_stats wait/synch/sxlock/innodb/fil_space_latch wait/synch/sxlock/innodb/fts_cache_init_rw_lock wait/synch/sxlock/innodb/fts_cache_rw_lock -wait/synch/sxlock/innodb/hash_table_locks wait/synch/sxlock/innodb/index_online_log wait/synch/sxlock/innodb/index_tree_rw_lock wait/synch/sxlock/innodb/trx_i_s_cache_lock diff --git a/mysql-test/suite/perfschema/r/transaction_nested_events.result b/mysql-test/suite/perfschema/r/transaction_nested_events.result index 6fa3822f090..52fa3783a8b 100644 --- a/mysql-test/suite/perfschema/r/transaction_nested_events.result +++ b/mysql-test/suite/perfschema/r/transaction_nested_events.result @@ -327,7 +327,7 @@ FROM performance_schema.events_transactions_current WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 3 10 transaction COMMITTED READ WRITE REPEATABLE READ NO 2 STATEMENT +thread_id 10 12 transaction COMMITTED READ WRITE REPEATABLE READ NO 9 STATEMENT # # EVENTS_TRANSACTIONS_HISTORY_LONG # @@ -345,7 +345,9 @@ FROM performance_schema.events_transactions_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 3 10 transaction COMMITTED READ WRITE REPEATABLE READ NO 2 STATEMENT +thread_id 2 2 transaction COMMITTED READ WRITE REPEATABLE READ YES 1 STATEMENT +thread_id 10 10 transaction COMMITTED READ WRITE REPEATABLE READ NO 9 STATEMENT +thread_id 10 12 transaction COMMITTED READ WRITE REPEATABLE READ NO 9 STATEMENT # # EVENTS_STATEMENTS_HISTORY_LONG # @@ -362,15 +364,15 @@ FROM performance_schema.events_statements_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME OBJECT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE LEVEL SQL_TEXT -thread_id 1 1 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_update() UPDATE t1 SET s1 = s1 + 1 -thread_id 2 3 statement/sql/begin NULL NULL NULL 0 START TRANSACTION -thread_id 4 4 statement/sql/insert NULL 3 TRANSACTION 0 INSERT INTO t1 VALUES (310, "INSERT 310") -thread_id 5 5 statement/sql/insert NULL 3 TRANSACTION 0 INSERT INTO t1 VALUES (311, "INSERT 311") -thread_id 6 6 statement/sql/insert NULL 3 TRANSACTION 0 INSERT INTO t1 VALUES (312, "INSERT 312") -thread_id 7 7 statement/sql/insert NULL 3 TRANSACTION 0 INSERT INTO t1 VALUES (313, "INSERT 313") -thread_id 8 9 statement/sql/call_procedure NULL 3 TRANSACTION 0 CALL tp_update() -thread_id 9 9 statement/sp/stmt tp_update 8 STATEMENT 1 UPDATE t1 SET s1 = s1 + 1 -thread_id 10 10 statement/sql/commit NULL 3 TRANSACTION 0 COMMIT +thread_id 1 2 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_update() UPDATE t1 SET s1 = s1 + 1 +thread_id 3 4 statement/sql/begin NULL NULL NULL 0 START TRANSACTION +thread_id 5 5 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (310, "INSERT 310") +thread_id 6 6 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (311, "INSERT 311") +thread_id 7 7 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (312, "INSERT 312") +thread_id 8 8 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (313, "INSERT 313") +thread_id 9 11 statement/sql/call_procedure NULL 4 TRANSACTION 0 CALL tp_update() +thread_id 11 11 statement/sp/stmt tp_update 9 STATEMENT 1 UPDATE t1 SET s1 = s1 + 1 +thread_id 12 12 statement/sql/commit NULL NULL NULL 0 COMMIT # ### Combined statement and transaction event history ordered by event id # @@ -397,16 +399,18 @@ FROM performance_schema.events_statements_history_long s WHERE ((s.thread_id = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, r_event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE SQL_TXT -thread_id 1 1 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_update() UPDATE t1 SET s1 = s1 + 1 -thread_id 2 3 statement/sql/begin NULL NULL START TRANSACTION -thread_id 3 10 transaction 2 STATEMENT -thread_id 4 4 statement/sql/insert 3 TRANSACTION INSERT INTO t1 VALUES (310, "INSERT 310") -thread_id 5 5 statement/sql/insert 3 TRANSACTION INSERT INTO t1 VALUES (311, "INSERT 311") -thread_id 6 6 statement/sql/insert 3 TRANSACTION INSERT INTO t1 VALUES (312, "INSERT 312") -thread_id 7 7 statement/sql/insert 3 TRANSACTION INSERT INTO t1 VALUES (313, "INSERT 313") -thread_id 8 9 statement/sql/call_proced 3 TRANSACTION CALL tp_update() -thread_id 9 9 statement/sp/stmt 8 STATEMENT UPDATE t1 SET s1 = s1 + 1 -thread_id 10 10 statement/sql/commit 3 TRANSACTION COMMIT +thread_id 1 2 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_update() UPDATE t1 SET s1 = s1 + 1 +thread_id 2 2 transaction 1 STATEMENT +thread_id 3 4 statement/sql/begin NULL NULL START TRANSACTION +thread_id 5 5 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (310, "INSERT 310") +thread_id 6 6 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (311, "INSERT 311") +thread_id 7 7 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (312, "INSERT 312") +thread_id 8 8 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (313, "INSERT 313") +thread_id 9 11 statement/sql/call_proced 4 TRANSACTION CALL tp_update() +thread_id 10 10 transaction 9 STATEMENT +thread_id 10 12 transaction 9 STATEMENT +thread_id 11 11 statement/sp/stmt 9 STATEMENT UPDATE t1 SET s1 = s1 + 1 +thread_id 12 12 statement/sql/commit NULL NULL COMMIT # ### Clear statement and transaction history # CALL test.clear_history(); @@ -464,7 +468,7 @@ FROM performance_schema.events_transactions_current WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 4 9 transaction COMMITTED READ WRITE REPEATABLE READ NO 3 STATEMENT +thread_id 6 11 transaction COMMITTED READ WRITE REPEATABLE READ NO 5 STATEMENT # # EVENTS_TRANSACTIONS_HISTORY_LONG # @@ -482,7 +486,9 @@ FROM performance_schema.events_transactions_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 4 9 transaction COMMITTED READ WRITE REPEATABLE READ NO 3 STATEMENT +thread_id 2 2 transaction COMMITTED READ WRITE REPEATABLE READ YES 1 STATEMENT +thread_id 4 4 transaction COMMITTED READ WRITE REPEATABLE READ YES 3 STATEMENT +thread_id 6 11 transaction COMMITTED READ WRITE REPEATABLE READ NO 5 STATEMENT # # EVENTS_STATEMENTS_HISTORY_LONG # @@ -499,14 +505,14 @@ FROM performance_schema.events_statements_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME OBJECT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE LEVEL SQL_TEXT -thread_id 1 1 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_start() START TRANSACTION -thread_id 2 4 statement/sql/call_procedure NULL NULL NULL 0 CALL tp_start() -thread_id 3 4 statement/sp/stmt tp_start 2 STATEMENT 1 START TRANSACTION -thread_id 5 5 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (320, "INSERT 320"),(321, "INSERT 321") -thread_id 6 6 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (322, "INSERT 322"),(323, "INSERT 323") -thread_id 7 7 statement/sql/update NULL 4 TRANSACTION 0 UPDATE t1 SET s1 = s1 + 1 WHERE s1 > 320 -thread_id 8 8 statement/sql/select NULL 4 TRANSACTION 0 SELECT * FROM t1 ORDER BY s1 -thread_id 9 9 statement/sql/commit NULL 4 TRANSACTION 0 COMMIT +thread_id 1 2 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_start() START TRANSACTION +thread_id 3 6 statement/sql/call_procedure NULL NULL NULL 0 CALL tp_start() +thread_id 5 6 statement/sp/stmt tp_start 3 STATEMENT 1 START TRANSACTION +thread_id 7 7 statement/sql/insert NULL 6 TRANSACTION 0 INSERT INTO t1 VALUES (320, "INSERT 320"),(321, "INSERT 321") +thread_id 8 8 statement/sql/insert NULL 6 TRANSACTION 0 INSERT INTO t1 VALUES (322, "INSERT 322"),(323, "INSERT 323") +thread_id 9 9 statement/sql/update NULL 6 TRANSACTION 0 UPDATE t1 SET s1 = s1 + 1 WHERE s1 > 320 +thread_id 10 10 statement/sql/select NULL 6 TRANSACTION 0 SELECT * FROM t1 ORDER BY s1 +thread_id 11 11 statement/sql/commit NULL 6 TRANSACTION 0 COMMIT # ### Combined statement and transaction event history ordered by event id # @@ -533,15 +539,17 @@ FROM performance_schema.events_statements_history_long s WHERE ((s.thread_id = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, r_event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE SQL_TXT -thread_id 1 1 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_start() START TRANSACTION -thread_id 2 4 statement/sql/call_proced NULL NULL CALL tp_start() -thread_id 3 4 statement/sp/stmt 2 STATEMENT START TRANSACTION -thread_id 4 9 transaction 3 STATEMENT -thread_id 5 5 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (320, "INSERT 320"),(321, "INSERT 321") -thread_id 6 6 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (322, "INSERT 322"),(323, "INSERT 323") -thread_id 7 7 statement/sql/update 4 TRANSACTION UPDATE t1 SET s1 = s1 + 1 WHERE s1 > 320 -thread_id 8 8 statement/sql/select 4 TRANSACTION SELECT * FROM t1 ORDER BY s1 -thread_id 9 9 statement/sql/commit 4 TRANSACTION COMMIT +thread_id 1 2 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_start() START TRANSACTION +thread_id 2 2 transaction 1 STATEMENT +thread_id 3 6 statement/sql/call_proced NULL NULL CALL tp_start() +thread_id 4 4 transaction 3 STATEMENT +thread_id 5 6 statement/sp/stmt 3 STATEMENT START TRANSACTION +thread_id 6 11 transaction 5 STATEMENT +thread_id 7 7 statement/sql/insert 6 TRANSACTION INSERT INTO t1 VALUES (320, "INSERT 320"),(321, "INSERT 321") +thread_id 8 8 statement/sql/insert 6 TRANSACTION INSERT INTO t1 VALUES (322, "INSERT 322"),(323, "INSERT 323") +thread_id 9 9 statement/sql/update 6 TRANSACTION UPDATE t1 SET s1 = s1 + 1 WHERE s1 > 320 +thread_id 10 10 statement/sql/select 6 TRANSACTION SELECT * FROM t1 ORDER BY s1 +thread_id 11 11 statement/sql/commit 6 TRANSACTION COMMIT # ### Clear statement and transaction history # CALL test.clear_history(); @@ -609,7 +617,7 @@ FROM performance_schema.events_transactions_current WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 18 18 transaction COMMITTED READ WRITE REPEATABLE READ YES 17 STATEMENT +thread_id 22 22 transaction COMMITTED READ WRITE REPEATABLE READ YES 21 STATEMENT # # EVENTS_TRANSACTIONS_HISTORY_LONG # @@ -627,10 +635,14 @@ FROM performance_schema.events_transactions_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 4 9 transaction COMMITTED READ WRITE REPEATABLE READ NO 3 STATEMENT -thread_id 11 11 transaction COMMITTED READ WRITE REPEATABLE READ YES 10 STATEMENT -thread_id 13 16 transaction ROLLED BACK READ WRITE REPEATABLE READ NO 12 STATEMENT -thread_id 18 18 transaction COMMITTED READ WRITE REPEATABLE READ YES 17 STATEMENT +thread_id 2 2 transaction COMMITTED READ WRITE REPEATABLE READ YES 1 STATEMENT +thread_id 4 4 transaction COMMITTED READ WRITE REPEATABLE READ YES 3 STATEMENT +thread_id 11 11 transaction COMMITTED READ WRITE REPEATABLE READ NO 10 STATEMENT +thread_id 11 12 transaction COMMITTED READ WRITE REPEATABLE READ NO 10 STATEMENT +thread_id 14 14 transaction COMMITTED READ WRITE REPEATABLE READ YES 13 STATEMENT +thread_id 19 19 transaction COMMITTED READ WRITE REPEATABLE READ NO 18 STATEMENT +thread_id 19 20 transaction ROLLED BACK READ WRITE REPEATABLE READ NO 18 STATEMENT +thread_id 22 22 transaction COMMITTED READ WRITE REPEATABLE READ YES 21 STATEMENT # # EVENTS_STATEMENTS_HISTORY_LONG # @@ -647,20 +659,20 @@ FROM performance_schema.events_statements_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME OBJECT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE LEVEL SQL_TEXT -thread_id 1 1 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_rollback() ROLLBACK -thread_id 2 2 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_commit() COMMIT -thread_id 3 4 statement/sql/begin NULL NULL NULL 0 START TRANSACTION -thread_id 5 5 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (330, "INSERT 330"),(331, "INSERT 331") -thread_id 6 6 statement/sql/insert NULL 4 TRANSACTION 0 INSERT INTO t1 VALUES (332, "INSERT 332"),(333, "INSERT 333") -thread_id 7 7 statement/sql/delete NULL 4 TRANSACTION 0 DELETE FROM t1 WHERE s1 > 331 -thread_id 8 9 statement/sql/call_procedure NULL 4 TRANSACTION 0 CALL tp_commit() -thread_id 9 9 statement/sp/stmt tp_commit 8 STATEMENT 1 COMMIT -thread_id 10 11 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 -thread_id 12 13 statement/sql/begin NULL NULL NULL 0 START TRANSACTION -thread_id 14 14 statement/sql/update NULL 13 TRANSACTION 0 UPDATE t1 SET s1 = s1*2 WHERE s1 > 331 -thread_id 15 16 statement/sql/call_procedure NULL 13 TRANSACTION 0 CALL tp_rollback() -thread_id 16 16 statement/sp/stmt tp_rollback 15 STATEMENT 1 ROLLBACK -thread_id 17 18 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 +thread_id 1 2 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_rollback() ROLLBACK +thread_id 3 4 statement/sql/create_procedure NULL NULL NULL 0 CREATE PROCEDURE tp_commit() COMMIT +thread_id 5 6 statement/sql/begin NULL NULL NULL 0 START TRANSACTION +thread_id 7 7 statement/sql/insert NULL 6 TRANSACTION 0 INSERT INTO t1 VALUES (330, "INSERT 330"),(331, "INSERT 331") +thread_id 8 8 statement/sql/insert NULL 6 TRANSACTION 0 INSERT INTO t1 VALUES (332, "INSERT 332"),(333, "INSERT 333") +thread_id 9 9 statement/sql/delete NULL 6 TRANSACTION 0 DELETE FROM t1 WHERE s1 > 331 +thread_id 10 12 statement/sql/call_procedure NULL 6 TRANSACTION 0 CALL tp_commit() +thread_id 12 12 statement/sp/stmt tp_commit 10 STATEMENT 1 COMMIT +thread_id 13 14 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 +thread_id 15 16 statement/sql/begin NULL NULL NULL 0 START TRANSACTION +thread_id 17 17 statement/sql/update NULL 16 TRANSACTION 0 UPDATE t1 SET s1 = s1*2 WHERE s1 > 331 +thread_id 18 20 statement/sql/call_procedure NULL 16 TRANSACTION 0 CALL tp_rollback() +thread_id 20 20 statement/sp/stmt tp_rollback 18 STATEMENT 1 ROLLBACK +thread_id 21 22 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 # ### Combined statement and transaction event history ordered by event id # @@ -687,24 +699,28 @@ FROM performance_schema.events_statements_history_long s WHERE ((s.thread_id = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, r_event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE SQL_TXT -thread_id 1 1 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_rollback() ROLLBACK -thread_id 2 2 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_commit() COMMIT -thread_id 3 4 statement/sql/begin NULL NULL START TRANSACTION -thread_id 4 9 transaction 3 STATEMENT -thread_id 5 5 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (330, "INSERT 330"),(331, "INSERT 331") -thread_id 6 6 statement/sql/insert 4 TRANSACTION INSERT INTO t1 VALUES (332, "INSERT 332"),(333, "INSERT 333") -thread_id 7 7 statement/sql/delete 4 TRANSACTION DELETE FROM t1 WHERE s1 > 331 -thread_id 8 9 statement/sql/call_proced 4 TRANSACTION CALL tp_commit() -thread_id 9 9 statement/sp/stmt 8 STATEMENT COMMIT -thread_id 10 11 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 +thread_id 1 2 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_rollback() ROLLBACK +thread_id 2 2 transaction 1 STATEMENT +thread_id 3 4 statement/sql/create_proc NULL NULL CREATE PROCEDURE tp_commit() COMMIT +thread_id 4 4 transaction 3 STATEMENT +thread_id 5 6 statement/sql/begin NULL NULL START TRANSACTION +thread_id 7 7 statement/sql/insert 6 TRANSACTION INSERT INTO t1 VALUES (330, "INSERT 330"),(331, "INSERT 331") +thread_id 8 8 statement/sql/insert 6 TRANSACTION INSERT INTO t1 VALUES (332, "INSERT 332"),(333, "INSERT 333") +thread_id 9 9 statement/sql/delete 6 TRANSACTION DELETE FROM t1 WHERE s1 > 331 +thread_id 10 12 statement/sql/call_proced 6 TRANSACTION CALL tp_commit() thread_id 11 11 transaction 10 STATEMENT -thread_id 12 13 statement/sql/begin NULL NULL START TRANSACTION -thread_id 13 16 transaction 12 STATEMENT -thread_id 14 14 statement/sql/update 13 TRANSACTION UPDATE t1 SET s1 = s1*2 WHERE s1 > 331 -thread_id 15 16 statement/sql/call_proced 13 TRANSACTION CALL tp_rollback() -thread_id 16 16 statement/sp/stmt 15 STATEMENT ROLLBACK -thread_id 17 18 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 -thread_id 18 18 transaction 17 STATEMENT +thread_id 11 12 transaction 10 STATEMENT +thread_id 12 12 statement/sp/stmt 10 STATEMENT COMMIT +thread_id 13 14 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 +thread_id 14 14 transaction 13 STATEMENT +thread_id 15 16 statement/sql/begin NULL NULL START TRANSACTION +thread_id 17 17 statement/sql/update 16 TRANSACTION UPDATE t1 SET s1 = s1*2 WHERE s1 > 331 +thread_id 18 20 statement/sql/call_proced 16 TRANSACTION CALL tp_rollback() +thread_id 19 19 transaction 18 STATEMENT +thread_id 19 20 transaction 18 STATEMENT +thread_id 20 20 statement/sp/stmt 18 STATEMENT ROLLBACK +thread_id 21 22 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 +thread_id 22 22 transaction 21 STATEMENT # ### Clear statement and transaction history # CALL test.clear_history(); @@ -783,7 +799,7 @@ FROM performance_schema.events_transactions_current WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 13 13 transaction COMMITTED READ WRITE REPEATABLE READ YES 12 STATEMENT +thread_id 14 14 transaction COMMITTED READ WRITE REPEATABLE READ YES 13 STATEMENT # # EVENTS_TRANSACTIONS_HISTORY_LONG # @@ -801,8 +817,9 @@ FROM performance_schema.events_transactions_history_long WHERE ((THREAD_ID = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME STATE ACCESS_MODE ISOLATION_LEVEL AUTO R_NESTING_EVENT_ID NESTING_EVENT_TYPE -thread_id 2 11 transaction COMMITTED READ WRITE REPEATABLE READ NO 1 STATEMENT -thread_id 13 13 transaction COMMITTED READ WRITE REPEATABLE READ YES 12 STATEMENT +thread_id 9 9 transaction COMMITTED READ WRITE REPEATABLE READ NO 8 STATEMENT +thread_id 9 12 transaction COMMITTED READ WRITE REPEATABLE READ NO 8 STATEMENT +thread_id 14 14 transaction COMMITTED READ WRITE REPEATABLE READ YES 13 STATEMENT # # EVENTS_STATEMENTS_HISTORY_LONG # @@ -825,11 +842,11 @@ thread_id 4 4 statement/sql/insert NULL thread_id 5 5 statement/sql/insert NULL 2 TRANSACTION 0 INSERT INTO t1 VALUES (412, "INSERT 412") thread_id 6 6 statement/sql/delete NULL 2 TRANSACTION 0 DELETE FROM t1 WHERE s1 > 410 thread_id 7 7 statement/sql/select NULL 2 TRANSACTION 0 SELECT * FROM t1 ORDER BY s1 -thread_id 8 10 statement/sql/select NULL 2 TRANSACTION 0 SELECT fn_add(413, 414) -thread_id 9 9 statement/sp/stmt fn_add 8 STATEMENT 1 INSERT INTO t1 VALUES (x, "INSERT x"),(y, "INSERT y") -thread_id 10 10 statement/sp/freturn fn_add 8 STATEMENT 1 NULL -thread_id 11 11 statement/sql/commit NULL 2 TRANSACTION 0 COMMIT -thread_id 12 13 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 +thread_id 8 11 statement/sql/select NULL 2 TRANSACTION 0 SELECT fn_add(413, 414) +thread_id 10 10 statement/sp/stmt fn_add 8 STATEMENT 1 INSERT INTO t1 VALUES (x, "INSERT x"),(y, "INSERT y") +thread_id 11 11 statement/sp/freturn fn_add 8 STATEMENT 1 NULL +thread_id 12 12 statement/sql/commit NULL NULL NULL 0 COMMIT +thread_id 13 14 statement/sql/select NULL NULL NULL 0 SELECT * FROM t1 ORDER BY s1 # ### Combined statement and transaction event history ordered by event id # @@ -857,18 +874,19 @@ WHERE ((s.thread_id = @con1_thread_id) OR (@all_threads = 1)) ORDER BY thread_id, r_event_id; THREAD_ID R_EVENT_ID R_END_EVENT_ID EVENT_NAME R_NESTING_EVENT_ID NESTING_EVENT_TYPE SQL_TXT thread_id 1 2 statement/sql/begin NULL NULL START TRANSACTION -thread_id 2 11 transaction 1 STATEMENT thread_id 3 3 statement/sql/insert 2 TRANSACTION INSERT INTO t1 VALUES (410, "INSERT 410") thread_id 4 4 statement/sql/insert 2 TRANSACTION INSERT INTO t1 VALUES (411, "INSERT 411") thread_id 5 5 statement/sql/insert 2 TRANSACTION INSERT INTO t1 VALUES (412, "INSERT 412") thread_id 6 6 statement/sql/delete 2 TRANSACTION DELETE FROM t1 WHERE s1 > 410 thread_id 7 7 statement/sql/select 2 TRANSACTION SELECT * FROM t1 ORDER BY s1 -thread_id 8 10 statement/sql/select 2 TRANSACTION SELECT fn_add(413, 414) -thread_id 9 9 statement/sp/stmt 8 STATEMENT INSERT INTO t1 VALUES (x, "INSERT x"),(y, "INSERT y") -thread_id 10 10 statement/sp/freturn 8 STATEMENT NULL -thread_id 11 11 statement/sql/commit 2 TRANSACTION COMMIT -thread_id 12 13 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 -thread_id 13 13 transaction 12 STATEMENT +thread_id 8 11 statement/sql/select 2 TRANSACTION SELECT fn_add(413, 414) +thread_id 9 9 transaction 8 STATEMENT +thread_id 9 12 transaction 8 STATEMENT +thread_id 10 10 statement/sp/stmt 8 STATEMENT INSERT INTO t1 VALUES (x, "INSERT x"),(y, "INSERT y") +thread_id 11 11 statement/sp/freturn 8 STATEMENT NULL +thread_id 12 12 statement/sql/commit NULL NULL COMMIT +thread_id 13 14 statement/sql/select NULL NULL SELECT * FROM t1 ORDER BY s1 +thread_id 14 14 transaction 13 STATEMENT # ### Clear statement and transaction history # CALL test.clear_history(); @@ -1023,11 +1041,11 @@ connection con1; SELECT fn_err1(); ERROR 42000: FUNCTION db.fn_err1 does not exist # -## Expect 0 transactions +## Expect 1 transactions connection default; SELECT COUNT(*) FROM performance_schema.events_transactions_history; COUNT(*) -0 +1 connection con1; # CREATE FUNCTION fn_err2() RETURNS VARCHAR(10) BEGIN COMMIT; RETURN 'invalid' ; END| @@ -1040,11 +1058,11 @@ DELETE FROM t1 WHERE s1 > 320; SELECT fn_err2(); ERROR 42000: FUNCTION db.fn_err2 does not exist # -## Expect 0 transactions +## Expect 2 transactions connection default; SELECT COUNT(*) FROM performance_schema.events_transactions_history; COUNT(*) -0 +2 # ## Clear transaction and statement tables CALL test.clear_history(); diff --git a/mysql-test/suite/perfschema/t/grant.test b/mysql-test/suite/perfschema/t/grant.test new file mode 100644 index 00000000000..446965dfe9d --- /dev/null +++ b/mysql-test/suite/perfschema/t/grant.test @@ -0,0 +1,12 @@ +--source include/not_embedded.inc +--source include/have_perfschema.inc +# +# MDEV-22884 Assertion `grant_table || grant_table_role' failed on perfschema +# +create user a@localhost; +connect a,localhost,a; +select * from performance_schema.global_status where variable_name='b'; +connection default; +disconnect a; +drop user a@localhost; + diff --git a/mysql-test/suite/perfschema/t/no_threads.test b/mysql-test/suite/perfschema/t/no_threads.test index 3cf9a9e3126..b7b8767f1cc 100644 --- a/mysql-test/suite/perfschema/t/no_threads.test +++ b/mysql-test/suite/perfschema/t/no_threads.test @@ -2,7 +2,6 @@ --source include/not_embedded.inc --source include/have_perfschema.inc ---source include/not_threadpool.inc # Setup : in this main thread diff --git a/mysql-test/suite/perfschema/t/one_thread_per_con.test b/mysql-test/suite/perfschema/t/one_thread_per_con.test index 7a66cd2088f..11a203a12e5 100644 --- a/mysql-test/suite/perfschema/t/one_thread_per_con.test +++ b/mysql-test/suite/perfschema/t/one_thread_per_con.test @@ -2,7 +2,6 @@ --source include/not_embedded.inc --source include/have_perfschema.inc ---source include/not_threadpool.inc # Setup diff --git a/mysql-test/suite/perfschema/t/show_sanity.test b/mysql-test/suite/perfschema/t/show_sanity.test index 029e1d9033e..f6c43c88111 100644 --- a/mysql-test/suite/perfschema/t/show_sanity.test +++ b/mysql-test/suite/perfschema/t/show_sanity.test @@ -486,7 +486,6 @@ insert into test.sanity values ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_OPTIMIZE_FULLTEXT_ONLY"), ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PAGE_CLEANERS"), ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PAGE_CLEANER_DISABLED_DEBUG"), - ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PAGE_HASH_LOCKS"), ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PAGE_SIZE"), ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PRINT_ALL_DEADLOCKS"), ("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "INNODB_PURGE_BATCH_SIZE"), diff --git a/mysql-test/suite/perfschema/t/thread_cache.test b/mysql-test/suite/perfschema/t/thread_cache.test index 90823988f8c..92309bb9ca1 100644 --- a/mysql-test/suite/perfschema/t/thread_cache.test +++ b/mysql-test/suite/perfschema/t/thread_cache.test @@ -2,7 +2,6 @@ --source include/not_embedded.inc --source include/have_perfschema.inc ---source include/not_threadpool.inc # # Important note: diff --git a/mysql-test/suite/perfschema/t/transaction_nested_events.test b/mysql-test/suite/perfschema/t/transaction_nested_events.test index c6cab52525b..1be7dc0f937 100644 --- a/mysql-test/suite/perfschema/t/transaction_nested_events.test +++ b/mysql-test/suite/perfschema/t/transaction_nested_events.test @@ -235,7 +235,7 @@ SELECT COUNT(*) FROM performance_schema.events_transactions_history; SELECT fn_err1(); --echo # ---echo ## Expect 0 transactions +--echo ## Expect 1 transactions --connection default SELECT COUNT(*) FROM performance_schema.events_transactions_history; --connection con1 @@ -255,7 +255,7 @@ DELETE FROM t1 WHERE s1 > 320; SELECT fn_err2(); --echo # ---echo ## Expect 0 transactions +--echo ## Expect 2 transactions --connection default SELECT COUNT(*) FROM performance_schema.events_transactions_history; diff --git a/mysql-test/suite/period/engines.combinations b/mysql-test/suite/period/engines.combinations index b740ec62a42..62bf838de6c 100644 --- a/mysql-test/suite/period/engines.combinations +++ b/mysql-test/suite/period/engines.combinations @@ -3,4 +3,5 @@ innodb default-storage-engine=innodb [myisam] +innodb default-storage-engine=myisam diff --git a/mysql-test/suite/period/r/overlaps.result b/mysql-test/suite/period/r/overlaps.result index 2d9af4e23c3..fcd54a0a942 100644 --- a/mysql-test/suite/period/r/overlaps.result +++ b/mysql-test/suite/period/r/overlaps.result @@ -62,6 +62,61 @@ id s e 1 2003-01-01 2003-02-01 1 2003-03-01 2003-05-01 1 2003-05-01 2003-07-01 +# UPDATE ... FOR PORTION test +insert t values (2, '2003-04-15', '2003-05-01'); +update t for portion of p from '2003-01-01' to '2003-01-15' + set id= 2; +select * from t; +id s e +1 2003-01-15 2003-02-01 +1 2003-03-01 2003-05-01 +1 2003-05-01 2003-07-01 +2 2003-01-01 2003-01-15 +2 2003-04-15 2003-05-01 +update t for portion of p from '2003-01-15' to '2003-02-01' + set id= 2; +select * from t; +id s e +1 2003-03-01 2003-05-01 +1 2003-05-01 2003-07-01 +2 2003-01-01 2003-01-15 +2 2003-01-15 2003-02-01 +2 2003-04-15 2003-05-01 +# Next, test UPDATE ... FOR PORTION resulting with an error +# Since MyISAM/Aria engines lack atomicity, the results would differ with +# innodb. So a table is going to be copied to one with explicit engine. +create table t_myisam (id int, s date, e date, +period for p(s,e), +primary key(id, p without overlaps)) +engine=myisam +select * from t; +update t_myisam for portion of p from '2003-04-01' to '2003-06-01' + set id= 2 order by s desc; +ERROR 23000: Duplicate entry '2-2003-05-01-2003-04-01' for key 'PRIMARY' +select * from t_myisam; +id s e +1 2003-03-01 2003-05-01 +1 2003-06-01 2003-07-01 +2 2003-01-01 2003-01-15 +2 2003-01-15 2003-02-01 +2 2003-04-15 2003-05-01 +2 2003-05-01 2003-06-01 +create table t_innodb (id int, s date, e date, +period for p(s,e), +primary key(id, p without overlaps)) +engine=innodb +select * from t; +update t_innodb for portion of p from '2003-04-01' to '2003-06-01' + set id= 2 order by s desc; +ERROR 23000: Duplicate entry '2-2003-05-01-2003-04-01' for key 'PRIMARY' +select * from t_innodb; +id s e +1 2003-03-01 2003-05-01 +1 2003-05-01 2003-07-01 +2 2003-01-01 2003-01-15 +2 2003-01-15 2003-02-01 +2 2003-04-15 2003-05-01 +drop table t_myisam, t_innodb; create or replace table t(id int, s date, e date, period for p(s,e), primary key(id, q without overlaps)); @@ -120,7 +175,7 @@ insert into t values (3, NULL, '2003-03-01', '2003-05-01'); insert into t values (1, 1, '2003-03-01', '2003-05-01'); insert into t values (1, 2, '2003-05-01', '2003-07-01'); insert into t values (4, NULL, '2003-03-01', '2003-05-01'); -create sequence seq start=5; +create sequence seq start=5 engine=myisam; update t set id= nextval(seq), u= nextval(seq), s='2003-05-01', e='2003-07-01' where u is NULL; select * from t; @@ -130,6 +185,7 @@ id u s e 5 6 2003-05-01 2003-07-01 7 8 2003-05-01 2003-07-01 9 10 2003-05-01 2003-07-01 +drop sequence seq; create or replace table t(id int, s date, e date, period for p(s,e)); insert into t values (1, '2003-01-01', '2003-03-01'), @@ -226,4 +282,42 @@ Warnings: Warning 1062 Duplicate entry '1-2020-03-05-2020-03-01' for key 'x' load data infile 'tmp_t.txt' replace into table t; ERROR 42000: This version of MariaDB doesn't yet support 'WITHOUT OVERLAPS' -create or replace database test; +# MDEV-22599 WITHOUT OVERLAPS does not work with prefix indexes +create or replace table t1 (a varchar(6), s timestamp, e timestamp, +period for p(s,e), +unique(a(3), p without overlaps)); +insert into t1 values ('foo', '2012-01-01', '2015-12-31'); +insert into t1 values ('foobar', '2013-01-01', '2014-01-01'); +ERROR 23000: Duplicate entry 'foo-2014-01-01 00:00:00-2013-01-01 00:00:00' for key 'a' +insert into t1 values ('bar', '2012-01-01', '2015-12-31'), +('baz', '2013-01-01', '2014-01-01'); +select * from t1; +a s e +foo 2012-01-01 00:00:00 2015-12-31 00:00:00 +bar 2012-01-01 00:00:00 2015-12-31 00:00:00 +baz 2013-01-01 00:00:00 2014-01-01 00:00:00 +# MDEV-22753 Server crashes in handler::ha_check_overlaps or error 190 +# "Incompatible key or row definition" upon INSERT into versioned +# partitioned table with WITHOUT OVERLAPS +create or replace table t1 (f int, s date, e date, period for p(s,e), +unique(f, p without overlaps) +) engine=innodb with system versioning +partition by system_time limit 1000 +(partition p1 history, partition pn current); +alter table t1 add partition (partition p2 history); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f` int(11) DEFAULT NULL, + `s` date NOT NULL, + `e` date NOT NULL, + PERIOD FOR `p` (`s`, `e`), + UNIQUE KEY `f` (`f`,`p` WITHOUT OVERLAPS) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING + PARTITION BY SYSTEM_TIME LIMIT 1000 +(PARTITION `p1` HISTORY ENGINE = InnoDB, + PARTITION `p2` HISTORY ENGINE = InnoDB, + PARTITION `pn` CURRENT ENGINE = InnoDB) +insert into t1 values (1,'2013-01-12','2015-11-04'), +(2,'2016-03-15','2024-11-09'); +drop table t, t1; diff --git a/mysql-test/suite/period/t/overlaps.test b/mysql-test/suite/period/t/overlaps.test index a3399570bd8..30032f9898c 100644 --- a/mysql-test/suite/period/t/overlaps.test +++ b/mysql-test/suite/period/t/overlaps.test @@ -67,6 +67,47 @@ update t set e= '2003-05-01' where s = '2003-01-01'; select * from t where year(s) = 2003; +--echo # UPDATE ... FOR PORTION test +insert t values (2, '2003-04-15', '2003-05-01'); + +update t for portion of p from '2003-01-01' to '2003-01-15' + set id= 2; +--sorted_result +select * from t; + +update t for portion of p from '2003-01-15' to '2003-02-01' + set id= 2; +--sorted_result +select * from t; + +--echo # Next, test UPDATE ... FOR PORTION resulting with an error +--echo # Since MyISAM/Aria engines lack atomicity, the results would differ with +--echo # innodb. So a table is going to be copied to one with explicit engine. + +create table t_myisam (id int, s date, e date, + period for p(s,e), + primary key(id, p without overlaps)) + engine=myisam + select * from t; +--error ER_DUP_ENTRY +update t_myisam for portion of p from '2003-04-01' to '2003-06-01' + set id= 2 order by s desc; +--sorted_result +select * from t_myisam; + +create table t_innodb (id int, s date, e date, + period for p(s,e), + primary key(id, p without overlaps)) + engine=innodb + select * from t; +--error ER_DUP_ENTRY +update t_innodb for portion of p from '2003-04-01' to '2003-06-01' + set id= 2 order by s desc; +--sorted_result +select * from t_innodb; + +drop table t_myisam, t_innodb; + --error ER_PERIOD_NOT_FOUND create or replace table t(id int, s date, e date, period for p(s,e), @@ -116,12 +157,13 @@ insert into t values (1, 1, '2003-03-01', '2003-05-01'); insert into t values (1, 2, '2003-05-01', '2003-07-01'); insert into t values (4, NULL, '2003-03-01', '2003-05-01'); -create sequence seq start=5; +create sequence seq start=5 engine=myisam; update t set id= nextval(seq), u= nextval(seq), s='2003-05-01', e='2003-07-01' where u is NULL; --sorted_result select * from t; +drop sequence seq; create or replace table t(id int, s date, e date, period for p(s,e)); @@ -229,4 +271,33 @@ load data infile 'tmp_t.txt' replace into table t; remove_file $MYSQLD_DATADIR/test/tmp_t.txt; -create or replace database test; + +--echo # MDEV-22599 WITHOUT OVERLAPS does not work with prefix indexes +create or replace table t1 (a varchar(6), s timestamp, e timestamp, + period for p(s,e), + unique(a(3), p without overlaps)); + +insert into t1 values ('foo', '2012-01-01', '2015-12-31'); +--error ER_DUP_ENTRY +insert into t1 values ('foobar', '2013-01-01', '2014-01-01'); + +insert into t1 values ('bar', '2012-01-01', '2015-12-31'), + ('baz', '2013-01-01', '2014-01-01'); +select * from t1; + +--echo # MDEV-22753 Server crashes in handler::ha_check_overlaps or error 190 +--echo # "Incompatible key or row definition" upon INSERT into versioned +--echo # partitioned table with WITHOUT OVERLAPS +create or replace table t1 (f int, s date, e date, period for p(s,e), + unique(f, p without overlaps) + ) engine=innodb with system versioning + partition by system_time limit 1000 + (partition p1 history, partition pn current); +alter table t1 add partition (partition p2 history); +show create table t1; +insert into t1 values (1,'2013-01-12','2015-11-04'), + (2,'2016-03-15','2024-11-09'); + + + +drop table t, t1; diff --git a/mysql-test/suite/roles/set_default_role_for.result b/mysql-test/suite/roles/set_default_role_for.result index dff41917879..533a646e6e3 100644 --- a/mysql-test/suite/roles/set_default_role_for.result +++ b/mysql-test/suite/roles/set_default_role_for.result @@ -14,7 +14,7 @@ set default role role_a for user_a@localhost; set default role invalid_role for user_a@localhost; ERROR OP000: Invalid role specification `invalid_role` set default role role_b for user_a@localhost; -ERROR OP000: Invalid role specification `role_b` +ERROR OP000: User `user_a@localhost` has not been granted role `role_b` set default role role_b for user_b@localhost; show grants; Grants for user_a@localhost @@ -36,7 +36,7 @@ User Host default_role user_a localhost role_a user_b localhost role_b set default role role_b for current_user; -ERROR OP000: Invalid role specification `role_b` +ERROR OP000: User `user_a@localhost` has not been granted role `role_b` show grants; Grants for user_b@localhost GRANT `role_b` TO `user_b`@`localhost` diff --git a/mysql-test/suite/roles/set_default_role_invalid.result b/mysql-test/suite/roles/set_default_role_invalid.result index 5af0cc12be2..c8789594593 100644 --- a/mysql-test/suite/roles/set_default_role_invalid.result +++ b/mysql-test/suite/roles/set_default_role_invalid.result @@ -38,3 +38,90 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us drop role test_role; drop role not_granted_role; drop user test_user@localhost; +# +# MDEV-22312: Bad error message for SET DEFAULT ROLE when user account +# is not granted the role +# +CREATE USER a; +CREATE USER b; +CREATE ROLE r1; +CREATE ROLE r2; +SET DEFAULT ROLE r1 FOR a; +ERROR OP000: User `a@%` has not been granted role `r1` +GRANT r1 TO b; +GRANT r2 TO b; +SET DEFAULT ROLE r1 FOR b; +# Change user b +SELECT CURRENT_ROLE; +CURRENT_ROLE +r1 +SET ROLE r2; +SELECT CURRENT_ROLE; +CURRENT_ROLE +r2 +SET DEFAULT ROLE r1 FOR a; +ERROR 42000: Access denied for user 'b'@'%' to database 'mysql' +SET DEFAULT ROLE r2; +# Change user root (session 1: select_priv to b) +GRANT SELECT ON mysql.* TO b; +# Change user b (session 1: select_priv) +SHOW GRANTS FOR b; +Grants for b@% +GRANT `r1` TO `b`@`%` +GRANT `r2` TO `b`@`%` +GRANT USAGE ON *.* TO `b`@`%` +GRANT SELECT ON `mysql`.* TO `b`@`%` +SET DEFAULT ROLE r1 FOR a; +ERROR 42000: Access denied for user 'b'@'%' to database 'mysql' +SELECT CURRENT_ROLE; +CURRENT_ROLE +r2 +SET DEFAULT ROLE NONE; +SELECT CURRENT_ROLE; +CURRENT_ROLE +r2 +SET DEFAULT ROLE current_role FOR current_user; +SET DEFAULT ROLE invalid_role; +ERROR OP000: Invalid role specification `invalid_role` +SET DEFAULT ROLE invalid_role FOR a; +ERROR 42000: Access denied for user 'b'@'%' to database 'mysql' +SET DEFAULT ROLE none FOR a; +ERROR 42000: Access denied for user 'b'@'%' to database 'mysql' +# Change user root (session 2: adding update_priv to user b) +GRANT UPDATE ON mysql.* TO b; +# Change user b +SHOW GRANTS FOR b; +Grants for b@% +GRANT `r1` TO `b`@`%` +GRANT `r2` TO `b`@`%` +GRANT USAGE ON *.* TO `b`@`%` +GRANT SELECT, UPDATE ON `mysql`.* TO `b`@`%` +SET DEFAULT ROLE r1 FOR a; +ERROR OP000: User `a@%` has not been granted role `r1` +SET DEFAULT ROLE invalid_role; +ERROR OP000: Invalid role specification `invalid_role` +SET DEFAULT ROLE invalid_role FOR a; +ERROR OP000: Invalid role specification `invalid_role` +SET DEFAULT ROLE none FOR a; +# Change user root (session 3: Grant role to user a) +GRANT r1 TO a; +SET DEFAULT ROLE r1 FOR a; +# Change user a (verify session 3) +SELECT CURRENT_ROLE; +CURRENT_ROLE +r1 +SET DEFAULT ROLE None; +# Change user b (session 3: role granted to user a) +SET DEFAULT ROLE r1 FOR a; +SET DEFAULT ROLE r2 FOR a; +ERROR OP000: User `a@%` has not been granted role `r2` +SET DEFAULT ROLE invalid_role; +ERROR OP000: Invalid role specification `invalid_role` +SET DEFAULT ROLE invalid_role FOR a; +ERROR OP000: Invalid role specification `invalid_role` +SELECT user, host, default_role FROM mysql.user where user='a' or user='b'; +User Host default_role +a % r1 +b % r2 +DROP ROLE r1, r2; +DROP USER a, b; diff --git a/mysql-test/suite/roles/set_default_role_invalid.test b/mysql-test/suite/roles/set_default_role_invalid.test index 8e72e316d4b..02fca1107e2 100644 --- a/mysql-test/suite/roles/set_default_role_invalid.test +++ b/mysql-test/suite/roles/set_default_role_invalid.test @@ -60,3 +60,110 @@ change_user 'root'; drop role test_role; drop role not_granted_role; drop user test_user@localhost; + +--echo # +--echo # MDEV-22312: Bad error message for SET DEFAULT ROLE when user account +--echo # is not granted the role +--echo # + +CREATE USER a; +CREATE USER b; +CREATE ROLE r1; +CREATE ROLE r2; +# Role has not been granted to user a, but the role is visible to current_user +--error ER_INVALID_ROLE +SET DEFAULT ROLE r1 FOR a; +# Granting roles to user b +GRANT r1 TO b; +GRANT r2 TO b; +# After granting the role, role can be set as default +SET DEFAULT ROLE r1 FOR b; + +--echo # Change user b +change_user b; +SELECT CURRENT_ROLE; +SET ROLE r2; +SELECT CURRENT_ROLE; +# User b has no UPDATE_PRIV for mysql.user +--error ER_DBACCESS_DENIED_ERROR +SET DEFAULT ROLE r1 FOR a; +SET DEFAULT ROLE r2; + +--echo # Change user root (session 1: select_priv to b) +change_user root; +# Let's grant select_priv to user b +GRANT SELECT ON mysql.* TO b; + +--echo # Change user b (session 1: select_priv) +change_user b; +SHOW GRANTS FOR b; +# User must have update_priv before setting the role +--error ER_DBACCESS_DENIED_ERROR +SET DEFAULT ROLE r1 FOR a; +# Testing the `CURRENT_ROLE` as a special case +SELECT CURRENT_ROLE; +SET DEFAULT ROLE NONE; +SELECT CURRENT_ROLE; +SET DEFAULT ROLE current_role FOR current_user; +# Testing of non-existing role +--error ER_INVALID_ROLE +SET DEFAULT ROLE invalid_role; +# Testing of non-existing role for different user +--error ER_DBACCESS_DENIED_ERROR +SET DEFAULT ROLE invalid_role FOR a; +# Testing the `None` role for different user +-- error ER_DBACCESS_DENIED_ERROR +SET DEFAULT ROLE none FOR a; + +--echo # Change user root (session 2: adding update_priv to user b) +change_user root; +# update_priv are enough +GRANT UPDATE ON mysql.* TO b; + +--echo # Change user b +change_user b; +SHOW GRANTS FOR b; +# In all tests in session user a has not been granted the role +# Testing setting role for different user, should fail with new error +--error ER_INVALID_ROLE +SET DEFAULT ROLE r1 FOR a; +# Testing of non-existing role +--error ER_INVALID_ROLE +SET DEFAULT ROLE invalid_role; +# Testing of non-existing role for different user with update_priv +--error ER_INVALID_ROLE +SET DEFAULT ROLE invalid_role FOR a; +# Testing the `None` role for different user with update_priv +SET DEFAULT ROLE none FOR a; + +--echo # Change user root (session 3: Grant role to user a) +change_user root; +# After granting the privilege for a, user b can set default role +GRANT r1 TO a; +SET DEFAULT ROLE r1 FOR a; + +--echo # Change user a (verify session 3) +change_user a; +SELECT CURRENT_ROLE; +SET DEFAULT ROLE None; + +--echo # Change user b (session 3: role granted to user a) +change_user b; +# This should set role because b has update_priv +SET DEFAULT ROLE r1 FOR a; +# Testing non-granted role r2 still should fail +-- error ER_INVALID_ROLE +SET DEFAULT ROLE r2 FOR a; +# Testing of non-existing role +--error ER_INVALID_ROLE +SET DEFAULT ROLE invalid_role; +# Testing of non-existing role for different user +--error ER_INVALID_ROLE +SET DEFAULT ROLE invalid_role FOR a; + +# Clear the workspace +change_user root; +--sorted_result +SELECT user, host, default_role FROM mysql.user where user='a' or user='b'; +DROP ROLE r1, r2; +DROP USER a, b; diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result index 0413a9c4e04..be11728ad4e 100644 --- a/mysql-test/suite/roles/set_role-recursive.result +++ b/mysql-test/suite/roles/set_role-recursive.result @@ -67,7 +67,7 @@ Grants for test_user@localhost GRANT USAGE ON *.* TO `test_user`@`localhost` GRANT `test_role1` TO `test_user`@`localhost` set role test_role2; -ERROR OP000: Invalid role specification `test_role2` +ERROR OP000: User `test_user@localhost` has not been granted role `test_role2` select current_user(), current_role(); current_user() current_role() test_user@localhost NULL diff --git a/mysql-test/suite/rpl/disabled.def b/mysql-test/suite/rpl/disabled.def index 67e710f2637..9e52c277726 100644 --- a/mysql-test/suite/rpl/disabled.def +++ b/mysql-test/suite/rpl/disabled.def @@ -15,7 +15,6 @@ rpl_spec_variables : BUG#11755836 2009-10-27 jasonh rpl_spec_variables fa rpl_partition_archive : MDEV-5077 2013-09-27 svoj Cannot exchange partition with archive table rpl_row_binlog_max_cache_size : MDEV-11092 rpl_row_index_choice : MDEV-11666 -rpl_parallel2 : fails after MDEV-16172 rpl_semi_sync_after_sync : fails after MDEV-16172 rpl_slave_grp_exec: MDEV-10514 rpl_auto_increment_update_failure : disabled for now diff --git a/mysql-test/suite/rpl/extension/checksum.pl b/mysql-test/suite/rpl/extension/checksum.pl index f94341446cd..8369d1bbdce 100755 --- a/mysql-test/suite/rpl/extension/checksum.pl +++ b/mysql-test/suite/rpl/extension/checksum.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # diff --git a/mysql-test/suite/rpl/include/rpl_binlog_errors.inc b/mysql-test/suite/rpl/include/rpl_binlog_errors.inc index 7dd09ad1a24..bf92736a2af 100644 --- a/mysql-test/suite/rpl/include/rpl_binlog_errors.inc +++ b/mysql-test/suite/rpl/include/rpl_binlog_errors.inc @@ -49,6 +49,7 @@ call mtr.add_suppression("Can't generate a unique log-filename"); call mtr.add_suppression("Writing one row to the row-based binary log failed.*"); call mtr.add_suppression("Error writing file .*"); +call mtr.add_suppression("Could not use master-bin for logging"); SET @old_debug= @@global.debug_dbug; diff --git a/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result new file mode 100644 index 00000000000..98688df7273 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result @@ -0,0 +1,47 @@ +include/master-slave.inc +[connection master] +connection master; +SET GLOBAL LOG_WARNINGS=2; +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=current_pos; +include/start_slave.inc +connection master; +"Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')" +FOUND 1 /using_gtid\(1\), gtid\(\'\'\).*/ in mysqld.1.err +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +include/start_slave.inc +connection master; +"Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')" +FOUND 1 /using_gtid\(0\), gtid\(\'\'\).*/ in mysqld.1.err +CREATE TABLE t (f INT) ENGINE=INNODB; +INSERT INTO t VALUES(10); +connection slave; +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +include/start_slave.inc +connection master; +"Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')" +FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2\'\).*/ in mysqld.1.err +SET @@SESSION.gtid_domain_id=10; +INSERT INTO t VALUES(20); +connection slave; +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +include/start_slave.inc +connection master; +"Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')" +FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*/ in mysqld.1.err +"===== Clean up =====" +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +include/start_slave.inc +connection master; +DROP TABLE t; +SET GLOBAL LOG_WARNINGS=default; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_binlog_errors.result b/mysql-test/suite/rpl/r/rpl_binlog_errors.result index c8a10577517..4c667bd7f5a 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_errors.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_errors.result @@ -9,6 +9,7 @@ connection master; call mtr.add_suppression("Can't generate a unique log-filename"); call mtr.add_suppression("Writing one row to the row-based binary log failed.*"); call mtr.add_suppression("Error writing file .*"); +call mtr.add_suppression("Could not use master-bin for logging"); SET @old_debug= @@global.debug_dbug; SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data'; SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data'; diff --git a/mysql-test/suite/rpl/r/rpl_failed_drop_tbl_binlog.result b/mysql-test/suite/rpl/r/rpl_failed_drop_tbl_binlog.result deleted file mode 100644 index df36fa82e0f..00000000000 --- a/mysql-test/suite/rpl/r/rpl_failed_drop_tbl_binlog.result +++ /dev/null @@ -1,32 +0,0 @@ -include/master-slave.inc -[connection master] -create table t1 (a int) engine=innodb; -create table t2 (b longblob) engine=innodb; -create table t3 (c int) engine=innodb; -insert into t2 values (repeat('b',1024*1024)); -insert into t2 select * from t2; -insert into t2 select * from t2; -insert into t2 select * from t2; -insert into t2 select * from t2; -set debug_sync='rm_table_no_locks_before_delete_table SIGNAL nogo WAIT_FOR go EXECUTE 2'; -drop table t1, t2, t3; -connect foo,localhost,root; -set debug_sync='now SIGNAL go'; -kill query CONNECTION_ID; -connection master; -ERROR 70100: Query execution was interrupted -"Tables t2 and t3 should be listed" -SHOW TABLES; -Tables_in_test -t2 -t3 -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ -connection slave; -drop table t2, t3; -connection master; -set debug_sync='RESET'; -drop table t2, t3; -include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result new file mode 100644 index 00000000000..a83a9b61b9f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_until.result @@ -0,0 +1,291 @@ +include/master-slave.inc +[connection master] +connection slave; +include/stop_slave.inc +RESET MASTER; +RESET SLAVE; +connection master; +RESET MASTER; +CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB; +INSERT INTO t1 SET a=25, b='trx0'; +connection slave; +include/start_slave.inc +connection master; +connection slave; +include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=2; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; +connection slave; +SET @old_max_relay_log_size = @@global.max_relay_log_size; +SET @@global.max_relay_log_size=4096; +connection master; +BEGIN; +INSERT INTO t1 SET a=1, b='trx1'; +INSERT INTO t1 SET a=2, b='trx1'; +INSERT INTO t1 SET a=3, b='trx1'; +INSERT INTO t1 SET a=4, b='trx1'; +INSERT INTO t1 SET a=5, b='trx1'; +INSERT INTO t1 SET a=6, b='trx1'; +INSERT INTO t1 SET a=7, b='trx1'; +INSERT INTO t1 SET a=8, b='trx1'; +INSERT INTO t1 SET a=9, b='trx1'; +INSERT INTO t1 SET a=10, b='trx1'; +INSERT INTO t1 SET a=11, b='trx1'; +INSERT INTO t1 SET a=12, b='trx1'; +INSERT INTO t1 SET a=13, b='trx1'; +INSERT INTO t1 SET a=14, b='trx1'; +INSERT INTO t1 SET a=15, b='trx1'; +INSERT INTO t1 SET a=16, b='trx1'; +INSERT INTO t1 SET a=17, b='trx1'; +INSERT INTO t1 SET a=18, b='trx1'; +INSERT INTO t1 SET a=19, b='trx1'; +INSERT INTO t1 SET a=20, b='trx1'; +INSERT INTO t1 SET a=21, b='trx1'; +INSERT INTO t1 SET a=22, b='trx1'; +INSERT INTO t1 SET a=23, b='trx1'; +INSERT INTO t1 SET a=24, b='trx1'; +COMMIT; +FLUSH LOGS; +BEGIN; +UPDATE t1 SET b='trx2_0' WHERE a = 25; +UPDATE t1 SET b='trx2' WHERE a = 25; +COMMIT; +INSERT INTO t1 SET a=26,b='trx3'; +*** case 1 UNTIL inside trx2 +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; +connection slave; +SELECT <= AND < as "pos_until < trx0 and is within trx2"; +pos_until < trx0 and is within trx2 +1 +CHANGE MASTER TO MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = ; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'; +trx2 is committed +1 +SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'; +trx3 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 2 UNTIL inside trx2 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; +connection slave; +include/stop_slave.inc +SELECT <= AND < as "pos_until >= trx0 and is within trx2"; +pos_until >= trx0 and is within trx2 +1 +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = , MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = ; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2'; +trx2 is committed +1 +SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3'; +trx3 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 3 UNTIL inside trx1 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; # block trx1; +connection slave; +include/stop_slave.inc +SELECT < as "pos_until before trx2 start position"; +pos_until before trx2 start position +1 +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = , MASTER_USE_GTID=no; +START SLAVE UNTIL MASTER_LOG_FILE = 'file_2', MASTER_LOG_POS = ; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 25-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'; +trx1 is committed +1 +SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'; +trx2 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 4 Relay-log UNTIL inside trx1 +connection slave; +DELETE FROM t1 WHERE a <> 25; +UPDATE t1 SET b='trx0' WHERE a = 25; +connection slave1; +BEGIN; +INSERT INTO t1 SET a= 1; # block trx1; +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_LOG_FILE = 'file_1', MASTER_LOG_POS = , MASTER_USE_GTID=no; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = ; +connection slave1; +ROLLBACK; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +SELECT count(*) = 25-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1'; +trx1 is committed +1 +SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2'; +trx2 is not committed +1 +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +*** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs +connection master; +CREATE TABLE t2 (a TEXT) ENGINE=InnoDB; +FLUSH LOGS; +connection slave; +connection slave; +include/stop_slave.inc +connection master; +BEGIN; +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +INSERT INTO t2 SET a=repeat('a',1024); +COMMIT; +INSERT INTO t2 SET a='a'; +connection slave; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = ; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +include/diff_tables.inc [master:t2,slave:t2] +*** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs +connection slave; +include/stop_slave.inc +connection master; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +BEGIN; +DELETE FROM t2 LIMIT 1; +COMMIT; +COMMIT; +connection slave; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +connection master; +include/sync_slave_io_with_master.inc +connection slave; +START SLAVE UNTIL RELAY_LOG_FILE = 'file_2', RELAY_LOG_POS = ; +Proof 1: Correct stop +connection slave; +include/wait_for_slave_sql_to_stop.inc +Proof 2: Resume works out +include/start_slave.inc +connection master; +connection slave; +include/diff_tables.inc [master:t2,slave:t2] +connection slave; +include/stop_slave.inc +SET GLOBAL max_relay_log_size=@old_max_relay_log_size; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +include/start_slave.inc +connection master; +DROP TABLE t1, t2; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_slave_alias_replica.result b/mysql-test/suite/rpl/r/rpl_slave_alias_replica.result index 8262cf8212a..2a49e80075f 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_alias_replica.result +++ b/mysql-test/suite/rpl/r/rpl_slave_alias_replica.result @@ -18,10 +18,9 @@ START REPLICA; include/wait_for_slave_io_to_start.inc include/wait_for_slave_sql_to_start.inc connection master; +connection slave; +connection master; "Command: SHOW SLAVE HOSTS --> SHOW REPLICA HOSTS" -SHOW REPLICA HOSTS; -Server_id Host Port Master_id -2 127.0.0.1 SLAVE_PORT 1 DROP USER 'repl_user'; connection slave; "Command: SHOW SLAVE IO/SQL THREAD --> SHOW REPLICA IO/SQL THREAD" diff --git a/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result b/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result index 4d666c6e8bf..99e7a184e1f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result +++ b/mysql-test/suite/rpl/r/rpl_stm_EE_err2.result @@ -11,7 +11,7 @@ drop table t1; connection slave; include/wait_for_slave_sql_to_stop.inc call mtr.add_suppression("Slave SQL.*Query caused different errors on master and slave.*Error on master:.* error code=1062.*Error on slave:.* error.* 0"); -Error: "Query caused different errors on master and slave. Error on master: message (format)='Duplicate entry '%-.192s' for key %d' error code=1062 ; Error on slave: actual message='no error', error code=0. Default database: 'test'. Query: 'insert into t1 values(1),(2)'" (expected different error codes on master and slave) +Error: "Query caused different errors on master and slave. Error on master: message (format)='Duplicate entry '%-.192T' for key %d' error code=1062 ; Error on slave: actual message='no error', error code=0. Default database: 'test'. Query: 'insert into t1 values(1),(2)'" (expected different error codes on master and slave) Errno: "0" (expected 0) drop table t1; include/stop_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test new file mode 100644 index 00000000000..f26e9565671 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test @@ -0,0 +1,121 @@ +# ==== Purpose ==== +# +# Test verifies that Start binlog_dump message will report GTID position +# requested by slave when log_warnings > 1. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Have LOG_WARNINGS=2 +# 1 - On a fresh slave server which has not replicated any GTIDs execute +# "CHANGE MASTER TO MASTER_USE_GTID=current_pos;" command. Start the +# slave. +# 2 - In Master error log verify that pattern "using_gtid(1), gtid('')" is +# present. +# 3 - On slave server do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=no;" command. Start the slave threads. +# 4 - In Master error log verify that pattern "using_gtid(0), gtid('')" is +# present. +# 5- Execute a DDL and DML on master server. This will generated two GTIDs +# on the master server ('0-1-2'). Sync the slave server with master. +# 6 - On slave do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=slave_pos;" command. Start slave threads. +# 7 - In Master error verify that pattern "using_gtid(1), gtid('0-1-2')" is +# present. +# 8 - On Master change domain ID to 10 and execute a DML operation. It will +# generate a GTID 10-1-1. +# 9 - On slave do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=slave_pos;" command. Start slave threads. +# 10 -In Master error verify that pattern "using_gtid(1), +# gtid('0-1-2,10-1-1')" is present. +# +# ==== References ==== +# +# MDEV-20428: "Start binlog_dump" message doesn't indicate GTID position +# + +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection master +SET GLOBAL LOG_WARNINGS=2; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=current_pos; +--source include/start_slave.inc + +--connection master +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} +--echo "Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'\'\).* +--source include/search_pattern_in_file.inc + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +--source include/start_slave.inc + +--connection master +--echo "Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(0\), gtid\(\'\'\).* +--source include/search_pattern_in_file.inc +CREATE TABLE t (f INT) ENGINE=INNODB; +INSERT INTO t VALUES(10); +save_master_pos; + +--connection slave +sync_with_master; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +--connection master +--echo "Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2\'\).* +--source include/search_pattern_in_file.inc +SET @@SESSION.gtid_domain_id=10; +INSERT INTO t VALUES(20); +save_master_pos; + +--connection slave +sync_with_master; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +--connection master +--echo "Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).* +--source include/search_pattern_in_file.inc + +--echo "===== Clean up =====" +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +--source include/start_slave.inc + +--connection master +DROP TABLE t; +SET GLOBAL LOG_WARNINGS=default; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test index d0502e734e2..d95a5c5f1c3 100644 --- a/mysql-test/suite/rpl/t/rpl_fail_register.test +++ b/mysql-test/suite/rpl/t/rpl_fail_register.test @@ -17,13 +17,12 @@ set global debug_dbug=@old_dbug; connection master; -### Dump thread is hanging despite slave has gracefully exited. let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`; if ($id) { replace_result $id DUMP_THREAD; eval kill $id; - let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Binlog Dump'; + let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed'; source include/wait_condition.inc; } diff --git a/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.test b/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.test deleted file mode 100644 index 1d544891a9c..00000000000 --- a/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.test +++ /dev/null @@ -1,69 +0,0 @@ -# ==== Purpose ==== -# -# Check that when the execution of a DROP TABLE command with single table -# fails it should not be written to the binary log. Also test that when the -# execution of DROP TABLE command with multiple tables fails the command -# should be written into the binary log. -# -# ==== Implementation ==== -# -# Steps: -# 0 - Create tables named t1, t2, t3 -# 1 - Execute DROP TABLE t1,t2,t3 command. -# 2 - Kill the DROP TABLE command while it is trying to drop table 't2'. -# 3 - Verify that tables t2,t3 are present after the DROP command execution -# was interrupted. -# 4 - Check that table 't1' is present in binary log as part of DROP -# command. -# -# ==== References ==== -# -# MDEV-20348: DROP TABLE IF EXISTS killed on master but was replicated. -# - ---source include/have_innodb.inc ---source include/have_debug_sync.inc ---source include/have_binlog_format_statement.inc ---source include/master-slave.inc - -if (!`select @@GLOBAL.innodb_adaptive_hash_index`) -{ - --skip Need innodb_adaptive_hash_index -} - -create table t1 (a int) engine=innodb; -create table t2 (b longblob) engine=innodb; -create table t3 (c int) engine=innodb; -insert into t2 values (repeat('b',1024*1024)); -insert into t2 select * from t2; -insert into t2 select * from t2; -insert into t2 select * from t2; -insert into t2 select * from t2; -let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); - -let $id=`select connection_id()`; -set debug_sync='rm_table_no_locks_before_delete_table SIGNAL nogo WAIT_FOR go EXECUTE 2'; -send drop table t1, t2, t3; - -connect foo,localhost,root; -set debug_sync='now SIGNAL go'; -let $wait_condition=select 1 from information_schema.processlist where state like 'debug sync point:%'; -source include/wait_condition.inc; ---replace_result $id CONNECTION_ID -eval kill query $id; - -connection master; -error ER_QUERY_INTERRUPTED; -reap; - ---echo "Tables t2 and t3 should be listed" -SHOW TABLES; ---source include/show_binlog_events.inc ---sync_slave_with_master -drop table t2, t3; - -connection master; -set debug_sync='RESET'; -drop table t2, t3; - -source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test new file mode 100644 index 00000000000..508213c9075 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test @@ -0,0 +1,465 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc +# Format is restricted because the test expects a specific result of +# relay-logging that splits a transaction into two different files. +--source include/have_binlog_format_row.inc + +# +# MDEV-15152 Optimistic parallel slave doesn't cope well with START SLAVE UNTIL +# +--connection slave +--source include/stop_slave.inc +RESET MASTER; +RESET SLAVE; + +--connection master +RESET MASTER; +CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB; +--let $a0 = 25 +--eval INSERT INTO t1 SET a=$a0, b='trx0' +# Memorize the position for replication restart from it +--let $pos_trx0 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +--source include/start_slave.inc + +--connection master +# --connection slave +--sync_slave_with_master +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=2; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + +# Run the slave in the following modes one by one. +# +# 1. the until position is set in the middle of trx2 +# below $pos_trx0 of the last exec position in the first file +# 2. and above $pos_trx0 +# In either case trx2 must commit before slave stops. +# 3. the until postion is inside trx1 +# 4. RELAY log until inside trx1 +# 5. RELAY log until inside a "big" trx +# 6. RELAY log until inside a trx within a sequence of relay logs +# +# Execution flaw for Until_Master_Pos cases follows as: +# create the transaction trx1, trx2 +# logged at the beginning of two subsequent binlog files. +# Set the until position to at the middle of the 2rd transaction. +# Engage the optimistic scheduler while having trx1 execution blocked. +# Lift the block after trx2 has reached waiting its order to commit. +# *Proof 1* +# Observe that the slave applier stops at a correct position. +# In the bug condition it would stop prematurely having the stop position +# in the first file, therefore trx2 not committed. +# Specifically, an internal transaction position until makes the applier to run +# beyond it to commit commit the current transaction. +# *Proof 2* +# Observe the following START SLAVE resumes OK. +# +# Auxiliary third trx3 on master is just for triggering the actual stop +# (whihc is a legacy UNTIL's property). +# trx0 is to produce a specific value of the last executed binlog file:pos +# to emulate the bug condition. +# +# Intermediate checks via SELECT are supposed to succeed +# with putting out value 1. +# +# NOTE: Relay log until tests have to use explicit log names and position +# which may require to adjust with future changes to event formats etc. +# + +--connection slave +SET @old_max_relay_log_size = @@global.max_relay_log_size; +SET @@global.max_relay_log_size=4096; + +--connection master +# trx1 +--let $a=1 +BEGIN; +while (`SELECT $a < $a0`) +{ + --eval INSERT INTO t1 SET a=$a, b='trx1' +--inc $a +} +COMMIT; +--let $fil_1 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx1 = query_get_value(SHOW MASTER STATUS, Position, 1) + +FLUSH LOGS; + +# $pos_0 the offset of the first event of trx2 in new file +--let $pos_0=query_get_value(SHOW MASTER STATUS, Position, 1) +# trx2 +--let $a=$a0 +BEGIN; +--eval UPDATE t1 SET b='trx2_0' WHERE a = $a +--eval UPDATE t1 SET b='trx2' WHERE a = $a +COMMIT; +--let $fil_2=query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx2=query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx3 +--let $a=$a0 +--inc $a +--eval INSERT INTO t1 SET a=$a,b='trx3' +--let $pos_trx3=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $a= + + +--echo *** case 1 UNTIL inside trx2 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 +--connection slave +--let $pos_until=`SELECT $pos_trx0 - 1` +--replace_result $pos_0 $pos_until $pos_trx2 +--eval SELECT $pos_0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until < trx0 and is within trx2" +CHANGE MASTER TO MASTER_USE_GTID=no; +--replace_result $fil_2 file_2 $pos_until +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 2 UNTIL inside trx2 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_trx2 - 1` +--replace_result $pos_trx0 $pos_until $pos_trx2 +--eval SELECT $pos_trx0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until >= trx0 and is within trx2" +--replace_result $fil_1 file_1 $pos_trx0 +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 3 UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_0 - 1` +--replace_result $pos_0 $pos_until $pos_trx2 +--eval SELECT $pos_until < $pos_0 as "pos_until before trx2 start position" +--replace_result $fil_1 file_1 $pos_trx0 +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 4 Relay-log UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc +--replace_result $fil_1 file_1 $pos_trx0 +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# The following test sets the stop coordinate is set to inside the first event +# of a relay log that holds events of a transaction started in an earlier log. +# Peek the stop position in the middle of trx1, not even on a event boundary. +--let $pos_until=255 +--let $file_rl=slave-relay-bin.000003 +--let $binlog_file=$file_rl + +--let $pos_xid=508 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_xid LIMIT 1, Info, 1) + +if (`SELECT "$info" NOT LIKE "COMMIT /* xid=% */" OR $pos_xid < $pos_until`) +{ + --echo *** Unexpected offset. Refine it to point to the correct XID event! + --die +} + +--replace_result $file_rl file_2 $pos_until +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_rl","$file_stop") > -1`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + + +--echo *** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs + +--connection master +CREATE TABLE t2 (a TEXT) ENGINE=InnoDB; +FLUSH LOGS; + +--sync_slave_with_master +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--let $records=`SELECT floor(4*@@global.max_relay_log_size / 1024) + 1` + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx4 +BEGIN; +--let $i=$records +while ($i) +{ + INSERT INTO t2 SET a=repeat('a',1024); + +--dec $i +} +COMMIT; + +# slave will stop there: +--let $file_trx4 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx4 = query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx5 +INSERT INTO t2 SET a='a'; +--let $pos_trx5 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# Set position inside the transaction though the value +# specified is beyond that relay log file. +# The coordianate may point to in a different event in future changes +# but should not move away from inside this big group of events. +# So we don't test which event in the transaction it points to. +--let $pos_until= 4500 +--let $file_rl= slave-relay-bin.000010 + +--replace_result $file_rl file_2 $pos_until +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +# It's showed the actual stop occurred before trx5 +if (`SELECT strcmp("$file_trx4", "$file_stop") <> 0 OR $pos_stop >= $pos_trx5 OR count(*) <> $records FROM t2`) +{ + --echo *** ERROR: Slave stopped at *binlog* $file_stop:$pos_stop which is not $file_trx4:$pos_trx4. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + + + +--echo *** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx6 +--let $records=`SELECT count(*) FROM t2` +while ($records) +{ + BEGIN; + DELETE FROM t2 LIMIT 1; + COMMIT; +--dec $records +} +COMMIT; + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection master +--source include/sync_slave_io_with_master.inc + +--connection slave +# The relay-log coordinate is not at an event boundary and +# also may change across the server version. +# The test makes its best to check its coherance. +--let $pos_until= 3130 +--let $file_rl= slave-relay-bin.000018 + +--let $pos_gtid = 2987 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_gtid LIMIT 1, Info, 1) + +if (`SELECT "$info" != "BEGIN GTID 0-1-23"`) +{ + --echo *** Unexpected offset. Refine it to point to the correct GTID! + --die +} +--let $pos_event = 3120 +--let $type= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_event LIMIT 1, Event_type, 1) +if (`SELECT "$type" != "Delete_rows_v1"`) +{ + --echo *** Unexpected offset. Refine it to point to the expected event! + --die +} + +--replace_result $file_rl file_2 $pos_until +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_stop", "$file_rl") = -1 OR + strcmp("$file_stop", "$file_rl") = 0 AND $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at *relay* $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +SET GLOBAL max_relay_log_size=@old_max_relay_log_size; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1, t2; + +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test index 8f2cd1a4eb3..324821a325f 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test +++ b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test @@ -45,10 +45,16 @@ START REPLICA; --source include/wait_for_slave_io_to_start.inc --source include/wait_for_slave_sql_to_start.inc +--connection master +--sync_slave_with_master + --connection master --echo "Command: SHOW SLAVE HOSTS --> SHOW REPLICA HOSTS" ---replace_result $SLAVE_MYPORT SLAVE_PORT -SHOW REPLICA HOSTS; +let $show_statement= SHOW REPLICA HOSTS; +let $field= Server_id; +# Slave's server_id 2 +let $condition= ='2'; +source include/wait_show_condition.inc; DROP USER 'repl_user'; --sync_slave_with_master diff --git a/mysql-test/suite/s3/alter2.result b/mysql-test/suite/s3/alter2.result index d2849905c67..8d2cae035c9 100644 --- a/mysql-test/suite/s3/alter2.result +++ b/mysql-test/suite/s3/alter2.result @@ -20,3 +20,30 @@ connection con1; disconnect con1; connection default; DROP TABLE t1; +# +# MDEV-20302 Server hangs upon concurrent SELECT from partitioned S3 +# table +# +CREATE TABLE t1 ( +pk INT AUTO_INCREMENT, +c CHAR(12), +PRIMARY KEY(pk), +KEY(c) +) ENGINE=Aria +PARTITION BY KEY(pk) PARTITIONS 2; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (NULL,'ill'),(NULL,'loop'); +ALTER TABLE t1 ENGINE=S3; +connect con1,localhost,root,,$database; +SELECT * FROM t1 WHERE c BETWEEN 'bar' AND 'foo'; +connection default; +SELECT pk FROM v1; +pk +1 +2 +connection con1; +pk c +disconnect con1; +connection default; +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/suite/s3/alter2.test b/mysql-test/suite/s3/alter2.test index de2bc001298..856b141573b 100644 --- a/mysql-test/suite/s3/alter2.test +++ b/mysql-test/suite/s3/alter2.test @@ -1,4 +1,5 @@ --source include/have_s3.inc +--source include/have_partition.inc --source create_database.inc --echo # @@ -26,6 +27,37 @@ SELECT * FROM t1; --connection default DROP TABLE t1; +--echo # +--echo # MDEV-20302 Server hangs upon concurrent SELECT from partitioned S3 +--echo # table +--echo # + +CREATE TABLE t1 ( + pk INT AUTO_INCREMENT, + c CHAR(12), + PRIMARY KEY(pk), + KEY(c) +) ENGINE=Aria + PARTITION BY KEY(pk) PARTITIONS 2; + +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (NULL,'ill'),(NULL,'loop'); +ALTER TABLE t1 ENGINE=S3; +--connect (con1,localhost,root,,$database) +--send + SELECT * FROM t1 WHERE c BETWEEN 'bar' AND 'foo'; + +--connection default +SELECT pk FROM v1; + +--connection con1 +--reap + +--disconnect con1 +--connection default +DROP VIEW v1; +DROP TABLE t1; + # # clean up # diff --git a/mysql-test/suite/s3/my.cnf b/mysql-test/suite/s3/my.cnf index 1958a04343f..6f8c27d4d0d 100644 --- a/mysql-test/suite/s3/my.cnf +++ b/mysql-test/suite/s3/my.cnf @@ -2,6 +2,7 @@ !include include/default_client.cnf [mysqld.1] +plugin-load-add=ha_s3 s3=ON #s3-host-name=s3.amazonaws.com #s3-protocol-version=Amazon diff --git a/mysql-test/suite/s3/replication.inc b/mysql-test/suite/s3/replication.inc index deef0209542..26dd9a5da25 100644 --- a/mysql-test/suite/s3/replication.inc +++ b/mysql-test/suite/s3/replication.inc @@ -5,7 +5,7 @@ # Tests for S3 replication # -connection slave; +sync_slave_with_master; let $SLAVE_DATADIR= `select @@datadir`; connection master; diff --git a/mysql-test/suite/s3/replication_mixed.result b/mysql-test/suite/s3/replication_mixed.result index 98b9a78d5f5..47cf907b187 100644 --- a/mysql-test/suite/s3/replication_mixed.result +++ b/mysql-test/suite/s3/replication_mixed.result @@ -194,34 +194,30 @@ slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; flush tables slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; set @@sql_if_exists=1; alter table t1 add column e int, engine=s3 -slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `database`; CREATE TABLE `t1` ( +slave-bin.000001 # Query # # use `database`; CREATE OR REPLACE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, `e` int(11) DEFAULT NULL ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Annotate_rows # # alter table t1 engine=aria slave-bin.000001 # Table_map # # table_id: # (database.t1) slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F slave-bin.000001 # Query # # COMMIT slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; alter table t1 engine=s3 -slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `database`; CREATE TABLE `t2` ( +slave-bin.000001 # Query # # use `database`; CREATE OR REPLACE TABLE `t2` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, `e` int(11) DEFAULT NULL ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Annotate_rows # # alter table t1 rename t2, engine=aria slave-bin.000001 # Table_map # # table_id: # (database.t2) slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/s3/replication_partition.result b/mysql-test/suite/s3/replication_partition.result index 9df6216ab2c..40fb2aec698 100644 --- a/mysql-test/suite/s3/replication_partition.result +++ b/mysql-test/suite/s3/replication_partition.result @@ -225,10 +225,9 @@ slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; set @@sql_if_exists=1; rename table t2 to t1 slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; set @@sql_if_exists=1; alter table t1 drop partition p1 -slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `database`; CREATE TABLE `t1` ( +slave-bin.000001 # Query # # use `database`; CREATE OR REPLACE TABLE `t1` ( `c1` int(11) NOT NULL, `c2` int(11) DEFAULT NULL, PRIMARY KEY (`c1`) @@ -236,7 +235,6 @@ slave-bin.000001 # Query # # use `database`; CREATE TABLE `t1` ( PARTITION BY RANGE (`c1`) (PARTITION `p2` VALUES LESS THAN (300) ENGINE = InnoDB, PARTITION `p3` VALUES LESS THAN (400) ENGINE = InnoDB) -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Annotate_rows # # alter table t1 engine=innodb slave-bin.000001 # Table_map # # table_id: # (database.t1) slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/s3/replication_partition.test b/mysql-test/suite/s3/replication_partition.test index 8751ab33730..0430d14d7a7 100644 --- a/mysql-test/suite/s3/replication_partition.test +++ b/mysql-test/suite/s3/replication_partition.test @@ -6,7 +6,7 @@ --source include/master-slave.inc --source create_database.inc -connection slave; +sync_slave_with_master; let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $database database --eval use $database diff --git a/mysql-test/suite/s3/replication_stmt.result b/mysql-test/suite/s3/replication_stmt.result index ba6573bf219..56fd07445a4 100644 --- a/mysql-test/suite/s3/replication_stmt.result +++ b/mysql-test/suite/s3/replication_stmt.result @@ -194,34 +194,30 @@ slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; flush tables slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; set @@sql_if_exists=1; alter table t1 add column e int, engine=s3 -slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `database`; CREATE TABLE `t1` ( +slave-bin.000001 # Query # # use `database`; CREATE OR REPLACE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, `e` int(11) DEFAULT NULL ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Annotate_rows # # alter table t1 engine=aria slave-bin.000001 # Table_map # # table_id: # (database.t1) slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F slave-bin.000001 # Query # # COMMIT slave-bin.000001 # Gtid # # GTID #-#-# slave-bin.000001 # Query # # use `database`; alter table t1 engine=s3 -slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1` /* generated by server */ -slave-bin.000001 # Gtid # # GTID #-#-# -slave-bin.000001 # Query # # use `database`; CREATE TABLE `t2` ( +slave-bin.000001 # Query # # use `database`; CREATE OR REPLACE TABLE `t2` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, `e` int(11) DEFAULT NULL ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 -slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Annotate_rows # # alter table t1 rename t2, engine=aria slave-bin.000001 # Table_map # # table_id: # (database.t2) slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/s3/suite.pm b/mysql-test/suite/s3/suite.pm index 5bf1559ae97..b3d78874b19 100644 --- a/mysql-test/suite/s3/suite.pm +++ b/mysql-test/suite/s3/suite.pm @@ -2,7 +2,7 @@ package My::Suite::S3; @ISA = qw(My::Suite); -return "Need S3 engine" unless $::mysqld_variables{'s3'} eq "ON"; +return "Need S3 engine" unless $::mysqld_variables{'s3'} eq "ON" or $ENV{HA_S3_SO}; bless { }; diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 3cf085bc948..612e2201d26 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -238,3 +238,14 @@ select next value for t1; next value for t1 90 drop sequence t1; +CREATE SEQUENCE t1 engine=innodb; +ALTER IGNORE TABLE t1 ADD CHECK (start_value < minimum_value); +ERROR HY000: Sequence 'test.t1' table structure is invalid (Sequence tables cannot have any constraints) +DROP SEQUENCE t1; +CREATE SEQUENCE s; +ALTER TABLE s ORDER BY cache_size; +ERROR HY000: Sequence 'test.s' table structure is invalid (ORDER BY) +SELECT NEXTVAL(s); +NEXTVAL(s) +1 +DROP SEQUENCE s; diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index fd1809ccd2f..53f71018337 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -139,3 +139,24 @@ select next value for t1; alter sequence t1 restart with 90; select next value for t1; drop sequence t1; + +# +# MDEV-19977 Assertion `(0xFUL & mode) == LOCK_S || (0xFUL & mode) == LOCK_X' +# failed in lock_rec_lock +# + +CREATE SEQUENCE t1 engine=innodb; +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +ALTER IGNORE TABLE t1 ADD CHECK (start_value < minimum_value); +DROP SEQUENCE t1; + +# +# MDEV-19320 Sequence gets corrupted and produces ER_KEY_NOT_FOUND (Can't +# find record) after ALTER .. ORDER BY +# + +CREATE SEQUENCE s; +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +ALTER TABLE s ORDER BY cache_size; +SELECT NEXTVAL(s); +DROP SEQUENCE s; diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 55d45a75abf..6f70f335d88 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -165,7 +165,7 @@ drop sequence t1; ERROR 42S02: 'test.t1' is not a SEQUENCE drop sequence if exists t1; Warnings: -Note 4091 Unknown SEQUENCE: 'test.t1' +Note 4090 'test.t1' is not a SEQUENCE create sequence t1 start with 10 maxvalue=9; ERROR HY000: Sequence 'test.t1' values are conflicting create sequence t1 minvalue= 100 maxvalue=10; @@ -375,6 +375,40 @@ CREATE OR REPLACE TABLE t1 ( key key1 (next_not_cached_value) ) sequence=1; ERROR HY000: Sequence 'test.t1' table structure is invalid (Sequence tables cannot have any keys) +CREATE TABLE t1 ( +`next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL, +`increment` bigint(21) NOT NULL, +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL, +`cycle_count` bigint(21) NOT NULL, +CHECK (start_value < minimum_value) +) sequence=1; +ERROR HY000: Sequence 'test.t1' table structure is invalid (Sequence tables cannot have any constraints) +CREATE TABLE t1 ( +`next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL CHECK (start_value < minimum_value), +`increment` bigint(21) NOT NULL, +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL, +`cycle_count` bigint(21) NOT NULL +) sequence=1; +ERROR HY000: Sequence 'test.t1' table structure is invalid (start_value) +CREATE TABLE t1 ( +`next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL, +`increment` bigint(21) NOT NULL, +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL, +`cycle_count` bigint(21) generated always as (1) virtual +) sequence=1; +ERROR HY000: Sequence 'test.t1' table structure is invalid (cycle_count) drop sequence if exists t1; Warnings: Note 4091 Unknown SEQUENCE: 'test.t1' @@ -387,12 +421,11 @@ CREATE SEQUENCE s1; drop sequence s1; drop sequence if exists t1,t2,t3,t4; Warnings: -Note 4091 Unknown SEQUENCE: 'test.t3' +Note 4090 'test.t3' is not a SEQUENCE Note 4091 Unknown SEQUENCE: 'test.t4' drop table if exists t1,t2,t3; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t1,test.t2' CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); CREATE SEQUENCE s1; @@ -407,15 +440,15 @@ CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); CREATE SEQUENCE s1; drop sequence t1,t2,s1,s2; -ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.t2,test.s2' +ERROR 42S02: 'test.t1' is not a SEQUENCE drop table if exists t1,t2; CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); CREATE SEQUENCE s1; drop sequence if exists t1,t2,s1,s2; Warnings: -Note 4091 Unknown SEQUENCE: 'test.t1' -Note 4091 Unknown SEQUENCE: 'test.t2' +Note 4090 'test.t1' is not a SEQUENCE +Note 4090 'test.t2' is not a SEQUENCE Note 4091 Unknown SEQUENCE: 'test.s2' drop table if exists t1,t2; CREATE TEMPORARY SEQUENCE s1; diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 1bc62117526..61430740560 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -270,6 +270,48 @@ CREATE OR REPLACE TABLE t1 ( key key1 (next_not_cached_value) ) sequence=1; +# Check constraint + +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +CREATE TABLE t1 ( + `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL, + `increment` bigint(21) NOT NULL, + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL, + `cycle_count` bigint(21) NOT NULL, + CHECK (start_value < minimum_value) +) sequence=1; + +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +CREATE TABLE t1 ( + `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL CHECK (start_value < minimum_value), + `increment` bigint(21) NOT NULL, + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL, + `cycle_count` bigint(21) NOT NULL +) sequence=1; + + +# Virtual field + +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +CREATE TABLE t1 ( + `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL, + `increment` bigint(21) NOT NULL, + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL, + `cycle_count` bigint(21) generated always as (1) virtual +) sequence=1; + drop sequence if exists t1; # @@ -300,7 +342,7 @@ drop table if exists t1,t2,s1,s2; CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); CREATE SEQUENCE s1; ---error ER_UNKNOWN_SEQUENCES +--error ER_NOT_SEQUENCE2 drop sequence t1,t2,s1,s2; drop table if exists t1,t2; diff --git a/mysql-test/suite/sql_sequence/default.result b/mysql-test/suite/sql_sequence/default.result index 37d536d9020..14abc656423 100644 --- a/mysql-test/suite/sql_sequence/default.result +++ b/mysql-test/suite/sql_sequence/default.result @@ -1,8 +1,6 @@ drop table if exists t1,s1,s2; Warnings: -Note 1051 Unknown table 'test.t1' -Note 1051 Unknown table 'test.s1' -Note 1051 Unknown table 'test.s2' +Note 1051 Unknown table 'test.t1,test.s1,test.s2' drop view if exists v1; Warnings: Note 4092 Unknown VIEW: 'test.v1' diff --git a/mysql-test/suite/stress/r/misc.result b/mysql-test/suite/stress/r/misc.result new file mode 100644 index 00000000000..6d0a3ea5050 --- /dev/null +++ b/mysql-test/suite/stress/r/misc.result @@ -0,0 +1,9 @@ +# +# MDEV-22339 - Assertion `str_length < len' failed in +# Binary_string::realloc_raw +# +CREATE TABLE t1(a INT) ENGINE=MyISAM; +connect con1, localhost, root; +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/stress/t/misc.test b/mysql-test/suite/stress/t/misc.test new file mode 100644 index 00000000000..e8255cb3a81 --- /dev/null +++ b/mysql-test/suite/stress/t/misc.test @@ -0,0 +1,32 @@ +--echo # +--echo # MDEV-22339 - Assertion `str_length < len' failed in +--echo # Binary_string::realloc_raw +--echo # +CREATE TABLE t1(a INT) ENGINE=MyISAM; +connect con1, localhost, root; +let $i=1000; +disable_query_log; +disable_result_log; +while ($i) +{ + connection default; + HANDLER t1 OPEN; + send SELECT * FROM t1, t1 t1a1over8, t1 t1a2over8, t1 t1a3over8, t1 t1a4over8, t1 t1a5over8, t1 t1a6over8; + + connection con1; + send REPAIR TABLE t1; + + connection default; + reap; + HANDLER t1 CLOSE; + + connection con1; + reap; + dec $i; +} +enable_query_log; +enable_result_log; +disconnect con1; + +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_page_hash_locks_basic.result b/mysql-test/suite/sys_vars/r/innodb_page_hash_locks_basic.result deleted file mode 100644 index e8915387aad..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_page_hash_locks_basic.result +++ /dev/null @@ -1,24 +0,0 @@ -select @@global.innodb_page_hash_locks between 1 and 1024; -@@global.innodb_page_hash_locks between 1 and 1024 -1 -select @@global.innodb_page_hash_locks; -@@global.innodb_page_hash_locks -16 -select @@session.innodb_page_hash_locks; -ERROR HY000: Variable 'innodb_page_hash_locks' is a GLOBAL variable -show global variables like 'innodb_page_hash_locks'; -Variable_name Value -innodb_page_hash_locks 16 -show session variables like 'innodb_page_hash_locks'; -Variable_name Value -innodb_page_hash_locks 16 -select * from information_schema.global_variables where variable_name='innodb_page_hash_locks'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_PAGE_HASH_LOCKS 16 -select * from information_schema.session_variables where variable_name='innodb_page_hash_locks'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_PAGE_HASH_LOCKS 16 -set global innodb_page_hash_locks=1; -ERROR HY000: Variable 'innodb_page_hash_locks' is a read only variable -set @@session.innodb_page_hash_locks='some'; -ERROR HY000: Variable 'innodb_page_hash_locks' is a read only variable diff --git a/mysql-test/suite/sys_vars/r/max_sort_length_basic.result b/mysql-test/suite/sys_vars/r/max_sort_length_basic.result index a8876b2c81e..b48b045897c 100644 --- a/mysql-test/suite/sys_vars/r/max_sort_length_basic.result +++ b/mysql-test/suite/sys_vars/r/max_sort_length_basic.result @@ -27,14 +27,14 @@ SELECT @@session.max_sort_length = 1024; @@session.max_sort_length = 1024 1 '#--------------------FN_DYNVARS_084_03-------------------------#' -SET @@global.max_sort_length = 4; +SET @@global.max_sort_length = 8; SELECT @@global.max_sort_length; @@global.max_sort_length -4 -SET @@global.max_sort_length = 5; +8 +SET @@global.max_sort_length = 9; SELECT @@global.max_sort_length; @@global.max_sort_length -5 +9 SET @@global.max_sort_length = 8388608; SELECT @@global.max_sort_length; @@global.max_sort_length @@ -48,14 +48,14 @@ SELECT @@global.max_sort_length; @@global.max_sort_length 65536 '#--------------------FN_DYNVARS_084_04-------------------------#' -SET @@session.max_sort_length = 4; +SET @@session.max_sort_length = 8; SELECT @@session.max_sort_length; @@session.max_sort_length -4 -SET @@session.max_sort_length = 5; +8 +SET @@session.max_sort_length = 9; SELECT @@session.max_sort_length; @@session.max_sort_length -5 +9 SET @@session.max_sort_length = 8388608; SELECT @@session.max_sort_length; @@session.max_sort_length @@ -74,13 +74,13 @@ Warnings: Warning 1292 Truncated incorrect max_sort_length value: '-1024' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@global.max_sort_length = 3; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '3' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@global.max_sort_length = 8388609; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '8388609' @@ -92,17 +92,17 @@ Warnings: Warning 1292 Truncated incorrect max_sort_length value: '0' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@global.max_sort_length = 65530.34; ERROR 42000: Incorrect argument type to variable 'max_sort_length' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@global.max_sort_length = test; ERROR 42000: Incorrect argument type to variable 'max_sort_length' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@session.max_sort_length = 8388610; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '8388610' @@ -114,19 +114,19 @@ Warnings: Warning 1292 Truncated incorrect max_sort_length value: '-1' SELECT @@session.max_sort_length; @@session.max_sort_length -4 +8 SET @@session.max_sort_length = 3; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '3' SELECT @@session.max_sort_length; @@session.max_sort_length -4 +8 SET @@session.max_sort_length = 0; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '0' SELECT @@session.max_sort_length; @@session.max_sort_length -4 +8 SET @@session.max_sort_length = 65530.34; ERROR 42000: Incorrect argument type to variable 'max_sort_length' SET @@session.max_sort_length = 10737418241; @@ -158,13 +158,13 @@ Warnings: Warning 1292 Truncated incorrect max_sort_length value: '1' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 SET @@global.max_sort_length = FALSE; Warnings: Warning 1292 Truncated incorrect max_sort_length value: '0' SELECT @@global.max_sort_length; @@global.max_sort_length -4 +8 '#---------------------FN_DYNVARS_084_09----------------------#' SET @@global.max_sort_length = 2048; SELECT @@max_sort_length = @@global.max_sort_length; diff --git a/mysql-test/suite/sys_vars/r/sysvars_aria,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_aria,32bit.rdiff index 979f9d8903a..17d04208aac 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_aria,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_aria,32bit.rdiff @@ -1,16 +1,16 @@ ---- sysvars_aria.result 2015-01-09 11:49:32.000000000 +0100 -+++ sysvars_aria,32bit.result 2015-01-09 17:30:11.000000000 +0100 -@@ -7,7 +7,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +--- sysvars_aria.result 2020-04-29 11:35:30.042243474 +0300 ++++ sysvars_aria,32bit.reject 2020-04-30 11:45:51.128740906 +0300 +@@ -5,7 +5,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 8192 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Block size to be used for Aria index pages. - NUMERIC_MIN_VALUE 1024 + NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 32768 -@@ -21,7 +21,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -17,7 +17,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 30 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -18,8 +18,8 @@ VARIABLE_COMMENT Interval between tries to do an automatic checkpoints. In seconds; 0 means 'no automatic checkpoints' which makes sense only for testing. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -35,7 +35,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -29,7 +29,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -27,8 +27,8 @@ VARIABLE_COMMENT Number of bytes that the transaction log has to grow between checkpoints before a new checkpoint is written to the log. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -63,7 +63,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -53,7 +53,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -36,17 +36,17 @@ VARIABLE_COMMENT Number of consecutive log recovery failures after which logs will be automatically deleted to cure the problem; 0 (the default) disables the feature. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -91,7 +91,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -77,7 +77,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used + VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -105,7 +105,7 @@ - GLOBAL_VALUE_ORIGIN CONFIG +@@ -89,7 +89,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -54,8 +54,8 @@ VARIABLE_COMMENT Limit for transaction log size NUMERIC_MIN_VALUE 8388608 NUMERIC_MAX_VALUE 4294967295 -@@ -147,10 +147,10 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -125,10 +125,10 @@ + SESSION_VALUE NULL DEFAULT_VALUE 300 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -67,8 +67,8 @@ NUMERIC_BLOCK_SIZE 100 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -175,7 +175,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -149,7 +149,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -76,8 +76,8 @@ VARIABLE_COMMENT The minimum percentage of warm blocks in key cache NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100 -@@ -189,7 +189,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -161,7 +161,7 @@ + SESSION_VALUE NULL DEFAULT_VALUE 512 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED @@ -85,8 +85,8 @@ VARIABLE_COMMENT Number of hash buckets for open and changed files. If you have a lot of Aria files open you should increase this for faster flush of changes. A good value is probably 1/10 of number of possible open Aria files. NUMERIC_MIN_VALUE 128 NUMERIC_MAX_VALUE 16384 -@@ -231,7 +231,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME +@@ -197,7 +197,7 @@ + SESSION_VALUE 1 DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED @@ -94,7 +94,7 @@ VARIABLE_COMMENT Number of threads to use when repairing Aria tables. The value of 1 disables parallel repair. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -248,7 +248,7 @@ +@@ -212,7 +212,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE. NUMERIC_MIN_VALUE 4096 diff --git a/mysql-test/suite/sys_vars/r/sysvars_aria.result b/mysql-test/suite/sys_vars/r/sysvars_aria.result index 7b74c85b6da..5b0ac74a889 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_aria.result +++ b/mysql-test/suite/sys_vars/r/sysvars_aria.result @@ -78,7 +78,7 @@ SESSION_VALUE NULL DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used +VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index 1771ee10832..84aecf2ce36 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -380,15 +380,6 @@ VARIABLE_COMMENT Deprecated parameter with no effect. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 -@@ -1513,7 +1513,7 @@ - SESSION_VALUE NULL - DEFAULT_VALUE 16 - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2 - NUMERIC_MIN_VALUE 1 - NUMERIC_MAX_VALUE 1024 @@ -1525,7 +1525,7 @@ SESSION_VALUE NULL DEFAULT_VALUE 16384 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index ef70b437a85..4d062995b1e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -700,7 +700,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Number of threads performing background key rotation NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 +NUMERIC_MAX_VALUE 255 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO @@ -1509,18 +1509,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME INNODB_PAGE_HASH_LOCKS -SESSION_VALUE NULL -DEFAULT_VALUE 16 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2 -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 1024 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_PAGE_SIZE SESSION_VALUE NULL DEFAULT_VALUE 16384 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index bd7224348bd..510a9c28051 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -42,7 +42,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used + VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -105,7 +105,7 @@ diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 924005a3001..704f893e32e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -96,7 +96,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used +VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 @@ -1947,7 +1947,7 @@ VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) -NUMERIC_MIN_VALUE 4 +NUMERIC_MIN_VALUE 8 NUMERIC_MAX_VALUE 8388608 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index 66ca924dea0..beea596b212 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result -+++ mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.result~ +--- sysvars_server_notembedded.result 2020-04-29 11:35:30.046243428 +0300 ++++ sysvars_server_notembedded,32bit.reject 2020-04-30 11:45:50.488748076 +0300 @@ -35,7 +35,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE @@ -42,7 +42,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used + VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -105,7 +105,7 @@ @@ -1254,7 +1254,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3265,10 +3265,10 @@ +@@ -3365,10 +3365,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1267,7 +1267,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3285,20 +3285,20 @@ +@@ -3385,20 +3385,20 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -1292,7 +1292,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3355,10 +3355,10 @@ +@@ -3455,10 +3455,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL VARIABLE_SCOPE GLOBAL @@ -1305,7 +1305,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3395,7 +3395,7 @@ +@@ -3495,7 +3495,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1314,7 +1314,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3535,7 +3535,7 @@ +@@ -3635,7 +3635,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1323,7 +1323,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3565,7 +3565,7 @@ +@@ -3665,7 +3665,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1332,7 +1332,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3585,7 +3585,7 @@ +@@ -3685,7 +3685,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED VARIABLE_SCOPE GLOBAL @@ -1341,7 +1341,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3605,7 +3605,7 @@ +@@ -3705,7 +3705,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SLAVE_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1350,7 +1350,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3615,7 +3615,7 @@ +@@ -3715,7 +3715,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_WORKERS VARIABLE_SCOPE GLOBAL @@ -1359,7 +1359,7 @@ VARIABLE_COMMENT Alias for slave_parallel_threads NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3655,7 +3655,7 @@ +@@ -3755,7 +3755,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_TRANSACTION_RETRIES VARIABLE_SCOPE GLOBAL @@ -1368,7 +1368,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3675,7 +3675,7 @@ +@@ -3775,7 +3775,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_TRANSACTION_RETRY_INTERVAL VARIABLE_SCOPE GLOBAL @@ -1377,7 +1377,7 @@ VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3600 -@@ -3695,7 +3695,7 @@ +@@ -3795,7 +3795,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1386,7 +1386,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3738,7 +3738,7 @@ +@@ -3838,7 +3838,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1395,7 +1395,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3955,7 +3955,7 @@ +@@ -4065,7 +4065,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1404,7 +1404,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4055,7 +4055,7 @@ +@@ -4165,7 +4165,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1413,7 +1413,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -4065,7 +4065,7 @@ +@@ -4175,7 +4175,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1422,7 +1422,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -4125,7 +4125,7 @@ +@@ -4235,7 +4235,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1431,7 +1431,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4298,7 +4298,7 @@ +@@ -4408,7 +4408,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1440,7 +1440,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4308,7 +4308,7 @@ +@@ -4418,7 +4418,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 0 @@ -1449,7 +1449,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4318,14 +4318,14 @@ +@@ -4428,14 +4428,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 0 @@ -1466,7 +1466,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4335,7 +4335,7 @@ +@@ -4445,7 +4445,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1475,7 +1475,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4475,7 +4475,7 @@ +@@ -4585,7 +4585,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1484,7 +1484,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4502,7 +4502,7 @@ +@@ -4612,7 +4612,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index e07d2c503e4..f2b7f14cc99 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -96,7 +96,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used +VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 @@ -2107,7 +2107,7 @@ VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) -NUMERIC_MIN_VALUE 4 +NUMERIC_MIN_VALUE 8 NUMERIC_MAX_VALUE 8388608 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL @@ -3543,16 +3543,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME SESSION_TRACK_USER_VARIABLES -VARIABLE_SCOPE SESSION -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Track changes to user variables. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SKIP_EXTERNAL_LOCKING VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN diff --git a/mysql-test/suite/sys_vars/t/all_vars.test b/mysql-test/suite/sys_vars/t/all_vars.test index c0127e1ef12..06edc04d25c 100644 --- a/mysql-test/suite/sys_vars/t/all_vars.test +++ b/mysql-test/suite/sys_vars/t/all_vars.test @@ -1,5 +1,4 @@ --source include/not_embedded.inc ---source include/not_threadpool.inc # # load everything we want to include in the testing diff --git a/mysql-test/suite/sys_vars/t/innodb_page_hash_locks_basic.test b/mysql-test/suite/sys_vars/t/innodb_page_hash_locks_basic.test deleted file mode 100644 index ee4798c1f90..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_page_hash_locks_basic.test +++ /dev/null @@ -1,24 +0,0 @@ ---source include/have_innodb.inc ---source include/have_debug.inc - -# -# exists as global only -# -select @@global.innodb_page_hash_locks between 1 and 1024; -select @@global.innodb_page_hash_locks; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.innodb_page_hash_locks; -show global variables like 'innodb_page_hash_locks'; -show session variables like 'innodb_page_hash_locks'; ---disable_warnings -select * from information_schema.global_variables where variable_name='innodb_page_hash_locks'; -select * from information_schema.session_variables where variable_name='innodb_page_hash_locks'; ---enable_warnings - -# -# show that it's read-only -# ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global innodb_page_hash_locks=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set @@session.innodb_page_hash_locks='some'; diff --git a/mysql-test/suite/sys_vars/t/max_sort_length_basic.test b/mysql-test/suite/sys_vars/t/max_sort_length_basic.test index 9c3b88d3c3c..fcd6db017f1 100644 --- a/mysql-test/suite/sys_vars/t/max_sort_length_basic.test +++ b/mysql-test/suite/sys_vars/t/max_sort_length_basic.test @@ -74,9 +74,9 @@ SELECT @@session.max_sort_length = 1024; # Change the value of max_sort_length to a valid value for GLOBAL Scope # ######################################################################### -SET @@global.max_sort_length = 4; +SET @@global.max_sort_length = 8; SELECT @@global.max_sort_length; -SET @@global.max_sort_length = 5; +SET @@global.max_sort_length = 9; SELECT @@global.max_sort_length; SET @@global.max_sort_length = 8388608; SELECT @@global.max_sort_length; @@ -90,10 +90,10 @@ SELECT @@global.max_sort_length; # Change the value of max_sort_length to a valid value for SESSION Scope # ########################################################################## -SET @@session.max_sort_length = 4; +SET @@session.max_sort_length = 8; SELECT @@session.max_sort_length; -SET @@session.max_sort_length = 5; +SET @@session.max_sort_length = 9; SELECT @@session.max_sort_length; SET @@session.max_sort_length = 8388608; diff --git a/mysql-test/suite/sys_vars/t/thread_pool_size_basic.opt b/mysql-test/suite/sys_vars/t/thread_pool_size_basic.opt index 7a2696875b8..b680d0c4b4f 100644 --- a/mysql-test/suite/sys_vars/t/thread_pool_size_basic.opt +++ b/mysql-test/suite/sys_vars/t/thread_pool_size_basic.opt @@ -1 +1 @@ ---loose-thread-handling=pool-of-threads +--loose-thread-handling=pool-of-threads --loose-thread-pool-mode=generic \ No newline at end of file diff --git a/mysql-test/suite/sys_vars/t/thread_pool_size_basic.test b/mysql-test/suite/sys_vars/t/thread_pool_size_basic.test index 5d432eb9940..3d17f3befa0 100644 --- a/mysql-test/suite/sys_vars/t/thread_pool_size_basic.test +++ b/mysql-test/suite/sys_vars/t/thread_pool_size_basic.test @@ -1,5 +1,4 @@ # uint global ---source include/not_windows.inc --source include/not_embedded.inc --source include/have_pool_of_threads.inc SET @start_global_value = @@global.thread_pool_size; diff --git a/mysql-test/suite/sys_vars/t/wait_timeout_func.test b/mysql-test/suite/sys_vars/t/wait_timeout_func.test index ee129b147dd..d388fc9f263 100644 --- a/mysql-test/suite/sys_vars/t/wait_timeout_func.test +++ b/mysql-test/suite/sys_vars/t/wait_timeout_func.test @@ -22,7 +22,6 @@ ############################################################################### --source include/not_embedded.inc ---source include/not_threadpool.inc SET @start_value= @@global.wait_timeout; diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index 33375a14803..1e6c854e0d9 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -409,3 +409,12 @@ SELECT * FROM t1 WHERE d2 < d1; i d1 d2 t 1 2023-03-16 2023-03-15 1 DROP TABLE t1; +# +# MDEV-20015 Assertion `!in_use->is_error()' failed in TABLE::update_virtual_field +# +create or replace table t1 (a int); +insert into t1 (a) values (1), (1); +create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk), key(c)); +insert into t2 (pk) select a from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +drop tables t1, t2; diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 6afdd120d26..1df31a4dfab 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -427,6 +427,26 @@ aaa Warnings: Warning 1918 Encountered illegal value '\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7' when converting to DOUBLE # +# MDEV-22579 No error when inserting DEFAULT(non_virtual_column) into a virtual column +# +SET sql_mode=STRICT_ALL_TABLES; +CREATE OR REPLACE TABLE t1 ( +a INT NOT NULL DEFAULT 10, +b INT AS (a+1) VIRTUAL +) ENGINE=MyISAM; +INSERT INTO t1 (b) VALUES (10); +ERROR HY000: The value specified for generated column 'b' in table 't1' has been ignored +INSERT INTO t1 (b) VALUES (DEFAULT(a)); +ERROR HY000: The value specified for generated column 'b' in table 't1' has been ignored +INSERT INTO t1 (b) VALUES (DEFAULT); +INSERT INTO t1 VALUES (10,10); +ERROR HY000: The value specified for generated column 'b' in table 't1' has been ignored +INSERT INTO t1 VALUES (10,DEFAULT(a)); +ERROR HY000: The value specified for generated column 'b' in table 't1' has been ignored +INSERT INTO t1 VALUES (10, DEFAULT); +DROP TABLE t1; +SET sql_mode=DEFAULT; +# # End of 10.1 tests # # @@ -481,5 +501,37 @@ Warning 1264 Out of range value for column 'vi' at row 1 DROP TABLE t1; SET @sql_mode=@old_sql_mode; # +# MDEV-22579 No error when inserting DEFAULT(non_virtual_column) into a virtual column +# 10.2+ specific part +# +SET sql_mode=STRICT_ALL_TABLES; +CREATE OR REPLACE TABLE t1 ( +a INT NOT NULL DEFAULT 10, +b INT AS (a+1) VIRTUAL +) ENGINE=MyISAM; +EXECUTE IMMEDIATE 'INSERT INTO t1 (b) VALUES(?)' USING DEFAULT; +EXECUTE IMMEDIATE 'INSERT INTO t1 (b) VALUES(?)' USING IGNORE; +INSERT INTO t1 (b) VALUES (DEFAULT); +INSERT INTO t1 (b) VALUES (IGNORE); +SELECT * FROM t1; +a b +10 11 +10 11 +10 11 +10 11 +DELETE FROM t1; +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES(10,?)' USING DEFAULT; +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES(11,?)' USING IGNORE; +INSERT INTO t1 VALUES (12,DEFAULT); +INSERT INTO t1 VALUES (13,IGNORE); +SELECT * FROM t1; +a b +10 11 +11 12 +12 13 +13 14 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# # End of 10.2 tests # diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test index 0856616dcc3..b8cbf9ef705 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test @@ -300,3 +300,14 @@ DROP TABLE t1; # Cleanup --let $datadir= `SELECT @@datadir` --remove_file $datadir/test/load_t1 + + +--echo # +--echo # MDEV-20015 Assertion `!in_use->is_error()' failed in TABLE::update_virtual_field +--echo # +create or replace table t1 (a int); +insert into t1 (a) values (1), (1); +create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk), key(c)); +--error ER_DUP_ENTRY +insert into t2 (pk) select a from t1; +drop tables t1, t2; diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 39f4f4142e6..1bbd18d6eab 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -385,6 +385,36 @@ SELECT COLUMN_GET(@aaa, 'price' AS DECIMAL) aaa; SELECT COLUMN_GET(@aaa, 'price' AS INT) aaa; SELECT COLUMN_GET(@aaa, 'price' AS DOUBLE) aaa; + +--echo # +--echo # MDEV-22579 No error when inserting DEFAULT(non_virtual_column) into a virtual column +--echo # + +SET sql_mode=STRICT_ALL_TABLES; +CREATE OR REPLACE TABLE t1 ( + a INT NOT NULL DEFAULT 10, + b INT AS (a+1) VIRTUAL +) ENGINE=MyISAM; + +# Testing with a column list + +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN +INSERT INTO t1 (b) VALUES (10); +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN +INSERT INTO t1 (b) VALUES (DEFAULT(a)); +INSERT INTO t1 (b) VALUES (DEFAULT); + +# Testing without a column list +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN +INSERT INTO t1 VALUES (10,10); +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN +INSERT INTO t1 VALUES (10,DEFAULT(a)); +INSERT INTO t1 VALUES (10, DEFAULT); + +DROP TABLE t1; +SET sql_mode=DEFAULT; + + --echo # --echo # End of 10.1 tests --echo # @@ -442,6 +472,37 @@ REPLACE INTO t1 (pk,i) VALUES (1,2); DROP TABLE t1; SET @sql_mode=@old_sql_mode; +--echo # +--echo # MDEV-22579 No error when inserting DEFAULT(non_virtual_column) into a virtual column +--echo # 10.2+ specific part +--echo # + +SET sql_mode=STRICT_ALL_TABLES; +CREATE OR REPLACE TABLE t1 ( + a INT NOT NULL DEFAULT 10, + b INT AS (a+1) VIRTUAL +) ENGINE=MyISAM; + +# Testing with column list + +EXECUTE IMMEDIATE 'INSERT INTO t1 (b) VALUES(?)' USING DEFAULT; +EXECUTE IMMEDIATE 'INSERT INTO t1 (b) VALUES(?)' USING IGNORE; +INSERT INTO t1 (b) VALUES (DEFAULT); +INSERT INTO t1 (b) VALUES (IGNORE); +SELECT * FROM t1; +DELETE FROM t1; + +# Testing without column list + +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES(10,?)' USING DEFAULT; +EXECUTE IMMEDIATE 'INSERT INTO t1 VALUES(11,?)' USING IGNORE; +INSERT INTO t1 VALUES (12,DEFAULT); +INSERT INTO t1 VALUES (13,IGNORE); +SELECT * FROM t1; + +DROP TABLE t1; +SET sql_mode=DEFAULT; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc index 355b571e5a0..efb081a02e4 100644 --- a/mysql-test/suite/versioning/common.inc +++ b/mysql-test/suite/versioning/common.inc @@ -50,6 +50,10 @@ if ($MTR_COMBINATION_MYISAM) { --let $MTR_COMBINATION_TIMESTAMP= 1 } +if ($MTR_COMBINATION_TRADITIONAL) +{ + --let $MTR_COMBINATION_TIMESTAMP= 1 +} if ($MTR_COMBINATION_HEAP) { --let $MTR_COMBINATION_TIMESTAMP= 1 diff --git a/mysql-test/suite/versioning/engines.combinations b/mysql-test/suite/versioning/engines.combinations index 26b5bab23f1..57e2af6cd06 100644 --- a/mysql-test/suite/versioning/engines.combinations +++ b/mysql-test/suite/versioning/engines.combinations @@ -7,5 +7,10 @@ default-storage-engine=innodb [myisam] default-storage-engine=myisam +[traditional] +default-storage-engine=myisam +sql-mode=traditional + [heap] default-storage-engine=memory + diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index 874c617d049..b945ca4fb5b 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -1021,6 +1021,98 @@ insert into t2 values (0), (2); update t1 left join t2 on a > b set b= 2 order by b; drop table t1, t2; # +# MDEV-17091 Assertion `old_part_id == m_last_part' failed in +# ha_partition::update_row or `part_id == m_last_part' in +# ha_partition::delete_row upon UPDATE/DELETE after dropping versioning +# +create or replace table t1 (pk int primary key, f int) engine=innodb +with system versioning +partition by key() partitions 2; +insert into t1 values (1,10),(2,20); +# expected to hit same partition +select * from t1 partition (p0); +pk f +1 10 +2 20 +alter table t1 drop system versioning; +# 1 and 2 are expected to be in different partitions +select * from t1 partition(p0); +pk f +1 10 +select * from t1 partition(p1); +pk f +2 20 +update t1 set f=pk; +delete from t1; +drop table t1; +# +# MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table +# +create or replace table t1 (f char(6)) engine innodb with system versioning; +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; +create or replace view v1 as select * from t1 for system_time all; +update v1 set f = ''; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +create or replace table t1 (f char(6)) engine innodb with system versioning +partition by system_time limit 1 +(partition p1 history, partition p2 history, partition pn current); +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; +create or replace view v1 as select * from t1 for system_time all; +update v1 set f= ''; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +delete from v1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop view v1; +drop table t1; +# +# MDEV-22112 Assertion `tab_part_info->part_type == RANGE_PARTITION || tab_part_info->part_type == LIST_PARTITION' failed in prep_alter_part_table +# +create table t1 (a int) with system versioning partition by system_time; +drop table t1; +create table t1 (a int) with system versioning partition by system_time +(partition p1 history, partition pn current); +alter table t1 add partition (partition p2); +ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME` +drop table t1; +# End of 10.3 tests +# +# MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine +# +create table t1 (a int primary key) engine=aria page_checksum=0 +with system versioning +partition by system_time (partition p1 history, partition pn current); +alter table t1 add partition (partition p2 history); +Warnings: +Warning 4115 Maybe missing parameters: no rotation condition for multiple HISTORY partitions. +show table status; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary +t1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL Got error 174 "Fatal error during initialization of handler" from storage engine Aria NULL NULL +Warnings: +Warning 1030 Got error 174 "Fatal error during initialization of handler" from storage engine Aria +drop table t1; +create table t1 (b int) engine=aria row_format=dynamic with system versioning +partition by system_time (partition p1 history, partition pn current); +insert into t1 values (1); +replace into t1 values (1); +drop table t1; +# +# MDEV-18794 Assertion `!m_innodb' failed in ha_partition::cmp_ref upon SELECT from partitioned table +# +create or replace table t1 (pk int auto_increment, i int, c char(1), primary key (pk), key(i)) +engine=innodb with system versioning partition by key() partitions 2; +insert into t1 (i, c) values (1, 'a'), (2, 'b'), (null, 'c'), (null, 'b'); +alter table t1 drop system versioning; +replace into t1 select * from t1; +select * from t1 where i > 0 or pk = 1000 limit 1; +pk i c +1 1 a +drop table t1; +# End of 10.4 tests +# # MDEV-22153 ALTER add default history partitions makes table inaccessible # create or replace table t1 (x int) with system versioning partition by system_time; @@ -1056,31 +1148,6 @@ t1 CREATE TABLE `t1` ( PARTITIONS 8 drop tables t1; # -# MDEV-17091 Assertion `old_part_id == m_last_part' failed in -# ha_partition::update_row or `part_id == m_last_part' in -# ha_partition::delete_row upon UPDATE/DELETE after dropping versioning -# -create or replace table t1 (pk int primary key, f int) engine=innodb -with system versioning -partition by key() partitions 2; -insert into t1 values (1,10),(2,20); -# expected to hit same partition -select * from t1 partition (p0); -pk f -1 10 -2 20 -alter table t1 drop system versioning; -# 1 and 2 are expected to be in different partitions -select * from t1 partition(p0); -pk f -1 10 -select * from t1 partition(p1); -pk f -2 20 -update t1 set f=pk; -delete from t1; -drop table t1; -# # MDEV-22207 Drop default history partitions renders table inaccessible # create or replace table t1 (i int) with system versioning @@ -1149,3 +1216,6 @@ t1 CREATE TABLE `t1` ( PARTITION `p16` HISTORY ENGINE = DEFAULT_ENGINE, PARTITION `pn` CURRENT ENGINE = DEFAULT_ENGINE) drop tables t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index d33edb50968..3489909e925 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -45,7 +45,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -57,7 +57,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -242,8 +242,7 @@ ERROR HY000: Table `t1` is not system-versioned create or replace table t1 (x int) with system versioning; insert into t1 values (1); select * from t1 for system_time all for update; -x -1 +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated create or replace table t1 (a int not null auto_increment primary key) with system versioning; select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; a @@ -284,7 +283,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/select2,trx_id.rdiff b/mysql-test/suite/versioning/r/select2,trx_id.rdiff index 89399516777..bdc20d1dc4f 100644 --- a/mysql-test/suite/versioning/r/select2,trx_id.rdiff +++ b/mysql-test/suite/versioning/r/select2,trx_id.rdiff @@ -22,7 +22,7 @@ 7 107 8 108 9 109 --select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +-select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; +select x as FROMTO2_x, y from t1 for system_time from transaction @x0 to transaction @x1; FROMTO2_x y 0 100 @@ -31,7 +31,7 @@ 7 107 8 108 9 109 --select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; +-select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; +select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; BETWAND2_x y 0 100 diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result index abe1c821172..353bdf8e696 100644 --- a/mysql-test/suite/versioning/r/select2.result +++ b/mysql-test/suite/versioning/r/select2.result @@ -48,7 +48,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -60,7 +60,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -98,7 +98,7 @@ ASOF2_x y 7 107 8 108 9 109 -select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; FROMTO2_x y 0 100 1 101 @@ -110,7 +110,7 @@ FROMTO2_x y 7 107 8 108 9 109 -select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; +select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; BETWAND2_x y 0 100 1 101 @@ -233,8 +233,7 @@ ERROR HY000: Table `t1` is not system-versioned create or replace table t1 (x int) with system versioning; insert into t1 values (1); select * from t1 for system_time as of now() for update; -x -1 +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated create or replace table t1 (a int not null auto_increment primary key) with system versioning; select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1; a @@ -275,7 +274,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index 165458ef170..ac0a1237902 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -134,11 +134,11 @@ select * from t for system_time all; a 2 1 -select * from t for system_time from '0-0-0' to current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); a 2 1 -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); a 2 1 @@ -147,6 +147,35 @@ Variable_name Value Feature_system_versioning 2 drop table t; # +# MDEV-22906 Disallow system_versioning_asof in DML +# +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +insert into t1 values (1); +insert into t2 values (1); +set system_versioning_asof= '1970-01-01 00:00:00'; +delete t1, t2 from t1 join t2 where t1.x = t2.y; +select * from t1 for system_time as of timestamp now(6); +x +insert into t1 values (1); +insert into t2 values (1); +update t1, t2 set x= 2, y= 2 where x = y; +select * from t1 for system_time as of timestamp now(6); +x +2 +replace t2 select x + 1 from t1; +select * from t2; +y +2 +3 +insert t2 select x + 2 from t1; +select * from t2; +y +2 +3 +4 +drop tables t1, t2; +# # MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP # SET sql_mode=TIME_ROUND_FRACTIONAL; @@ -157,3 +186,4 @@ SELECT @@global.system_versioning_asof; @@global.system_versioning_asof 2002-01-01 00:00:00.000000 SET @@global.system_versioning_asof= DEFAULT; +# End of 10.4 tests diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result index 3b3fe580af4..e9e74899790 100644 --- a/mysql-test/suite/versioning/r/view.result +++ b/mysql-test/suite/versioning/r/view.result @@ -79,7 +79,7 @@ create or replace view vt12 as select * from t1 cross join t2; select * from vt12; a b 1 2 -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; a b # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index e64fc09b8e7..507e8d40256 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -853,21 +853,6 @@ update t1 left join t2 on a > b set b= 2 order by b; # cleanup drop table t1, t2; ---echo # ---echo # MDEV-22153 ALTER add default history partitions makes table inaccessible ---echo # -create or replace table t1 (x int) with system versioning partition by system_time; -alter table t1 add partition partitions 1; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -alter table t1 add partition partitions 2; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -alter table t1 add partition partitions 3; ---replace_result $default_engine DEFAULT_ENGINE -show create table t1; -drop tables t1; - --echo # --echo # MDEV-17091 Assertion `old_part_id == m_last_part' failed in --echo # ha_partition::update_row or `part_id == m_last_part' in @@ -889,6 +874,101 @@ update t1 set f=pk; delete from t1; drop table t1; +--echo # +--echo # MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table +--echo # +create or replace table t1 (f char(6)) engine innodb with system versioning; + +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; + +create or replace view v1 as select * from t1 for system_time all; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +update v1 set f = ''; + +create or replace table t1 (f char(6)) engine innodb with system versioning +partition by system_time limit 1 +(partition p1 history, partition p2 history, partition pn current); + +insert into t1 values (null); +update t1 set f= 'foo'; +update t1 set f= 'bar'; + +create or replace view v1 as select * from t1 for system_time all; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +update v1 set f= ''; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +delete from v1; + +# cleanup +drop view v1; +drop table t1; + +--echo # +--echo # MDEV-22112 Assertion `tab_part_info->part_type == RANGE_PARTITION || tab_part_info->part_type == LIST_PARTITION' failed in prep_alter_part_table +--echo # + +create table t1 (a int) with system versioning partition by system_time; +drop table t1; + +create table t1 (a int) with system versioning partition by system_time +(partition p1 history, partition pn current); +--error ER_PARTITION_WRONG_TYPE +alter table t1 add partition (partition p2); + +# Cleanup +drop table t1; + +--echo # End of 10.3 tests + +--echo # +--echo # MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine +--echo # +create table t1 (a int primary key) engine=aria page_checksum=0 +with system versioning +partition by system_time (partition p1 history, partition pn current); + +alter table t1 add partition (partition p2 history); +show table status; +drop table t1; + +create table t1 (b int) engine=aria row_format=dynamic with system versioning +partition by system_time (partition p1 history, partition pn current); +insert into t1 values (1); +replace into t1 values (1); + +# cleanup +drop table t1; + +--echo # +--echo # MDEV-18794 Assertion `!m_innodb' failed in ha_partition::cmp_ref upon SELECT from partitioned table +--echo # +create or replace table t1 (pk int auto_increment, i int, c char(1), primary key (pk), key(i)) +engine=innodb with system versioning partition by key() partitions 2; +insert into t1 (i, c) values (1, 'a'), (2, 'b'), (null, 'c'), (null, 'b'); +alter table t1 drop system versioning; +replace into t1 select * from t1; +select * from t1 where i > 0 or pk = 1000 limit 1; +drop table t1; + +--echo # End of 10.4 tests + +--echo # +--echo # MDEV-22153 ALTER add default history partitions makes table inaccessible +--echo # +create or replace table t1 (x int) with system versioning partition by system_time; +alter table t1 add partition partitions 1; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +alter table t1 add partition partitions 2; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +alter table t1 add partition partitions 3; +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; +drop tables t1; + --echo # --echo # MDEV-22207 Drop default history partitions renders table inaccessible --echo # @@ -920,4 +1000,8 @@ show create table t1; drop tables t1; +--echo # +--echo # End of 10.5 tests +--echo # + --source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index c8932ddf272..6c3e401e1cb 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -48,8 +48,8 @@ if ($MTR_COMBINATION_TRX_ID) select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; --disable_query_log @@ -62,8 +62,8 @@ if ($MTR_COMBINATION_TRX_ID) if ($MTR_COMBINATION_TIMESTAMP) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; - select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; + select x as FROMTO2_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; } --enable_query_log @@ -149,6 +149,7 @@ select * from t1 for system_time all; create or replace table t1 (x int) with system versioning; insert into t1 values (1); +--error ER_TABLE_NOT_LOCKED_FOR_WRITE select * from t1 for system_time all for update; create or replace table t1 (a int not null auto_increment primary key) with system versioning; @@ -186,7 +187,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/select2.test b/mysql-test/suite/versioning/t/select2.test index f624c512c87..1ab7bcf27c1 100644 --- a/mysql-test/suite/versioning/t/select2.test +++ b/mysql-test/suite/versioning/t/select2.test @@ -36,8 +36,8 @@ if($MTR_COMBINATION_TRX_ID) { select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; if($MTR_COMBINATION_TRX_ID) { @@ -47,8 +47,8 @@ if($MTR_COMBINATION_TRX_ID) { } if(!$MTR_COMBINATION_TRX_ID) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; - select x as BETWAND2_x, y from t1 for system_time between '0-0-0 0:0:0' and @t1; + select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; + select x as BETWAND2_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; } drop table t1; @@ -128,6 +128,7 @@ select * from t1 for system_time all; create or replace table t1 (x int) with system versioning; insert into t1 values (1); +--error ER_TABLE_NOT_LOCKED_FOR_WRITE select * from t1 for system_time as of now() for update; create or replace table t1 (a int not null auto_increment primary key) with system versioning; @@ -165,7 +166,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index e82a116f30e..7c5e818ec81 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -97,13 +97,37 @@ select * from t for system_time all; select * from t; select * from t for system_time as of timestamp current_timestamp(6); select * from t for system_time all; -select * from t for system_time from '0-0-0' to current_timestamp(6); -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); show status like "Feature_system_versioning"; drop table t; +--echo # +--echo # MDEV-22906 Disallow system_versioning_asof in DML +--echo # +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +insert into t1 values (1); +insert into t2 values (1); +set system_versioning_asof= '1970-01-01 00:00:00'; +delete t1, t2 from t1 join t2 where t1.x = t2.y; +select * from t1 for system_time as of timestamp now(6); + +insert into t1 values (1); +insert into t2 values (1); +update t1, t2 set x= 2, y= 2 where x = y; +select * from t1 for system_time as of timestamp now(6); + +replace t2 select x + 1 from t1; +select * from t2; + +insert t2 select x + 2 from t1; +select * from t2; + +drop tables t1, t2; + --echo # --echo # MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP @@ -113,3 +137,5 @@ SET sql_mode=TIME_ROUND_FRACTIONAL; SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999'; SELECT @@global.system_versioning_asof; SET @@global.system_versioning_asof= DEFAULT; + +--echo # End of 10.4 tests diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test index 288f1eb6e21..37676a7fb50 100644 --- a/mysql-test/suite/versioning/t/view.test +++ b/mysql-test/suite/versioning/t/view.test @@ -65,7 +65,7 @@ insert into t1 values (1); insert into t2 values (2); create or replace view vt12 as select * from t1 cross join t2; select * from vt12; -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; --echo # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index c18b59d710c..d1c97dd1537 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -23,133 +23,159 @@ # ############################################################################## # -# Based on bb-10.4-release cc5b7fe11f942aaec8b2d6cc0b1142a4d6349f5f -# Fri May 8 17:51:45 2020 +0200 : Merge branch '10.3' into 10.4 +# Based on 10.5 e341fb0dae1008b98d6fc96f8847e6f1bd975db3 +main.alter_table : Modified in 10.5.4 main.alter_table_trans : MDEV-12084 - timeout main.alter_user : Modified in 10.4.13 main.analyze_stmt_slow_query_log : MDEV-12237 - Wrong result main.auth_named_pipe : MDEV-14724 - System error 2 main.backup_interaction : Modified in 10.4.13 +main.backup_lock : Modified in 10.5.4 +main.backup_stages : Modified in 10.5.4 main.binary_to_hex : MDEV-20211 - Wrong result -main.cache_temporal_4265 : Modified in 10.4.12 main.column_compression : Modified in 10.4.13 +main.comment_table : Modified in 10.5.4 +main.commit_1innodb : Include file modified in 10.5.4 main.connect : MDEV-17282 - Wrong result main.connect-abstract : MDEV-20162 - Could not execute 'check-testcase' main.connect2 : MDEV-13885 - Server crash -main.connect_debug : Modified in 10.4.12 +main.connect_debug : MDEV-22950 - Server crash main.count_distinct2 : MDEV-11768 - timeout main.create_delayed : MDEV-10605 - failed with timeout main.create_drop_event : MDEV-16271 - Wrong result -main.create_or_replace2 : Modified in 10.4.12 +main.create_drop_view : Modified in 10.5.4 +main.create_or_replace : MDEV-22954 - Wrong result main.cte_nonrecursive : Modified in 10.4.13 +main.cte_recursive : Modified in 10.5.4 +main.ctype_big5 : Modified in 10.5.4 +main.ctype_binary : Modified in 10.5.4 +main.ctype_cp932 : Modified in 10.5.4 +main.ctype_cp932_binlog_row : MDEV-20540 - Wrong result main.ctype_cp932_binlog_stm : MDEV-20534 - Wrong result +main.ctype_dec8 : Added in 10.5.4 +main.ctype_eucjpms : Modified in 10.5.4 +main.ctype_euckr : Modified in 10.5.4 +main.ctype_filename : Modified in 10.5.4 +main.ctype_gb2312 : Modified in 10.5.4 +main.ctype_gbk : Modified in 10.5.4 +main.ctype_sjis : Modified in 10.5.4 +main.ctype_swe7 : Modified in 10.5.4 main.ctype_ucs : MDEV-17681 - Data too long for column main.ctype_upgrade : MDEV-16945 - Error upon mysql_upgrade -main.ctype_utf16 : MDEV-10675: timeout or extra warnings -main.ctype_utf16le : MDEV-10675: timeout or extra warnings -main.ctype_utf8mb4_innodb : MDEV-17744 - Timeout; MDEV-18567 - ASAN use-after-poison +main.ctype_utf16 : MDEV-10675 - Timeout or extra warnings; modified in 10.5.4 +main.ctype_utf16_uca : Modified in 10.5.4 +main.ctype_utf16le : MDEV-10675 - Timeout or extra warnings; modified in 10.5.4 +main.ctype_utf32 : Modified in 10.5.4 +main.ctype_utf32_uca : Modified in 10.5.4 +main.ctype_utf8 : Modified in 10.5.4 +main.ctype_utf8mb4 : Modified in 10.5.4 +main.ctype_utf8mb4_heap : Include file modified in 10.5.4 +main.ctype_utf8mb4_innodb : MDEV-17744 - Timeout; MDEV-18567 - ASAN use-after-poison; include file modified in 10.5.4 +main.ctype_utf8mb4_myisam : Include file modified in 10.5.4 +main.custom_aggregate_functions : Modified in 10.5.4 main.debug_sync : MDEV-10607 - internal error -main.default_session : Modified in 10.4.12 main.default_storage_engine : Modified in 10.4.13 main.delayed : MDEV-20961 - Assertion failure -main.delete_use_source : Modified in 10.4.12 main.derived_cond_pushdown : MDEV-20532 - Floating point differences; modified in 10.4.13 main.derived_opt : MDEV-11768 - timeout main.dirty_close : MDEV-19368 - mysqltest failed but provided no output main.distinct : MDEV-14194 - Crash -main.drop_bad_db_type : MDEV-15676 - Wrong result; modified in 10.4.12 +main.drop : Modified in 10.5.4 +main.drop_bad_db_type : MDEV-15676 - Wrong result +main.drop_combinations : Added in 10.5.4 +main.drop_table_force : Added in 10.5.4 main.dyncol : MDEV-19455 - Extra warning -main.engine_error_in_alter-8453 : Modified in 10.4.12 -main.error_simulation : Modified in 10.4.12 main.errors : Modified in 10.4.13 main.events_2 : MDEV-13277 - Crash -main.events_bugs : MDEV-12892 - Crash; modified in 10.4.12 +main.events_bugs : MDEV-12892 - Crash main.events_restart : MDEV-12236 - Server shutdown problem; modified in 10.4.13 main.events_slowlog : MDEV-12821 - Wrong result main.failed_auth_3909 : Modified in 10.4.13 main.failed_auth_unixsocket : Modified in 10.4.13 main.flush : MDEV-19368 - mysqltest failed but provided no output +main.flush_read_lock : MDEV-22953 - Unknown XID; modified in 10.5.4 main.flush_ssl : MDEV-21276 - Aria recovery failure -main.foreign_key : Modified in 10.4.12 main.fulltext : Modified in 10.4.13 -main.func_math : MDEV-20966 - Wrong error code; modified in 10.4.13 -main.func_misc : Modified in 10.4.12 -main.func_regexp_pcre : Modified in 10.4.12 -main.func_regexp_pcre_debug : Modified in 10.4.12 +main.func_bit : Added in 10.5.4 +main.func_gconcat : Modified in 10.5.4 +main.func_json : Modified in 10.5.4 +main.func_math : MDEV-20966 - Wrong error code; modified in 10.5.4 main.func_str : Modified in 10.4.13 -main.func_time : Modified in 10.4.12 -main.gis : MDEV-13411 - wrong result on P8; modified in 10.4.13 +main.gis : MDEV-13411 - wrong result on P8; modified in 10.5.4 main.gis-rtree : Modified in 10.4.13 main.gis_notembedded : MDEV-21264 - Wrong result with non-default charset -main.grant : Modified in 10.4.13 +main.grant : Modified in 10.5.4 main.grant2 : Modified in 10.4.13 -main.grant5 : Modified in 10.4.13 +main.grant5 : Modified in 10.5.4 main.grant_repair : Added in 10.4.13 main.group_by : Modified in 10.4.13 -main.having_cond_pushdown : Modified in 10.4.12 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout -main.index_merge_innodb : MDEV-7142 - Plan mismatch +main.index_merge_innodb : MDEV-7142 - Plan mismatch; modified in 10.5.4 main.index_merge_myisam : Modified in 10.4.13 +main.information_schema : Modified in 10.5.4 +main.information_schema_db : Modified in 10.5.4 +main.innodb_ext_key : Modified in 10.5.4 main.innodb_icp : MDEV-20168 - Wrong execution plans; include file modified in 10.4.13 main.innodb_mysql_lock : Modified in 10.4.13 -main.insert_debug : Added in 10.4.12 main.invisible_field_grant_completely : MDEV-22254 - Syscall param write points to uninitialised bytes main.ipv4_and_ipv6 : MDEV-20964 - Wrong result main.ipv6 : MDEV-20964 - Wrong result -main.join : Modified in 10.4.12 main.join_cache : MDEV-17743 - Bad address from storage engine MyISAM; modified in 10.4.13 main.key : Modified in 10.4.13 -main.kill-2 : MDEV-13257 - Wrong result +main.kill : Modified in 10.5.4 +main.kill-2 : MDEV-13257 - Wrong result; modified in 10.5.4 main.kill_processlist-6619 : MDEV-10793 - Wrong result main.loaddata : MDEV-19368 - mysqltest failed but provided no output main.locale : MDEV-20521 - Missing warning; configuration added in 10.4.13 +main.lock : Modified in 10.5.4 main.lock_user : Modified in 10.4.13 main.log_slow : MDEV-13263 - Wrong result -main.log_slow_debug : Modified in 10.4.12 main.log_tables-big : MDEV-13408 - wrong result main.log_tables_upgrade : MDEV-20962 - Wrong result -main.long_unique_bugs : Modified in 10.4.13 +main.long_unique_bugs : Modified in 10.5.4 +main.long_unique_bugs_replication : Added in 10.5.4 main.lowercase_fs_off : Modified in 10.4.13 main.mdev-504 : MDEV-15171 - warning main.mdev375 : MDEV-10607 - sporadic "can't connect"; modified in 10.4.13 -main.mdev6830 : Modified in 10.4.12 +main.mdev_22370 : Added in 10.5.4 +main.mdl : MDEV-22954 - Wrong result main.merge : MDEV-10607 - sporadic "can't connect" -main.merge-big : Modified in 10.4.12 -main.merge_debug : Modified in 10.4.12 main.multi_update : Modified in 10.4.13 main.multi_update_debug : Modified in 10.4.13 -main.myisam_debug : Modified in 10.4.12 main.myisam_icp : Include file modified in 10.4.13 +main.myisampack : Modified in 10.5.4 main.mysql : MDEV-20156 - Wrong result main.mysql_client_test : MDEV-19369 - error: 5888, status: 23, errno: 2; MDEV-19511 - Big endian issue; modified in 10.4.13 main.mysql_client_test_comp : MDEV-16641 - Error in exec main.mysql_client_test_nonblock : CONC-208 - Error on Power; MDEV-15096 - exec failed main.mysql_cp932 : MDEV-21275 - Wrong result -main.mysql_upgrade : MDEV-20161 - Wrong result; MDEV-20166 - FATAL ERROR: Upgrade failed; modified in 10.4.13 +main.mysql_upgrade : MDEV-20161 - Wrong result; MDEV-20166 - FATAL ERROR: Upgrade failed; modified in 10.5.4 main.mysql_upgrade-6984 : MDEV-22514 - Wrong result; modified in 10.4.13 main.mysql_upgrade_no_innodb : MDEV-20537 - Wrong result main.mysql_upgrade_noengine : MDEV-14355 - Wrong result main.mysql_upgrade_view : MDEV-20161 - Wrong result main.mysqladmin : MDEV-20535 - Wrong result +main.mysqlbinlog_row_compressed : MDEV-22964 - Wrong result main.mysqlcheck : MDEV-20164 - Wrong result main.mysqld--defaults-file : Modified in 10.4.13 main.mysqld_option_err : MDEV-21236 - Wrong error; MDEV-21571 - Crash on bootstrap -main.mysqldump : MDEV-22147 - Wrong result; MDEV-14800 - Stack smashing detected; modified in 10.4.13 +main.mysqldump : MDEV-14800 - Stack smashing detected; modified in 10.4.13 main.mysqldump-max : MDEV-21272 - Wrong result main.mysqlhotcopy_myisam : MDEV-10995 - Hang on debug -main.mysqlshow : MDEV-20965 - Wrong result +main.mysqlshow : MDEV-20965 - Wrong result; modified in 10.5.4 main.mysqlslap : MDEV-11801 - timeout main.mysqltest : MDEV-13887 - Wrong result -main.mysqltest_tracking_info : Modified in 10.4.13 +main.mysqltest_tracking_info : Modified in 10.5.4 +main.named_pipe : Modified in 10.5.4 main.old-mode : MDEV-19373 - Wrong result main.openssl_6975 : MDEV-17184 - Failures with OpenSSL 1.1.1 -main.opt_trace : Modified in 10.4.13 -main.opt_tvc : Modified in 10.4.12 +main.opt_trace : Modified in 10.5.4 +main.order_by : Modified in 10.5.4 main.order_by_optimizer_innodb : MDEV-10683 - Wrong result main.parser : Modified in 10.4.13 -main.partition_alter : Modified in 10.4.13 +main.partition_alter : Modified in 10.5.4 main.partition_debug_sync : MDEV-15669 - Deadlock found when trying to get lock main.partition_innodb : MDEV-20169 - Wrong result; modified in 10.4.13 main.partition_innodb_plugin : MDEV-12901 - Valgrind warnings @@ -159,71 +185,73 @@ main.partition_mrr_aria : Include file modified in 10.4.13 main.partition_mrr_innodb : Include file modified in 10.4.13 main.partition_mrr_myisam : Modified in 10.4.13 main.partition_range : Modified in 10.4.13 +main.percona_nonflushing_analyze_debug : Added in 10.5.4 main.plugin_auth : MDEV-20957 - Upgrade file was not properly created main.plugin_auth_qa_2 : MDEV-20165 - Wrong result main.pool_of_threads : MDEV-18135 - SSL error: key too small -main.processlist_notembedded : MDEV-22513 - Timeout in wait_until_count_sessions; modified in 10.4.13 -main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count +main.processlist_notembedded : Modified in 10.5.4 +main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count; modified in 10.5.4 main.ps_grant : Modified in 10.4.13 -main.query_cache : MDEV-16180 - Wrong result +main.query_cache : MDEV-16180 - Wrong result; modified in 10.5.4 main.query_cache_debug : MDEV-15281 - Query cache is disabled main.range : Modified in 10.4.13 main.range_innodb : Modified in 10.4.13 -main.range_interrupted-13751 : Modified in 10.4.12 main.range_vs_index_merge : Modified in 10.4.13 main.range_vs_index_merge_innodb : MDEV-15283 - Server has gone away +main.repair : Modified in 10.5.4 +main.row : Modified in 10.5.4 main.rowid_filter : Modified in 10.4.13 main.rowid_filter_innodb : MDEV-20538 - Wrong result; modified in 10.4.13 main.rpl_mysql_upgrade_slave_repo_check : Added in 10.4.13 main.select : MDEV-20532 - Floating point differences -main.select_debug : Modified in 10.4.12 main.select_jcl6 : MDEV-20532 - Floating point differences main.select_pkeycache : MDEV-20532 - Floating point differences +main.selectivity : Modified in 10.5.4 main.set_statement : MDEV-13183 - Wrong result main.set_statement_notembedded : MDEV-19414 - Wrong result main.shm : MDEV-12727 - Mismatch, ERROR 2013 -main.show_explain : MDEV-10674 - Wrong result code; modified in 10.4.12 -main.show_explain_non_select : Modified in 10.4.12 -main.show_explain_ps : Modified in 10.4.12 -main.slowlog_enospace-10508 : Modified in 10.4.12 +main.show_explain : MDEV-10674 - Wrong result code main.sp : MDEV-7866 - Mismatch -main.sp-security : MDEV-10607 - sporadic "can't connect" +main.sp-error : Modified in 10.5.4 +main.sp-security : MDEV-10607 - sporadic "can't connect"; modified in 10.5.4 +main.sp-vars : Modified in 10.5.4 +main.sp2 : Added in 10.5.4 main.sp_notembedded : MDEV-10607 - internal error main.ssl : MDEV-17184 - Failures with OpenSSL 1.1.1 -main.ssl_7937 : MDEV-20958 - Wrong result; modified in 10.4.12 -main.ssl_8k_key : Modified in 10.4.12 +main.ssl_7937 : MDEV-20958 - Wrong result main.ssl_ca : MDEV-10895 - SSL connection error on Power main.ssl_cipher : MDEV-17184 - Failures with OpenSSL 1.1.1 main.ssl_crl : MDEV-19119 - Wrong error code -main.ssl_crl_clients : Modified in 10.4.12 -main.ssl_system_ca : Added in 10.4.12 main.ssl_timeout : MDEV-11244 - Crash -main.stat_tables-enospc : Modified in 10.4.12 -main.stat_tables_par : MDEV-13266 - Wrong result main.stat_tables_par_innodb : MDEV-14155 - Wrong rounding main.status : MDEV-13255 - Wrong result +main.status_bug17954 : Modified in 10.5.4 main.subselect : MDEV-20551 - Valgrind failure +main.subselect4 : Modified in 10.5.4 main.subselect_innodb : MDEV-10614 - Wrong result main.subselect_sj2_mat : Modified in 10.4.13 +main.table_value_constr : Modified in 10.5.4 main.tc_heuristic_recover : MDEV-14189 - Wrong result -main.timezone2 : Modified in 10.4.12 -main.tls_version : MDEV-21965 - SSL connection error; MDEV-21965 - SSL connection error -main.tls_version1 : MDEV-21965 - SSL connection error; MDEV-21965 - SSL connection error main.type_blob : MDEV-15195 - Wrong result; modified in 10.4.13 -main.type_datetime : Modified in 10.4.12 -main.type_datetime_hires : MDEV-10687 - Timeout +main.type_date : Modified in 10.5.4 +main.type_datetime : Modified in 10.5.4 +main.type_datetime_hires : MDEV-10687 - Timeout; modified in 10.5.4 main.type_float : MDEV-20532 - Floating point differences -main.type_int : Modified in 10.4.12 main.type_newdecimal : MDEV-20532 - Floating point differences main.type_ranges : MDEV-20532 - Floating point differences -main.type_time : Modified in 10.4.12 -main.union_crash-714 : Modified in 10.4.12 +main.type_time : Modified in 10.5.4 +main.type_timestamp : Modified in 10.5.4 +main.udf : Modified in 10.5.4 main.upgrade_MDEV-19650 : Added in 10.4.13 main.userstat : MDEV-12904 - SSL errors +main.view : Modified in 10.5.4 main.wait_timeout : MDEV-19023 - Lost connection to MySQL server during query -main.warnings_debug : Modified in 10.4.12 -main.win : Modified in 10.4.12 -main.xa : MDEV-11769 - lock wait timeout +main.warnings_debug : Modified in 10.5.4 +main.win : Modified in 10.5.4 +main.win_percentile : Modified in 10.5.4 +main.xa : MDEV-11769 - lock wait timeout; modified in 10.5.4 +main.xa_binlog : Modified in 10.5.4 +main.xml : MDEV-21968 - Crash on armhf #----------------------------------------------------------------------- @@ -239,32 +267,33 @@ archive-test_sql_discovery.discover : MDEV-16817 - Table marked as crashed #----------------------------------------------------------------------- -binlog.binlog_commit_wait : MDEV-10150 - Mismatch -binlog.binlog_index : Include file modified in 10.2.31 -binlog.binlog_innodb : MDEV-22516 - Wrong result -binlog.binlog_invalid_read_in_rotate : MDEV-22455 - Server crash; added in 10.4.12 -binlog.binlog_ioerr : MDEV-20159 - Assertion failure; include file modified in 10.2.31 -binlog.binlog_killed : MDEV-12925 - Wrong result -binlog.binlog_max_extension : MDEV-19762 - Crash on shutdown -binlog.binlog_mysqlbinlog_row_innodb : MDEV-20530 - Binary files differ -binlog.binlog_mysqlbinlog_row_myisam : MDEV-20530 - Binary files differ -binlog.binlog_parallel_replication_marks_row : Include file modified in 10.4.12 -binlog.binlog_parallel_replication_marks_stm_mix : Include file modified in 10.4.12 -binlog.binlog_row_binlog : MDEV-20213 - Server crash -binlog.binlog_show_binlog_event_random_pos : MDEV-22473 - Server crash; added in 10.4.12 -binlog.binlog_stm_binlog : MDEV-20412 - Wrong result -binlog.binlog_write_error : Include file Include file modified in 10.2.31 -binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint -binlog.flashback-largebinlog : MDEV-19764 - Out of memory -binlog.load_data_stm_view : MDEV-16948 - Wrong result -binlog.show_concurrent_rotate : MDEV-20215 - Wrong result +binlog.binlog_base64_flag : Modified in 10.5.4 +binlog.binlog_commit_wait : MDEV-10150 - Mismatch +binlog.binlog_drop_if_exists : Modified in 10.5.4 +binlog.binlog_index : Include file modified in 10.2.31 +binlog.binlog_innodb : MDEV-22516 - Wrong result +binlog.binlog_invalid_read_in_rotate : MDEV-22455 - Server crash +binlog.binlog_ioerr : MDEV-20159 - Assertion failure; include file modified in 10.2.31 +binlog.binlog_killed : MDEV-12925 - Wrong result +binlog.binlog_max_extension : MDEV-19762 - Crash on shutdown +binlog.binlog_mixed : Added in 10.5.4 +binlog.binlog_mysqlbinlog_row_frag : Modified in 10.5.4 +binlog.binlog_mysqlbinlog_row_innodb : MDEV-20530 - Binary files differ +binlog.binlog_mysqlbinlog_row_myisam : MDEV-20530 - Binary files differ +binlog.binlog_no_uniqfile_crash : Added in 10.5.4 +binlog.binlog_row_binlog : MDEV-20213 - Server crash; include file modified in 10.5.4 +binlog.binlog_show_binlog_event_random_pos : MDEV-22473 - Server crash +binlog.binlog_stm_binlog : MDEV-20412 - Wrong result; include file modified in 10.5.4 +binlog.binlog_write_error : Include file Include file modified in 10.2.31 +binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint +binlog.flashback-largebinlog : MDEV-19764 - Out of memory +binlog.load_data_stm_view : MDEV-16948 - Wrong result +binlog.show_concurrent_rotate : MDEV-20215 - Wrong result #----------------------------------------------------------------------- binlog_encryption.binlog_incident : MDEV-20213 - Server crash -binlog_encryption.binlog_index : Include file modified in 10.4.12 -binlog_encryption.binlog_ioerr : Include file modified in 10.4.12 -binlog_encryption.binlog_write_error : Include file Include file modified in 10.4.12 +binlog_encryption.binlog_row_annotate : MDEV-20213 - Server crash binlog_encryption.binlog_xa_recover : MDEV-12908 - Extra checkpoint binlog_encryption.encrypted_master : MDEV-14201 - Extra warnings binlog_encryption.encrypted_master_switch_to_unencrypted : MDEV-14190 - Can't init tc log @@ -273,15 +302,15 @@ binlog_encryption.encryption_combo : MDEV-14199 - Table binlog_encryption.multisource : MDEV-20213 - Server crash; MDEV-21289 - Wrong error code binlog_encryption.mysqlbinlog : MDEV-20213 - Server crash binlog_encryption.rpl_binlog_errors : MDEV-12742 - Crash; include file include file modified in 10.4.13 -binlog_encryption.rpl_checksum : MDEV-16951 - Wrong result; include file modified in 10.4.12 +binlog_encryption.rpl_checksum : MDEV-16951 - Wrong result binlog_encryption.rpl_corruption : MDEV-20159 - Assertion failure; MDEV-20953 - Wrong error code; include file modified in 10.4.13 binlog_encryption.rpl_gtid_basic : MDEV-16947 - Server failed to start -binlog_encryption.rpl_incident : MDEV-21569 - mutex: LOCK_global_system_variables unlocking; include file modified in 10.4.12 -binlog_encryption.rpl_init_slave_errors : MDEV-20213 - Server crash; include file modified in 10.4.12 +binlog_encryption.rpl_incident : MDEV-21569 - mutex: LOCK_global_system_variables unlocking +binlog_encryption.rpl_init_slave_errors : MDEV-20213 - Server crash binlog_encryption.rpl_loadfile : MDEV-16645 - Timeout in include binlog_encryption.rpl_mixed_binlog_max_cache_size : MDEV-20956 - Incorrect checksum for freed object -binlog_encryption.rpl_parallel : MDEV-10653 - Timeout in include; include file modified in 10.4.12 -binlog_encryption.rpl_parallel_ignored_errors : MDEV-22471 - Slave crash; include file modified in 10.4.12 +binlog_encryption.rpl_parallel : MDEV-10653 - Timeout in include +binlog_encryption.rpl_parallel_ignored_errors : MDEV-22471 - Slave crash binlog_encryption.rpl_relayrotate : MDEV-15194 - Timeout binlog_encryption.rpl_semi_sync : MDEV-11673 - Valgrind binlog_encryption.rpl_skip_replication : MDEV-13571 - Unexpected warning; MDEV-20573 - Wrong result @@ -294,8 +323,11 @@ binlog_encryption.rpl_typeconv : MDEV-14362 - Lost c #----------------------------------------------------------------------- -compat/oracle.sp-goto : Modified in 10.4.12 -compat/oracle.sp-goto-debug : Added in 10.4.12 +columnstore.* : Engine enabled in 10.5.4 + +#----------------------------------------------------------------------- + +compat/oracle.parser : Modified in 10.5.4 #----------------------------------------------------------------------- @@ -311,6 +343,7 @@ connect.part_file : MDEV-18135 - SSL error: key too small connect.part_table : MDEV-18135 - SSL error: key too small connect.pivot : MDEV-14803 - Failed to discover table connect.secure_file_priv : MDEV-18135 - SSL error: key too small +connect.type_inet6 : Added in 10.5.4 connect.vcol : MDEV-12374 - Fails on Windows connect.xml2_grant : Include file modified in 10.1.44 connect.xml_grant : Include file modified in 10.1.44 @@ -322,7 +355,7 @@ disks.disks_notembedded : MDEV-21587 - Wrong result #----------------------------------------------------------------------- -encryption.corrupted_during_recovery : MDEV-20159 - Assertion failure +encryption.corrupted_during_recovery : MDEV-20159 - Assertion failure; modified in 10.5.4 encryption.create_or_replace : MDEV-16115 - Trying to access tablespace encryption.debug_key_management : MDEV-13841 - Timeout encryption.encrypt_and_grep : MDEV-13765 - Wrong result @@ -338,7 +371,7 @@ encryption.innodb-missing-key : MDEV-14728 - SSL error encryption.innodb-page_encryption : MDEV-10641 - mutex problem encryption.innodb-page_encryption_log_encryption : MDEV-17339 - Crash on restart encryption.innodb-read-only : MDEV-16563 - Crash on startup -encryption.innodb-redo-badkey : Modified in 10.4.12 +encryption.innodb-redo-badkey : Modified in 10.5.4 encryption.innodb-redo-nokeys : MDEV-20159 - Assertion failure encryption.innodb-remove-encryption : MDEV-16493 - Timeout in wait condition encryption.innodb-spatial-index : MDEV-13746 - Wrong result @@ -347,7 +380,7 @@ encryption.innodb_encrypt_log : MDEV-13725 - Wrong result encryption.innodb_encrypt_log_corruption : MDEV-14379 - Server crash encryption.innodb_encrypt_temporary_tables : MDEV-20142 - Wrong result encryption.innodb_encryption : MDEV-14728 - Unable to get certificate; MDEV-15675 - Timeout -encryption.innodb_encryption-page-compression : MDEV-12630 - crash or assertion failure +encryption.innodb_encryption-page-compression : MDEV-12630 - Crash or assertion failure; MDEV-21843 - Assertion failure encryption.innodb_encryption_discard_import : MDEV-16116 - Wrong result encryption.innodb_encryption_filekeys : MDEV-15673 - Timeout encryption.innodb_encryption_is : MDEV-12898 - Server hang on startup @@ -355,9 +388,7 @@ encryption.innodb_encryption_row_compressed : MDEV-16113 - Crash encryption.innodb_encryption_tables : MDEV-17339 - Crash on restart encryption.innodb_first_page : MDEV-10689 - Crash encryption.innodb_onlinealter_encryption : MDEV-17287 - SIGABRT on server restart -encryption.innodb_scrub : MDEV-8139 - scrubbing tests need fixing -encryption.innodb_scrub_background : MDEV-8139 - scrubbing tests need fixing -encryption.innodb_scrub_compressed : MDEV-8139 - scrubbing tests need fixing +encryption.tempfiles_encrypted : Added in 10.5.4 #----------------------------------------------------------------------- @@ -381,10 +412,10 @@ federated.federated_partition : MDEV-10417 - Fails on Mips federated.federated_transactions : MDEV-10617 - Wrong checksum federated.federatedx : MDEV-10617 - Wrong checksum federated.federatedx_create_handlers : Modified in 10.4.13 +federated.federatedx_versioning : Modified in 10.5.4 #----------------------------------------------------------------------- -funcs_1.is_check_constraints : Modified in 10.4.12 funcs_1.memory_views : MDEV-11773 - timeout funcs_1.processlist_val_no_prot : MDEV-11223 - Wrong result funcs_1.processlist_val_ps : MDEV-12175 - Wrong plan @@ -408,11 +439,19 @@ galera_3nodes.* : Suite is not stable yet #----------------------------------------------------------------------- +gcol.gcol_purge : Added in 10.5.4 gcol.gcol_rollback : MDEV-16954 - Unknown storage engine 'InnoDB' gcol.innodb_virtual_basic : MDEV-16950 - Failing assertion -gcol.innodb_virtual_debug : MDEV-19114 - Assertion failure gcol.innodb_virtual_debug_purge : MDEV-16952 - Wrong result; modified in 10.4.13 gcol.innodb_virtual_fk_restart : MDEV-17466 - Assertion failure +gcol.innodb_virtual_purge : MDEV-22952 - Lock wait timeout + +#----------------------------------------------------------------------- + +handler.aria : Include file modified in 10.5.4 +handler.heap : Include file modified in 10.5.4 +handler.innodb : Modified in 10.5.4 +handler.myisam : Include file modified in 10.5.4 #----------------------------------------------------------------------- @@ -420,87 +459,86 @@ innodb.101_compatibility : MDEV-13891 - Wrong result innodb.alter_algorithm : Modified in 10.4.13 innodb.alter_algorithm2 : Added in 10.4.13 innodb.alter_copy : MDEV-16181 - Assertion failure -innodb.alter_crash : MDEV-16944 - The process cannot access the file +innodb.alter_crash : MDEV-16944 - The process cannot access the file; modified in 10.5.4 innodb.alter_large_dml : MDEV-20148 - Debug sync point wait timed out innodb.alter_missing_tablespace : Modified in 10.4.13 -innodb.alter_not_null_debug : Modified in 10.4.12 +innodb.analyze_table : Modified in 10.5.4 innodb.autoinc_persist : MDEV-15282 - Assertion failure innodb.binlog_consistent : MDEV-10618 - Server fails to start innodb.blob-crash : MDEV-19298 - Assertion failure -innodb.blob-update-debug : Modified in 10.4.12 innodb.buf_pool_resize_oom : Added in 10.4.13 -innodb.corrupted_during_recovery : Modified in 10.4.13 +innodb.corrupted_during_recovery : Modified in 10.5.4 innodb.create-index : MDEV-20159 - Assertion failure innodb.default_row_format_compatibility : MDEV-20159 - Assertion failure innodb.doublewrite : MDEV-12905 - Server crash -innodb.foreign_key : Modified in 10.4.13 +innodb.foreign_key : Modified in 10.5.4 innodb.foreign_key_debug : Added in 10.4.13 -innodb.full_crc32_import : Modified in 10.4.12 innodb.group_commit_crash : MDEV-14191 - InnoDB registration failed innodb.group_commit_crash_no_optimize_thread : MDEV-13830 - Assertion failure innodb.ibuf_not_empty : MDEV-19021 - Wrong result innodb.innodb-32k-crash : MDEV-20194 - Extra warnings innodb.innodb-64k-crash : MDEV-13872 - Failure and crash on startup -innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS +innodb.innodb-alter : MDEV-22955 - Extra warning; MDEV-22955 - Extra warning +innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS; modified in 10.5.4 innodb.innodb-alter-table : MDEV-10619 - Testcase timeout innodb.innodb-alter-timestamp : Modified in 10.4.13 innodb.innodb-bigblob : MDEV-18655 - ASAN unknown crash innodb.innodb-blob : MDEV-12053 - Client crash; modified in 10.4.13 innodb.innodb-change-buffer-recovery : MDEV-19115 - Lost connection to MySQL server during query innodb.innodb-dict : MDEV-20159 - Assertion failure -innodb.innodb-fk : MDEV-13832 - Assertion failure on shutdown +innodb.innodb-fk : MDEV-13832 - Assertion failure on shutdown; modified in 10.5.4 innodb.innodb-get-fk : MDEV-13276 - Server crash innodb.innodb-index-online : MDEV-14809 - Cannot save statistics -innodb.innodb-online-alter-gis : MDEV-22071 - Uninitialised value innodb.innodb-page_compression_default : MDEV-13644 - Assertion failure innodb.innodb-page_compression_lzma : MDEV-14353 - Wrong result innodb.innodb-page_compression_snappy : MDEV-13644 - Assertion failure innodb.innodb-page_compression_tables : MDEV-13644 - Assertion failure innodb.innodb-page_compression_zip : MDEV-10641 - mutex problem -innodb.innodb-replace-debug : Modified in 10.4.12 -innodb.innodb-stats-initialize-failure : Modified in 10.4.12 innodb.innodb-table-online : MDEV-13894 - Wrong result innodb.innodb-timeout : MDEV-20159 - Assertion failure innodb.innodb-wl5522 : MDEV-13644 - Assertion failure; modified in 10.4.13 +innodb.innodb-wl5522-1 : MDEV-22945 - Server crash innodb.innodb-wl5522-debug : MDEV-14200 - Wrong errno; modified in 10.4.13 innodb.innodb_buffer_pool_dump_pct : MDEV-20139 - Timeout in wait_condition.inc innodb.innodb_buffer_pool_load_now : Added in 10.4.13 innodb.innodb_buffer_pool_resize : MDEV-16964 - Assertion failure innodb.innodb_buffer_pool_resize_debug : MDEV-22515 - Timeout in wait_condition; added in 10.4.13 innodb.innodb_buffer_pool_resize_with_chunks : MDEV-16964 - Assertion failure -innodb.innodb_bug11754376 : Modified in 10.4.12 -innodb.innodb_bug14147491 : MDEV-11808 - Index is corrupt -innodb.innodb_bug30113362 : Added in 10.4.12 +innodb.innodb_bug14147491 : MDEV-11808 - Index is corrupt; modified in 10.5.4 innodb.innodb_bug30423 : MDEV-7311 - Wrong result innodb.innodb_bug47167 : MDEV-20524 - Table 'user' is marked as crashed and should be repaired innodb.innodb_bug48024 : MDEV-14352 - Assertion failure -innodb.innodb_bug56947 : Modified in 10.4.12 innodb.innodb_bug59641 : MDEV-13830 - Assertion failure +innodb.innodb_bug60049 : MDEV-20213 - Server crash innodb.innodb_bulk_create_index_replication : MDEV-15273 - Slave failed to start -innodb.innodb_corrupt_bit : Modified in 10.4.12 innodb.innodb_defrag_concurrent : Modified in 10.4.13 innodb.innodb_defrag_stats_many_tables : MDEV-14198 - Table is full +innodb.innodb_force_recovery : MDEV-20213 - Server crash; modified in 10.5.4 +innodb.innodb_force_recovery_rollback : MDEV-22889 - Wrong result; added in 10.5.4 innodb.innodb_information_schema : MDEV-8851 - Wrong result +innodb.innodb_information_schema_buffer : Modified in 10.5.4 innodb.innodb_max_recordsize_32k : MDEV-14801 - Operation failed innodb.innodb_max_recordsize_64k : MDEV-15203 - Wrong result innodb.innodb_monitor : MDEV-10939 - Testcase timeout innodb.innodb_mysql : MDEV-19873 - Wrong result innodb.innodb_prefix_index_restart_server : MDEV-20213 - Server crash +innodb.innodb_scrub : Added in 10.5.4 innodb.innodb_simulate_comp_failures_small : MDEV-20526 - ASAN use-after-poison innodb.innodb_stats : MDEV-10682 - wrong result innodb.innodb_stats_persistent : MDEV-17745 - Wrong result; MDEV-21567 - Wrong result in execution plan innodb.innodb_stats_persistent_debug : MDEV-14801 - Operation failed -innodb.innodb_sys_semaphore_waits : MDEV-10331 - Semaphore wait; modified in 10.4.12 +innodb.innodb_sys_semaphore_waits : MDEV-10331 - Semaphore wait innodb.innodb_sys_var_valgrind : Added in 10.4.13 -innodb.innodb_wl6326 : Added in 10.4.12 -innodb.innodb_wl6326_big : Added in 10.4.12 innodb.innodb_zip_innochecksum2 : MDEV-13882 - Warning: difficult to find free blocks innodb.instant_alter : Modified in 10.4.13 innodb.instant_alter_bugs : Modified in 10.4.13 innodb.instant_alter_charset : Modified in 10.4.13 -innodb.instant_alter_debug : Modified in 10.4.13 +innodb.instant_alter_crash : MDEV-13830 - Assertion failure +innodb.instant_alter_debug : MDEV-22958 - Wrong result; modified in 10.5.4 innodb.instant_alter_extend : MDEV-20963 - Binary files differ innodb.instant_alter_index_rename : Modified in 10.4.13 +innodb.instant_alter_limit : Modified in 10.5.4 +innodb.leaf_page_corrupted_during_recovery : Modified in 10.5.4 innodb.log_corruption : MDEV-13251 - Wrong result innodb.log_data_file_size : MDEV-14204 - Server failed to start; MDEV-20648 - Assertion failure innodb.log_file : MDEV-20159 - Assertion failure @@ -513,24 +551,22 @@ innodb.purge_secondary : MDEV-15681 - Wrong result innodb.purge_thread_shutdown : MDEV-13792 - Wrong result innodb.read_only_recovery : MDEV-13886 - Server crash innodb.recovery_shutdown : MDEV-15671 - Checksum mismatch in datafile -innodb.redo_log_during_checkpoint : Modified in 10.4.12 innodb.row_format_redundant : MDEV-15192 - Trying to access missing tablespace -innodb.row_size_error_log_warnings_3 : Modified in 10.4.12 innodb.table_definition_cache_debug : MDEV-14206 - Extra warning innodb.table_flags : MDEV-13572 - Wrong result; MDEV-19374 - Server failed to start +innodb.temp_table_savepoint : Modified in 10.5.4 innodb.temporary_table : MDEV-13265 - Wrong result innodb.truncate_foreign : MDEV-22511 - Wrong error code innodb.truncate_inject : Modified in 10.2.31 innodb.undo_truncate : MDEV-17340 - Server hung; MDEV-20840 - Sporadic timeout innodb.undo_truncate_recover : MDEV-17679 - Server has gone away; MDEV-19200 - Shutdown fails innodb.update_time : MDEV-14804 - Wrong result -innodb.xa_recovery : MDEV-15279 - mysqld got exception -innodb.xa_recovery_debug : Added in 10.4.13 +innodb.xa_recovery : MDEV-15279 - mysqld got exception; modified in 10.5.4 +innodb.xa_recovery_debug : Modified in 10.5.4 #----------------------------------------------------------------------- -innodb_fts.concurrent_insert : Modified in 10.4.12 -innodb_fts.innodb_fts_misc : Modified in 10.4.13 +innodb_fts.innodb_fts_misc : MDEV-22955 - Extra warning; modified in 10.4.13 innodb_fts.innodb_fts_misc_debug : MDEV-14156 - Unexpected warning innodb_fts.innodb_fts_plugin : MDEV-13888 - Errors in server log innodb_fts.innodb_fts_stopword_charset : MDEV-13259 - Table crashed @@ -538,7 +574,6 @@ innodb_fts.misc_debug : Modified in 10.4.13 innodb_fts.misc_debug2 : Added in 10.4.13 innodb_fts.stopword : Added in 10.4.13 innodb_fts.sync : Modified in 10.4.13 -innodb_fts.sync_block : Modified in 10.4.12 innodb_fts.sync_ddl : MDEV-21568 - Errno: 2000; MDEV-18654 - Assertion failure #----------------------------------------------------------------------- @@ -553,22 +588,21 @@ innodb_gis.innodb_gis_rtree : MDEV-20213 - Server crash innodb_gis.point_big : Re-enabled in 10.4.13 innodb_gis.rtree_compress2 : MDEV-16269 - Wrong result innodb_gis.rtree_concurrent_srch : MDEV-15284 - Wrong result with embedded -innodb_gis.rtree_debug : Modified in 10.4.12 innodb_gis.rtree_multi_pk : Modified in 10.4.13 innodb_gis.rtree_purge : MDEV-15275 - Timeout innodb_gis.rtree_recovery : MDEV-15274 - Error on check -innodb_gis.rtree_rollback1 : Modified in 10.4.12 -innodb_gis.rtree_rollback2 : Modified in 10.4.12 innodb_gis.rtree_split : MDEV-14208 - Too many arguments; modified in 10.4.13 innodb_gis.rtree_undo : MDEV-14456 - Timeout in include file innodb_gis.types : MDEV-15679 - Table is marked as crashed #----------------------------------------------------------------------- -innodb_zip.cmp_per_index : MDEV-14490 - Table is marked as crashed; modified in 10.4.12 +innodb_zip.cmp_per_index : MDEV-14490 - Table is marked as crashed +innodb_zip.create_options : MDEV-21329 - Assertion failure innodb_zip.index_large_prefix_4k : MDEV-21679 - Row size too large innodb_zip.innochecksum : MDEV-14486 - Server failed to shut down innodb_zip.innochecksum_3 : MDEV-13279 - Extra warnings +innodb_zip.page_size : MDEV-14711 - Assertion failure innodb_zip.recover : MDEV-22512 - Server failed to restart innodb_zip.restart : MDEV-20213 - Server crash innodb_zip.wl5522_debug_zip : MDEV-11600 - Operating system error number 2; modified in 10.4.13 @@ -579,12 +613,17 @@ innodb_zip.wl6501_scale_1 : MDEV-13254 - Timeout, MDEV-14104 - Error 192 #----------------------------------------------------------------------- -maria.aria_pack_mdev14183 : Added in 10.4.12 -maria.icp : Include file modified in 10.4.13 -maria.insert_select : MDEV-12757 - Timeout -maria.insert_select-7314 : MDEV-16492 - Timeout -maria.maria : MDEV-14430 - Extra warning -maria.maria-no-logging : MDEV-20196 - Crash on shutdown or server can't start +maria.bulk_insert_crash : Added in 10.5.4 +maria.create : Modified in 10.5.4 +maria.icp : Include file modified in 10.4.13 +maria.insert_select : MDEV-12757 - Timeout +maria.insert_select-7314 : MDEV-16492 - Timeout +maria.lock : Modified in 10.5.4 +maria.maria : MDEV-14430 - Extra warning +maria.maria-connect : Modified in 10.5.4 +maria.maria-no-logging : MDEV-20196 - Crash on shutdown or server can't start +maria.rollback : Added in 10.5.4 +maria.transaction : Added in 10.5.4 #----------------------------------------------------------------------- @@ -599,17 +638,18 @@ mariabackup.huge_lsn : MDEV-15662 - Sequence num mariabackup.incremental_backup : MDEV-21222 - Memory allocation failure mariabackup.incremental_encrypted : MDEV-15667 - timeout mariabackup.incremental_rocksdb : MDEV-20954 - Cannot access the file -mariabackup.innodb_redo_log_overwrite : Added in 10.4.12 -mariabackup.innodb_xa_rollback : MDEV-22398 - Log sequence number is in the future; added in 10.4.13 +mariabackup.innodb_xa_rollback : Added in 10.4.13 mariabackup.log_checksum_mismatch : MDEV-16571 - Wrong result mariabackup.mdev-14447 : MDEV-15201 - Timeout +mariabackup.options_check : Added in 10.5.4 mariabackup.partial : MDEV-19298 - Assertion failure mariabackup.partial_exclude : MDEV-15270 - Error on exec; modified in 10.4.13 mariabackup.unencrypted_page_compressed : MDEV-18653 - Wrong error mariabackup.xb_compressed_encrypted : MDEV-14812 - Segmentation fault mariabackup.xb_file_key_management : MDEV-16571 - Wrong result +mariabackup.xb_fulltext_encrypted : Modified in 10.5.4 mariabackup.xb_page_compress : MDEV-14810 - status: 1, errno: 11 -mariabackup.xb_partition : MDEV-17584 - Crash upon shutdown +mariabackup.xb_partition : MDEV-17584 - Crash upon shutdown; modified in 10.5.4 mariabackup.xb_rocksdb : MDEV-17338 - Server hung on shutdown #----------------------------------------------------------------------- @@ -638,26 +678,16 @@ mroonga/wrapper.repair_table_no_index_file : MDEV-14807 - Wrong error message #----------------------------------------------------------------------- -multi_source.gtid : MDEV-14202 - Crash -multi_source.info_logs : MDEV-12629 - Valgrind, MDEV-10042 - wrong result; MDEV-21290 - Wrong result -multi_source.load_data : MDEV-21235 - Slave crash -multi_source.mdev-8874 : MDEV-19415 - AddressSanitizer: heap-use-after-free -multi_source.mdev-9544 : MDEV-19415 - AddressSanitizer: heap-use-after-free -multi_source.multisource : MDEV-10417 - Fails on Mips -multi_source.reset_slave : MDEV-10690 - Wrong result -multi_source.simple : MDEV-4633 - Wrong result -multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_heartbeats - -#----------------------------------------------------------------------- - -optimizer_unfixed_bugs.bug36981 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug40992 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug41996 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug42991 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug43249 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug43360 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug43448 : Modified in 10.4.12 -optimizer_unfixed_bugs.bug43617 : Modified in 10.4.12 +multi_source.gtid : MDEV-14202 - Crash +multi_source.info_logs : MDEV-12629 - Valgrind, MDEV-10042 - wrong result; MDEV-21290 - Wrong result +multi_source.load_data : MDEV-21235 - Slave crash +multi_source.mdev-8874 : MDEV-19415 - AddressSanitizer: heap-use-after-free +multi_source.mdev-9544 : MDEV-19415 - AddressSanitizer: heap-use-after-free +multi_source.multi_source_slave_alias_replica : MDEV-22957 - Wrong result +multi_source.multisource : MDEV-10417 - Fails on Mips +multi_source.reset_slave : MDEV-10690 - Wrong result +multi_source.simple : MDEV-4633 - Wrong result +multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_heartbeats #----------------------------------------------------------------------- @@ -665,19 +695,30 @@ oqgraph.social : MDEV-22280 - Timeout; MDEV-22280 - Timeout #----------------------------------------------------------------------- -parts.partition_alter1_1_2_innodb : MDEV-18655 - ASAN unknown crash -parts.partition_alter1_1_innodb : MDEV-18655 - ASAN unknown crash -parts.partition_alter1_2_innodb : MDEV-18655 - ASAN unknown crash -parts.partition_alter2_2_maria : MDEV-14364 - Lost connection to MySQL server during query -parts.partition_alter_instant : Added in 10.4.13 -parts.partition_auto_increment_archive : MDEV-16491 - Marked as crashed and should be repaired -parts.partition_auto_increment_maria : MDEV-14430 - Extra warning -parts.partition_basic_innodb : MDEV-20214 - ASAN error -parts.partition_debug : Modified in 10.4.12 -parts.partition_debug_innodb : MDEV-10891 - Can't create UNIX socket; MDEV-15095 - Table doesn't exist; modified in 10.4.12 -parts.partition_exch_qa_10 : MDEV-11765 - wrong result -parts.partition_innodb_status_file : MDEV-12901 - Valgrind -parts.partition_special_innodb : MDEV-16942 - Timeout; modified in 10.4.13 +parts.alter_table : Added in 10.5.4 +parts.debug_innodb_crash : Added in 10.5.4 +parts.debug_innodb_fail : Added in 10.5.4 +parts.debug_myisam_crash : Include file modified in 10.5.4 +parts.debug_myisam_fail : Added in 10.5.4 +parts.longname : Modified in 10.5.4 +parts.partition_alter1_1_2_innodb : MDEV-18655 - ASAN unknown crash +parts.partition_alter1_1_innodb : MDEV-18655 - ASAN unknown crash +parts.partition_alter1_2_innodb : MDEV-18655 - ASAN unknown crash +parts.partition_alter2_2_maria : MDEV-14364 - Lost connection to MySQL server during query +parts.partition_alter_instant : Added in 10.4.13 +parts.partition_auto_increment_archive : MDEV-16491 - Marked as crashed and should be repaired; include file modified in 10.5.4 +parts.partition_auto_increment_blackhole : Include file modified in 10.5.4 +parts.partition_auto_increment_innodb : Include file modified in 10.5.4 +parts.partition_auto_increment_maria : MDEV-14430 - Extra warning; include file modified in 10.5.4 +parts.partition_auto_increment_memory : Include file modified in 10.5.4 +parts.partition_auto_increment_myisam : Include file modified in 10.5.4 +parts.partition_basic_innodb : MDEV-20214 - ASAN error +parts.partition_debug_innodb : MDEV-10891 - Can't create UNIX socket; MDEV-15095 - Table doesn't exist; modified in 10.5.4 +parts.partition_debug_myisam : Modified in 10.5.4 +parts.partition_exch_qa_10 : MDEV-11765 - wrong result +parts.partition_innodb_status_file : MDEV-12901 - Valgrind +parts.partition_special_innodb : MDEV-16942 - Timeout; modified in 10.4.13 +parts.percona_nonflushing_analyze_debug : Added in 10.5.4 #----------------------------------------------------------------------- @@ -685,65 +726,43 @@ percona.* : MDEV-10997 - Not maintained #----------------------------------------------------------------------- -perfschema.bad_option_1 : MDEV-21571 - Crash on bootstrap -perfschema.connect_attrs : MDEV-17283 - Wrong result -perfschema.dml_file_instances : MDEV-15179 - Wrong result -perfschema.dml_threads : MDEV-17746 - Wrong errno -perfschema.func_file_io : MDEV-5708 - fails for s390x -perfschema.func_mutex : MDEV-5708 - fails for s390x -perfschema.hostcache_ipv4_addrinfo_again_allow : MDEV-12759 - Crash; modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_again_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_bad_allow : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_bad_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_good_allow : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_good_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_noname_allow : Modified in 10.4.12 -perfschema.hostcache_ipv4_addrinfo_noname_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_auth_plugin : Modified in 10.4.12 -perfschema.hostcache_ipv4_blocked : Modified in 10.4.12 -perfschema.hostcache_ipv4_format : Modified in 10.4.12 -perfschema.hostcache_ipv4_max_con : Modified in 10.4.12 -perfschema.hostcache_ipv4_nameinfo_again_allow : Modified in 10.4.12 -perfschema.hostcache_ipv4_nameinfo_again_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_nameinfo_noname_allow : Modified in 10.4.12 -perfschema.hostcache_ipv4_nameinfo_noname_deny : Modified in 10.4.12 -perfschema.hostcache_ipv4_passwd : Modified in 10.4.12 -perfschema.hostcache_ipv4_ssl : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_again_allow : MDEV-12752 - Crash; modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_again_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_bad_allow : MDEV-13260 - Crash; modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_bad_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_good_allow : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_good_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_noname_allow : Modified in 10.4.12 -perfschema.hostcache_ipv6_addrinfo_noname_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_auth_plugin : Modified in 10.4.12 -perfschema.hostcache_ipv6_blocked : Modified in 10.4.12 -perfschema.hostcache_ipv6_max_con : Modified in 10.4.12 -perfschema.hostcache_ipv6_nameinfo_again_allow : Modified in 10.4.12 -perfschema.hostcache_ipv6_nameinfo_again_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_nameinfo_noname_allow : Modified in 10.4.12 -perfschema.hostcache_ipv6_nameinfo_noname_deny : Modified in 10.4.12 -perfschema.hostcache_ipv6_passwd : Modified in 10.4.12 -perfschema.hostcache_ipv6_ssl : MDEV-10696 - Crash; modified in 10.4.12 -perfschema.hostcache_peer_addr : MDEV-21462 - Test condition timeout; modified in 10.4.12 -perfschema.pfs_upgrade_event : MDEV-20957 - Wrong result -perfschema.pfs_upgrade_func : MDEV-20957 - Upgrade file was not properly created -perfschema.pfs_upgrade_proc : MDEV-20533 - Upgrade file was not properly created -perfschema.pfs_upgrade_table : MDEV-20533 - Exec failed -perfschema.pfs_upgrade_view : MDEV-20533 - Upgrade file was not properly created -perfschema.privilege_table_io : MDEV-13184 - Extra lines -perfschema.relaylog : MDEV-18134 - Wrong result -perfschema.rpl_gtid_func : MDEV-16897 - Wrong result -perfschema.socket_instances_func : MDEV-20140 - Wrong result -perfschema.socket_summary_by_event_name_func : MDEV-10622 - Wrong result -perfschema.socket_summary_by_instance_func : MDEV-19413 - Wrong result -perfschema.stage_mdl_function : MDEV-20157 - Wrong result -perfschema.stage_mdl_global : MDEV-11803 - wrong result on slow builders -perfschema.stage_mdl_procedure : MDEV-11545 - Missing row -perfschema.stage_mdl_table : MDEV-12638 - Wrong result -perfschema.start_server_low_digest : MDEV-21221 - Wrong result -perfschema.threads_mysql : MDEV-10677 - Wrong result +perfschema.bad_option_1 : MDEV-21571 - Crash on bootstrap +perfschema.connect_attrs : MDEV-17283 - Wrong result +perfschema.dml_file_instances : MDEV-15179 - Wrong result +perfschema.dml_threads : MDEV-17746 - Wrong errno +perfschema.func_file_io : MDEV-5708 - fails for s390x +perfschema.func_mutex : MDEV-5708 - fails for s390x +perfschema.grant : Added in 10.5.4 +perfschema.hostcache_ipv4_addrinfo_again_allow : MDEV-12759 - Crash +perfschema.hostcache_ipv6_addrinfo_again_allow : MDEV-12752 - Crash +perfschema.hostcache_ipv6_addrinfo_bad_allow : MDEV-13260 - Crash +perfschema.hostcache_ipv6_ssl : MDEV-10696 - Crash +perfschema.memory_aggregate_no_a_no_h : MDEV-22949 - Wrong result +perfschema.memory_aggregate_no_a_no_u : MDEV-22949 - Wrong result; MDEV-22949 - Wrong result +perfschema.no_threads : Modified in 10.5.4 +perfschema.one_thread_per_con : Modified in 10.5.4 +perfschema.pfs_upgrade_event : MDEV-20957 - Wrong result +perfschema.pfs_upgrade_func : MDEV-20957 - Upgrade file was not properly created +perfschema.pfs_upgrade_proc : MDEV-20533 - Upgrade file was not properly created +perfschema.pfs_upgrade_table : MDEV-20533 - Exec failed +perfschema.pfs_upgrade_view : MDEV-20533 - Upgrade file was not properly created +perfschema.privilege_table_io : MDEV-13184 - Extra lines +perfschema.relaylog : MDEV-18134 - Wrong result +perfschema.rpl_gtid_func : MDEV-16897 - Wrong result +perfschema.show_aggregate : MDEV-22962 - Wrong results +perfschema.show_sanity : Modified in 10.5.4 +perfschema.socket_instances_func : MDEV-20140 - Wrong result +perfschema.socket_summary_by_event_name_func : MDEV-10622 - Wrong result +perfschema.socket_summary_by_instance_func : MDEV-19413 - Wrong result +perfschema.stage_mdl_function : MDEV-20157 - Wrong result +perfschema.stage_mdl_global : MDEV-11803 - wrong result on slow builders +perfschema.stage_mdl_procedure : MDEV-11545 - Missing row +perfschema.stage_mdl_table : MDEV-12638 - Wrong result +perfschema.start_server_low_digest : MDEV-21221 - Wrong result +perfschema.thread_cache : Modified in 10.5.4 +perfschema.threads_history : MDEV-22948 - Wrong result +perfschema.threads_mysql : MDEV-10677 - Wrong result +perfschema.transaction_nested_events : Modified in 10.5.4 #----------------------------------------------------------------------- @@ -752,8 +771,10 @@ perfschema_stress.* : MDEV-10996 - Not maintained #----------------------------------------------------------------------- period.alter : Modified in 10.4.13 +period.engines : Combinations modified in 10.5.4 +period.overlaps : Modified in 10.5.4 period.update : Modified in 10.4.13 -period.versioning : MDEV-20159 - Assertion failure +period.versioning : MDEV-20159 - Assertion failure; include file modified in 10.5.4 #----------------------------------------------------------------------- @@ -800,8 +821,9 @@ rocksdb_sys_vars.rocksdb_rate_limiter_bytes_per_sec_basic : MDEV-16639 - Crash #----------------------------------------------------------------------- -roles.create_and_grant_role : MDEV-11772 - wrong result -roles.grant_revoke_current : Modified in 10.4.13 +roles.create_and_grant_role : MDEV-11772 - wrong result +roles.grant_revoke_current : Modified in 10.4.13 +roles.set_default_role_invalid : Modified in 10.5.4 #----------------------------------------------------------------------- @@ -810,7 +832,6 @@ rpl.create_or_replace2 : MDEV-19412 - Lost connection to MySQL s rpl.create_or_replace_mix : MDEV-20523 - Wrong result rpl.create_or_replace_statement : MDEV-20523 - Wrong result rpl.create_select : MDEV-14121 - Assertion failure -rpl.kill_race_condition : Modified in 10.4.12 rpl.last_insert_id : MDEV-10625 - warnings in error log rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips @@ -818,8 +839,6 @@ rpl.rpl_auto_increment_update_failure : MDEV-10625 - warnings in error log rpl.rpl_binlog_errors : MDEV-12742 - Crash; include file modified in 10.4.13 rpl.rpl_binlog_grant : MDEV-21274 - Lost connection at handshake rpl.rpl_binlog_index : MDEV-9501 - Failed registering on master -rpl.rpl_binlog_rollback_cleanup : Added in 10.4.12 -rpl.rpl_bug33931 : Modified in 10.4.12 rpl.rpl_bug41902 : Configuration deleted in 10.4.13 rpl.rpl_cant_read_event_incident : MDEV-20960 - Abort on shutdown rpl.rpl_checksum : Include file modified in 10.2.31 @@ -833,13 +852,13 @@ rpl.rpl_ctype_latin1 : MDEV-14813 - Wrong result on Mac rpl.rpl_ddl : MDEV-10417 - Fails on Mips rpl.rpl_domain_id_filter : MDEV-20213 - Server crash rpl.rpl_domain_id_filter_io_crash : MDEV-12729 - Timeout in include file, MDEV-13677 - Server crash; modified in 10.4.13 -rpl.rpl_domain_id_filter_master_crash : MDEV-19043 - Table marked as crashed; modified in 10.4.12 +rpl.rpl_domain_id_filter_master_crash : MDEV-19043 - Table marked as crashed rpl.rpl_domain_id_filter_restart : MDEV-10684 - Wrong result; MDEV-19043 - Table marked as crashed rpl.rpl_drop_db_fail : MDEV-16898 - Slave fails to start rpl.rpl_dual_pos_advance : MDEV-20213 - Server crash rpl.rpl_extra_col_master_innodb : MDEV-16570 - Extra warning rpl.rpl_extra_col_master_myisam : MDEV-14203 - Extra warning -rpl.rpl_fail_register : MDEV-22472 - Wrong result; added in 10.4.13 +rpl.rpl_fail_register : Modified in 10.5.4 rpl.rpl_flushlog_loop : MDEV-21570 - Server crash rpl.rpl_get_lock : MDEV-19368 - mysqltest failed but provided no output rpl.rpl_get_master_version_and_clock : Re-enabled in 10.4.13; include file modified in 10.4.13 @@ -848,13 +867,12 @@ rpl.rpl_gtid_crash : MDEV-9501 - Failed registering on maste rpl.rpl_gtid_delete_domain : MDEV-14463 - Timeout rpl.rpl_gtid_errorhandling : MDEV-13261 - Crash rpl.rpl_gtid_mdev9033 : MDEV-10680 - warnings -rpl.rpl_gtid_reconnect : MDEV-14497 - Crash; modified in 10.4.12 +rpl.rpl_gtid_reconnect : MDEV-14497 - Crash rpl.rpl_gtid_startpos : MDEV-20141 - mysqltest failed but provided no output rpl.rpl_gtid_stop_start : MDEV-10629 - Crash on shutdown, MDEV-12629 - Valgrind warnings rpl.rpl_gtid_strict : Modified in 10.4.13 rpl.rpl_gtid_until : MDEV-10625 - warnings in error log rpl.rpl_heartbeat : MDEV-20213 - Server crash -rpl.rpl_heartbeat_debug : Modified in 10.4.12 rpl.rpl_ignore_grant : MDEV-20159 - Assertion failure rpl.rpl_ignore_table : Modified in 10.4.13 rpl.rpl_ignore_table_update : MDEV-20159 - Assertion failure @@ -868,20 +886,24 @@ rpl.rpl_insert_id_pk : MDEV-16567 - Assertion failure rpl.rpl_insert_ignore : MDEV-14365 - Lost connection to MySQL server during query rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips rpl.rpl_ipv4_as_ipv6 : MDEV-20147 - Incorrect checksum for freed object +rpl.rpl_known_bugs_detection : MDEV-20213 - Server crash rpl.rpl_lcase_tblnames_rewrite_db : MDEV-20213 - Server crash -rpl.rpl_mariadb_slave_capability : MDEV-11018 - Extra lines in binlog; modified in 10.4.12 +rpl.rpl_mariadb_slave_capability : MDEV-11018 - Extra lines in binlog +rpl.rpl_mdev-11092 : MDEV-20213 - Server crash rpl.rpl_mdev12179 : MDEV-19043 - Table marked as crashed rpl.rpl_mdev6020 : MDEV-15272 - Server crash rpl.rpl_mixed_mixing_engines : MDEV-21266 - Timeout rpl.rpl_non_direct_row_mixing_engines : MDEV-16561 - Timeout in master_pos_wait +rpl.rpl_old_master : MDEV-22956 - Assertion failure rpl.rpl_parallel : MDEV-10653 - Timeouts rpl.rpl_parallel2 : MDEV-17390 - Operation cannot be performed rpl.rpl_parallel_conflicts : MDEV-15272 - Server crash rpl.rpl_parallel_mdev6589 : MDEV-12979 - Assertion failure rpl.rpl_parallel_multilevel : MDEV-20160 - Server crash rpl.rpl_parallel_multilevel2 : MDEV-14723 - Timeout -rpl.rpl_parallel_optimistic : MDEV-15278 - Failed to sync with master; modified in 10.4.12 +rpl.rpl_parallel_optimistic : MDEV-15278 - Failed to sync with master rpl.rpl_parallel_optimistic_nobinlog : MDEV-15278 - Failed to sync with master +rpl.rpl_parallel_optimistic_until : Added in 10.5.4 rpl.rpl_parallel_retry : MDEV-11119 - Crash; MDEV-17109 - Timeout rpl.rpl_parallel_temptable : MDEV-10356 - Crash; MDEV-19076 - Wrong result rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips @@ -892,22 +914,19 @@ rpl.rpl_relayrotate : MDEV-20213 - Server crash rpl.rpl_row_001 : MDEV-16653 - MTR's internal check fails rpl.rpl_row_basic_11bugs : MDEV-12171 - Server failed to start rpl.rpl_row_basic_2myisam : MDEV-13875 - command "diff_files" failed -rpl.rpl_row_big_table_id : Modified in 10.4.12 rpl.rpl_row_corruption : MDEV-21569 - mutex: LOCK_global_system_variables unlocking; modified in 10.4.13 rpl.rpl_row_drop_create_temp_table : MDEV-14487 - Wrong result rpl.rpl_row_end_of_statement_loss : MDEV-21237 - Server crash -rpl.rpl_row_find_row_debug : Modified in 10.4.12 rpl.rpl_row_img_blobs : MDEV-13875 - command "diff_files" failed rpl.rpl_row_img_eng_min : MDEV-13875 - diff_files failed rpl.rpl_row_img_eng_noblob : MDEV-13875 - command "diff_files" failed -rpl.rpl_row_index_choice : MDEV-15196 - Slave crash; modified in 10.4.12 +rpl.rpl_row_index_choice : MDEV-15196 - Slave crash rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_row_until : MDEV-14052 - Master will not send events with checksum rpl.rpl_semi_sync : MDEV-11220 - Wrong result rpl.rpl_semi_sync_after_sync : MDEV-14366 - Wrong result rpl.rpl_semi_sync_after_sync_row : MDEV-14366 - Wrong result rpl.rpl_semi_sync_event_after_sync : MDEV-11806 - warnings -rpl.rpl_semi_sync_skip_repl : Modified in 10.4.12 rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Assorted failures rpl.rpl_semi_sync_wait_no_slave : MDEV-20159 - Assertion failure rpl.rpl_semi_sync_wait_point : MDEV-11807 - timeout in wait condition @@ -915,23 +934,19 @@ rpl.rpl_semisync_ali_issues : MDEV-16272 - Wrong result rpl.rpl_set_null_myisam : MDEV-20213 - Server crash rpl.rpl_set_statement_default_master : MDEV-13258 - Extra warning rpl.rpl_show_slave_hosts : MDEV-10681 - Crash -rpl.rpl_show_slave_running : Modified in 10.4.12 rpl.rpl_shutdown_wait_semisync_slaves : MDEV-20213 - Server crash rpl.rpl_shutdown_wait_slaves : MDEV-22517 - Timeout on sync_with_master rpl.rpl_skip_replication : MDEV-13258 - Extra warning +rpl.rpl_slave_alias_replica : MDEV-22951 - Wrong result rpl.rpl_slave_grp_exec : MDEV-10514 - Deadlock rpl.rpl_slave_load_in : MDEV-20159 - Assertion failure -rpl.rpl_slave_load_remove_tmpfile : Modified in 10.4.12 rpl.rpl_slave_load_tmpdir_not_exist : MDEV-14203 - Extra warning -rpl.rpl_slave_shutdown_mdev20821 : Added in 10.4.12 rpl.rpl_slow_query_log : MDEV-13250 - Test abort rpl.rpl_sp_effects : MDEV-13249 - Crash rpl.rpl_start_stop_slave : MDEV-13567 - Sync slave timeout -rpl.rpl_stm_lcase_tblnames : Modified in 10.4.12 rpl.rpl_stm_multi_query : MDEV-9501 - Failed registering on master rpl.rpl_stm_relay_ign_space : MDEV-14360 - Test assertion rpl.rpl_stm_stop_middle_group : MDEV-13791 - Server crash; include file modified in 10.4.13 -rpl.rpl_stop_slave : Modified in 10.4.12 rpl.rpl_sync : MDEV-13830 - Assertion failure rpl.rpl_temporal_mysql56_to_mariadb53 : MDEV-9501 - Failed registering on master rpl.rpl_temporary_error2 : MDEV-10634 - Wrong number of retries @@ -941,7 +956,6 @@ rpl.rpl_truncate_3innodb : MDEV-19454 - Syntax error rpl.rpl_upgrade_master_info : MDEV-16567 - Assertion failure rpl.rpl_user_variables : MDEV-20522 - Wrong result rpl.rpl_variables : MDEV-20150 - Server crash -rpl.rpl_view_debug : Modified in 10.4.12 rpl.sec_behind_master-5114 : MDEV-13878 - Wrong result rpl.show_status_stop_slave_race-7126 : MDEV-17438 - Timeout @@ -951,17 +965,28 @@ rpl/extra/rpl_tests.* : MDEV-10994 - Not maintained #----------------------------------------------------------------------- +s3.* : Engine enabled in 10.5.4 +s3.alter2 : Modified in 10.5.4 +s3.replication_mixed : Include file modified in 10.5.4 +s3.replication_partition : Modified in 10.5.4 +s3.replication_stmt : Include file modified in 10.5.4 + +#----------------------------------------------------------------------- + sphinx.* : MDEV-10986 - Tests have not been maintained sphinx.sphinx : MDEV-10986 - Sporadic failures sphinx.union-5539 : MDEV-10986 - Sporadic failures #----------------------------------------------------------------------- -spider.* : MDEV-9329, MDEV-18737 - tests are too memory-consuming -spider.basic_sql : MDEV-11186 - Internal check fails +spider.* : MDEV-9329, MDEV-18737 - tests are too memory-consuming; include files modified in 10.5.4 +spider.basic_sql : MDEV-11186 - Internal check fails +spider.slave_trx_isolation : Modified in 10.5.4 +spider.spider_wrapper_protocols : Added in 10.5.4 #----------------------------------------------------------------------- +spider/bg.* : Include fieles modified in 10.5.4 spider/bg.direct_aggregate : MDEV-7098 - Packets out of order spider/bg.direct_aggregate_part : MDEV-7098 - Trying to unlock mutex that wasn't locked spider/bg.ha : MDEV-9329 - failures on s390x @@ -974,10 +999,15 @@ spider/bg.vp_fixes : MDEV-9329 - Fails on Ubuntu/s390x #----------------------------------------------------------------------- +spider/bugfix.* : Include fieles modified in 10.5.4 +spider/bugfix.insert_select : Added in 10.5.4 spider/bugfix.mdev_20502 : Added in 10.4.13 spider/bugfix.mdev_21884 : Added in 10.4.13 spider/bugfix.return_found_rows_insert : Modified in 10.4.13 spider/bugfix.return_found_rows_update : Modified in 10.4.13 +spider/bugfix.self_reference : Added in 10.5.4 +spider/bugfix.slave_trx_isolation : Modified in 10.5.4 +spider/bugfix.strict_group_by : Added in 10.5.4 #----------------------------------------------------------------------- @@ -985,7 +1015,9 @@ spider/handler.* : MDEV-10987, MDEV-10990 - Tests have not been maintained #----------------------------------------------------------------------- +sql_sequence.alter : Modified in 10.5.4 sql_sequence.concurrent_create : MDEV-16635 - Server crash +sql_sequence.create : Modified in 10.5.4 sql_sequence.rebuild : Modified in 10.4.13 #----------------------------------------------------------------------- @@ -994,24 +1026,35 @@ storage_engine.* : Tests are not always timely maintained #----------------------------------------------------------------------- +stress.* : Added to the main set in 10.5.4 stress.ddl_innodb : MDEV-10635 - Testcase timeout +stress.misc : Added in 10.5.4 #----------------------------------------------------------------------- +sys_vars.all_vars : Modified in 10.5.4 sys_vars.alter_algorithm_basic : Added in 10.4.13 sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x -sys_vars.debug_dbug_func : Modified in 10.4.12 sys_vars.host_cache_size_auto : MDEV-20112 - Wrong result sys_vars.innodb_buffer_pool_dump_at_shutdown_basic : MDEV-14280 - Unexpected error -sys_vars.innodb_buffer_pool_size_basic : Modified in 10.4.12 sys_vars.innodb_checksum_algorithm_basic : MDEV-21568 - Errno: 2000 +sys_vars.innodb_fatal_semaphore_wait_threshold : MDEV-22961 - Server failed to dissapear sys_vars.innodb_instant_alter_column_allowed_basic : Added in 10.4.13 sys_vars.keep_files_on_create_basic : MDEV-10676 - timeout sys_vars.log_slow_admin_statements_func : MDEV-12235 - Server crash +sys_vars.max_sort_length_basic : Modified in 10.5.4 sys_vars.rpl_init_slave_func : MDEV-10149 - Test assertion sys_vars.slow_query_log_func : MDEV-14273 - Wrong result sys_vars.thread_cache_size_func : MDEV-11775 - Wrong result -sys_vars.wait_timeout_func : MDEV-12896 - Wrong result +sys_vars.thread_pool_size_basic : Modified in 10.5.4 +sys_vars.wait_timeout_func : MDEV-12896 - Wrong result; modified in 10.5.4 +tokudb_parts.partition_auto_increment_tokudb : Include file modified in 10.5.4 +tokudb_parts.partition_debug_tokudb : Include file modified in 10.5.4 + +#----------------------------------------------------------------------- + +type_inet.type_inet6 : Modified in 10.5.4 +type_inet.type_inet6_stat_tables : Modified in 10.5.4 #----------------------------------------------------------------------- @@ -1029,30 +1072,39 @@ unit.mf_iocache : MDEV-20952 - ASAN stack-buffer-overflow vcol.not_supported : MDEV-10639 - Testcase timeout vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout -vcol.vcol_misc : MDEV-16651 - Wrong error message +vcol.vcol_keys_myisam : Modified in 10.5.4 +vcol.vcol_misc : MDEV-16651 - Wrong error message; modified in 10.5.4 #----------------------------------------------------------------------- -versioning.alter : Modified in 10.4.13 -versioning.partition : Modified in 10.4.13 -versioning.sysvars : Modified in 10.4.13 -versioning.update : MDEV-22475 - Wrong result code; modified in 10.4.13 +versioning.alter : Include file modified in 10.5.4 +versioning.auto_increment : Include file modified in 10.5.4 +versioning.commit_id : Include file modified in 10.5.4 +versioning.create : Include file modified in 10.5.4 +versioning.delete : Include file modified in 10.5.4 +versioning.delete_history : Include file modified in 10.5.4 +versioning.engines : Combinations modified in 10.5.4 +versioning.foreign : Include file modified in 10.5.4 +versioning.insert : Include file modified in 10.5.4 +versioning.online : Include file modified in 10.5.4 +versioning.partition : Modified in 10.5.4 +versioning.replace : MDEV-22960 - OS errors, crash; include file modified in 10.5.4 +versioning.select : Modified in 10.5.4 +versioning.select2 : Modified in 10.5.4 +versioning.sysvars : Modified in 10.5.4 +versioning.update : MDEV-22475 - Wrong result code; include file modified in 10.5.4 +versioning.update-big : Include file modified in 10.5.4 +versioning.view : Modified in 10.5.4 #----------------------------------------------------------------------- -wsrep.* : suite.pm modified in 10.4.13 -wsrep.MDEV-20625 : Added in 10.4.13 -wsrep.alter_table_innodb : Configuration deleted in 10.4.12 -wsrep.binlog_format : Configuration added in 10.4.12 -wsrep.foreign_key : MDEV-14725 - WSREP has not yet prepared node -wsrep.mdev_10186 : Configuration modified in 10.4.12 -wsrep.mdev_6832 : MDEV-14195 - Check testcase failed -wsrep.mysql_tzinfo_to_sql_symlink : Modified in 10.4.12 -wsrep.mysql_tzinfo_to_sql_symlink_skip : Modified in 10.4.12 -wsrep.plugin : Modified in 10.4.12 -wsrep.pool_of_threads : MDEV-17345 - WSREP has not yet prepared node for application use; re-enabled in 10.4.12 -wsrep.trans : Modified in 10.4.13 -wsrep.variables : MDEV-17585 - Deadlock; modified in 10.4.12 +wsrep.* : suite.pm modified in 10.4.13 +wsrep.MDEV-20625 : Added in 10.4.13 +wsrep.foreign_key : MDEV-14725 - WSREP has not yet prepared node +wsrep.mdev_6832 : MDEV-14195 - Check testcase failed +wsrep.pool_of_threads : MDEV-17345 - WSREP has not yet prepared node for application use +wsrep.trans : Modified in 10.4.13 +wsrep.variables : MDEV-17585 - Deadlock #----------------------------------------------------------------------- diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 9ebf1bd04af..fc6d2e7ec86 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -750,45 +750,6 @@ # Note the wildcard in the (mangled) function signatures of # write_keys() and find_all_keys(). # They both return ha_rows, which is platform dependent. -# -# The '...' wildcards are for 'fun:inline_mysql_file_write' and -# 'fun:find_all_keys' which *may* be inlined. -{ - Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / one - Memcheck:Param - write(buf) - obj:*/libpthread*.so - fun:my_write - ... - fun:my_b_flush_io_cache - fun:_my_b_write - fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_ - ... - fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy -} - -{ - Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / two - Memcheck:Param - write(buf) - obj:*/libpthread*.so - fun:my_write - ... - fun:my_b_flush_io_cache - fun:_Z15merge_many_buffP13st_sort_paramPhP10st_buffpekPjP11st_io_cache - fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy -} - -{ - Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / three - Memcheck:Param - write(buf) - obj:*/libpthread*.so - fun:my_write - ... - fun:my_b_flush_io_cache - fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy -} { OpenSSL still reachable. diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index ef159748092..3d8a20e4f9a 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -58,6 +58,59 @@ IF (WIN32) my_win_popen.cc) ENDIF() +IF(NOT MSVC AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") + #Check for PCLMUL instruction (x86) + CHECK_C_SOURCE_COMPILES(" + int main() + { + asm volatile (\"pclmulqdq \\$0x00, %%xmm1, %%xmm0\":::\"cc\"); + return 0; + }" HAVE_CLMUL_INSTRUCTION) + + IF(HAVE_CLMUL_INSTRUCTION) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_x86.c) + ENDIF() +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64") + IF(CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) + include(CheckCXXSourceCompiles) + + CHECK_CXX_SOURCE_COMPILES(" + #define CRC32CX(crc, value) __asm__(\"crc32cx %w[c], %w[c], %x[v]\":[c]\"+r\"(crc):[v]\"r\"(value)) + asm(\".arch_extension crc\"); + unsigned int foo(unsigned int ret) { + CRC32CX(ret, 0); + return ret; + } + #include + int main() { foo(0); getauxval(AT_HWCAP); }" HAVE_ARMV8_CRC) + + CHECK_CXX_SOURCE_COMPILES(" + asm(\".arch_extension crypto\"); + unsigned int foo(unsigned int ret) { + __asm__(\"pmull v2.1q, v2.1d, v1.1d\"); + return ret; + } + int main() { foo(0); }" HAVE_ARMV8_CRYPTO) + + CHECK_C_COMPILER_FLAG(-march=armv8-a+crc+crypto HAVE_ARMV8_CRC_CRYPTO_INTRINSICS) + IF(HAVE_ARMV8_CRC_CRYPTO_INTRINSICS) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_arm64.c) + SET_SOURCE_FILES_PROPERTIES(crc32/crc32_arm64.c PROPERTIES + COMPILE_FLAGS "-march=armv8-a+crc+crypto") + ENDIF() + ENDIF() +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64") + SET(HAVE_CRC32_VPMSUM 1 PARENT_SCOPE) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} $ $) + + ADD_LIBRARY(crc32c OBJECT crc32/crc32_ppc64.c) + ADD_LIBRARY(crc32ieee OBJECT crc32/crc32_ppc64.c) + + SET_TARGET_PROPERTIES(crc32c crc32ieee PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -maltivec -mvsx -mpower8-vector -mcrypto -mpower8-vector") + SET_TARGET_PROPERTIES(crc32ieee PROPERTIES COMPILE_DEFINITIONS "CRC32_FUNCTION=my_checksum;CRC32_CONSTANTS_HEADER=\"pcc_crc32_constants.h\"") + SET_TARGET_PROPERTIES(crc32c PROPERTIES COMPILE_DEFINITIONS "CRC32_FUNCTION=crc32c_vpmsum;CRC32_CONSTANTS_HEADER=\"pcc_crc32c_constants.h\"") +ENDIF() + IF(UNIX) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c my_setuser.c) ENDIF() @@ -73,7 +126,7 @@ ENDIF() ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) MAYBE_DISABLE_IPO(mysys) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY} - ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO} ${CRC32_LIBRARY}) + ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO}) DTRACE_INSTRUMENT(mysys) IF(HAVE_BFD_H) diff --git a/mysys/checksum.c b/mysys/checksum.c index 91e681d0db4..948b9be6164 100644 --- a/mysys/checksum.c +++ b/mysys/checksum.c @@ -18,25 +18,41 @@ #include #include -/* - Calculate a long checksum for a memoryblock. - - SYNOPSIS - my_checksum() - crc start value for crc - pos pointer to memory block - length length of the block -*/ - -ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) +#if !defined(HAVE_CRC32_VPMSUM) +/* TODO: remove this once zlib adds inherent support for hardware accelerated +crc32 for all architectures. */ +static unsigned int my_crc32_zlib(unsigned int crc, const void *data, + size_t len) { -#ifdef HAVE_CRC32_VPMSUM - extern unsigned int crc32ieee_vpmsum(unsigned int crc, const unsigned char *p, - unsigned long len); - crc= (ha_checksum) crc32ieee_vpmsum((uint) crc, pos, (uint) length); -#else - crc= (ha_checksum) crc32((uint)crc, pos, (uint) length); -#endif - DBUG_PRINT("info", ("crc: %lu", (ulong) crc)); - return crc; + return (unsigned int) crc32(crc, data, (unsigned int) len); } + +my_crc32_t my_checksum= my_crc32_zlib; +#endif + +#if __GNUC__ >= 4 && defined(__x86_64__) + +extern int crc32_pclmul_enabled(); +extern unsigned int crc32_pclmul(unsigned int, const void *, size_t); + +/*----------------------------- x86_64 ---------------------------------*/ +void my_checksum_init(void) +{ + if (crc32_pclmul_enabled()) + my_checksum= crc32_pclmul; +} +#elif defined(__GNUC__) && defined(HAVE_ARMV8_CRC) +/*----------------------------- aarch64 --------------------------------*/ + +extern unsigned int crc32_aarch64(unsigned int, const void *, size_t); + +/* Ideally all ARM 64 bit processor should support crc32 but if some model +doesn't support better to find it out through auxillary vector. */ +void my_checksum_init(void) +{ + if (crc32_aarch64_available()) + my_checksum= crc32_aarch64; +} +#else +void my_checksum_init(void) {} +#endif diff --git a/extra/crc32-vpmsum/clang_workaround.h b/mysys/crc32/clang_workaround.h similarity index 100% rename from extra/crc32-vpmsum/clang_workaround.h rename to mysys/crc32/clang_workaround.h diff --git a/extra/crc32_armv8_neon/crc32_armv8.c b/mysys/crc32/crc32_arm64.c similarity index 88% rename from extra/crc32_armv8_neon/crc32_armv8.c rename to mysys/crc32/crc32_arm64.c index 20f341552e2..09ac7a12a66 100644 --- a/extra/crc32_armv8_neon/crc32_armv8.c +++ b/mysys/crc32/crc32_arm64.c @@ -1,8 +1,8 @@ #include #include +#include - -#if defined(__GNUC__) && defined(__linux__) && defined(HAVE_ARMV8_CRC) +#if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) #include #include @@ -11,12 +11,13 @@ #define HWCAP_CRC32 (1 << 7) #endif -unsigned int crc32c_aarch64_available(void) +/* ARM made crc32 default from ARMv8.1 but optional in ARMv8A +so the runtime check. */ +int crc32_aarch64_available(void) { - unsigned long auxv = getauxval(AT_HWCAP); - return (auxv & HWCAP_CRC32) != 0; + unsigned long auxv= getauxval(AT_HWCAP); + return (auxv & HWCAP_CRC32) != 0; } - #endif #ifndef HAVE_ARMV8_CRC_CRYPTO_INTRINSICS @@ -299,3 +300,35 @@ uint32_t crc32c_aarch64(uint32_t crc, const unsigned char *buffer, uint64_t len) return (~crc); } + +/* There are multiple approaches to calculate crc. +Approach-1: Process 8 bytes then 4 bytes then 2 bytes and then 1 bytes +Approach-2: Process 8 bytes and remaining workload using 1 bytes +Apporach-3: Process 64 bytes at once by issuing 8 crc call and remaining + using 8/1 combination. + +Based on micro-benchmark testing we found that Approach-2 works best especially +given small chunk of variable data. */ +unsigned int crc32_aarch64(unsigned int crc, const void *buf, size_t len) +{ + const uint8_t *buf1= buf; + const uint64_t *buf8= (const uint64_t *) (((uintptr_t) buf + 7) & ~7); + + crc= ~crc; + + /* if start pointer is not 8 bytes aligned */ + while ((buf1 != (const uint8_t *) buf8) && len) + { + crc= __crc32b(crc, *buf1++); + len--; + } + + for (; len >= 8; len-= 8) + crc= __crc32d(crc, *buf8++); + + buf1= (const uint8_t *) buf8; + while (len--) + crc= __crc32b(crc, *buf1++); + + return ~crc; +} diff --git a/extra/crc32-vpmsum/vec_crc32.c b/mysys/crc32/crc32_ppc64.c similarity index 99% rename from extra/crc32-vpmsum/vec_crc32.c rename to mysys/crc32/crc32_ppc64.c index bb2204b247c..2e8b9fc1b12 100644 --- a/extra/crc32-vpmsum/vec_crc32.c +++ b/mysys/crc32/crc32_ppc64.c @@ -151,6 +151,7 @@ __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len) { 0xffffffffffffffffUL}; #ifdef REFLECT + __vector unsigned char vsht_splat; const __vector unsigned long long vmask_32bit = (__vector unsigned long long)vec_sld((__vector unsigned char)vzero, (__vector unsigned char)vones, 4); @@ -598,7 +599,7 @@ __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len) { #ifdef REFLECT /* shift left one bit */ - __vector unsigned char vsht_splat = vec_splat_u8 (1); + vsht_splat = vec_splat_u8 (1); v0 = (__vector unsigned long long)vec_sll ((__vector unsigned char)v0, vsht_splat); #endif diff --git a/extra/mariabackup/crc/crc-intel-pclmul.c b/mysys/crc32/crc32_x86.c similarity index 94% rename from extra/mariabackup/crc/crc-intel-pclmul.c rename to mysys/crc32/crc32_x86.c index 032802c1823..3f176a6c145 100644 --- a/extra/mariabackup/crc/crc-intel-pclmul.c +++ b/mysys/crc32/crc32_x86.c @@ -39,6 +39,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA * */ +#include + #include #include #include @@ -55,7 +57,7 @@ typedef uint8_t byte; # define _gcry_bswap32 __builtin_bswap32 -#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION) +#if __GNUC__ >= 4 && defined(__x86_64__) #if defined(_GCRY_GCC_VERSION) && _GCRY_GCC_VERSION >= 40400 /* 4.4 */ /* Prevent compiler from issuing SSE instructions between asm blocks. */ @@ -508,4 +510,36 @@ crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen) #endif } +#ifdef __GNUC__ +int crc32_pclmul_enabled(void) +{ + int eax, ecx; + /* We assume that the CPUID instruction and its parameter 1 are available. + We do not support any precursors of the Intel 80486. */ + asm("cpuid" : "=a"(eax), "=c"(ecx) : "0"(1) : "ebx", "edx"); + return !(~ecx & (1 << 19 | 1 << 1)); +} +#elif 0 /* defined _MSC_VER */ /* FIXME: implement the pclmul interface */ +#include +int crc32_pclmul_enabled(void) +{ + /* We assume that the CPUID instruction and its parameter 1 are available. + We do not support any precursors of the Intel 80486. */ + int regs[4]; + __cpuid(regs, 1); + return !(~regs[2] & (1 << 19 | 1 << 1)); +} +#else +int crc32_pclmul_enabled(void) +{ + return 0; +} +#endif + +unsigned int crc32_pclmul(unsigned int crc32, const void *buf, size_t len) +{ + crc32= ~crc32; + crc32_intel_pclmul(&crc32, buf, len); + return ~crc32; +} #endif diff --git a/extra/crc32-vpmsum/crc32ieee_constants.h b/mysys/crc32/pcc_crc32_constants.h similarity index 100% rename from extra/crc32-vpmsum/crc32ieee_constants.h rename to mysys/crc32/pcc_crc32_constants.h diff --git a/extra/crc32-vpmsum/crc32c_constants.h b/mysys/crc32/pcc_crc32c_constants.h similarity index 100% rename from extra/crc32-vpmsum/crc32c_constants.h rename to mysys/crc32/pcc_crc32c_constants.h diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index b3aa494a58c..2e34cef5d19 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -50,10 +50,6 @@ TODO: #include "mysys_priv.h" #include -#ifdef HAVE_AIOWAIT -#include "mysys_err.h" -static void my_aiowait(my_aio_result *result); -#endif #include #include "mysql/psi/mysql_file.h" @@ -295,16 +291,6 @@ int init_io_cache_ext(IO_CACHE *info, File file, size_t cachesize, info->error=0; info->type= type; init_functions(info); -#ifdef HAVE_AIOWAIT - if (use_async_io && ! my_disable_async_io) - { - DBUG_PRINT("info",("Using async io")); - DBUG_ASSERT(!(cache_myflags & MY_ENCRYPT)); - info->read_length/=2; - info->read_function=_my_b_async_read; - } - info->inited=info->aio_result.pending=0; -#endif DBUG_RETURN(0); } @@ -420,33 +406,6 @@ void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset) } } - /* Wait until current request is ready */ - -#ifdef HAVE_AIOWAIT -static void my_aiowait(my_aio_result *result) -{ - if (result->pending) - { - struct aio_result_t *tmp; - for (;;) - { - if ((int) (tmp=aiowait((struct timeval *) 0)) == -1) - { - if (errno == EINTR) - continue; - DBUG_PRINT("error",("No aio request, error: %d",errno)); - result->pending=0; /* Assume everything is ok */ - break; - } - ((my_aio_result*) tmp)->pending=0; - if ((my_aio_result*) tmp == result) - break; - } - } - return; -} -#endif - /* Use this to reset cache to re-start reading or to change the type @@ -499,9 +458,6 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->write_pos=pos; else info->read_pos= pos; -#ifdef HAVE_AIOWAIT - my_aiowait(&info->aio_result); /* Wait for outstanding req */ -#endif } else { @@ -515,8 +471,11 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, if (info->type == WRITE_CACHE) info->end_of_file= my_b_tell(info); else - info->end_of_file= mysql_file_seek(info->file, 0L, MY_SEEK_END, - MYF(0)); + { + if (!(info->myflags & MY_ENCRYPT)) + info->end_of_file= mysql_file_seek(info->file, 0L, + MY_SEEK_END, MYF(0)); + } } /* flush cache if we want to reuse it */ if (!clear_cache && my_b_flush_io_cache(info,1)) @@ -553,18 +512,6 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->type=type; info->error=0; init_functions(info); - -#ifdef HAVE_AIOWAIT - if (use_async_io && ! my_disable_async_io && - ((ulong) info->buffer_length < - (ulong) (info->end_of_file - seek_offset))) - { - DBUG_ASSERT(!(cache_myflags & MY_ENCRYPT)); - info->read_length=info->buffer_length/2; - info->read_function=_my_b_async_read; - } - info->inited=0; -#endif DBUG_RETURN(0); } /* reinit_io_cache */ @@ -1530,193 +1477,6 @@ read_append_buffer: } -#ifdef HAVE_AIOWAIT - -/* - Read from the IO_CACHE into a buffer and feed asynchronously - from disk when needed. - - SYNOPSIS - _my_b_async_read() - info IO_CACHE pointer - Buffer Buffer to retrieve count bytes from file - Count Number of bytes to read into Buffer - - RETURN VALUE - -1 An error has occurred; my_errno is set. - 0 Success - 1 An error has occurred; IO_CACHE to error state. -*/ - -int _my_b_async_read(IO_CACHE *info, uchar *Buffer, size_t Count) -{ - size_t length, read_length, diff_length, left_length=0, use_length, org_Count; - size_t max_length; - my_off_t next_pos_in_file; - uchar *read_buffer; - - org_Count=Count; - - if (info->inited) - { /* wait for read block */ - info->inited=0; /* No more block to read */ - my_aiowait(&info->aio_result); /* Wait for outstanding req */ - if (info->aio_result.result.aio_errno) - { - if (info->myflags & MY_WME) - my_error(EE_READ, MYF(ME_BELL), my_filename(info->file), - info->aio_result.result.aio_errno); - my_errno=info->aio_result.result.aio_errno; - info->error= -1; - return(1); - } - if (! (read_length= (size_t) info->aio_result.result.aio_return) || - read_length == (size_t) -1) - { - my_errno=0; /* For testing */ - info->error= (read_length == (size_t) -1 ? -1 : - (int) (read_length+left_length)); - return(1); - } - info->pos_in_file+= (size_t) (info->read_end - info->request_pos); - - if (info->request_pos != info->buffer) - info->request_pos=info->buffer; - else - info->request_pos=info->buffer+info->read_length; - info->read_pos=info->request_pos; - next_pos_in_file=info->aio_read_pos+read_length; - - /* Check if pos_in_file is changed - (_ni_read_cache may have skipped some bytes) */ - - if (info->aio_read_pos < info->pos_in_file) - { /* Fix if skipped bytes */ - if (info->aio_read_pos + read_length < info->pos_in_file) - { - read_length=0; /* Skip block */ - next_pos_in_file=info->pos_in_file; - } - else - { - my_off_t offset= (info->pos_in_file - info->aio_read_pos); - info->pos_in_file=info->aio_read_pos; /* Whe are here */ - info->read_pos=info->request_pos+offset; - read_length-=offset; /* Bytes left from read_pos */ - } - } -#ifndef DBUG_OFF - if (info->aio_read_pos > info->pos_in_file) - { - my_errno=EINVAL; - return(info->read_length= (size_t) -1); - } -#endif - /* Copy found bytes to buffer */ - length=MY_MIN(Count,read_length); - memcpy(Buffer,info->read_pos,(size_t) length); - Buffer+=length; - Count-=length; - left_length+=length; - info->read_end=info->rc_pos+read_length; - info->read_pos+=length; - } - else - next_pos_in_file=(info->pos_in_file+ (size_t) - (info->read_end - info->request_pos)); - - /* If reading large blocks, or first read or read with skip */ - if (Count) - { - if (next_pos_in_file == info->end_of_file) - { - info->error=(int) (read_length+left_length); - return 1; - } - - if (mysql_file_seek(info->file, next_pos_in_file, MY_SEEK_SET, MYF(0)) - == MY_FILEPOS_ERROR) - { - info->error= -1; - return (1); - } - - read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1)); - if (Count < read_length) - { /* Small block, read to cache */ - if ((read_length=mysql_file_read(info->file,info->request_pos, - read_length, info->myflags)) == (size_t) -1) - return info->error= -1; - use_length=MY_MIN(Count,read_length); - memcpy(Buffer,info->request_pos,(size_t) use_length); - info->read_pos=info->request_pos+Count; - info->read_end=info->request_pos+read_length; - info->pos_in_file=next_pos_in_file; /* Start of block in cache */ - next_pos_in_file+=read_length; - - if (Count != use_length) - { /* Didn't find hole block */ - if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count) - my_error(EE_EOFERR, MYF(ME_BELL), my_filename(info->file), my_errno); - info->error=(int) (read_length+left_length); - return 1; - } - } - else - { /* Big block, don't cache it */ - if ((read_length= mysql_file_read(info->file, Buffer, Count,info->myflags)) - != Count) - { - info->error= read_length == (size_t) -1 ? -1 : read_length+left_length; - return 1; - } - info->read_pos=info->read_end=info->request_pos; - info->pos_in_file=(next_pos_in_file+=Count); - } - } - - /* Read next block with asyncronic io */ - diff_length=(next_pos_in_file & (IO_SIZE-1)); - max_length= info->read_length - diff_length; - if (max_length > info->end_of_file - next_pos_in_file) - max_length= (size_t) (info->end_of_file - next_pos_in_file); - - if (info->request_pos != info->buffer) - read_buffer=info->buffer; - else - read_buffer=info->buffer+info->read_length; - info->aio_read_pos=next_pos_in_file; - if (max_length) - { - info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */ - DBUG_PRINT("aioread",("filepos: %ld length: %lu", - (ulong) next_pos_in_file, (ulong) max_length)); - if (aioread(info->file,read_buffer, max_length, - (my_off_t) next_pos_in_file,MY_SEEK_SET, - &info->aio_result.result)) - { /* Skip async io */ - my_errno=errno; - DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped", - errno, info->aio_result.result.aio_errno)); - if (info->request_pos != info->buffer) - { - bmove(info->buffer,info->request_pos, - (size_t) (info->read_end - info->read_pos)); - info->request_pos=info->buffer; - info->read_pos-=info->read_length; - info->read_end-=info->read_length; - } - info->read_length=info->buffer_length; /* Use hole buffer */ - info->read_function=_my_b_cache_read; /* Use normal IO_READ next */ - } - else - info->inited=info->aio_result.pending=1; - } - return 0; /* Block read, async in use */ -} /* _my_b_async_read */ -#endif - - /* Read one byte when buffer is empty */ int _my_b_get(IO_CACHE *info) @@ -1806,6 +1566,8 @@ int my_b_append(IO_CACHE *info, const uchar *Buffer, size_t Count) { size_t rest_length,length; + MEM_CHECK_DEFINED(Buffer, Count); + /* Assert that we cannot come here with a shared cache. If we do one day, we might need to add a call to copy_to_read_buffer(). @@ -1975,13 +1737,6 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) DBUG_RETURN(info->error); } } -#ifdef HAVE_AIOWAIT - else if (info->type != READ_NET) - { - my_aiowait(&info->aio_result); /* Wait for outstanding req */ - info->inited=0; - } -#endif UNLOCK_APPEND_BUFFER; DBUG_RETURN(0); } diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index b671d87a933..bf2bacd213c 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -248,7 +248,8 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); @@ -281,7 +282,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); @@ -310,8 +312,8 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) uint prefix_bytes, prefix_bits, d; uchar *m= (uchar *)map->bitmap; - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); set_if_smaller(prefix_size, map->n_bits); if ((prefix_bytes= prefix_size / 8)) memset(m, 0xff, prefix_bytes); @@ -333,7 +335,8 @@ my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) uchar *m= (uchar*) map->bitmap; uchar *end_prefix= m+(prefix_size-1)/8; uchar *end; - DBUG_ASSERT(m && prefix_size <= map->n_bits); + DBUG_ASSERT(m); + DBUG_ASSERT(prefix_size <= map->n_bits); /* Empty prefix is always true */ if (!prefix_size) @@ -386,8 +389,8 @@ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap && map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -405,8 +408,9 @@ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -424,7 +428,8 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; uint len= no_words_in_map(map), len2 = no_words_in_map(map2); - DBUG_ASSERT(map->bitmap && map2->bitmap); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); end= to+MY_MIN(len,len2); while (to < end) @@ -469,7 +474,8 @@ my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, uint i, j, start_idx, end_idx; my_bitmap_map cur_res; - DBUG_ASSERT(bitmap_count && end_bit >= start_bit); + DBUG_ASSERT(bitmap_count); + DBUG_ASSERT(end_bit >= start_bit); for (j= 0; j < bitmap_count; j++) DBUG_ASSERT(end_bit < bitmap_array[j]->n_bits); @@ -497,8 +503,9 @@ my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while ( m1 < end) if ((*m1++ | *m2++) != 0xFFFFFFFF) @@ -543,8 +550,9 @@ void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits==map2->n_bits); end= map->last_word_ptr; @@ -557,8 +565,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -569,8 +578,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); while (to <= end) *to++ ^= *from++; } @@ -607,8 +617,9 @@ void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -737,7 +748,8 @@ uint bitmap_lock_set_next(MY_BITMAP *map) void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) { bitmap_lock(map); - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } diff --git a/mysys/my_default.c b/mysys/my_default.c index 7eefa7aa044..c76ab8c6eb1 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -740,7 +740,7 @@ static int search_default_file_with_ext(struct handle_option_ctx *ctx, for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; end[0]=0; - strmake(curr_gr, ptr, MY_MIN((size_t) (end-ptr)+1, sizeof(curr_gr)-1)); + strmake(curr_gr, ptr, MY_MIN((size_t) (end-ptr), sizeof(curr_gr)-1)); found_group= find_type(curr_gr, ctx->group, FIND_TYPE_NO_PREFIX) ? PARSE : SKIP; continue; diff --git a/mysys/my_delete.c b/mysys/my_delete.c index a0210558dfd..3d80f187e19 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -43,9 +43,12 @@ int my_delete(const char *name, myf MyFlags) err= unlink(name); #endif - if(err) + if ((MyFlags & MY_IGNORE_ENOENT) && errno == ENOENT) + DBUG_RETURN(0); + + if (err) { - my_errno=errno; + my_errno= errno; if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_DELETE, MYF(ME_BELL), name, errno); } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 5576c8b5d5d..9747ee4214e 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2013, Oracle and/or its affiliates - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -79,6 +79,12 @@ my_bool my_getopt_skip_unknown= 0; */ my_bool my_getopt_prefix_matching= 1; +/* + This is a flag that can be set in client programs. 1 means that + handle_options() will not initialize options to default values. +*/ +my_bool my_handle_options_init_variables = 1; + my_getopt_value my_getopt_get_addr= 0; static void default_reporter(enum loglevel level, const char *format, ...) @@ -205,7 +211,8 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, DBUG_ASSERT(*argv); (*argc)--; /* Skip the program name */ (*argv)++; /* --- || ---- */ - init_variables(longopts, init_one_value); + if (my_handle_options_init_variables) + init_variables(longopts, init_one_value); is_cmdline_arg= !is_file_marker(**argv); diff --git a/mysys/my_init.c b/mysys/my_init.c index 4ae0cb9966c..cd9875017f0 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -59,7 +59,6 @@ static ulong atoi_octal(const char *str) MYSQL_FILE *mysql_stdin= NULL; static MYSQL_FILE instrumented_stdin; - /** Initialize my_sys functions, resources and variables @@ -101,6 +100,9 @@ my_bool my_init(void) /* Initialize our mutex handling */ my_mutex_init(); + /* Initialize CPU architecture specific hardware based crc32 optimization */ + my_checksum_init(); + if (my_thread_global_init()) return 1; diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index 32897087f9e..447d5c50a59 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -45,8 +45,6 @@ static my_bool my_use_large_pages= 0; #define my_use_large_pages 0 #endif -static inline my_bool my_is_2pow(size_t n) { return !((n) & ((n) - 1)); } - #if defined(HAVE_GETPAGESIZES) || defined(__linux__) /* Descending sort */ @@ -76,6 +74,8 @@ static size_t my_large_page_sizes[my_large_page_sizes_length]; Linux-specific function to determine the sizes of large pages */ #ifdef __linux__ +static inline my_bool my_is_2pow(size_t n) { return !((n) & ((n) - 1)); } + static void my_get_large_page_sizes(size_t sizes[my_large_page_sizes_length]) { DIR *dirp; diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index aef77333e75..0b580ecd32f 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -170,6 +170,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) in this case both the symlink and the symlinked file are deleted, but only if the symlinked file is not in the datadir. */ + int my_handler_delete_with_symlink(const char *filename, myf sync_dir) { char real[FN_REFLEN]; @@ -182,8 +183,9 @@ int my_handler_delete_with_symlink(const char *filename, myf sync_dir) Delete the symlinked file only if the symlink is not pointing into datadir. */ - if (!(my_realpath(real, filename, MYF(0)) || mysys_test_invalid_symlink(real))) + if (!(my_realpath(real, filename, MYF(0)) || + mysys_test_invalid_symlink(real))) res= my_delete(real, MYF(MY_NOSYMLINKS | sync_dir)); } - DBUG_RETURN(my_delete(filename, MYF(sync_dir)) || res); + DBUG_RETURN(my_delete(filename, sync_dir) || res); } diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index c798c8595e7..5004428505a 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -468,7 +468,7 @@ void thr_lock_delete(THR_LOCK *lock) void thr_lock_info_init(THR_LOCK_INFO *info, struct st_my_thread_var *tmp) { - if (tmp) + if (!tmp) tmp= my_thread_var; info->thread= tmp->pthread_self; info->thread_id= tmp->id; @@ -634,9 +634,10 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, else { result= THR_LOCK_SUCCESS; - if (data->lock->get_status) - (*data->lock->get_status)(data->status_param, - data->type == TL_WRITE_CONCURRENT_INSERT); + if (data->lock->get_status && + (*data->lock->get_status)(data->status_param, + data->type == TL_WRITE_CONCURRENT_INSERT)) + result= THR_LOCK_ABORTED; check_locks(data->lock,"got wait_for_lock", data->type, 0); } mysql_mutex_unlock(&data->lock->mutex); @@ -811,8 +812,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) if (lock_type == TL_READ_NO_INSERT) lock->read_no_write_count++; check_locks(lock,"read lock with old write lock", lock_type, 0); - if (lock->get_status) - (*lock->get_status)(data->status_param, 0); + if ((lock->get_status) && (*lock->get_status)(data->status_param, 0)) + result= THR_LOCK_ABORTED; statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } @@ -835,8 +836,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) if (lock_type == TL_READ_NO_INSERT) lock->read_no_write_count++; check_locks(lock,"read lock with no write locks", lock_type, 0); - if (lock->get_status) - (*lock->get_status)(data->status_param, 0); + if ((lock->get_status) && (*lock->get_status)(data->status_param, 0)) + result= THR_LOCK_ABORTED; statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } @@ -951,9 +952,10 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) data->prev=lock->write.last; lock->write.last= &data->next; check_locks(lock,"second write lock", lock_type, 0); - if (lock->get_status) - (*lock->get_status)(data->status_param, - lock_type == TL_WRITE_CONCURRENT_INSERT); + if ((lock->get_status) && + (*lock->get_status)(data->status_param, + lock_type == TL_WRITE_CONCURRENT_INSERT)) + result= THR_LOCK_ABORTED; statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } @@ -986,8 +988,9 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) (*lock->write.last)=data; /* Add as current write lock */ data->prev=lock->write.last; lock->write.last= &data->next; - if (lock->get_status) - (*lock->get_status)(data->status_param, concurrent_insert); + if ((lock->get_status) && + (*lock->get_status)(data->status_param, concurrent_insert)) + result= THR_LOCK_ABORTED; check_locks(lock,"only write lock", lock_type, 0); statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; @@ -1581,6 +1584,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, { if (!lock->read.data) /* No read locks */ { /* We have the lock */ + /* For this function, get_status is not allowed to fail */ if (data->lock->get_status) (*data->lock->get_status)(data->status_param, 0); mysql_mutex_unlock(&lock->mutex); @@ -1781,9 +1785,10 @@ static ulong sum=0; /* The following functions is for WRITE_CONCURRENT_INSERT */ -static void test_get_status(void* param __attribute__((unused)), - my_bool concurrent_insert __attribute__((unused))) +static my_bool test_get_status(void* param __attribute__((unused)), + my_bool concurrent_insert __attribute__((unused))) { + return 0; } static void test_update_status(void* param __attribute__((unused))) diff --git a/plugin/auth_gssapi/CMakeLists.txt b/plugin/auth_gssapi/CMakeLists.txt index d2f854c2918..3c43d169d07 100644 --- a/plugin/auth_gssapi/CMakeLists.txt +++ b/plugin/auth_gssapi/CMakeLists.txt @@ -20,10 +20,11 @@ ELSE() SET(CMAKE_REQUIRED_INCLUDES ${GSSAPI_INCS}) SET(CMAKE_REQUIRED_LIBRARIES ${GSSAPI_LIBS}) + SET(CMAKE_REQUIRED_FLAGS "-Werror -Wall") INCLUDE(CheckCXXSymbolExists) - CHECK_CXX_SYMBOL_EXISTS(krb5_free_unparsed_name "krb5.h" HAVE_KRB5_FREE_UNPARSED_NAME) - IF(HAVE_KRB5_FREE_UNPARSED_NAME) - ADD_DEFINITIONS(-DHAVE_KRB5_FREE_UNPARSED_NAME=1) + CHECK_CXX_SYMBOL_EXISTS(krb5_xfree "krb5.h" HAVE_KRB5_XFREE) + IF(HAVE_KRB5_XFREE) + ADD_DEFINITIONS(-DHAVE_KRB5_XFREE=1) ENDIF() ELSE() diff --git a/plugin/auth_gssapi/gssapi_server.cc b/plugin/auth_gssapi/gssapi_server.cc index 8aa13aac6c9..db7bda9a6b4 100644 --- a/plugin/auth_gssapi/gssapi_server.cc +++ b/plugin/auth_gssapi/gssapi_server.cc @@ -30,7 +30,7 @@ static void log_error( OM_uint32 major, OM_uint32 minor, const char *msg) Generate default principal service name formatted as principal name "mariadb/server.fqdn@REALM" */ #include -#ifndef HAVE_KRB5_FREE_UNPARSED_NAME +#ifdef HAVE_KRB5_XFREE #define krb5_free_unparsed_name(a,b) krb5_xfree(b) #endif static char* get_default_principal_name() @@ -158,8 +158,8 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) gss_buffer_desc client_name_buf, input, output; char *client_name_str; const char *user= 0; - size_t userlen; - int use_full_name; + size_t userlen= 0; + int use_full_name= 0; /* server acquires credential */ major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE, @@ -244,7 +244,7 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) && userlen < client_name_buf.length && client_name_str[userlen] == '@')) { - if (strncmp(client_name_str, user, userlen) == 0) + if (user && strncmp(client_name_str, user, userlen) == 0) { rc= CR_OK; } diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c index 2075d5fdbf3..f61a8da7682 100644 --- a/plugin/auth_pam/testing/pam_mariadb_mtr.c +++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c @@ -22,9 +22,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags __attribute__((unused)), struct pam_response *resp = 0; int pam_err, retval = PAM_SYSTEM_ERR; struct pam_message msg[N] = { - { PAM_TEXT_INFO, "Challenge input first." }, - { PAM_PROMPT_ECHO_OFF, "Enter:" }, - { PAM_ERROR_MSG, "Now, the magic number!" } + { PAM_TEXT_INFO, (char*)"Challenge input first." }, + { PAM_PROMPT_ECHO_OFF, (char*)"Enter:" }, + { PAM_ERROR_MSG, (char*)"Now, the magic number!" } }; const struct pam_message *msgp[N] = { msg, msg+1, msg+2 }; char *r1 = 0, *r2 = 0; @@ -46,7 +46,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags __attribute__((unused)), { free(resp); msg[0].msg_style = PAM_PROMPT_ECHO_ON; - msg[0].msg = "PIN:"; + msg[0].msg = (char*)"PIN:"; pam_err = (*conv->conv)(1, msgp, &resp, conv->appdata_ptr); if (pam_err != PAM_SUCCESS || !resp || !((r2= resp[0].resp))) diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 6715d40f20d..042cfaffaa4 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -34,9 +34,9 @@ ST_FIELD_INFO disks_table_fields[]= { Column("Disk", Varchar(PATH_MAX), NOT_NULL), Column("Path", Varchar(PATH_MAX), NOT_NULL), - Column("Total", SLong(32), NOT_NULL), // Total amount available - Column("Used", SLong(32), NOT_NULL), // Amount of space used - Column("Available", SLong(32), NOT_NULL), // Amount available to users other than root. + Column("Total", SLonglong(32), NOT_NULL), // Total amount available + Column("Used", SLonglong(32), NOT_NULL), // Amount of space used + Column("Available", SLonglong(32), NOT_NULL), // Amount available to users other than root. CEnd() }; @@ -55,9 +55,10 @@ int disks_table_add_row(THD* pThd, // f_bfree Total number of free blocks. // f_bavail Number of free blocks available to non-privileged process. - size_t total = (info.f_frsize * info.f_blocks) / 1024; - size_t used = (info.f_frsize * (info.f_blocks - info.f_bfree)) / 1024; - size_t avail = (info.f_frsize * info.f_bavail) / 1024; + ulonglong total = ((ulonglong)info.f_frsize * info.f_blocks) / 1024; + ulonglong used = ((ulonglong)info.f_frsize * + (info.f_blocks - info.f_bfree)) / 1024; + ulonglong avail = ((ulonglong)info.f_frsize * info.f_bavail) / 1024; pTable->field[0]->store(zDisk, strlen(zDisk), system_charset_info); pTable->field[1]->store(zPath, strlen(zPath), system_charset_info); diff --git a/plugin/disks/mysql-test/disks/disks.result b/plugin/disks/mysql-test/disks/disks.result index 65b1127d479..0b4ee6249aa 100644 --- a/plugin/disks/mysql-test/disks/disks.result +++ b/plugin/disks/mysql-test/disks/disks.result @@ -3,9 +3,9 @@ Table Create Table DISKS CREATE TEMPORARY TABLE `DISKS` ( `Disk` varchar(4096) NOT NULL DEFAULT '', `Path` varchar(4096) NOT NULL DEFAULT '', - `Total` int(32) NOT NULL DEFAULT 0, - `Used` int(32) NOT NULL DEFAULT 0, - `Available` int(32) NOT NULL DEFAULT 0 + `Total` bigint(32) NOT NULL DEFAULT 0, + `Used` bigint(32) NOT NULL DEFAULT 0, + `Available` bigint(32) NOT NULL DEFAULT 0 ) ENGINE=MEMORY DEFAULT CHARSET=utf8 select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; sum(Total) > sum(Available) sum(Total)>sum(Used) diff --git a/plugin/handler_socket/client/hspool_test.pl b/plugin/handler_socket/client/hspool_test.pl index 091cb4967cb..03227e31b56 100755 --- a/plugin/handler_socket/client/hspool_test.pl +++ b/plugin/handler_socket/client/hspool_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/plugin/handler_socket/client/hstest.pl b/plugin/handler_socket/client/hstest.pl index de39fcb6d6c..1363e153c44 100755 --- a/plugin/handler_socket/client/hstest.pl +++ b/plugin/handler_socket/client/hstest.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=8:ai:ts=8 diff --git a/plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm b/plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm index c51fe60d591..b6ea62651a3 100755 --- a/plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm +++ b/plugin/handler_socket/perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl package Net::HandlerSocket::HSPool; diff --git a/plugin/handler_socket/regtest/test_01_lib/test01.pl b/plugin/handler_socket/regtest/test_01_lib/test01.pl index d3a072fb3cc..0a3ad9e9b25 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test01.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test01.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test02.pl b/plugin/handler_socket/regtest/test_01_lib/test02.pl index c69515d76e9..f9bdc8b6738 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test02.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test02.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test03.pl b/plugin/handler_socket/regtest/test_01_lib/test03.pl index a081786c132..a51aaf3b257 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test03.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test03.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test04.pl b/plugin/handler_socket/regtest/test_01_lib/test04.pl index 52fe11364c8..d922b713271 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test04.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test04.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test05.pl b/plugin/handler_socket/regtest/test_01_lib/test05.pl index 10b1a0805a0..2993e7a9680 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test05.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test05.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test06.pl b/plugin/handler_socket/regtest/test_01_lib/test06.pl index fb0549f2295..69dd107e1ff 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test06.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test06.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test07.pl b/plugin/handler_socket/regtest/test_01_lib/test07.pl index fa9802366d8..2286aeba9fe 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test07.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test07.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test08.pl b/plugin/handler_socket/regtest/test_01_lib/test08.pl index c33bf190d29..da736ef34c3 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test08.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test08.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test09.pl b/plugin/handler_socket/regtest/test_01_lib/test09.pl index 14fd9c26641..7d6165ece1e 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test09.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test09.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test10.pl b/plugin/handler_socket/regtest/test_01_lib/test10.pl index fd294fe8b78..560976ba9b2 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test10.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test10.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test11.pl b/plugin/handler_socket/regtest/test_01_lib/test11.pl index 5cfe3e83614..cfaa940572c 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test11.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test11.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test12.pl b/plugin/handler_socket/regtest/test_01_lib/test12.pl index 100a779de4e..0cae3798372 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test12.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test12.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test13.pl b/plugin/handler_socket/regtest/test_01_lib/test13.pl index 1e1104d2a07..2068c4bc9b6 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test13.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test13.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test14.pl b/plugin/handler_socket/regtest/test_01_lib/test14.pl index ff4e433ae8f..ab89073370b 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test14.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test14.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test15.pl b/plugin/handler_socket/regtest/test_01_lib/test15.pl index 4c56d355708..2205be5b363 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test15.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test15.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test16.pl b/plugin/handler_socket/regtest/test_01_lib/test16.pl index 6db8c576d7a..c0c3fc556ff 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test16.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test16.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test17.pl b/plugin/handler_socket/regtest/test_01_lib/test17.pl index 1ffd7fa1242..7c150dab746 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test17.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test17.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test18.pl b/plugin/handler_socket/regtest/test_01_lib/test18.pl index 87047bc9cba..7854642af15 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test18.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test18.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test19.pl b/plugin/handler_socket/regtest/test_01_lib/test19.pl index 9870199c1a7..2e5363c8137 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test19.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test19.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test20.pl b/plugin/handler_socket/regtest/test_01_lib/test20.pl index 139bbf9aba1..96307e0a5f0 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test20.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test20.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test21.pl b/plugin/handler_socket/regtest/test_01_lib/test21.pl index 413ea636400..34e9d43972b 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test21.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test21.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test22.pl b/plugin/handler_socket/regtest/test_01_lib/test22.pl index cf029944292..370d16d6027 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test22.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test22.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test23.pl b/plugin/handler_socket/regtest/test_01_lib/test23.pl index 83c2194bfa6..d9bd0381251 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test23.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test23.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/handler_socket/regtest/test_01_lib/test24.pl b/plugin/handler_socket/regtest/test_01_lib/test24.pl index 6cd95a995e5..f4e3bb3f10c 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test24.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test24.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # vim:sw=2:ai diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result b/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result index e21fb47fea8..0e879aad58f 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6-debug.result @@ -6,8 +6,8 @@ SET debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (c01 INET6, c02 INET6); Warnings: Note 1105 build_frm_image: Field data type info length: 14 -Note 1105 DBUG: [0] name='c01' type_info='in...' -Note 1105 DBUG: [1] name='c02' type_info='in...' +Note 1105 DBUG: [0] name='c01' type_info='inet6' +Note 1105 DBUG: [1] name='c02' type_info='inet6' SET debug_dbug=@old_debug_dbug; SHOW CREATE TABLE t1; Table Create Table diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index 15c8dbf8ca9..ecf64d8484a 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -909,6 +909,17 @@ a GROUP_CONCAT(a ORDER BY a) ::2 ::2,::2,::2,::2 DROP TABLE t1; # +# MDEV-21765 Possibly inconsistent behavior of BIT_xx functions with INET6 field +# +CREATE TABLE t1 (a INET6); +SELECT BIT_AND(a) FROM t1; +ERROR HY000: Illegal parameter data type inet6 for operation 'bit_and(' +SELECT BIT_OR(a) FROM t1; +ERROR HY000: Illegal parameter data type inet6 for operation 'bit_or(' +SELECT BIT_XOR(a) FROM t1; +ERROR HY000: Illegal parameter data type inet6 for operation 'bit_xor(' +DROP TABLE t1; +# # Window functions # CREATE TABLE t1 (a INET6); @@ -1977,3 +1988,135 @@ SELECT MIN(a), MAX(a) FROM t1 GROUP BY id; MIN(a) MAX(a) fff:: 8888:: DROP TABLE t1; +# +# MDEV-20809 EXTRACT from INET6 value does not produce any warnings +# +CREATE TABLE t1 (a INET6); +SELECT EXTRACT(DAY FROM a) FROM t1; +ERROR HY000: Illegal parameter data type inet6 for operation 'extract(day)' +DROP TABLE t1; +SELECT EXTRACT(DAY FROM CAST('::' AS INET6)); +ERROR HY000: Illegal parameter data type inet6 for operation 'extract(day)' +# +# MDEV-22764 Crash with a stored aggregate function returning INET6 +# +CREATE OR REPLACE AGGREGATE FUNCTION aggregate_min_inet6(x INET6) RETURNS INET6 +BEGIN +DECLARE res INET6 DEFAULT NULL; +DECLARE CONTINUE HANDLER FOR NOT FOUND +RETURN res; +LOOP +FETCH GROUP NEXT ROW; +IF (res IS NULL) OR (res > x) THEN +SET res= x; +END IF; +END LOOP; +END; +$$ +CREATE OR REPLACE TABLE t1 (name CHAR(30), val INET6); +INSERT INTO t1 VALUES ('a', '::05'); +INSERT INTO t1 VALUES ('a', '::03'); +INSERT INTO t1 VALUES ('b', '::01'); +INSERT INTO t1 VALUES ('b', '::02'); +INSERT INTO t1 VALUES ('b', '::05'); +SELECT name, aggregate_min_inet6(val) pc FROM t1 GROUP BY name; +name pc +a ::3 +b ::1 +CREATE OR REPLACE TABLE t2 (name CHAR(30), val INET6); +INSERT INTO t2 SELECT name, aggregate_min_inet6(val) pc FROM t1 GROUP BY name; +SELECT * FROM t2; +name val +a ::3 +b ::1 +DROP TABLE t2; +DROP TABLE t1; +DROP FUNCTION aggregate_min_inet6; +# +# MDEV-20280 PERCENTILE_DISC() rejects temporal and string input +# +CREATE TABLE t1 (name CHAR(30), star_rating INET6); +INSERT INTO t1 VALUES ('Lord of the Ladybirds', '::5'); +INSERT INTO t1 VALUES ('Lord of the Ladybirds', '::3'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::1'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::2'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::5'); +SELECT name, PERCENTILE_DISC(0.5) +WITHIN GROUP (ORDER BY star_rating) +OVER (PARTITION BY name) AS pc FROM t1; +name pc +Lady of the Flies ::2 +Lady of the Flies ::2 +Lady of the Flies ::2 +Lord of the Ladybirds ::3 +Lord of the Ladybirds ::3 +SELECT name, PERCENTILE_DISC(0) +WITHIN GROUP (ORDER BY star_rating) +OVER (PARTITION BY name) AS pc FROM t1; +name pc +Lady of the Flies ::1 +Lady of the Flies ::1 +Lady of the Flies ::1 +Lord of the Ladybirds ::3 +Lord of the Ladybirds ::3 +SELECT name, PERCENTILE_DISC(1) +WITHIN GROUP (ORDER BY star_rating) +OVER (PARTITION BY name) AS pc FROM t1; +name pc +Lady of the Flies ::5 +Lady of the Flies ::5 +Lady of the Flies ::5 +Lord of the Ladybirds ::5 +Lord of the Ladybirds ::5 +DROP TABLE t1; +# +# MDEV-22758 Assertion `!item->null_value' failed in Type_handler_inet6::make_sort_key_part +# +CREATE TABLE t1 (a VARCHAR(8) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('foo','::'),('bar','1::1'); +SELECT * FROM t1 ORDER BY CASE WHEN a THEN b ELSE a END; +a b +foo :: +bar 1::1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'foo' +Warning 1292 Incorrect inet6 value: 'foo' +Warning 1292 Truncated incorrect DOUBLE value: 'bar' +Warning 1292 Incorrect inet6 value: 'bar' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARCHAR(8) NOT NULL); +INSERT INTO t1 VALUES ('foo'),('bar'); +SELECT * FROM t1 ORDER BY CAST(a AS INET6); +a +foo +bar +Warnings: +Warning 1292 Incorrect inet6 value: 'foo' +Warning 1292 Incorrect inet6 value: 'bar' +DROP TABLE t1; +CREATE TABLE t1 (a INET6 NOT NULL, b VARCHAR(32) NOT NULL); +CREATE TABLE t2 AS SELECT CAST(a AS INET6) AS ca, CAST(b AS INET6) AS cb FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `ca` inet6 NOT NULL, + `cb` inet6 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT COALESCE(a,a), COALESCE(a,b) FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `COALESCE(a,a)` inet6 NOT NULL, + `COALESCE(a,b)` inet6 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT a AS ca,a AS cb FROM t1 UNION SELECT a,b FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `ca` inet6 NOT NULL DEFAULT '::', + `cb` inet6 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test index 8559748c7dd..69583286380 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test @@ -536,6 +536,20 @@ SELECT GROUP_CONCAT(a ORDER BY a) FROM t1; SELECT a, GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY a; DROP TABLE t1; +--echo # +--echo # MDEV-21765 Possibly inconsistent behavior of BIT_xx functions with INET6 field +--echo # + +CREATE TABLE t1 (a INET6); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_AND(a) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_OR(a) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT BIT_XOR(a) FROM t1; +DROP TABLE t1; + + --echo # --echo # Window functions --echo # @@ -1445,3 +1459,104 @@ CREATE TABLE t1 (id INT, a INET6) ENGINE=MyISAM; INSERT INTO t1 VALUES (1, 'fff::'),(1, '8888::'); SELECT MIN(a), MAX(a) FROM t1 GROUP BY id; DROP TABLE t1; + + +--echo # +--echo # MDEV-20809 EXTRACT from INET6 value does not produce any warnings +--echo # + +CREATE TABLE t1 (a INET6); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT EXTRACT(DAY FROM a) FROM t1; +DROP TABLE t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT EXTRACT(DAY FROM CAST('::' AS INET6)); + + +--echo # +--echo # MDEV-22764 Crash with a stored aggregate function returning INET6 +--echo # + +DELIMITER $$; +CREATE OR REPLACE AGGREGATE FUNCTION aggregate_min_inet6(x INET6) RETURNS INET6 +BEGIN + DECLARE res INET6 DEFAULT NULL; + DECLARE CONTINUE HANDLER FOR NOT FOUND + RETURN res; + LOOP + FETCH GROUP NEXT ROW; + IF (res IS NULL) OR (res > x) THEN + SET res= x; + END IF; + END LOOP; +END; +$$ +DELIMITER ;$$ + +CREATE OR REPLACE TABLE t1 (name CHAR(30), val INET6); +INSERT INTO t1 VALUES ('a', '::05'); +INSERT INTO t1 VALUES ('a', '::03'); +INSERT INTO t1 VALUES ('b', '::01'); +INSERT INTO t1 VALUES ('b', '::02'); +INSERT INTO t1 VALUES ('b', '::05'); +SELECT name, aggregate_min_inet6(val) pc FROM t1 GROUP BY name; + +CREATE OR REPLACE TABLE t2 (name CHAR(30), val INET6); +INSERT INTO t2 SELECT name, aggregate_min_inet6(val) pc FROM t1 GROUP BY name; +SELECT * FROM t2; +DROP TABLE t2; + +DROP TABLE t1; +DROP FUNCTION aggregate_min_inet6; + + +--echo # +--echo # MDEV-20280 PERCENTILE_DISC() rejects temporal and string input +--echo # + +CREATE TABLE t1 (name CHAR(30), star_rating INET6); +INSERT INTO t1 VALUES ('Lord of the Ladybirds', '::5'); +INSERT INTO t1 VALUES ('Lord of the Ladybirds', '::3'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::1'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::2'); +INSERT INTO t1 VALUES ('Lady of the Flies', '::5'); +SELECT name, PERCENTILE_DISC(0.5) + WITHIN GROUP (ORDER BY star_rating) + OVER (PARTITION BY name) AS pc FROM t1; +SELECT name, PERCENTILE_DISC(0) + WITHIN GROUP (ORDER BY star_rating) + OVER (PARTITION BY name) AS pc FROM t1; +SELECT name, PERCENTILE_DISC(1) + WITHIN GROUP (ORDER BY star_rating) + OVER (PARTITION BY name) AS pc FROM t1; +DROP TABLE t1; + + +--echo # +--echo # MDEV-22758 Assertion `!item->null_value' failed in Type_handler_inet6::make_sort_key_part +--echo # + +CREATE TABLE t1 (a VARCHAR(8) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('foo','::'),('bar','1::1'); +SELECT * FROM t1 ORDER BY CASE WHEN a THEN b ELSE a END; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a VARCHAR(8) NOT NULL); +INSERT INTO t1 VALUES ('foo'),('bar'); +SELECT * FROM t1 ORDER BY CAST(a AS INET6); +DROP TABLE t1; + +CREATE TABLE t1 (a INET6 NOT NULL, b VARCHAR(32) NOT NULL); +CREATE TABLE t2 AS SELECT CAST(a AS INET6) AS ca, CAST(b AS INET6) AS cb FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT COALESCE(a,a), COALESCE(a,b) FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT a AS ca,a AS cb FROM t1 UNION SELECT a,b FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result index 6d84d105c99..1cbedad1c3c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result @@ -13,5 +13,19 @@ test.t1 analyze status OK INSERT INTO t1 VALUES ('3::3'); DROP TABLE t1; # +# MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null +# +CREATE TABLE t1 (a INT, b INET6 NOT NULL); +INSERT INTO t1 VALUES (1,'::'),(2,'::'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT t1.a from t1; +a +1 +2 +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test index fb092db6bc4..063581b12f5 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test @@ -14,6 +14,16 @@ ANALYZE TABLE t1 PERSISTENT FOR ALL; INSERT INTO t1 VALUES ('3::3'); DROP TABLE t1; +--echo # +--echo # MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null +--echo # + +CREATE TABLE t1 (a INT, b INET6 NOT NULL); +INSERT INTO t1 VALUES (1,'::'),(2,'::'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT t1.a from t1; +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc index 29234aa4a56..76334ad1615 100644 --- a/plugin/type_inet/sql_type_inet.cc +++ b/plugin/type_inet/sql_type_inet.cc @@ -508,7 +508,19 @@ size_t Inet6::to_string(char *dst, size_t dstsize) const } -bool Inet6::make_from_item(Item *item) +bool Inet6::fix_fields_maybe_null_on_conversion_to_inet6(Item *item) +{ + if (item->maybe_null) + return true; + if (item->type_handler() == &type_handler_inet6) + return false; + if (!item->const_item() || item->is_expensive()) + return true; + return Inet6_null(item, false).is_null(); +} + + +bool Inet6::make_from_item(Item *item, bool warn) { if (item->type_handler() == &type_handler_inet6) { @@ -523,18 +535,18 @@ bool Inet6::make_from_item(Item *item) } StringBufferInet6 tmp; String *str= item->val_str(&tmp); - return str ? make_from_character_or_binary_string(str) : true; + return str ? make_from_character_or_binary_string(str, warn) : true; } -bool Inet6::make_from_character_or_binary_string(const String *str) +bool Inet6::make_from_character_or_binary_string(const String *str, bool warn) { static Name name= type_handler_inet6.name(); if (str->charset() != &my_charset_bin) { bool rc= character_string_to_ipv6(str->ptr(), str->length(), str->charset()); - if (rc) + if (rc && warn) current_thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, name.ptr(), ErrConvString(str).ptr()); @@ -542,9 +554,10 @@ bool Inet6::make_from_character_or_binary_string(const String *str) } if (str->length() != sizeof(m_buffer)) { - current_thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, - name.ptr(), - ErrConvString(str).ptr()); + if (warn) + current_thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, + name.ptr(), + ErrConvString(str).ptr()); return true; } DBUG_ASSERT(str->ptr() != m_buffer); @@ -1036,6 +1049,8 @@ public: bool fix_length_and_dec() override { Type_std_attributes::operator=(Type_std_attributes_inet6()); + if (Inet6::fix_fields_maybe_null_on_conversion_to_inet6(args[0])) + maybe_null= true; return false; } String *val_str(String *to) override @@ -1411,7 +1426,7 @@ void Type_handler_inet6::sort_length(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const { - attr->length= Inet6::binary_length(); + attr->original_length= attr->length= Inet6::binary_length(); attr->suffix_length= 0; } diff --git a/plugin/type_inet/sql_type_inet.h b/plugin/type_inet/sql_type_inet.h index c8118a111e4..e924e966357 100644 --- a/plugin/type_inet/sql_type_inet.h +++ b/plugin/type_inet/sql_type_inet.h @@ -137,7 +137,7 @@ class Inet6 { protected: char m_buffer[IN6_ADDR_SIZE]; - bool make_from_item(Item *item); + bool make_from_item(Item *item, bool warn); bool ascii_to_ipv6(const char *str, size_t str_length); bool character_string_to_ipv6(const char *str, size_t str_length, CHARSET_INFO *cs) @@ -152,7 +152,7 @@ protected: } return ascii_to_ipv6(str, str_length); } - bool make_from_character_or_binary_string(const String *str); + bool make_from_character_or_binary_string(const String *str, bool warn); bool binary_to_ipv6(const char *str, size_t length) { if (length != sizeof(m_buffer)) @@ -182,11 +182,17 @@ public: return true; } + /* + Check at Item's fix_fields() time if "item" can return a nullable value + on conversion to INET6, or conversion produces a NOT NULL INET6 value. + */ + static bool fix_fields_maybe_null_on_conversion_to_inet6(Item *item); + public: - Inet6(Item *item, bool *error) + Inet6(Item *item, bool *error, bool warn= true) { - *error= make_from_item(item); + *error= make_from_item(item, warn); } void to_binary(char *str, size_t str_size) const { @@ -264,8 +270,8 @@ public: :Inet6_null(str.ptr(), str.length()) { } // Initialize from an Item - Inet6_null(Item *item) - :Null_flag(make_from_item(item)) + Inet6_null(Item *item, bool warn= true) + :Null_flag(make_from_item(item, warn)) { } public: const Inet6& to_inet6() const @@ -714,6 +720,14 @@ public: { attr->Type_std_attributes::operator=(Type_std_attributes_inet6()); h->set_handler(this); + for (uint i= 0; i < nitems; i++) + { + if (Inet6::fix_fields_maybe_null_on_conversion_to_inet6(items[i])) + { + attr->set_maybe_null(true); + break; + } + } return false; } bool Item_func_min_max_fix_attributes(THD *thd, diff --git a/plugin/type_test/mysql-test/type_test/type_test_double-debug.result b/plugin/type_test/mysql-test/type_test/type_test_double-debug.result index ba4c8ea7b6a..975decca11e 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_double-debug.result +++ b/plugin/type_test/mysql-test/type_test/type_test_double-debug.result @@ -8,14 +8,14 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 13 -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` test_double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' DROP TABLE t1; SET @@debug_dbug=@old_debug_dbug; # Testing what happens on failure to resolve a type handler by name @@ -24,7 +24,7 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_DOUBLE); Warnings: Note 1105 build_frm_image: Field data type info length: 13 -Note 1105 DBUG: [0] name='a' type_info='test_dou...' +Note 1105 DBUG: [0] name='a' type_info='test_double' FLUSH TABLES; SET @@debug_dbug="+d,emulate_handler_by_name_or_error_failure"; SHOW CREATE TABLE t1; diff --git a/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result b/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result index e348b5b5f18..952a63c8476 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result +++ b/plugin/type_test/mysql-test/type_test/type_test_int8-debug.result @@ -8,14 +8,14 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_INT8); Warnings: Note 1105 build_frm_image: Field data type info length: 11 -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` test_int8(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' DROP TABLE t1; SET @@debug_dbug=@old_debug_dbug; # Testing what happens on failure to resolve a type handler by name @@ -24,7 +24,7 @@ SET @@debug_dbug="+d,frm_data_type_info"; CREATE TABLE t1 (a TEST_INT8); Warnings: Note 1105 build_frm_image: Field data type info length: 11 -Note 1105 DBUG: [0] name='a' type_info='test_i...' +Note 1105 DBUG: [0] name='a' type_info='test_int8' FLUSH TABLES; SET @@debug_dbug="+d,emulate_handler_by_name_or_error_failure"; SHOW CREATE TABLE t1; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 38f44796148..4dad514f6af 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -250,10 +250,10 @@ ELSE() SET(TARGET_LINUX "false") ENDIF() -SET(mysql_config_COMPONENT COMPONENT Development) -SET(msql2mysql_COMPONENT COMPONENT Client) -SET(mysqlaccess_COMPONENT COMPONENT Client) -SET(mysql_find_rows_COMPONENT COMPONENT Client) +SET(mysql_config_COMPONENT Development) +SET(msql2mysql_COMPONENT Client) +SET(mariadb-access_COMPONENT Client) +SET(mariadb-find-rows_COMPONENT Client) SET(mytop_COMPONENT Mytop) IF(WIN32) diff --git a/scripts/convert-debug-for-diff.sh b/scripts/convert-debug-for-diff.sh index 5b3ce05b815..60b328d946b 100755 --- a/scripts/convert-debug-for-diff.sh +++ b/scripts/convert-debug-for-diff.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl -i +#!/usr/bin/env perl -i # # This script converts all numbers that look like addresses or memory sizes, # in a debug files generated by --debug (like mysqld --debug-dbug), to #. diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 3dda22507af..0da86726bfb 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -518,25 +518,25 @@ then # BASEDIR is already overridden on command line. Do not re-set. # Use BASEDIR to discover le. - if test -x "$MY_BASEDIR_VERSION/libexec/mysqld" + if test -x "$MY_BASEDIR_VERSION/libexec/mariadbd" then ledir="$MY_BASEDIR_VERSION/libexec" - elif test -x "$MY_BASEDIR_VERSION/sbin/mysqld" + elif test -x "$MY_BASEDIR_VERSION/sbin/mariadbd" then ledir="$MY_BASEDIR_VERSION/sbin" else ledir="$MY_BASEDIR_VERSION/bin" fi -elif test -x "$MY_PWD/bin/mysqld" +elif test -x "$MY_PWD/bin/mariadbd" then MY_BASEDIR_VERSION="$MY_PWD" # Where bin, share and data are ledir="$MY_PWD/bin" # Where mysqld is # Check for the directories we would expect from a source install -elif test -x "$MY_PWD/libexec/mysqld" +elif test -x "$MY_PWD/libexec/mariadbd" then MY_BASEDIR_VERSION="$MY_PWD" # Where libexec, share and var are ledir="$MY_PWD/libexec" # Where mysqld is -elif test -x "$MY_PWD/sbin/mysqld" +elif test -x "$MY_PWD/sbin/mariadbd" then MY_BASEDIR_VERSION="$MY_PWD" # Where sbin, share and var are ledir="$MY_PWD/sbin" # Where mysqld is @@ -570,7 +570,7 @@ else fi if test -z "$MYSQL_HOME" -then +then if test -r "$DATADIR/my.cnf" then log_error "WARNING: Found $DATADIR/my.cnf @@ -659,7 +659,7 @@ then # mysqld does not add ".err" to "--log-error=foo."; it considers a # trailing "." as an extension - + if expr "$err_log" : '.*\.[^/]*$' > /dev/null then : @@ -741,10 +741,10 @@ then chmod 755 $mysql_unix_port_dir fi -# If the user doesn't specify a binary, we assume name "mysqld" +# If the user doesn't specify a binary, we assume name "mariadbd" if test -z "$MYSQLD" then - MYSQLD=mysqld + MYSQLD=mariadbd fi if test ! -x "$ledir/$MYSQLD" @@ -1050,8 +1050,8 @@ do log_notice "Number of processes running now: $numofproces" I=1 while test "$I" -le "$numofproces" - do - PROC=`ps xaww | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'` + do + PROC=`ps xaww | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'` for T in $PROC do diff --git a/scripts/mytop.sh b/scripts/mytop.sh index c8de6c56f3e..f4e6dffb3b5 100644 --- a/scripts/mytop.sh +++ b/scripts/mytop.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # $Id: mytop,v 1.99-maria6 2019/10/22 14:53:51 jweisbuch Exp $ diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 799276258f2..1991fe4dd8d 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -56,8 +56,6 @@ sfmt="tar" strmcmd="" tfmt="" tcmd="" -rebuild=0 -rebuildcmd="" payload=0 pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' " pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE " @@ -201,7 +199,11 @@ get_transfer() tcmd="nc ${REMOTEIP} ${TSST_PORT}" elif nc -h 2>&1 | grep -q -- '-d\>';then # Debian netcat - tcmd="nc ${REMOTEIP} ${TSST_PORT}" + if nc -h 2>&1 | grep -q -- '-N\>';then + tcmd="nc -N ${REMOTEIP} ${TSST_PORT}" + else + tcmd="nc ${REMOTEIP} ${TSST_PORT}" + fi else # traditional netcat tcmd="nc -q0 ${REMOTEIP} ${TSST_PORT}" @@ -335,7 +337,6 @@ read_cnf() encrypt=$(parse_cnf sst encrypt 0) sockopt=$(parse_cnf sst sockopt "") progress=$(parse_cnf sst progress "") - rebuild=$(parse_cnf sst rebuild 0) ttime=$(parse_cnf sst time 0) cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') [[ $OS == "FreeBSD" ]] && cpat=$(parse_cnf sst cpat '.*galera\.cache$|.*sst_in_progress$|.*\.sst$|.*gvwstate\.dat$|.*grastate\.dat$|.*\.err$|.*\.log$|.*RPM_UPGRADE_MARKER$|.*RPM_UPGRADE_HISTORY$') @@ -704,7 +705,7 @@ if [[ ${FORCE_FTWRL:-0} -eq 1 ]];then iopts+=" --no-backup-locks " fi -INNOEXTRA=$WSREP_SST_OPT_MYSQLD +INNOEXTRA= INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} # Try to set INNODB_DATA_HOME_DIR from the command line: @@ -750,9 +751,9 @@ if [[ $ssyslog -eq 1 ]];then logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" } - INNOAPPLY="${INNOBACKUPEX_BIN} --innobackupex $disver $iapts \$INNOEXTRA --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" - INNOMOVE="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" - INNOBACKUP="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" + INNOAPPLY="${INNOBACKUPEX_BIN} --prepare $disver $iapts \$INNOEXTRA --target-dir=\${DATA} --mysqld-args \$WSREP_SST_OPT_MYSQLD 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" + INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --move-back $disver $impts --force-non-empty-directories --target-dir=\${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" + INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --backup $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt --target-dir=\$itmpdir --mysqld-args \$WSREP_SST_OPT_MYSQLD 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" fi else @@ -814,9 +815,9 @@ then fi - INNOAPPLY="${INNOBACKUPEX_BIN} --innobackupex $disver $iapts \$INNOEXTRA --apply-log \$rebuildcmd \${DATA} &> ${INNOAPPLYLOG}" - INNOMOVE="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &> ${INNOMOVELOG}" - INNOBACKUP="${INNOBACKUPEX_BIN} --innobackupex ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> ${INNOBACKUPLOG}" + INNOAPPLY="${INNOBACKUPEX_BIN} --prepare $disver $iapts \$INNOEXTRA --target-dir=\${DATA} --mysqld-args \$WSREP_SST_OPT_MYSQLD &> ${INNOAPPLYLOG}" + INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --move-back $disver $impts --move-back --force-non-empty-directories --target-dir=\${DATA} &> ${INNOMOVELOG}" + INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --backup $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt --target-dir=\$itmpdir --mysqld-args \$WSREP_SST_OPT_MYSQLD 2> ${INNOBACKUPLOG}" fi get_stream @@ -858,15 +859,6 @@ then INNOEXTRA+=" --password=" fi - get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $ekey ]];then - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey" - else - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile" - fi - fi - check_extra wsrep_log_info "Streaming GTID file before SST" @@ -1087,18 +1079,6 @@ then exit 2 fi - # Rebuild indexes for compact backups - if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then - wsrep_log_info "Index compaction detected" - rebuild=1 - fi - - if [[ $rebuild -eq 1 ]];then - nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) - wsrep_log_info "Rebuilding during prepare with $nthreads threads" - rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" - fi - if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then wsrep_log_info "Compressed qpress files found" diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 5403b9e8505..96e542ce844 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -200,6 +200,7 @@ fi # New filter - exclude everything except dirs (schemas) and innodb files FILTER="-f '- /lost+found' + -f '- /.zfs' -f '- /.fseventsd' -f '- /.Trashes' -f '+ /wsrep_sst_binlog.tar' @@ -357,7 +358,7 @@ EOF [ "$OS" = "Linux" ] && count=$(grep -c processor /proc/cpuinfo) [ "$OS" = "Darwin" -o "$OS" = "FreeBSD" ] && count=$(sysctl -n hw.ncpu) - find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" \ + find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" -not -name ".zfs" \ -print0 | xargs -I{} -0 -P $count \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ @@ -440,6 +441,7 @@ timeout = 300 $SILENT [$MODULE] path = $WSREP_SST_OPT_DATA + exclude = .zfs [$MODULE-log_dir] path = $WSREP_LOG_DIR [$MODULE-data_dir] diff --git a/sql-bench/as3ap.sh b/sql-bench/as3ap.sh index fd2b6ba3b25..8e4b3167429 100644 --- a/sql-bench/as3ap.sh +++ b/sql-bench/as3ap.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/bench-count-distinct.sh b/sql-bench/bench-count-distinct.sh index 9ce9b2fb168..b6465d0635f 100644 --- a/sql-bench/bench-count-distinct.sh +++ b/sql-bench/bench-count-distinct.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index a6a12603e6d..f23ef6f5949 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000-2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/compare-results.sh b/sql-bench/compare-results.sh index f0658160db2..06e247bae8a 100644 --- a/sql-bench/compare-results.sh +++ b/sql-bench/compare-results.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/copy-db.sh b/sql-bench/copy-db.sh index 38a010e52ab..d70472feaff 100644 --- a/sql-bench/copy-db.sh +++ b/sql-bench/copy-db.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh index a7298c5f9a1..26f66f94735 100644 --- a/sql-bench/crash-me.sh +++ b/sql-bench/crash-me.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- perl -*- # Copyright (c) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. diff --git a/sql-bench/graph-compare-results.sh b/sql-bench/graph-compare-results.sh index ddc9080acd6..d43f722cb14 100755 --- a/sql-bench/graph-compare-results.sh +++ b/sql-bench/graph-compare-results.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl #### #### Hello ... this is a heavily hacked script by Luuk #### instead of printing the result it makes a nice gif diff --git a/sql-bench/innotest1.sh b/sql-bench/innotest1.sh index 9e1ed32c273..1b99f601f42 100644 --- a/sql-bench/innotest1.sh +++ b/sql-bench/innotest1.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/InnoDB combined database # (c) 2002 Innobase Oy & MySQL AB diff --git a/sql-bench/innotest1a.sh b/sql-bench/innotest1a.sh index 1e428e33dcf..7183c901831 100644 --- a/sql-bench/innotest1a.sh +++ b/sql-bench/innotest1a.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/InnoDB combined database # (c) 2002 Innobase Oy & MySQL AB diff --git a/sql-bench/innotest1b.sh b/sql-bench/innotest1b.sh index 524a6e0e145..0a909d1a8f6 100644 --- a/sql-bench/innotest1b.sh +++ b/sql-bench/innotest1b.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/InnoDB combined database # (c) 2002 Innobase Oy & MySQL AB diff --git a/sql-bench/innotest2.sh b/sql-bench/innotest2.sh index fa0fd418968..941b0ac8b59 100644 --- a/sql-bench/innotest2.sh +++ b/sql-bench/innotest2.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/InnoDB combined database # (c) 2002 Innobase Oy & MySQL AB diff --git a/sql-bench/innotest2a.sh b/sql-bench/innotest2a.sh index 4a6e4b20a9a..e873d2b458c 100644 --- a/sql-bench/innotest2a.sh +++ b/sql-bench/innotest2a.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/Innobase combined database # (c) 2000 Innobase Oy & MySQL AB diff --git a/sql-bench/innotest2b.sh b/sql-bench/innotest2b.sh index b94325ff39e..56b44eda561 100644 --- a/sql-bench/innotest2b.sh +++ b/sql-bench/innotest2b.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl ############################################################################ # Stress test for MySQL/Innobase combined database # (c) 2000 Innobase Oy & MySQL AB diff --git a/sql-bench/run-all-tests.sh b/sql-bench/run-all-tests.sh index 5d77c8c388d..ecab48e88fe 100644 --- a/sql-bench/run-all-tests.sh +++ b/sql-bench/run-all-tests.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index 81254e03926..f0fca1d2f01 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -*- perl -*- # Copyright (c) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. diff --git a/sql-bench/test-ATIS.sh b/sql-bench/test-ATIS.sh index d7ef5dca476..c51688de0c2 100644 --- a/sql-bench/test-ATIS.sh +++ b/sql-bench/test-ATIS.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-alter-table.sh b/sql-bench/test-alter-table.sh index e092453b16a..350c6fae2c6 100644 --- a/sql-bench/test-alter-table.sh +++ b/sql-bench/test-alter-table.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-big-tables.sh b/sql-bench/test-big-tables.sh index e2cf983de1c..6be907d0ee6 100644 --- a/sql-bench/test-big-tables.sh +++ b/sql-bench/test-big-tables.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-connect.sh b/sql-bench/test-connect.sh index 1226301df9b..e3acb453a30 100644 --- a/sql-bench/test-connect.sh +++ b/sql-bench/test-connect.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-create.sh b/sql-bench/test-create.sh index 7af6fa13562..09961f0d698 100644 --- a/sql-bench/test-create.sh +++ b/sql-bench/test-create.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000-2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-insert.sh b/sql-bench/test-insert.sh index 3e35ac5ff5c..dbdc58fdcca 100644 --- a/sql-bench/test-insert.sh +++ b/sql-bench/test-insert.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000-2003, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-select.sh b/sql-bench/test-select.sh index 4c7147b57a4..e3020698cb8 100644 --- a/sql-bench/test-select.sh +++ b/sql-bench/test-select.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-table-elimination.sh b/sql-bench/test-table-elimination.sh index de440fc0633..c3a264492a4 100755 --- a/sql-bench/test-table-elimination.sh +++ b/sql-bench/test-table-elimination.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Test of table elimination feature use Cwd; diff --git a/sql-bench/test-transactions.sh b/sql-bench/test-transactions.sh index 4732658c529..334a6f0a385 100644 --- a/sql-bench/test-transactions.sh +++ b/sql-bench/test-transactions.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql-bench/test-wisconsin.sh b/sql-bench/test-wisconsin.sh index 47c9e050304..581db89712e 100644 --- a/sql-bench/test-wisconsin.sh +++ b/sql-bench/test-wisconsin.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2001, 2003, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index e01cb79e289..c2bf0c68f2f 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -76,6 +76,8 @@ IF(SSL_DEFINES) ENDIF() SET (SQL_SOURCE + ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc + ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc ../sql-common/client.c compat56.cc derror.cc des_key_file.cc discover.cc ../sql-common/errmsg.c field.cc field_conv.cc field_comp.cc @@ -156,8 +158,6 @@ SET (SQL_SOURCE opt_trace.cc table_cache.cc encryption.cc temporary_tables.cc proxy_protocol.cc backup.cc xa.cc - ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc - ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h ${GEN_SOURCES} diff --git a/sql/debug_sync.h b/sql/debug_sync.h index d92dc48cb0a..3b8aa8815e1 100644 --- a/sql/debug_sync.h +++ b/sql/debug_sync.h @@ -49,6 +49,8 @@ extern uchar *debug_sync_value_ptr(THD *thd); static inline void debug_sync_init_thread(THD *thd) {} static inline void debug_sync_end_thread(THD *thd) {} static inline void debug_sync_reset_thread(THD *thd) {} +static inline bool debug_sync_set_action(THD *, const char *, size_t) +{ return false; } #endif /* defined(ENABLED_DEBUG_SYNC) */ #endif /* DEBUG_SYNC_INCLUDED */ diff --git a/sql/encryption.cc b/sql/encryption.cc index fc07623883e..9c38713fdfa 100644 --- a/sql/encryption.cc +++ b/sql/encryption.cc @@ -18,6 +18,7 @@ #include "log.h" #include "sql_plugin.h" #include +#include /* there can be only one encryption plugin enabled */ static plugin_ref encryption_manager= 0; @@ -63,6 +64,8 @@ int initialize_encryption_plugin(st_plugin_int *plugin) if (encryption_manager) return 1; + vio_check_ssl_init(); + if (plugin->plugin->init && plugin->plugin->init(plugin)) { sql_print_error("Plugin '%s' init function returned error.", diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index af43d92dea7..9e8e5f06043 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -30,6 +30,7 @@ #include "events.h" #include "sql_show.h" #include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT +#include "transaction.h" /** @addtogroup Event_Scheduler @@ -533,23 +534,26 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *i_s_table, const char *db) { TABLE *schema_table= i_s_table->table; - Open_tables_backup open_tables_backup; TABLE_LIST event_table; int ret= 0; - DBUG_ENTER("Event_db_repository::fill_schema_events"); DBUG_PRINT("info",("db=%s", db? db:"(null)")); + start_new_trans new_trans(thd); + event_table.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_EVENT_NAME, 0, TL_READ); - if (open_system_tables_for_read(thd, &event_table, &open_tables_backup)) + if (open_system_tables_for_read(thd, &event_table)) + { + new_trans.restore_old_transaction(); DBUG_RETURN(TRUE); + } if (table_intact.check(event_table.table, &event_table_def)) { - close_system_tables(thd, &open_tables_backup); my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); - DBUG_RETURN(TRUE); + ret= 1; + goto err; } /* @@ -566,7 +570,9 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *i_s_table, else ret= table_scan_all_for_i_s(thd, schema_table, event_table.table); - close_system_tables(thd, &open_tables_backup); +err: + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_PRINT("info", ("Return code=%d", ret)); DBUG_RETURN(ret); @@ -612,7 +618,8 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, if (table_intact.check(*table, &event_table_def)) { - close_thread_tables(thd); + thd->commit_whole_transaction_and_close_tables(); + *table= 0; // Table is now closed my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); DBUG_RETURN(TRUE); } @@ -742,7 +749,8 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, ret= 0; end: - close_thread_tables(thd); + if (table) + thd->commit_whole_transaction_and_close_tables(); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); thd->variables.sql_mode= saved_mode; @@ -784,7 +792,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, */ MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); int ret= 1; - DBUG_ENTER("Event_db_repository::update_event"); /* None or both must be set */ @@ -857,7 +864,8 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, ret= 0; end: - close_thread_tables(thd); + if (table) + thd->commit_whole_transaction_and_close_tables(); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); thd->variables.sql_mode= saved_mode; @@ -919,7 +927,8 @@ Event_db_repository::drop_event(THD *thd, const LEX_CSTRING *db, ret= 0; end: - close_thread_tables(thd); + if (table) + thd->commit_whole_transaction_and_close_tables(); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); DBUG_RETURN(MY_TEST(ret)); @@ -999,12 +1008,16 @@ Event_db_repository::drop_schema_events(THD *thd, const LEX_CSTRING *schema) TABLE *table= NULL; READ_RECORD read_record_info; enum enum_events_table_field field= ET_FIELD_DB; - MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); DBUG_ENTER("Event_db_repository::drop_schema_events"); DBUG_PRINT("enter", ("field: %d schema: %s", field, schema->str)); + start_new_trans new_trans(thd); + if (open_event_table(thd, TL_WRITE, &table)) + { + new_trans.restore_old_transaction(); DBUG_VOID_RETURN; + } /* only enabled events are in memory, so we go now and delete the rest */ if (init_read_record(&read_record_info, thd, table, NULL, NULL, 1, 0, FALSE)) @@ -1033,13 +1046,8 @@ Event_db_repository::drop_schema_events(THD *thd, const LEX_CSTRING *schema) end_read_record(&read_record_info); end: - close_thread_tables(thd); - /* - Make sure to only release the MDL lock on mysql.event, not other - metadata locks DROP DATABASE might have acquired. - */ - thd->mdl_context.rollback_to_savepoint(mdl_savepoint); - + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_VOID_RETURN; } @@ -1060,29 +1068,29 @@ Event_db_repository::load_named_event(THD *thd, const LEX_CSTRING *dbname, Event_basic *etn) { bool ret; - Open_tables_backup open_tables_backup; TABLE_LIST event_table; - DBUG_ENTER("Event_db_repository::load_named_event"); DBUG_PRINT("enter",("thd: %p name: %*s", thd, (int) name->length, name->str)); - event_table.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_EVENT_NAME, 0, TL_READ); - + start_new_trans new_trans(thd); /* Reset sql_mode during data dictionary operations. */ Sql_mode_instant_set sms(thd, 0); + event_table.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_EVENT_NAME, 0, TL_READ); + /* We don't use open_event_table() here to make sure that SHOW CREATE EVENT works properly in transactional context, and does not release transactional metadata locks when the event table is closed. */ - if (!(ret= open_system_tables_for_read(thd, &event_table, &open_tables_backup))) + if (!(ret= open_system_tables_for_read(thd, &event_table))) { if (table_intact.check(event_table.table, &event_table_def)) { - close_system_tables(thd, &open_tables_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); DBUG_RETURN(TRUE); } @@ -1091,9 +1099,9 @@ Event_db_repository::load_named_event(THD *thd, const LEX_CSTRING *dbname, my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->str); else if ((ret= etn->load_from_row(thd, event_table.table))) my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event"); - - close_system_tables(thd, &open_tables_backup); + thd->commit_whole_transaction_and_close_tables(); } + new_trans.restore_old_transaction(); DBUG_RETURN(ret); } @@ -1117,22 +1125,20 @@ update_timing_fields_for_event(THD *thd, TABLE *table= NULL; Field **fields; int ret= 1; - enum_binlog_format save_binlog_format; MYSQL_TIME time; DBUG_ENTER("Event_db_repository::update_timing_fields_for_event"); - /* - Turn off row binlogging of event timing updates. These are not used - for RBR of events replicated to the slave. - */ - save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); - DBUG_ASSERT(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY); if (open_event_table(thd, TL_WRITE, &table)) - goto end; + DBUG_RETURN(1); fields= table->field; + /* + Turn off row binlogging of event timing updates. These are not used + for RBR of events replicated to the slave. + */ + table->file->row_logging= 0; if (find_named_event(event_db_name, event_name, table)) goto end; @@ -1153,12 +1159,9 @@ update_timing_fields_for_event(THD *thd, } ret= 0; - end: - if (table) - close_mysql_tables(thd); - - thd->restore_stmt_binlog_format(save_binlog_format); + if (thd->commit_whole_transaction_and_close_tables()) + ret= 1; DBUG_RETURN(MY_TEST(ret)); } diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 4ecf19c389b..78802a5e109 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -511,6 +511,8 @@ Event_scheduler::run(THD *thd) } DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str)); free_root(thd->mem_root, MYF(0)); + /* Ensure we don't have any open tables or table locks */ + DBUG_ASSERT(thd->lock == 0); } LOCK_DATA(); diff --git a/sql/field.cc b/sql/field.cc index 04c45dfb546..9b6f117a82e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1455,7 +1455,7 @@ void Field::error_generated_column_function_is_not_allowed(THD *thd, QT_ITEM_IDENT_SKIP_TABLE_NAMES)); my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(error ? 0 : ME_WARNING), - tmp.c_ptr(), vcol_info->get_vcol_type_name(), + tmp.c_ptr_safe(), vcol_info->get_vcol_type_name(), const_cast(field_name.str)); } @@ -1967,6 +1967,23 @@ int Field::store_timestamp_dec(const timeval &ts, uint dec) return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec); } + +int Field::store_to_statistical_minmax_field(Field *field, String *val) +{ + val_str(val); + size_t length= Well_formed_prefix(val->charset(), val->ptr(), + MY_MIN(val->length(), field->field_length)).length(); + return field->store(val->ptr(), length, &my_charset_bin); +} + + +int Field::store_from_statistical_minmax_field(Field *stat_field, String *str) +{ + stat_field->val_str(str); + return store_text(str->ptr(), str->length(), &my_charset_bin); +} + + /** Pack the field into a format suitable for storage and transfer. @@ -3517,10 +3534,9 @@ int Field_new_decimal::cmp(const uchar *a,const uchar*b) const } -void Field_new_decimal::sort_string(uchar *buff, - uint) +void Field_new_decimal::sort_string(uchar *buff, uint length) { - memcpy(buff, ptr, bin_size); + memcpy(buff, ptr, length); } @@ -5819,7 +5835,9 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, case ANY_SUBST: if (!is_temporal_type_with_date(const_item->field_type())) { - Datetime dt(thd, const_item, Datetime::Options_cmp(thd)); + Datetime dt= type_handler()->field_type() == MYSQL_TYPE_TIMESTAMP ? + Datetime(thd, const_item, Timestamp::DatetimeOptions(thd)) : + Datetime(thd, const_item, Datetime::Options_cmp(thd)); if (!dt.is_valid_datetime()) return NULL; return new (thd->mem_root) @@ -7680,6 +7698,15 @@ my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value) } +#ifdef HAVE_valgrind_or_MSAN +void Field_varstring::mark_unused_memory_as_defined() +{ + uint used_length= get_length(); + MEM_MAKE_DEFINED(get_data() + used_length, field_length - used_length); +} +#endif + + int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr, uint max_len) const { @@ -10166,11 +10193,12 @@ void Column_definition::create_length_to_internal_length_newdecimal() bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name, - enum_vcol_info_type type) + enum_vcol_info_type type, Alter_info *alter_info) { bool ret; Item::vcol_func_processor_result res; + res.alter_info= alter_info; if (!vcol->name.length) vcol->name= *name; @@ -10179,7 +10207,6 @@ bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name, Walk through the Item tree checking if all items are valid to be part of the virtual column */ - res.errors= 0; ret= vcol->expr->walk(&Item::check_vcol_func_processor, 0, &res); vcol->flags= res.errors; @@ -10948,6 +10975,13 @@ bool Field::save_in_field_default_value(bool view_error_processing) { THD *thd= table->in_use; + /* + TODO: MDEV-19597 Refactor TABLE::vers_update_fields() via stored virtual columns + This condition will go away as well as other conditions with vers_sys_field(). + */ + if (vers_sys_field()) + return false; + if (unlikely(flags & NO_DEFAULT_VALUE_FLAG && real_type() != MYSQL_TYPE_ENUM)) { @@ -11073,6 +11107,46 @@ void Field_blob::print_key_value(String *out, uint32 length) } +/* + @brief Print value of the key part + + @param + out Output string + key value of the key + length Length of field in bytes, + excluding NULL flag and length bytes +*/ + + +void +Field::print_key_part_value(String *out, const uchar* key, uint32 length) +{ + StringBuffer<128> tmp(system_charset_info); + uint null_byte= 0; + if (real_maybe_null()) + { + /* + Byte 0 of key is the null-byte. If set, key is NULL. + Otherwise, print the key value starting immediately after the + null-byte + */ + if (*key) + { + out->append(STRING_WITH_LEN("NULL")); + return; + } + null_byte++; // Skip null byte + } + + set_key_image(key + null_byte, length); + print_key_value(&tmp, length); + if (charset() == &my_charset_bin) + out->append(tmp.ptr(), tmp.length(), tmp.charset()); + else + tmp.print(out, system_charset_info); +} + + void Field::print_key_value_binary(String *out, const uchar* key, uint32 length) { out->append_semi_hex((const char*)key, length, charset()); @@ -11086,7 +11160,7 @@ Virtual_column_info* Virtual_column_info::clone(THD *thd) return NULL; if (expr) { - dst->expr= expr->get_copy(thd); + dst->expr= expr->build_clone(thd); if (!dst->expr) return NULL; } diff --git a/sql/field.h b/sql/field.h index d709a84e0fe..420ff6866bd 100644 --- a/sql/field.h +++ b/sql/field.h @@ -551,6 +551,7 @@ static inline const char *vcol_type_name(enum_vcol_info_type type) #define VCOL_AUTO_INC 16 #define VCOL_IMPOSSIBLE 32 #define VCOL_NOT_VIRTUAL 64 /* Function can't be virtual */ +#define VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS 128 #define VCOL_NOT_STRICTLY_DETERMINISTIC \ (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC) @@ -977,6 +978,37 @@ public: DBUG_ASSERT(ls.length < UINT_MAX32); return store(ls.str, (uint) ls.length, cs); } + + /* + @brief + Store minimum/maximum value of a column in the statistics table. + @param + field statistical table field + str value buffer + */ + virtual int store_to_statistical_minmax_field(Field *field, String *str); + + /* + @brief + Store minimum/maximum value of a column from the statistical table. + @param + field statistical table field + str value buffer + */ + virtual int store_from_statistical_minmax_field(Field *field, String *str); + +#ifdef HAVE_valgrind_or_MSAN + /** + Mark unused memory in the field as defined. Mainly used to ensure + that if we write full field to disk (for example in + Count_distinct_field::add(), we don't write unitalized data to + disk which would confuse valgrind or MSAN. + */ + virtual void mark_unused_memory_as_defined() {} +#else + void mark_unused_memory_as_defined() {} +#endif + virtual double val_real()=0; virtual longlong val_int()=0; /* @@ -1432,6 +1464,13 @@ public: const SORT_FIELD_ATTR *sort_field); virtual void make_send_field(Send_field *); + + /* + Some implementations actually may write up to 8 bytes regardless of what + size was requested. This is due to the minimum value of the system variable + max_sort_length. + */ + virtual void sort_string(uchar *buff,uint length)=0; virtual bool optimize_range(uint idx, uint part) const; virtual void free() {} @@ -1572,6 +1611,7 @@ public: bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment, ulong current_row=0) const; virtual void print_key_value(String *out, uint32 length); + void print_key_part_value(String *out, const uchar *key, uint32 length); void print_key_value_binary(String *out, const uchar* key, uint32 length); protected: bool set_warning(unsigned int code, int cuted_increment) const @@ -4096,6 +4136,9 @@ public: } int store(const char *to,size_t length,CHARSET_INFO *charset) override; using Field_str::store; +#ifdef HAVE_valgrind_or_MSAN + void mark_unused_memory_as_defined() override; +#endif double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; @@ -5678,7 +5721,7 @@ int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); int convert_null_to_field_value_or_error(Field *field); bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name, - enum_vcol_info_type type); + enum_vcol_info_type type, Alter_info *alter_info= NULL); /* The following are for the interface with the .frm file diff --git a/sql/filesort.cc b/sql/filesort.cc index 9b75d088289..f5d57a36685 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -58,7 +58,6 @@ static bool save_index(Sort_param *param, uint count, SORT_INFO *table_sort); static uint suffix_length(ulong string_length); static uint sortlength(THD *thd, Sort_keys *sortorder, - bool *multi_byte_charset, bool *allow_packing_for_sortkeys); static Addon_fields *get_addon_fields(TABLE *table, uint sortlength, uint *addon_length, @@ -200,7 +199,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, ha_rows num_rows= HA_POS_ERROR; IO_CACHE tempfile, buffpek_pointers, *outfile; Sort_param param; - bool multi_byte_charset, allow_packing_for_sortkeys; + bool allow_packing_for_sortkeys; Bounded_queue pq; SQL_SELECT *const select= filesort->select; ha_rows max_rows= filesort->limit; @@ -248,8 +247,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, sort->found_rows= HA_POS_ERROR; param.sort_keys= sort_keys; - uint sort_len= sortlength(thd, sort_keys, &multi_byte_charset, - &allow_packing_for_sortkeys); + uint sort_len= sortlength(thd, sort_keys, &allow_packing_for_sortkeys); param.init_for_filesort(sort_len, table, max_rows, filesort->sort_positions); @@ -309,12 +307,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, tracker->report_sort_keys_format(param.using_packed_sortkeys()); param.using_pq= false; - if ((multi_byte_charset || param.using_packed_sortkeys()) && - !(param.tmp_buffer= (char*) my_malloc(key_memory_Sort_param_tmp_buffer, param.sort_length, - MYF(MY_WME | MY_THREAD_SPECIFIC)))) - goto err; - - size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2); set_if_bigger(min_sort_memory, sizeof(Merge_chunk*)*MERGEBUFF2); @@ -345,6 +337,9 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, tracker->report_addon_fields_format(param.using_packed_addons()); } + if (param.tmp_buffer.alloc(param.sort_length)) + goto err; + if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))) goto err; @@ -438,7 +433,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, error= 0; err: - my_free(param.tmp_buffer); if (!subselect || !subselect->is_uncacheable()) { if (!param.using_addon_fields()) @@ -592,7 +586,14 @@ Filesort::make_sortorder(THD *thd, JOIN *join, table_map first_table_bit) if (item->type() == Item::FIELD_ITEM) pos->field= ((Item_field*) item)->field; else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) - pos->field= ((Item_sum*) item)->get_tmp_table_field(); + { + // Aggregate, or Item_aggregate_ref + DBUG_ASSERT(first->type() == Item::SUM_FUNC_ITEM || + (first->type() == Item::REF_ITEM && + static_cast(first)->ref_type() == + Item_ref::AGGREGATE_REF)); + pos->field= first->get_tmp_table_field(); + } else if (item->type() == Item::COPY_STR_ITEM) { // Blob patch pos->item= ((Item_copy*) item)->get_item(); @@ -1101,10 +1102,8 @@ Type_handler_string_result::make_sort_key_part(uchar *to, Item *item, if (maybe_null) *to++= 1; - char *tmp_buffer= param->tmp_buffer ? param->tmp_buffer : (char*) to; - String tmp(tmp_buffer, param->tmp_buffer ? param->sort_length : - sort_field->length, cs); - String *res= item->str_result(&tmp); + + String *res= item->str_result(¶m->tmp_buffer); if (!res) { if (maybe_null) @@ -1853,17 +1852,15 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file, offsetof(Merge_chunk,m_current_key), 0, (queue_compare) cmp, first_cmp_arg, 0, 0))) DBUG_RETURN(1); /* purecov: inspected */ + const size_t chunk_sz = (sort_buffer.size()/((uint) (Tb-Fb) +1)); for (buffpek= Fb ; buffpek <= Tb ; buffpek++) { - buffpek->set_buffer(strpos, - strpos + (sort_buffer.size()/((uint) (Tb-Fb) +1))); - + buffpek->set_buffer(strpos, strpos + chunk_sz); buffpek->set_max_keys(maxcount); bytes_read= read_to_buffer(from_file, buffpek, param, packed_format); if (unlikely(bytes_read == (ulong) -1)) goto err; /* purecov: inspected */ - strpos+= bytes_read; - buffpek->set_buffer_end(strpos); + strpos+= chunk_sz; // If less data in buffers than expected buffpek->set_max_keys(buffpek->mem_count()); queue_insert(&queue, (uchar*) buffpek); @@ -2181,8 +2178,6 @@ Type_handler_decimal_result::sort_length(THD *thd, @param thd Thread handler @param sortorder Order of items to sort @param s_length Number of items to sort - @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset - (In which case we have to use strxnfrm()) @param allow_packing_for_sortkeys [out] set to false if packing sort keys is not allowed @@ -2196,11 +2191,9 @@ Type_handler_decimal_result::sort_length(THD *thd, */ static uint -sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset, - bool *allow_packing_for_sortkeys) +sortlength(THD *thd, Sort_keys *sort_keys, bool *allow_packing_for_sortkeys) { uint length; - *multi_byte_charset= 0; *allow_packing_for_sortkeys= true; bool allow_packing_for_keys= true; @@ -2226,10 +2219,8 @@ sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset, sortorder->cs= cs; if (use_strnxfrm((cs=sortorder->field->sort_charset()))) - { - *multi_byte_charset= true; sortorder->length= (uint) cs->strnxfrmlen(sortorder->length); - } + if (sortorder->is_variable_sized() && allow_packing_for_keys) { allow_packing_for_keys= sortorder->check_if_packing_possible(thd); @@ -2243,17 +2234,12 @@ sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset, } else { - CHARSET_INFO *cs; sortorder->item->type_handler()->sort_length(thd, sortorder->item, sortorder); sortorder->type= sortorder->item->type_handler()->is_packable() ? SORT_FIELD_ATTR::VARIABLE_SIZE : SORT_FIELD_ATTR::FIXED_SIZE; - if (use_strnxfrm((cs=sortorder->item->collation.collation))) - { - *multi_byte_charset= true; - } - sortorder->cs= cs; + sortorder->cs= sortorder->item->collation.collation; if (sortorder->is_variable_sized() && allow_packing_for_keys) { allow_packing_for_keys= sortorder->check_if_packing_possible(thd); @@ -2565,8 +2551,7 @@ Type_handler_string_result::make_packed_sort_key_part(uchar *to, Item *item, if (maybe_null) *to++= 1; - String tmp(param->tmp_buffer, param->sort_length, cs); - String *res= item->str_result(&tmp); + String *res= item->str_result(¶m->tmp_buffer); if (!res) { if (maybe_null) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 582c9bb110b..dfbc8d52dcd 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -686,7 +686,9 @@ int ha_partition::create_partitioning_metadata(const char *path, if (m_part_info) { part= m_part_info->partitions.head(); - if ((part->engine_type)->create_partitioning_metadata && + /* part->engine_type may be 0 when we failed to create the partition */ + if (part->engine_type && + (part->engine_type)->create_partitioning_metadata && ((part->engine_type)->create_partitioning_metadata)(path, old_path, action_flag)) { @@ -1192,7 +1194,17 @@ int ha_partition::analyze(THD *thd, HA_CHECK_OPT *check_opt) { DBUG_ENTER("ha_partition::analyze"); - DBUG_RETURN(handle_opt_partitions(thd, check_opt, ANALYZE_PARTS)); + int result= handle_opt_partitions(thd, check_opt, ANALYZE_PARTS); + + if ((result == 0) && m_file[0] + && (m_file[0]->ha_table_flags() & HA_ONLINE_ANALYZE)) + { + /* If this is ANALYZE TABLE that will not force table definition cache + eviction, update statistics for the partition handler. */ + this->info(HA_STATUS_CONST | HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + } + + DBUG_RETURN(result); } @@ -2270,7 +2282,8 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info) sub_elem= subpart_it++; DBUG_ASSERT(sub_elem); part= i * num_subparts + j; - DBUG_ASSERT(part < m_file_tot_parts && m_file[part]); + DBUG_ASSERT(part < m_file_tot_parts); + DBUG_ASSERT(m_file[part]); dummy_info.data_file_name= dummy_info.index_file_name = NULL; m_file[part]->update_create_info(&dummy_info); sub_elem->data_file_name = (char*) dummy_info.data_file_name; @@ -3725,11 +3738,13 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) err_handler: DEBUG_SYNC(ha_thd(), "partition_open_error"); - file= &m_file[m_tot_parts - 1]; - while (file-- != m_file) + DBUG_ASSERT(m_tot_parts > 0); + for (uint i= m_tot_parts - 1; ; --i) { - if (bitmap_is_set(&m_opened_partitions, (uint)(file - m_file))) - (*file)->ha_close(); + if (bitmap_is_set(&m_opened_partitions, i)) + m_file[i]->ha_close(); + if (!i) + break; } err_alloc: free_partition_bitmaps(); @@ -3993,7 +4008,8 @@ int ha_partition::external_lock(THD *thd, int lock_type) MY_BITMAP *used_partitions; DBUG_ENTER("ha_partition::external_lock"); - DBUG_ASSERT(!auto_increment_lock && !auto_increment_safe_stmt_log_lock); + DBUG_ASSERT(!auto_increment_lock); + DBUG_ASSERT(!auto_increment_safe_stmt_log_lock); if (lock_type == F_UNLCK) used_partitions= &m_locked_partitions; @@ -4272,8 +4288,8 @@ void ha_partition::unlock_row() bool ha_partition::was_semi_consistent_read() { DBUG_ENTER("ha_partition::was_semi_consistent_read"); - DBUG_ASSERT(m_last_part < m_tot_parts && - bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); + DBUG_ASSERT(m_last_part < m_tot_parts); + DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); DBUG_RETURN(m_file[m_last_part]->was_semi_consistent_read()); } @@ -7175,8 +7191,8 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); m_ordered_scan_ongoing= m_ordered; } - DBUG_ASSERT(m_part_spec.start_part < m_tot_parts && - m_part_spec.end_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.end_part < m_tot_parts); DBUG_RETURN(0); } @@ -7237,8 +7253,6 @@ bool ha_partition::check_parallel_search() if (order_field && order_field->table == table_list->table) { Field *part_field= m_part_info->full_part_field_array[0]; - if (set_top_table_fields) - order_field= top_table_field[order_field->field_index]; DBUG_PRINT("info",("partition order_field: %p", order_field)); DBUG_PRINT("info",("partition part_field: %p", part_field)); if (part_field == order_field) @@ -7282,8 +7296,6 @@ bool ha_partition::check_parallel_search() if (group_field && group_field->table == table_list->table) { Field *part_field= m_part_info->full_part_field_array[0]; - if (set_top_table_fields) - group_field= top_table_field[group_field->field_index]; DBUG_PRINT("info",("partition group_field: %p", group_field)); DBUG_PRINT("info",("partition part_field: %p", part_field)); if (part_field == group_field) @@ -10619,7 +10631,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, DBUG_PRINT("enter", ("offset: %lu inc: %lu desired_values: %lu " "first_value: %lu", (ulong) offset, (ulong) increment, (ulong) nb_desired_values, (ulong) *first_value)); - DBUG_ASSERT(increment && nb_desired_values); + DBUG_ASSERT(increment); + DBUG_ASSERT(nb_desired_values); *first_value= 0; if (table->s->next_number_keypart) { @@ -11014,9 +11027,9 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair) /* If the engine supports transactions, the failure will be - rollbacked. + rolled back */ - if (!m_file[correct_part_id]->has_transactions()) + if (!m_file[correct_part_id]->has_transactions_and_rollback()) { /* Log this error, so the DBA can notice it and fix it! */ sql_print_error("Table '%-192s' failed to move/insert a row" @@ -11040,7 +11053,7 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair) /* Delete row from wrong partition. */ if ((result= m_file[read_part_id]->ha_delete_row(m_rec0))) { - if (m_file[correct_part_id]->has_transactions()) + if (m_file[correct_part_id]->has_transactions_and_rollback()) break; /* We have introduced a duplicate, since we failed to remove it @@ -11218,22 +11231,6 @@ const COND *ha_partition::cond_push(const COND *cond) COND *res_cond= NULL; DBUG_ENTER("ha_partition::cond_push"); - if (set_top_table_fields) - { - /* - We want to do this in a separate loop to not come into a situation - where we have only done cond_push() to some of the tables - */ - do - { - if (((*file)->set_top_table_and_fields(top_table, - top_table_field, - top_table_fields))) - DBUG_RETURN(cond); // Abort cond push, no error - } while (*(++file)); - file= m_file; - } - do { if ((*file)->pushed_cond != cond) @@ -11865,23 +11862,6 @@ int ha_partition::info_push(uint info_type, void *info) } -void ha_partition::clear_top_table_fields() -{ - handler **file; - DBUG_ENTER("ha_partition::clear_top_table_fields"); - - if (set_top_table_fields) - { - set_top_table_fields= FALSE; - top_table= NULL; - top_table_field= NULL; - top_table_fields= 0; - for (file= m_file; *file; file++) - (*file)->clear_top_table_fields(); - } - DBUG_VOID_RETURN; -} - bool ha_partition::can_convert_string(const Field_string* field, const Column_definition& new_type) const diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 225d69b1a56..120d5cb2b30 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -473,6 +473,10 @@ public: { return m_file; } + ha_partition *get_clone_source() + { + return m_is_clone_of; + } virtual part_id_range *get_part_spec() { return &m_part_spec; @@ -1548,7 +1552,6 @@ public: */ const COND *cond_push(const COND *cond) override; void cond_pop() override; - void clear_top_table_fields() override; int info_push(uint info_type, void *info) override; private: diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 71da208d775..bf3b5ce2cd0 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2017, Aliyun and/or its affiliates. - Copyright (c) 2017, MariaDB corporation + Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,13 +19,13 @@ #include "mariadb.h" #include "sql_list.h" #include "table.h" +#include "sql_table.h" #include "sql_sequence.h" #include "ha_sequence.h" #include "sql_plugin.h" #include "mysql/plugin.h" #include "sql_priv.h" #include "sql_parse.h" -#include "sql_table.h" #include "sql_update.h" #include "sql_base.h" #include "log_event.h" @@ -108,20 +108,25 @@ int ha_sequence::open(const char *name, int mode, uint flags) MY_TEST(flags & HA_OPEN_INTERNAL_TABLE); reset_statistics(); - /* Don't try to read the initial row the call is part of create code */ - if (!(flags & (HA_OPEN_FOR_CREATE | HA_OPEN_FOR_REPAIR))) + /* + Don't try to read the initial row if the call is part of CREATE, REPAIR + or FLUSH + */ + if (!(flags & (HA_OPEN_FOR_CREATE | HA_OPEN_FOR_REPAIR | + HA_OPEN_FOR_FLUSH))) { if (unlikely((error= table->s->sequence->read_initial_values(table)))) file->ha_close(); } else if (!table->s->tmp_table) - table->m_needs_reopen= true; + table->internal_set_needs_reopen(true); /* The following is needed to fix comparison of rows in ha_update_first_row() for InnoDB */ - memcpy(table->record[1], table->s->default_values, table->s->reclength); + if (!error) + memcpy(table->record[1], table->s->default_values, table->s->reclength); } DBUG_RETURN(error); } @@ -380,6 +385,13 @@ static handler *sequence_create_handler(handlerton *hton, MEM_ROOT *mem_root) { DBUG_ENTER("sequence_create_handler"); + if (unlikely(!share)) + { + /* + This can happen if we call get_new_handler with a non existing share + */ + DBUG_RETURN(0); + } DBUG_RETURN(new (mem_root) ha_sequence(hton, share)); } @@ -427,7 +439,8 @@ static int sequence_initialize(void *p) HTON_HIDDEN | HTON_TEMPORARY_NOT_SUPPORTED | HTON_ALTER_NOT_SUPPORTED | - HTON_NO_PARTITION); + HTON_NO_PARTITION | + HTON_AUTOMATIC_DELETE_TABLE); DBUG_RETURN(0); } diff --git a/sql/handler.cc b/sql/handler.cc index ffb89b30d92..c2fb7da384c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -61,6 +61,7 @@ #include "wsrep_xid.h" #include "wsrep_thd.h" #include "wsrep_trans_observer.h" /* wsrep transaction hooks */ +#include "wsrep_var.h" /* wsrep_hton_check() */ #endif /* WITH_WSREP */ /** @@ -147,6 +148,44 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"", static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; uint known_extensions_id= 0; + +class Table_exists_error_handler : public Internal_error_handler +{ +public: + Table_exists_error_handler() + : m_handled_errors(0), m_unhandled_errors(0) + {} + + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) + { + *cond_hdl= NULL; + if (non_existing_table_error(sql_errno)) + { + m_handled_errors++; + return TRUE; + } + + if (*level == Sql_condition::WARN_LEVEL_ERROR) + m_unhandled_errors++; + return FALSE; + } + + bool safely_trapped_errors() + { + return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); + } + +private: + int m_handled_errors; + int m_unhandled_errors; +}; + + static int commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans); @@ -1244,14 +1283,14 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg, ulonglong trxid) if (all) { - trans= &thd->transaction.all; + trans= &thd->transaction->all; thd->server_status|= SERVER_STATUS_IN_TRANS; if (thd->tx_read_only) thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY; DBUG_PRINT("info", ("setting SERVER_STATUS_IN_TRANS")); } else - trans= &thd->transaction.stmt; + trans= &thd->transaction->stmt; ha_info= thd->ha_data[ht_arg->slot].ha_info + (all ? 1 : 0); @@ -1263,8 +1302,8 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg, ulonglong trxid) trans->no_2pc|=(ht_arg->prepare==0); /* Set implicit xid even if there's explicit XA, it will be ignored anyway. */ - if (thd->transaction.implicit_xid.is_null()) - thd->transaction.implicit_xid.set(thd->query_id); + if (thd->transaction->implicit_xid.is_null()) + thd->transaction->implicit_xid.set(thd->query_id); /* Register transaction start in performance schema if not done already. @@ -1327,7 +1366,7 @@ static int prepare_or_error(handlerton *ht, THD *thd, bool all) int ha_prepare(THD *thd) { int error=0, all=1; - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + THD_TRANS *trans=all ? &thd->transaction->all : &thd->transaction->stmt; Ha_trx_info *ha_info= trans->ha_list; DBUG_ENTER("ha_prepare"); @@ -1377,7 +1416,7 @@ uint ha_count_rw_all(THD *thd, Ha_trx_info **ptr_ha_info) { unsigned rw_ha_count= 0; - for (auto ha_info= thd->transaction.all.ha_list; ha_info; + for (auto ha_info= thd->transaction->all.ha_list; ha_info; ha_info= ha_info->next()) { if (ha_info->is_trx_read_write()) @@ -1472,7 +1511,7 @@ int ha_commit_trans(THD *thd, bool all) 'all' means that this is either an explicit commit issued by user, or an implicit commit issued by a DDL. */ - THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt; + THD_TRANS *trans= all ? &thd->transaction->all : &thd->transaction->stmt; /* "real" is a nick name for a transaction for which a commit will make persistent changes. E.g. a 'stmt' transaction inside a 'all' @@ -1480,7 +1519,7 @@ int ha_commit_trans(THD *thd, bool all) the changes are not durable as they might be rolled back if the enclosing 'all' transaction is rolled back. */ - bool is_real_trans= ((all || thd->transaction.all.ha_list == 0) && + bool is_real_trans= ((all || thd->transaction->all.ha_list == 0) && !(thd->variables.option_bits & OPTION_GTID_BEGIN)); Ha_trx_info *ha_info= trans->ha_list; bool need_prepare_ordered, need_commit_ordered; @@ -1507,8 +1546,8 @@ int ha_commit_trans(THD *thd, bool all) flags will not get propagated to its normal transaction's counterpart. */ - DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL || - trans == &thd->transaction.stmt); + DBUG_ASSERT(thd->transaction->stmt.ha_list == NULL || + trans == &thd->transaction->stmt); if (thd->in_sub_stmt) { @@ -1531,16 +1570,6 @@ int ha_commit_trans(THD *thd, bool all) DBUG_RETURN(2); } -#ifdef WITH_ARIA_STORAGE_ENGINE - if ((error= ha_maria::implicit_commit(thd, TRUE))) - { - my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); - ha_rollback_trans(thd, all); - DBUG_RETURN(1); - } - -#endif - if (!ha_info) { /* @@ -1548,7 +1577,7 @@ int ha_commit_trans(THD *thd, bool all) */ if (is_real_trans) { - thd->transaction.cleanup(); + thd->transaction->cleanup(); MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi); thd->m_transaction_psi= NULL; } @@ -1556,6 +1585,7 @@ int ha_commit_trans(THD *thd, bool all) if (wsrep_is_active(thd) && is_real_trans && !error) wsrep_commit_empty(thd, all); #endif /* WITH_WSREP */ + DBUG_RETURN(0); } @@ -1570,9 +1600,15 @@ int ha_commit_trans(THD *thd, bool all) bool rw_trans= is_real_trans && (rw_ha_count > (thd->is_current_stmt_binlog_disabled()?0U:1U)); MDL_request mdl_request; + mdl_request.ticket= 0; DBUG_PRINT("info", ("is_real_trans: %d rw_trans: %d rw_ha_count: %d", is_real_trans, rw_trans, rw_ha_count)); + /* + We need to test maria_hton because of plugin_innodb.test that changes + the plugin table to innodb and thus plugin_load will call + mysql_close_tables() which calls trans_commit_trans() with maria_hton = 0 + */ if (rw_trans) { /* @@ -1587,8 +1623,8 @@ int ha_commit_trans(THD *thd, bool all) MDL_EXPLICIT); if (!WSREP(thd) && - thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) + thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) { ha_rollback_trans(thd, all); DBUG_RETURN(1); @@ -1596,7 +1632,6 @@ int ha_commit_trans(THD *thd, bool all) DEBUG_SYNC(thd, "ha_commit_trans_after_acquire_commit_lock"); } - if (rw_trans && opt_readonly && !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) && @@ -1636,7 +1671,7 @@ int ha_commit_trans(THD *thd, bool all) // Here, the call will not commit inside InnoDB. It is only working // around closing thd->transaction.stmt open by TR_table::open(). if (all) - commit_one_phase_2(thd, false, &thd->transaction.stmt, false); + commit_one_phase_2(thd, false, &thd->transaction->stmt, false); } } #endif @@ -1697,11 +1732,11 @@ int ha_commit_trans(THD *thd, bool all) goto done; } - DBUG_ASSERT(thd->transaction.implicit_xid.get_my_xid() == - thd->transaction.implicit_xid.quick_get_my_xid()); - DBUG_ASSERT(!thd->transaction.xid_state.is_explicit_XA() || + DBUG_ASSERT(thd->transaction->implicit_xid.get_my_xid() == + thd->transaction->implicit_xid.quick_get_my_xid()); + DBUG_ASSERT(!thd->transaction->xid_state.is_explicit_XA() || thd->lex->xa_opt == XA_ONE_PHASE); - xid= thd->transaction.implicit_xid.quick_get_my_xid(); + xid= thd->transaction->implicit_xid.quick_get_my_xid(); #ifdef WITH_WSREP if (run_wsrep_hooks && !error) @@ -1797,7 +1832,7 @@ err: thd->rgi_slave->is_parallel_exec); } end: - if (rw_trans && mdl_request.ticket) + if (mdl_request.ticket) { /* We do not always immediately release transactional locks @@ -1832,7 +1867,7 @@ end: int ha_commit_one_phase(THD *thd, bool all) { - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + THD_TRANS *trans=all ? &thd->transaction->all : &thd->transaction->stmt; /* "real" is a nick name for a transaction for which a commit will make persistent changes. E.g. a 'stmt' transaction inside a 'all' @@ -1846,7 +1881,7 @@ int ha_commit_one_phase(THD *thd, bool all) ha_commit_one_phase() can be called with an empty transaction.all.ha_list, see why in trans_register_ha()). */ - bool is_real_trans= ((all || thd->transaction.all.ha_list == 0) && + bool is_real_trans= ((all || thd->transaction->all.ha_list == 0) && !(thd->variables.option_bits & OPTION_GTID_BEGIN)); int res; DBUG_ENTER("ha_commit_one_phase"); @@ -1893,8 +1928,8 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) if (all) { #ifdef HAVE_QUERY_CACHE - if (thd->transaction.changed_tables) - query_cache.invalidate(thd, thd->transaction.changed_tables); + if (thd->transaction->changed_tables) + query_cache.invalidate(thd, thd->transaction->changed_tables); #endif } } @@ -1902,7 +1937,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) if (is_real_trans) { thd->has_waiter= false; - thd->transaction.cleanup(); + thd->transaction->cleanup(); if (count >= 2) statistic_increment(transactions_multi_engine, LOCK_status); } @@ -1914,7 +1949,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) int ha_rollback_trans(THD *thd, bool all) { int error=0; - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + THD_TRANS *trans=all ? &thd->transaction->all : &thd->transaction->stmt; Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; /* "real" is a nick name for a transaction for which a commit will @@ -1929,15 +1964,15 @@ int ha_rollback_trans(THD *thd, bool all) ha_commit_one_phase() is called with an empty transaction.all.ha_list, see why in trans_register_ha()). */ - bool is_real_trans=all || thd->transaction.all.ha_list == 0; + bool is_real_trans=all || thd->transaction->all.ha_list == 0; DBUG_ENTER("ha_rollback_trans"); /* We must not rollback the normal transaction if a statement transaction is pending. */ - DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL || - trans == &thd->transaction.stmt); + DBUG_ASSERT(thd->transaction->stmt.ha_list == NULL || + trans == &thd->transaction->stmt); #ifdef HAVE_REPLICATION if (is_real_trans) @@ -1954,7 +1989,7 @@ int ha_rollback_trans(THD *thd, bool all) builds, we explicitly do the signalling before rolling back. */ DBUG_ASSERT(!(thd->rgi_slave && thd->rgi_slave->did_mark_start_commit) || - thd->transaction.xid_state.is_explicit_XA()); + thd->transaction->xid_state.is_explicit_XA()); if (thd->rgi_slave && thd->rgi_slave->did_mark_start_commit) thd->rgi_slave->unmark_start_commit(); } @@ -1988,7 +2023,8 @@ int ha_rollback_trans(THD *thd, bool all) int err; handlerton *ht= ha_info->ht(); if ((err= ht->rollback(ht, thd, all))) - { // cannot happen + { + // cannot happen my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; #ifdef WITH_WSREP @@ -2029,10 +2065,10 @@ int ha_rollback_trans(THD *thd, bool all) transaction hasn't been started in any transactional storage engine. */ if (thd->transaction_rollback_request) - thd->transaction.xid_state.set_error(thd->get_stmt_da()->sql_errno()); + thd->transaction->xid_state.set_error(thd->get_stmt_da()->sql_errno()); thd->has_waiter= false; - thd->transaction.cleanup(); + thd->transaction->cleanup(); } if (all) thd->transaction_rollback_request= FALSE; @@ -2050,7 +2086,7 @@ int ha_rollback_trans(THD *thd, bool all) it doesn't matter if a warning is pushed to a system thread or not: No one will see it... */ - if (is_real_trans && thd->transaction.all.modified_non_trans_table && + if (is_real_trans && thd->transaction->all.modified_non_trans_table && !thd->slave_thread && thd->killed < KILL_CONNECTION) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, @@ -2392,8 +2428,8 @@ commit_checkpoint_notify_ha(handlerton *hton, void *cookie) bool ha_rollback_to_savepoint_can_release_mdl(THD *thd) { Ha_trx_info *ha_info; - THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : - &thd->transaction.all); + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction->stmt : + &thd->transaction->all); DBUG_ENTER("ha_rollback_to_savepoint_can_release_mdl"); @@ -2417,8 +2453,8 @@ bool ha_rollback_to_savepoint_can_release_mdl(THD *thd) int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int error=0; - THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : - &thd->transaction.all); + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction->stmt : + &thd->transaction->all); Ha_trx_info *ha_info, *ha_info_next; DBUG_ENTER("ha_rollback_to_savepoint"); @@ -2503,8 +2539,8 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv) } #endif /* WITH_WSREP */ int error=0; - THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : - &thd->transaction.all); + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction->stmt : + &thd->transaction->all); Ha_trx_info *ha_info= trans->ha_list; DBUG_ENTER("ha_savepoint"); @@ -2676,26 +2712,34 @@ const char *get_canonical_filename(handler *file, const char *path, } -/** delete a table in the engine +/** + Delete a table in the engine + + @return 0 Table was deleted + @return -1 Table didn't exists, no error given + @return # Error from table handler @note ENOENT and HA_ERR_NO_SUCH_TABLE are not considered errors. - The .frm file will be deleted only if we return 0. + The .frm file should be deleted by the caller only if we return <= 0. */ + int ha_delete_table(THD *thd, handlerton *table_type, const char *path, - const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning) + const LEX_CSTRING *db, const LEX_CSTRING *alias, + bool generate_warning) { handler *file; char tmp_path[FN_REFLEN]; int error; TABLE dummy_table; TABLE_SHARE dummy_share; + bool is_error= thd->is_error(); DBUG_ENTER("ha_delete_table"); /* table_type is NULL in ALTER TABLE when renaming only .frm files */ if (table_type == NULL || table_type == view_pseudo_hton || ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) - DBUG_RETURN(0); + DBUG_RETURN(-1); bzero((char*) &dummy_table, sizeof(dummy_table)); bzero((char*) &dummy_share, sizeof(dummy_share)); @@ -2705,11 +2749,11 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, if (unlikely((error= file->ha_delete_table(path)))) { /* - it's not an error if the table doesn't exist in the engine. + It's not an error if the table doesn't exist in the engine. warn the user, but still report DROP being a success */ - bool intercept= (error == ENOENT || error == HA_ERR_NO_SUCH_TABLE || - error == HA_ERR_UNSUPPORTED); + bool intercept= non_existing_table_error(error); + DBUG_ASSERT(error > 0); if ((!intercept || generate_warning) && ! thd->is_error()) { @@ -2725,8 +2769,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, } if (intercept) { - thd->clear_error(); - error= 0; + /* Clear error if we got it in this function */ + if (!is_error) + thd->clear_error(); + error= -1; } } delete file; @@ -3105,6 +3151,9 @@ int handler::ha_index_next(uchar * buf) table->update_virtual_fields(this, VCOL_UPDATE_FOR_READ); } table->status=result ? STATUS_NOT_FOUND: 0; + + DEBUG_SYNC(ha_thd(), "handler_ha_index_next_end"); + DBUG_RETURN(result); } @@ -4367,45 +4416,64 @@ uint handler::get_dup_key(int error) @note We assume that the handler may return more extensions than - was actually used for the file. + was actually used for the file. We also assume that the first + extension is the most important one (see the comment near + handlerton::tablefile_extensions). If this exist and we can't delete + that it, we will abort the delete. + If the first one doesn't exists, we have to try to delete all other + extension as there is chance that the server had crashed between + the delete of the first file and the next @retval 0 If we successfully deleted at least one file from base_ext and - didn't get any other errors than ENOENT + didn't get any other errors than ENOENT + @retval !0 Error */ + int handler::delete_table(const char *name) { - int saved_error= 0; - int error= 0; - int enoent_or_zero; + int saved_error= ENOENT; + bool abort_if_first_file_error= 1; + bool some_file_deleted= 0; + DBUG_ENTER("handler::delete_table"); + // For discovery tables, it's ok if first file doesn't exists if (ht->discover_table) - enoent_or_zero= 0; // the table may not exist in the engine, it's ok - else - enoent_or_zero= ENOENT; // the first file of bas_ext() *must* exist - - for (const char **ext=bas_ext(); *ext ; ext++) { - if (mysql_file_delete_with_symlink(key_file_misc, name, *ext, 0)) + abort_if_first_file_error= 0; + saved_error= 0; + if (!bas_ext()) + { + DBUG_ASSERT(ht->flags & HTON_AUTOMATIC_DELETE_TABLE); + DBUG_RETURN(0); // Drop succeded + } + } + + for (const char **ext= bas_ext(); *ext ; ext++) + { + int error; + if ((error= mysql_file_delete_with_symlink(key_file_misc, name, *ext, + MYF(0)))) { if (my_errno != ENOENT) { + saved_error= my_errno; /* - If error on the first existing file, return the error. + If error other than file not found on the first existing file, + return the error. Otherwise delete as much as possible. */ - if (enoent_or_zero) - return my_errno; - saved_error= my_errno; + if (abort_if_first_file_error) + DBUG_RETURN(saved_error); } } else - enoent_or_zero= 0; // No error for ENOENT - error= enoent_or_zero; + some_file_deleted= 1; + abort_if_first_file_error= 0; } - return saved_error ? saved_error : error; + DBUG_RETURN(some_file_deleted && saved_error == ENOENT ? 0 : saved_error); } @@ -4440,6 +4508,21 @@ void handler::drop_table(const char *name) } +/** + Return true if the error from drop table means that the + table didn't exists +*/ + +bool non_existing_table_error(int error) +{ + return (error == ENOENT || error == HA_ERR_NO_SUCH_TABLE || + error == HA_ERR_UNSUPPORTED || + error == ER_NO_SUCH_TABLE || + error == ER_NO_SUCH_TABLE_IN_ENGINE || + error == ER_WRONG_OBJECT); +} + + /** Performs checks upon the table. @@ -4455,6 +4538,7 @@ void handler::drop_table(const char *name) @retval HA_ADMIN_NOT_IMPLEMENTED */ + int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) { int error; @@ -4501,7 +4585,6 @@ void handler::mark_trx_read_write_internal() */ if (ha_info->is_started()) { - DBUG_ASSERT(has_transaction_manager()); /* table_share can be NULL in ha_delete_table(). See implementation of standalone function ha_delete_table() in sql_base.cc. @@ -4534,6 +4617,19 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) } +/** + End bulk insert +*/ + +int handler::ha_end_bulk_insert() +{ + DBUG_ENTER("handler::ha_end_bulk_insert"); + DBUG_EXECUTE_IF("crash_end_bulk_insert", + { extra(HA_EXTRA_FLUSH) ; DBUG_SUICIDE();}); + estimation_rows_to_insert= 0; + DBUG_RETURN(end_bulk_insert()); +} + /** Bulk update row: public interface. @@ -4888,6 +4984,88 @@ handler::ha_drop_table(const char *name) } +/** + Structure used during force drop table. +*/ + +struct st_force_drop_table_params +{ + const char *path; + const LEX_CSTRING *db; + const LEX_CSTRING *alias; + int error; +}; + + +/** + Try to delete table from a given plugin + Table types with discovery is ignored as these .frm files would have + been created during discovery and thus doesn't need to be found + for drop table force +*/ + +static my_bool delete_table_force(THD *thd, plugin_ref plugin, void *arg) +{ + handlerton *hton = plugin_hton(plugin); + st_force_drop_table_params *param = (st_force_drop_table_params *)arg; + + /* + We have to ignore HEAP tables as these may not have been created yet + We also remove engines that is using discovery (as these will recrate + any missing .frm if needed) and tables marked with + HTON_AUTOMATIC_DELETE_TABLE as for these we can't check if the table + ever existed. + */ + if (!hton->discover_table && hton->db_type != DB_TYPE_HEAP && + !(hton->flags & HTON_AUTOMATIC_DELETE_TABLE)) + { + int error; + error= ha_delete_table(thd, hton, param->path, param->db, + param->alias, 0); + if (error > 0 && !non_existing_table_error(error)) + param->error= error; + if (error == 0) + { + param->error= 0; + return TRUE; // Table was deleted + } + } + return FALSE; +} + +/** + @brief + Traverse all plugins to delete table when .frm file is missing. + + @return -1 Table was not found in any engine + @return 0 Table was found in some engine and delete succeded + @return # Error from first engine that had a table but didn't succeed to + delete the table + @return HA_ERR_ROW_IS_REFERENCED if foreign key reference is encountered, + +*/ + +int ha_delete_table_force(THD *thd, const char *path, const LEX_CSTRING *db, + const LEX_CSTRING *alias) +{ + st_force_drop_table_params param; + Table_exists_error_handler no_such_table_handler; + DBUG_ENTER("ha_delete_table_force"); + + param.path= path; + param.db= db; + param.alias= alias; + param.error= -1; // Table not found + + thd->push_internal_handler(&no_such_table_handler); + if (plugin_foreach(thd, delete_table_force, MYSQL_STORAGE_ENGINE_PLUGIN, + ¶m)) + param.error= 0; // Delete succeded + thd->pop_internal_handler(); + DBUG_RETURN(param.error); +} + + /** Create a table in the engine: public interface. @@ -5008,7 +5186,7 @@ int ha_enable_transaction(THD *thd, bool on) DBUG_ENTER("ha_enable_transaction"); DBUG_PRINT("enter", ("on: %d", (int) on)); - if ((thd->transaction.on= on)) + if ((thd->transaction->on= on)) { /* Now all storage engines should have transaction handling enabled. @@ -5602,43 +5780,6 @@ static my_bool discover_existence(THD *thd, plugin_ref plugin, return ht->discover_table_existence(ht, args->db, args->table_name); } -class Table_exists_error_handler : public Internal_error_handler -{ -public: - Table_exists_error_handler() - : m_handled_errors(0), m_unhandled_errors(0) - {} - - bool handle_condition(THD *thd, - uint sql_errno, - const char* sqlstate, - Sql_condition::enum_warning_level *level, - const char* msg, - Sql_condition ** cond_hdl) - { - *cond_hdl= NULL; - if (sql_errno == ER_NO_SUCH_TABLE || - sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE || - sql_errno == ER_WRONG_OBJECT) - { - m_handled_errors++; - return TRUE; - } - - if (*level == Sql_condition::WARN_LEVEL_ERROR) - m_unhandled_errors++; - return FALSE; - } - - bool safely_trapped_errors() - { - return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); - } - -private: - int m_handled_errors; - int m_unhandled_errors; -}; /** Check if a given table exists, without doing a full discover, if possible @@ -5709,20 +5850,25 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, if ((type= dd_frm_type(thd, path, &engine, is_sequence)) == TABLE_TYPE_UNKNOWN) - DBUG_RETURN(0); - + { + DBUG_PRINT("exit", ("Does not exist")); + DBUG_RETURN(true); // Frm exists + } if (type != TABLE_TYPE_VIEW) { plugin_ref p= plugin_lock_by_name(thd, &engine, MYSQL_STORAGE_ENGINE_PLUGIN); *hton= p ? plugin_hton(p) : NULL; if (*hton) + { // verify that the table really exists exists= discover_existence(thd, p, &args); + } } else *hton= view_pseudo_hton; } + DBUG_PRINT("exit", (exists ? "Exists" : "Does not exist")); DBUG_RETURN(exists); } @@ -5732,13 +5878,16 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, { if (hton) *hton= args.hton; + DBUG_PRINT("exit", ("discovery found file")); DBUG_RETURN(TRUE); } if (need_full_discover_for_existence) { TABLE_LIST table; + bool exists; uint flags = GTS_TABLE | GTS_VIEW; + if (!hton) flags|= GTS_NOLOCK; @@ -5755,9 +5904,12 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, } // the table doesn't exist if we've caught ER_NO_SUCH_TABLE and nothing else - DBUG_RETURN(!no_such_table_handler.safely_trapped_errors()); + exists= !no_such_table_handler.safely_trapped_errors(); + DBUG_PRINT("exit", (exists ? "Exists" : "Does not exist")); + DBUG_RETURN(exists); } + DBUG_PRINT("exit", ("Does not exist")); DBUG_RETURN(FALSE); } @@ -6167,7 +6319,7 @@ extern "C" check_result_t handler_index_cond_check(void* h_arg) THD *thd= h->table->in_use; check_result_t res; - enum thd_kill_levels abort_at= h->has_transactions() ? + enum thd_kill_levels abort_at= h->has_rollback() ? THD_ABORT_SOFTLY : THD_ABORT_ASAP; if (thd_kill_level(thd) > abort_at) return CHECK_ABORTED_BY_USER; @@ -6571,7 +6723,6 @@ int handler::ha_reset() cancel_pushed_idx_cond(); /* Reset information about pushed index conditions */ cancel_pushed_rowid_filter(); - clear_top_table_fields(); if (lookup_handler != this) { lookup_handler->ha_external_unlock(table->in_use); @@ -6586,6 +6737,9 @@ int handler::ha_reset() static int wsrep_after_row(THD *thd) { DBUG_ENTER("wsrep_after_row"); + if (thd->internal_transaction()) + DBUG_RETURN(0); + /* enforce wsrep_max_ws_rows */ thd->wsrep_affected_rows++; if (wsrep_max_ws_rows && @@ -6596,7 +6750,7 @@ static int wsrep_after_row(THD *thd) my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0)); DBUG_RETURN(ER_ERROR_DURING_COMMIT); } - else if (wsrep_after_row(thd, false)) + else if (wsrep_after_row_internal(thd)) { DBUG_RETURN(ER_LOCK_DEADLOCK); } @@ -6934,7 +7088,7 @@ bool handler::prepare_for_row_logging() row_logging_has_trans= ((sql_command_flags[table->in_use->lex->sql_command] & (CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) || - table->file->has_transactions()); + table->file->has_transactions_and_rollback()); } else { @@ -6997,6 +7151,7 @@ int handler::ha_write_row(const uchar *buf) } #ifdef WITH_WSREP if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE && + ht->flags & HTON_WSREP_REPLICATION && !error && (error= wsrep_after_row(ha_thd()))) { DBUG_RETURN(error); @@ -7047,6 +7202,7 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) } #ifdef WITH_WSREP if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE && + ht->flags & HTON_WSREP_REPLICATION && !error && (error= wsrep_after_row(ha_thd()))) return error; #endif /* WITH_WSREP */ @@ -7110,6 +7266,7 @@ int handler::ha_delete_row(const uchar *buf) } #ifdef WITH_WSREP if (WSREP_NNULL(ha_thd()) && table_share->tmp_table == NO_TMP_TABLE && + ht->flags & HTON_WSREP_REPLICATION && !error && (error= wsrep_after_row(ha_thd()))) { return error; diff --git a/sql/handler.h b/sql/handler.h index f0da7f7b404..786dc7c4d43 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -70,6 +70,7 @@ class Column_definition; #define HA_ADMIN_NEEDS_UPGRADE -10 #define HA_ADMIN_NEEDS_ALTER -11 #define HA_ADMIN_NEEDS_CHECK -12 +#define HA_ADMIN_COMMIT_ERROR -13 /** Return values for check_if_supported_inplace_alter(). @@ -339,8 +340,17 @@ enum chf_create_flags { #define HA_CAN_ONLINE_BACKUPS (1ULL << 56) /* Support native hash index */ -#define HA_CAN_HASH_KEYS (1ULL << 58) -#define HA_LAST_TABLE_FLAG HA_CAN_HASH_KEYS +#define HA_CAN_HASH_KEYS (1ULL << 57) +#define HA_CRASH_SAFE (1ULL << 58) + +/* + There is no need to evict the table from the table definition cache having + run ANALYZE TABLE on it + */ +#define HA_ONLINE_ANALYZE (1ULL << 59) + +#define HA_LAST_TABLE_FLAG HA_ONLINE_ANALYZE + /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ @@ -617,6 +627,8 @@ given at all. */ /* Create a sequence */ #define HA_CREATE_USED_SEQUENCE (1UL << 25) +/* Tell binlog_show_create_table to print all engine options */ +#define HA_CREATE_PRINT_ALL_OPTIONS (1UL << 26) typedef ulonglong alter_table_operations; typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*); @@ -1764,6 +1776,27 @@ handlerton *ha_default_tmp_handlerton(THD *thd); */ #define HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE (1 << 15) +/* + True if handler cannot rollback transactions. If not true, the transaction + will be put in the transactional binlog cache. + For some engines, like Aria, the rollback can happen in case of crash, but + not trough a handler rollback call. +*/ +#define HTON_NO_ROLLBACK (1 << 16) + +/* + This storage engine can support both transactional and non transactional + tables +*/ +#define HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL (1 << 17) + +/* + The engine doesn't keep track of tables, delete_table() is not + needed and delete_table() always returns 0 (table deleted). This flag + mainly used to skip storage engines in case of ha_delete_table_force() +*/ +#define HTON_AUTOMATIC_DELETE_TABLE (1 << 18) + class Ha_trx_info; struct THD_TRANS @@ -3222,12 +3255,6 @@ public: /** End a batch started with @c start_psi_batch_mode. */ void end_psi_batch_mode(); - bool set_top_table_fields; - - struct TABLE *top_table; - Field **top_table_field; - uint top_table_fields; - /* If we have row logging enabled for this table */ bool row_logging, row_logging_init; /* If the row logging should be done in transaction cache */ @@ -3276,8 +3303,6 @@ public: m_psi_batch_mode(PSI_BATCH_MODE_NONE), m_psi_numrows(0), m_psi_locker(NULL), - set_top_table_fields(FALSE), top_table(0), - top_table_field(0), top_table_fields(0), row_logging(0), row_logging_init(0), m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0) { @@ -3415,13 +3440,7 @@ public: start_bulk_insert(rows, flags); DBUG_VOID_RETURN; } - int ha_end_bulk_insert() - { - DBUG_ENTER("handler::ha_end_bulk_insert"); - estimation_rows_to_insert= 0; - int ret= end_bulk_insert(); - DBUG_RETURN(ret); - } + int ha_end_bulk_insert(); int ha_bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found); int ha_delete_all_rows(); @@ -3540,9 +3559,12 @@ public: virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; } /* - True if changes to the table is persistent (no rollback) - This is mainly used to decide how to log changes to the table in - the binary log. + True if changes to the table is persistent (if there are no rollback) + This is used to decide: + - If the table is stored in the transaction or non transactional binary + log + - How things are tracked in trx and in add_changed_table(). + - If we can combine several statements under one commit in the binary log. */ bool has_transactions() { @@ -3550,11 +3572,31 @@ public: == 0); } /* - True if the underlaying table doesn't support transactions + True if table has both transactions and rollback. This is used to decide + if we should write the changes to the binary log. If this is true, + we don't have to write failed statements to the log as they can be + rolled back. + */ + bool has_transactions_and_rollback() + { + return has_transactions() && has_rollback(); + } + /* + True if the underlaying table support transactions and rollback */ bool has_transaction_manager() { - return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0); + return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0 && has_rollback()); + } + + /* + True if table has rollback. Used to check if an update on the table + can be killed fast. + */ + + bool has_rollback() + { + return ((ht->flags & HTON_NO_ROLLBACK) == 0); } /** @@ -4302,36 +4344,6 @@ public: */ virtual int info_push(uint info_type, void *info) { return 0; }; - /** - This function is used to get correlating of a parent (table/column) - and children (table/column). When conditions are pushed down to child - table (like child of myisam_merge), child table needs to know about - which table/column is my parent for understanding conditions. - */ - virtual int set_top_table_and_fields(TABLE *top_table, - Field **top_table_field, - uint top_table_fields) - { - if (!set_top_table_fields) - { - set_top_table_fields= TRUE; - this->top_table= top_table; - this->top_table_field= top_table_field; - this->top_table_fields= top_table_fields; - } - return 0; - } - virtual void clear_top_table_fields() - { - if (set_top_table_fields) - { - set_top_table_fields= FALSE; - top_table= NULL; - top_table_field= NULL; - top_table_fields= 0; - } - } - /** Push down an index condition to the handler. @@ -4856,9 +4868,9 @@ private: DBUG_ASSERT(!(ha_table_flags() & HA_CAN_REPAIR)); return HA_ADMIN_NOT_IMPLEMENTED; } +protected: virtual void start_bulk_insert(ha_rows rows, uint flags) {} virtual int end_bulk_insert() { return 0; } -protected: virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } @@ -4974,7 +4986,6 @@ public: inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data); virtual void set_lock_type(enum thr_lock_type lock); - friend check_result_t handler_index_cond_check(void* h_arg); friend check_result_t handler_rowid_filter_check(void *h_arg); @@ -5104,7 +5115,11 @@ int ha_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, LEX_CUSTRING *frm); int ha_delete_table(THD *thd, handlerton *db_type, const char *path, - const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); + const LEX_CSTRING *db, const LEX_CSTRING *alias, + bool generate_warning); +int ha_delete_table_force(THD *thd, const char *path, const LEX_CSTRING *db, + const LEX_CSTRING *alias); + void ha_prepare_for_backup(); void ha_end_backup(); void ha_pre_shutdown(); @@ -5293,4 +5308,5 @@ void print_keydup_error(TABLE *table, KEY *key, myf errflag); int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table); uint ha_count_rw_all(THD *thd, Ha_trx_info **ptr_ha_info); +bool non_existing_table_error(int error); #endif /* HANDLER_INCLUDED */ diff --git a/sql/item.cc b/sql/item.cc index 1a28563a229..9b321103e07 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -99,6 +99,13 @@ void item_init(void) } +void Item::raise_error_not_evaluable() +{ + Item::Print tmp(this, QT_ORDINARY); + my_error(ER_NOT_ALLOWED_IN_THIS_CONTEXT, MYF(0), tmp.ptr()); +} + + void Item::push_note_converted_to_negative_complement(THD *thd) { push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, @@ -757,6 +764,29 @@ bool Item_field::collect_item_field_processor(void *arg) } +void Item_ident::undeclared_spvar_error() const +{ + /* + We assume this is an unknown SP variable, possibly a ROW variable. + Print the leftmost name in the error: + SET var=a; -> a + SET var=a.b; -> a + SET var=a.b.c; -> a + */ + my_error(ER_SP_UNDECLARED_VAR, MYF(0), db_name.str ? db_name.str : + table_name.str ? table_name.str : + field_name.str); +} + +bool Item_field::unknown_splocal_processor(void *arg) +{ + DBUG_ENTER("Item_field::unknown_splocal_processor"); + DBUG_ASSERT(type() == FIELD_ITEM); + undeclared_spvar_error(); + DBUG_RETURN(true); +} + + bool Item_field::add_field_to_set_processor(void *arg) { DBUG_ENTER("Item_field::add_field_to_set_processor"); @@ -1463,6 +1493,37 @@ bool mark_unsupported_function(const char *w1, const char *w2, } +bool Item_field::check_vcol_func_processor(void *arg) +{ + context= 0; + vcol_func_processor_result *res= (vcol_func_processor_result *) arg; + if (res && res->alter_info) + { + for (Key &k: res->alter_info->key_list) + { + if (k.type != Key::FOREIGN_KEY) + continue; + Foreign_key *fk= (Foreign_key*) &k; + if (fk->update_opt != FK_OPTION_CASCADE) + continue; + for (Key_part_spec& kp: fk->columns) + { + if (!lex_string_cmp(system_charset_info, &kp.field_name, &field_name)) + { + return mark_unsupported_function(field_name.str, arg, VCOL_IMPOSSIBLE); + } + } + } + } + if (field && (field->unireg_check == Field::NEXT_NUMBER)) + { + // Auto increment fields are unsupported + return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC); + } + return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF); +} + + Query_fragment::Query_fragment(THD *thd, sp_head *sphead, const char *start, const char *end) { @@ -2991,6 +3052,17 @@ Item_field::Item_field(THD *thd, Item_field *item) } +bool Item_field::is_json_type() +{ + if (!field->check_constraint || + field->check_constraint->expr->type() != FUNC_ITEM) + return FALSE; + + Item_func *f= (Item_func *) field->check_constraint->expr; + return f->functype() == Item_func::JSON_VALID_FUNC; +} + + void Item_field::set_field(Field *field_par) { field=result_field=field_par; // for easy coding with fields @@ -4298,6 +4370,23 @@ int Item_param::save_in_field(Field *field, bool no_conversions) } +bool Item_param::is_evaluable_expression() const +{ + switch (state) { + case SHORT_DATA_VALUE: + case LONG_DATA_VALUE: + case NULL_VALUE: + return true; + case NO_VALUE: + return true; // Not assigned yet, so we don't know + case IGNORE_VALUE: + case DEFAULT_VALUE: + break; + } + return false; +} + + bool Item_param::can_return_value() const { // There's no "default". See comments in Item_param::save_in_field(). @@ -6833,8 +6922,8 @@ Item_float::Item_float(THD *thd, const char *str_arg, size_t length): value= my_charset_bin.strntod((char*) str_arg, length, &end_not_used, &error); if (unlikely(error)) { - char tmp[NAME_LEN + 1]; - my_snprintf(tmp, sizeof(tmp), "%.*s", (int)length, str_arg); + char tmp[NAME_LEN + 2]; + my_snprintf(tmp, sizeof(tmp), "%.*s", static_cast(length), str_arg); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp); } presentation= name.str= str_arg; @@ -9229,12 +9318,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) Item_field *field_arg; Field *def_field; DBUG_ASSERT(fixed == 0); - - if (!arg) - { - fixed= 1; - return FALSE; - } + DBUG_ASSERT(arg); /* DEFAULT() do not need table field so should not ask handler to bring @@ -9309,11 +9393,7 @@ void Item_default_value::cleanup() void Item_default_value::print(String *str, enum_query_type query_type) { - if (!arg) - { - str->append(STRING_WITH_LEN("default")); - return; - } + DBUG_ASSERT(arg); str->append(STRING_WITH_LEN("default(")); /* We take DEFAULT from a field so do not need it value in case of const @@ -9327,11 +9407,18 @@ void Item_default_value::print(String *str, enum_query_type query_type) void Item_default_value::calculate() { + DBUG_ASSERT(arg); if (field->default_value) field->set_default(); DEBUG_SYNC(field->table->in_use, "after_Item_default_value_calculate"); } +bool Item_default_value::val_native(THD *thd, Native *to) +{ + calculate(); + return Item_field::val_native(thd, to); +} + String *Item_default_value::val_str(String *str) { calculate(); @@ -9370,14 +9457,8 @@ bool Item_default_value::send(Protocol *protocol, st_value *buffer) int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) { - if (arg) - { - calculate(); - return Item_field::save_in_field(field_arg, no_conversions); - } - - return field_arg->save_in_field_default_value(context->error_processor == - &view_error_processor); + calculate(); + return Item_field::save_in_field(field_arg, no_conversions); } table_map Item_default_value::used_tables() const @@ -9398,13 +9479,7 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer, uchar *args) { DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); - - /* - If the value of arg is NULL, then this object represents a constant, - so further transformation is unnecessary (and impossible). - */ - if (!arg) - return 0; + DBUG_ASSERT(arg); Item *new_item= arg->transform(thd, transformer, args); if (!new_item) @@ -9421,57 +9496,6 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer, return (this->*transformer)(thd, args); } -void Item_ignore_value::print(String *str, enum_query_type query_type) -{ - str->append(STRING_WITH_LEN("ignore")); -} - -int Item_ignore_value::save_in_field(Field *field_arg, bool no_conversions) -{ - return field_arg->save_in_field_ignore_value(context->error_processor == - &view_error_processor); -} - -String *Item_ignore_value::val_str(String *str) -{ - DBUG_ASSERT(0); // never should be called - null_value= 1; - return 0; -} - -double Item_ignore_value::val_real() -{ - DBUG_ASSERT(0); // never should be called - null_value= 1; - return 0.0; -} - -longlong Item_ignore_value::val_int() -{ - DBUG_ASSERT(0); // never should be called - null_value= 1; - return 0; -} - -my_decimal *Item_ignore_value::val_decimal(my_decimal *decimal_value) -{ - DBUG_ASSERT(0); // never should be called - null_value= 1; - return 0; -} - -bool Item_ignore_value::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) -{ - DBUG_ASSERT(0); // never should be called - null_value= 1; - return TRUE; -} - -bool Item_ignore_value::send(Protocol *protocol, st_value *buffer) -{ - DBUG_ASSERT(0); // never should be called - return TRUE; -} bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { diff --git a/sql/item.h b/sql/item.h index 3073a4d240d..8118b079ca1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -763,6 +763,7 @@ public: CONST_ITEM, NULL_ITEM, // Item_null or Item_param bound to NULL COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, + CONTEXTUALLY_TYPED_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, @@ -843,6 +844,7 @@ protected: const Tmp_field_param *param, bool is_explicit_null); + void raise_error_not_evaluable(); void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_positive_complement(THD *thd); @@ -1592,7 +1594,14 @@ public: a constant expression. Used in the optimizer to propagate basic constants. */ virtual bool basic_const_item() const { return 0; } - /* + /** + Determines if the expression is allowed as + a virtual column assignment source: + INSERT INTO t1 (vcol) VALUES (10) -> error + INSERT INTO t1 (vcol) VALUES (NULL) -> ok + */ + virtual bool vcol_assignment_allowed_value() const { return false; } + /** Test if "this" is an ORDER position (rather than an expression). Notes: - can be called before fix_fields(). @@ -1600,8 +1609,27 @@ public: positions. (And they can't be used before fix_fields is called for them). */ virtual bool is_order_clause_position() const { return false; } + /* + Determines if the Item is an evaluable expression, that is + it can return a value, so we can call methods val_xxx(), get_date(), etc. + Most items are evaluable expressions. + Examples of non-evaluable expressions: + - Item_contextually_typed_value_specification (handling DEFAULT and IGNORE) + - Item_type_param bound to DEFAULT and IGNORE + We cannot call the mentioned methods for these Items, + their method implementations typically have DBUG_ASSERT(0). + */ + virtual bool is_evaluable_expression() const { return true; } + bool check_is_evaluable_expression_or_error() + { + if (is_evaluable_expression()) + return false; // Ok + raise_error_not_evaluable(); + return true; // Error + } /* cloning of constant items (0 if it is not const) */ virtual Item *clone_item(THD *thd) { return 0; } + /* deep copy item */ virtual Item* build_clone(THD *thd) { return get_copy(thd); } virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const @@ -1898,6 +1926,7 @@ public: virtual bool cleanup_excluding_const_fields_processor (void *arg) { return cleanup_processor(arg); } virtual bool collect_item_field_processor(void *arg) { return 0; } + virtual bool unknown_splocal_processor(void *arg) { return 0; } virtual bool collect_outer_ref_processor(void *arg) {return 0; } virtual bool check_inner_refs_processor(void *arg) { return 0; } virtual bool find_item_in_field_list_processor(void *arg) { return 0; } @@ -2027,6 +2056,9 @@ public: { uint errors; /* Bits of possible errors */ const char *name; /* Not supported function */ + Alter_info *alter_info; + vcol_func_processor_result() : + errors(0), name(NULL), alter_info(NULL) {} }; struct func_processor_rename { @@ -2094,6 +2126,10 @@ public: */ virtual bool find_not_null_fields(table_map allowed) { return false; } + /* + Does not guarantee deep copy (depends on copy ctor). + See build_clone() for deep copy. + */ virtual Item *get_copy(THD *thd)=0; bool cache_const_expr_analyzer(uchar **arg); @@ -3240,6 +3276,8 @@ protected: LEX_CSTRING orig_table_name; LEX_CSTRING orig_field_name; + void undeclared_spvar_error() const; + public: Name_resolution_context *context; LEX_CSTRING db_name; @@ -3351,6 +3389,7 @@ public: my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); bool is_null_result(); + bool is_json_type(); bool send(Protocol *protocol, st_value *buffer); Load_data_outvar *get_load_data_outvar() { @@ -3456,6 +3495,7 @@ public: Item *get_tmp_table_item(THD *thd); bool find_not_null_fields(table_map allowed); bool collect_item_field_processor(void * arg); + bool unknown_splocal_processor(void *arg); bool add_field_to_set_processor(void * arg); bool find_item_in_field_list_processor(void *arg); bool register_field_in_read_map(void *arg); @@ -3470,16 +3510,7 @@ public: bool switch_to_nullable_fields_processor(void *arg); bool update_vcol_processor(void *arg); bool rename_fields_processor(void *arg); - bool check_vcol_func_processor(void *arg) - { - context= 0; - if (field && (field->unireg_check == Field::NEXT_NUMBER)) - { - // Auto increment fields are unsupported - return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC); - } - return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF); - } + bool check_vcol_func_processor(void *arg); bool set_fields_as_dependent_processor(void *arg) { if (!(used_tables() & OUTER_REF_TABLE_BIT)) @@ -3611,6 +3642,7 @@ public: collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } enum Type type() const { return NULL_ITEM; } + bool vcol_assignment_allowed_value() const { return true; } double val_real(); longlong val_int(); String *val_str(String *str); @@ -3646,9 +3678,11 @@ public: Field *result_field; Item_null_result(THD *thd): Item_null(thd), result_field(0) {} bool is_result_field() { return result_field != 0; } - enum_field_types field_type() const + const Type_handler *type_handler() const { - return result_field->type(); + if (result_field) + return result_field->type_handler(); + return &type_handler_null; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) @@ -3845,6 +3879,7 @@ class Item_param :public Item_basic_value, const String *value_query_val_str(THD *thd, String* str) const; Item *value_clone_item(THD *thd); + bool is_evaluable_expression() const; bool can_return_value() const; public: @@ -3856,6 +3891,21 @@ public: const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } + bool vcol_assignment_allowed_value() const + { + switch (state) { + case NULL_VALUE: + case DEFAULT_VALUE: + case IGNORE_VALUE: + return true; + case NO_VALUE: + case SHORT_DATA_VALUE: + case LONG_DATA_VALUE: + break; + } + return false; + } + Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); @@ -5274,6 +5324,7 @@ public: { return ref ? (*ref)->get_typelib() : NULL; } + bool is_json_type() { return (*ref)->is_json_type(); } bool walk(Item_processor processor, bool walk_subquery, void *arg) { @@ -6014,7 +6065,7 @@ public: table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } - bool check_vcol_func_processor(void *arg) + bool check_vcol_func_processor(void *arg) { return mark_unsupported_function("copy", arg, VCOL_IMPOSSIBLE); } @@ -6243,12 +6294,8 @@ class Item_default_value : public Item_field public: Item *arg= nullptr; Field *cached_field= nullptr; - Item_default_value(THD *thd, Name_resolution_context *context_arg) : - Item_field(thd, context_arg) {} Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) : Item_field(thd, context_arg), arg(a) {} - Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a) - :Item_field(thd, context_arg) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } bool eq(const Item *item, bool binary_cmp) const; bool fix_fields(THD *, Item **); @@ -6259,12 +6306,13 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to); bool send(Protocol *protocol, st_value *buffer); int save_in_field(Field *field_arg, bool no_conversions); bool save_in_param(THD *thd, Item_param *param) { // It should not be possible to have "EXECUTE .. USING DEFAULT(a)" - DBUG_ASSERT(arg == NULL); + DBUG_ASSERT(0); param->set_default(); return false; } @@ -6289,34 +6337,127 @@ public: Item *transform(THD *thd, Item_transformer transformer, uchar *args); }; + +class Item_contextually_typed_value_specification: public Item +{ +public: + Item_contextually_typed_value_specification(THD *thd) :Item(thd) + { } + enum Type type() const { return CONTEXTUALLY_TYPED_VALUE_ITEM; } + bool vcol_assignment_allowed_value() const { return true; } + bool eq(const Item *item, bool binary_cmp) const + { + return false; + } + bool is_evaluable_expression() const { return false; } + Field *create_tmp_field_ex(MEM_ROOT *root, + TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } + String *val_str(String *str) + { + DBUG_ASSERT(0); // never should be called + null_value= true; + return 0; + } + double val_real() + { + DBUG_ASSERT(0); // never should be called + null_value= true; + return 0.0; + } + longlong val_int() + { + DBUG_ASSERT(0); // never should be called + null_value= true; + return 0; + } + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(0); // never should be called + null_value= true; + return 0; + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + DBUG_ASSERT(0); // never should be called + return null_value= true; + } + bool send(Protocol *protocol, st_value *buffer) + { + DBUG_ASSERT(0); + return true; + } + const Type_handler *type_handler() const + { + DBUG_ASSERT(0); + return &type_handler_null; + } +}; + + +/* + ::= DEFAULT +*/ +class Item_default_specification: + public Item_contextually_typed_value_specification +{ +public: + Item_default_specification(THD *thd) + :Item_contextually_typed_value_specification(thd) + { } + void print(String *str, enum_query_type query_type) + { + str->append(STRING_WITH_LEN("default")); + } + int save_in_field(Field *field_arg, bool no_conversions) + { + return field_arg->save_in_field_default_value(false); + } + bool save_in_param(THD *thd, Item_param *param) + { + param->set_default(); + return false; + } + Item *get_copy(THD *thd) + { return get_item_copy(thd, this); } +}; + + /** This class is used as bulk parameter INGNORE representation. It just do nothing when assigned to a field + This is a non-standard MariaDB extension. */ -class Item_ignore_value : public Item_default_value +class Item_ignore_specification: + public Item_contextually_typed_value_specification { public: - Item_ignore_value(THD *thd, Name_resolution_context *context_arg) - :Item_default_value(thd, context_arg) - {}; - - void print(String *str, enum_query_type query_type); - int save_in_field(Field *field_arg, bool no_conversions); + Item_ignore_specification(THD *thd) + :Item_contextually_typed_value_specification(thd) + { } + void print(String *str, enum_query_type query_type) + { + str->append(STRING_WITH_LEN("ignore")); + } + int save_in_field(Field *field_arg, bool no_conversions) + { + return field_arg->save_in_field_ignore_value(false); + } bool save_in_param(THD *thd, Item_param *param) { param->set_ignore(); return false; } - String *val_str(String *str); - double val_real(); - longlong val_int(); - my_decimal *val_decimal(my_decimal *decimal_value); - bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); - bool send(Protocol *protocol, st_value *buffer); + Item *get_copy(THD *thd) + { return get_item_copy(thd, this); } }; @@ -6448,6 +6589,7 @@ private: */ bool read_only; public: + bool unknown_splocal_processor(void *arg) { return false; } bool check_vcol_func_processor(void *arg); }; @@ -6660,6 +6802,13 @@ public: bool cache_value(); bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); int save_in_field(Field *field, bool no_conversions); + bool setup(THD *thd, Item *item) + { + if (Item_cache_int::setup(thd, item)) + return true; + set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); + return false; + } void store_packed(longlong val_arg, Item *example); /* Having a clone_item method tells optimizer that this object @@ -7059,6 +7208,23 @@ public: enum Type type() const { return TYPE_HOLDER; } const TYPELIB *get_typelib() const { return enum_set_typelib; } + /* + When handling a query like this: + VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin); + Item_type_holder can be passed to + Type_handler_xxx::Item_hybrid_func_fix_attributes() + We don't want the latter to perform character set conversion of a + Item_type_holder by calling its val_str(), which calls DBUG_ASSERT(0). + Let's override const_item() and is_expensive() to avoid this. + Note, Item_hybrid_func_fix_attributes() could probably + have a new argument to distinguish what we need: + - (a) aggregate data type attributes only + - (b) install converters after attribute aggregation + So st_select_lex_unit::join_union_type_attributes() could + ask it to do (a) only, without (b). + */ + bool const_item() const { return false; } + bool is_expensive() { return true; } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7fe16848082..24914accc6f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4733,43 +4733,73 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding) } -longlong Item_func_bit_or::val_int() +class Func_handler_bit_or_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - ulonglong arg1= (ulonglong) args[0]->val_int(); - if (args[0]->null_value) +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ + DBUG_ASSERT(item->is_fixed()); + Longlong_null a= item->arguments()[0]->to_longlong_null(); + return a.is_null() ? a : a | item->arguments()[1]->to_longlong_null(); } - ulonglong arg2= (ulonglong) args[1]->val_int(); - if (args[1]->null_value) +}; + + +class Func_handler_bit_or_dec_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; - return 0; + DBUG_ASSERT(item->is_fixed()); + VDec a(item->arguments()[0]); + return a.is_null() ? Longlong_null() : + a.to_xlonglong_null() | VDec(item->arguments()[1]).to_xlonglong_null(); } - null_value=0; - return (longlong) (arg1 | arg2); +}; + + +bool Item_func_bit_or::fix_length_and_dec() +{ + static Func_handler_bit_or_int_to_ulonglong ha_int_to_ull; + static Func_handler_bit_or_dec_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull); } -longlong Item_func_bit_and::val_int() +class Func_handler_bit_and_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - ulonglong arg1= (ulonglong) args[0]->val_int(); - if (args[0]->null_value) +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ + DBUG_ASSERT(item->is_fixed()); + Longlong_null a= item->arguments()[0]->to_longlong_null(); + return a.is_null() ? a : a & item->arguments()[1]->to_longlong_null(); } - ulonglong arg2= (ulonglong) args[1]->val_int(); - if (args[1]->null_value) +}; + + +class Func_handler_bit_and_dec_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ + DBUG_ASSERT(item->is_fixed()); + VDec a(item->arguments()[0]); + return a.is_null() ? Longlong_null() : + a.to_xlonglong_null() & VDec(item->arguments()[1]).to_xlonglong_null(); } - null_value=0; - return (longlong) (arg1 & arg2); +}; + + +bool Item_func_bit_and::fix_length_and_dec() +{ + static Func_handler_bit_and_int_to_ulonglong ha_int_to_ull; + static Func_handler_bit_and_dec_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull); } Item_cond::Item_cond(THD *thd, Item_cond *item) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8d5cfb359ec..6d02d6642e2 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -396,6 +396,7 @@ public: { return args[1]; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } + enum precedence precedence() const { return args[1]->precedence(); } }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 52eeaf10cd5..9e30afd0239 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2139,44 +2139,103 @@ double Item_func_cot::val_real() // Shift-functions, same as << and >> in C/C++ -longlong Item_func_shift_left::val_int() +class Func_handler_shift_left_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - uint shift; - ulonglong res= ((ulonglong) args[0]->val_int() << - (shift=(uint) args[1]->val_int())); - if (args[0]->null_value || args[1]->null_value) +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; - return 0; + DBUG_ASSERT(item->is_fixed()); + return item->arguments()[0]->to_longlong_null() << + item->arguments()[1]->to_longlong_null(); } - null_value=0; - return (shift < sizeof(longlong)*8 ? (longlong) res : 0); -} +}; -longlong Item_func_shift_right::val_int() + +class Func_handler_shift_left_decimal_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - uint shift; - ulonglong res= (ulonglong) args[0]->val_int() >> - (shift=(uint) args[1]->val_int()); - if (args[0]->null_value || args[1]->null_value) +public: + Longlong_null to_longlong_null(Item_handled_func *item) const { - null_value=1; - return 0; + DBUG_ASSERT(item->is_fixed()); + return VDec(item->arguments()[0]).to_xlonglong_null() << + item->arguments()[1]->to_longlong_null(); } - null_value=0; - return (shift < sizeof(longlong)*8 ? (longlong) res : 0); +}; + + +bool Item_func_shift_left::fix_length_and_dec() +{ + static Func_handler_shift_left_int_to_ulonglong ha_int_to_ull; + static Func_handler_shift_left_decimal_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull); } -longlong Item_func_bit_neg::val_int() +class Func_handler_shift_right_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - ulonglong res= (ulonglong) args[0]->val_int(); - if ((null_value=args[0]->null_value)) - return 0; - return ~res; +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->fixed == 1); + return item->arguments()[0]->to_longlong_null() >> + item->arguments()[1]->to_longlong_null(); + } +}; + + +class Func_handler_shift_right_decimal_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return VDec(item->arguments()[0]).to_xlonglong_null() >> + item->arguments()[1]->to_longlong_null(); + } +}; + + +bool Item_func_shift_right::fix_length_and_dec() +{ + static Func_handler_shift_right_int_to_ulonglong ha_int_to_ull; + static Func_handler_shift_right_decimal_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull); +} + + +class Func_handler_bit_neg_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return ~ item->arguments()[0]->to_longlong_null(); + } +}; + + +class Func_handler_bit_neg_decimal_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return ~ VDec(item->arguments()[0]).to_xlonglong_null(); + } +}; + + +bool Item_func_bit_neg::fix_length_and_dec() +{ + static Func_handler_bit_neg_int_to_ulonglong ha_int_to_ull; + static Func_handler_bit_neg_decimal_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op1_std(&ha_int_to_ull, &ha_dec_to_ull); } @@ -2184,6 +2243,12 @@ longlong Item_func_bit_neg::val_int() void Item_func_int_val::fix_length_and_dec_int_or_decimal() { + /* + The INT branch of this code should be revised. + It creates too large data types, e.g. + CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(9999999.999) AS fa; + results in a BININT(10) column, while INT(7) should probably be enough. + */ ulonglong tmp_max_length= (ulonglong ) args[0]->max_length - (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2; max_length= tmp_max_length > (ulonglong) UINT_MAX32 ? @@ -2198,6 +2263,9 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal() */ if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2) { + fix_char_length( + my_decimal_precision_to_length_no_truncation( + args[0]->decimal_int_part(), 0, false)); set_handler(&type_handler_newdecimal); } else @@ -2314,6 +2382,8 @@ void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set) set_handler(&type_handler_newdecimal); unsigned_flag= args[0]->unsigned_flag; decimals= decimals_to_set; + if (!precision) + precision= 1; // DECIMAL(0,0) -> DECIMAL(1,0) max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, unsigned_flag); @@ -3188,13 +3258,39 @@ longlong Item_func_find_in_set::val_int() return 0; } -longlong Item_func_bit_count::val_int() + +class Func_handler_bit_count_int_to_slong: + public Item_handled_func::Handler_slong2 { - DBUG_ASSERT(fixed == 1); - ulonglong value= (ulonglong) args[0]->val_int(); - if ((null_value= args[0]->null_value)) - return 0; /* purecov: inspected */ - return (longlong) my_count_bits(value); +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return item->arguments()[0]->to_longlong_null().bit_count(); + } +}; + + +class Func_handler_bit_count_decimal_to_slong: + public Item_handled_func::Handler_slong2 +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return VDec(item->arguments()[0]).to_xlonglong_null().bit_count(); + } +}; + + +bool Item_func_bit_count::fix_length_and_dec() +{ + static Func_handler_bit_count_int_to_slong ha_int_to_slong; + static Func_handler_bit_count_decimal_to_slong ha_dec_to_slong; + set_func_handler(args[0]->cmp_type() == INT_RESULT ? + (const Handler *) &ha_int_to_slong : + (const Handler *) &ha_dec_to_slong); + return m_func_handler->fix_length_and_dec(this); } @@ -3651,12 +3747,13 @@ longlong Item_master_pos_wait::val_int() THD* thd = current_thd; String *log_name = args[0]->val_str(&value); int event_count= 0; + DBUG_ENTER("Item_master_pos_wait::val_int"); null_value=0; if (thd->slave_thread || !log_name || !log_name->length()) { null_value = 1; - return 0; + DBUG_RETURN(0); } #ifdef HAVE_REPLICATION longlong pos = (ulong)args[1]->val_int(); @@ -3692,13 +3789,15 @@ longlong Item_master_pos_wait::val_int() } mi->release(); #endif - return event_count; + DBUG_PRINT("exit", ("event_count: %d null_value: %d", event_count, + (int) null_value)); + DBUG_RETURN(event_count); #ifdef HAVE_REPLICATION err: { null_value = 1; - return 0; + DBUG_RETURN(0); } #endif } @@ -3709,11 +3808,12 @@ longlong Item_master_gtid_wait::val_int() DBUG_ASSERT(fixed == 1); longlong result= 0; String *gtid_pos __attribute__((unused)) = args[0]->val_str(&value); + DBUG_ENTER("Item_master_gtid_wait::val_int"); if (args[0]->null_value) { null_value= 1; - return 0; + DBUG_RETURN(0); } null_value=0; @@ -3730,7 +3830,7 @@ longlong Item_master_gtid_wait::val_int() #else null_value= 0; #endif /* REPLICATION */ - return result; + DBUG_RETURN(result); } @@ -4691,10 +4791,12 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, entry->unsigned_flag= unsigned_arg; } entry->type=type; +#ifdef USER_VAR_TRACKING #ifndef EMBEDDED_LIBRARY THD *thd= current_thd; thd->session_tracker.user_variables.mark_as_changed(thd, entry); #endif +#endif // USER_VAR_TRACKING return 0; } @@ -6210,14 +6312,38 @@ void Item_func_match::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("))")); } -longlong Item_func_bit_xor::val_int() + +class Func_handler_bit_xor_int_to_ulonglong: + public Item_handled_func::Handler_ulonglong { - DBUG_ASSERT(fixed == 1); - ulonglong arg1= (ulonglong) args[0]->val_int(); - ulonglong arg2= (ulonglong) args[1]->val_int(); - if ((null_value= (args[0]->null_value || args[1]->null_value))) - return 0; - return (longlong) (arg1 ^ arg2); +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return item->arguments()[0]->to_longlong_null() ^ + item->arguments()[1]->to_longlong_null(); + } +}; + + +class Func_handler_bit_xor_dec_to_ulonglong: + public Item_handled_func::Handler_ulonglong +{ +public: + Longlong_null to_longlong_null(Item_handled_func *item) const + { + DBUG_ASSERT(item->is_fixed()); + return VDec(item->arguments()[0]).to_xlonglong_null() ^ + VDec(item->arguments()[1]).to_xlonglong_null(); + } +}; + + +bool Item_func_bit_xor::fix_length_and_dec() +{ + static const Func_handler_bit_xor_int_to_ulonglong ha_int_to_ull; + static const Func_handler_bit_xor_dec_to_ulonglong ha_dec_to_ull; + return fix_length_and_dec_op2_std(&ha_int_to_ull, &ha_dec_to_ull); } diff --git a/sql/item_func.h b/sql/item_func.h index 3771992d617..4922d20bd0c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -76,7 +76,7 @@ public: SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC, DYNCOL_FUNC, - JSON_EXTRACT_FUNC, + JSON_EXTRACT_FUNC, JSON_VALID_FUNC, CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC // Used by ColumnStore/spider }; @@ -641,6 +641,87 @@ public: }; + class Handler_int: public Handler + { + public: + String *val_str(Item_handled_func *item, String *to) const + { + longlong nr= val_int(item); + if (item->null_value) + return 0; + to->set_int(nr, item->unsigned_flag, item->collation.collation); + return to; + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return item->Item::val_str_ascii(to); + } + double val_real(Item_handled_func *item) const + { + return item->unsigned_flag ? (double) ((ulonglong) val_int(item)) : + (double) val_int(item); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return item->val_decimal_from_int(to); + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzydate) const + { + return item->get_date_from_int(thd, to, fuzzydate); + } + longlong val_int(Item_handled_func *item) const + { + Longlong_null tmp= to_longlong_null(item); + item->null_value= tmp.is_null(); + return tmp.value(); + } + virtual Longlong_null to_longlong_null(Item_handled_func *item) const= 0; + }; + + class Handler_slong: public Handler_int + { + public: + const Type_handler *return_type_handler(const Item_handled_func *item) const + { + return &type_handler_slong; + } + bool fix_length_and_dec(Item_handled_func *item) const + { + item->unsigned_flag= false; + item->collation= DTCollation_numeric(); + item->fix_char_length(11); + return false; + } + }; + + class Handler_slong2: public Handler_slong + { + public: + bool fix_length_and_dec(Item_handled_func *func) const + { + bool rc= Handler_slong::fix_length_and_dec(func); + func->max_length= 2; + return rc; + } + }; + + class Handler_ulonglong: public Handler_int + { + public: + const Type_handler *return_type_handler(const Item_handled_func *item) const + { + return &type_handler_ulonglong; + } + bool fix_length_and_dec(Item_handled_func *item) const + { + item->unsigned_flag= true; + item->collation= DTCollation_numeric(); + item->fix_char_length(21); + return false; + } + }; + protected: const Handler *m_func_handler; public: @@ -1019,11 +1100,11 @@ public: decimals= 0; set_handler(type_handler_long_or_longlong()); } - void fix_length_and_dec_temporal() + void fix_length_and_dec_temporal(bool downcast_decimal_to_int) { set_handler(&type_handler_newdecimal); fix_length_and_dec_decimal(); - if (decimals == 0) + if (decimals == 0 && downcast_decimal_to_int) set_handler(type_handler_long_or_longlong()); } bool need_parentheses_in_default() { return true; } @@ -2188,84 +2269,99 @@ public: /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ -class Item_func_bit: public Item_longlong_func +class Item_func_bit_operator: public Item_handled_func { bool check_arguments() const { return check_argument_types_can_return_int(0, arg_count); } +protected: + bool fix_length_and_dec_op1_std(const Handler *ha_int, const Handler *ha_dec) + { + set_func_handler(args[0]->cmp_type() == INT_RESULT ? ha_int : ha_dec); + return m_func_handler->fix_length_and_dec(this); + } + bool fix_length_and_dec_op2_std(const Handler *ha_int, const Handler *ha_dec) + { + set_func_handler(args[0]->cmp_type() == INT_RESULT && + args[1]->cmp_type() == INT_RESULT ? ha_int : ha_dec); + return m_func_handler->fix_length_and_dec(this); + } public: - Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {} - Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {} - bool fix_length_and_dec() { unsigned_flag= 1; return FALSE; } - - virtual inline void print(String *str, enum_query_type query_type) + Item_func_bit_operator(THD *thd, Item *a) + :Item_handled_func(thd, a) {} + Item_func_bit_operator(THD *thd, Item *a, Item *b) + :Item_handled_func(thd, a, b) {} + void print(String *str, enum_query_type query_type) { print_op(str, query_type); } bool need_parentheses_in_default() { return true; } }; -class Item_func_bit_or :public Item_func_bit +class Item_func_bit_or :public Item_func_bit_operator { public: - Item_func_bit_or(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {} - longlong val_int(); + Item_func_bit_or(THD *thd, Item *a, Item *b) + :Item_func_bit_operator(thd, a, b) {} + bool fix_length_and_dec(); const char *func_name() const { return "|"; } enum precedence precedence() const { return BITOR_PRECEDENCE; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; -class Item_func_bit_and :public Item_func_bit +class Item_func_bit_and :public Item_func_bit_operator { public: - Item_func_bit_and(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {} - longlong val_int(); + Item_func_bit_and(THD *thd, Item *a, Item *b) + :Item_func_bit_operator(thd, a, b) {} + bool fix_length_and_dec(); const char *func_name() const { return "&"; } enum precedence precedence() const { return BITAND_PRECEDENCE; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; -class Item_func_bit_count :public Item_long_func +class Item_func_bit_count :public Item_handled_func { bool check_arguments() const { return args[0]->check_type_can_return_int(func_name()); } public: - Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {} - longlong val_int(); + Item_func_bit_count(THD *thd, Item *a): Item_handled_func(thd, a) {} const char *func_name() const { return "bit_count"; } - bool fix_length_and_dec() { max_length=2; return FALSE; } + bool fix_length_and_dec(); Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; -class Item_func_shift_left :public Item_func_bit +class Item_func_shift_left :public Item_func_bit_operator { public: - Item_func_shift_left(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {} - longlong val_int(); + Item_func_shift_left(THD *thd, Item *a, Item *b) + :Item_func_bit_operator(thd, a, b) {} + bool fix_length_and_dec(); const char *func_name() const { return "<<"; } enum precedence precedence() const { return SHIFT_PRECEDENCE; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; -class Item_func_shift_right :public Item_func_bit +class Item_func_shift_right :public Item_func_bit_operator { public: - Item_func_shift_right(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {} - longlong val_int(); + Item_func_shift_right(THD *thd, Item *a, Item *b) + :Item_func_bit_operator(thd, a, b) {} + bool fix_length_and_dec(); const char *func_name() const { return ">>"; } enum precedence precedence() const { return SHIFT_PRECEDENCE; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; -class Item_func_bit_neg :public Item_func_bit +class Item_func_bit_neg :public Item_func_bit_operator { public: - Item_func_bit_neg(THD *thd, Item *a): Item_func_bit(thd, a) {} - longlong val_int(); + Item_func_bit_neg(THD *thd, Item *a): Item_func_bit_operator(thd, a) {} + bool fix_length_and_dec(); const char *func_name() const { return "~"; } enum precedence precedence() const { return NEG_PRECEDENCE; } void print(String *str, enum_query_type query_type) @@ -3156,11 +3252,12 @@ private: }; -class Item_func_bit_xor : public Item_func_bit +class Item_func_bit_xor : public Item_func_bit_operator { public: - Item_func_bit_xor(THD *thd, Item *a, Item *b): Item_func_bit(thd, a, b) {} - longlong val_int(); + Item_func_bit_xor(THD *thd, Item *a, Item *b) + :Item_func_bit_operator(thd, a, b) {} + bool fix_length_and_dec(); const char *func_name() const { return "^"; } enum precedence precedence() const { return BITXOR_PRECEDENCE; } Item *get_copy(THD *thd) diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 134c2573ea7..aec3e1edcd3 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -951,6 +951,41 @@ double Item_func_json_extract::val_real() } +my_decimal *Item_func_json_extract::val_decimal(my_decimal *to) +{ + json_value_types type; + char *value; + int value_len; + + if (read_json(NULL, &type, &value, &value_len) != NULL) + { + switch (type) + { + case JSON_VALUE_STRING: + case JSON_VALUE_NUMBER: + { + my_decimal *res= decimal_from_string_with_check(to, collation.collation, + value, + value + value_len); + null_value= res == NULL; + return res; + } + case JSON_VALUE_TRUE: + int2my_decimal(E_DEC_FATAL_ERROR, 1, false/*unsigned_flag*/, to); + return to; + case JSON_VALUE_OBJECT: + case JSON_VALUE_ARRAY: + case JSON_VALUE_FALSE: + case JSON_VALUE_NULL: + break; + }; + } + int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to); + return to; +} + + + bool Item_func_json_contains::fix_length_and_dec() { a2_constant= args[1]->const_item(); @@ -1452,6 +1487,52 @@ append_null: } +static int append_json_value_from_field(String *str, + Item *i, Field *f, const uchar *key, size_t offset, String *tmp_val) +{ + if (i->type_handler()->is_bool_type()) + { + longlong v_int= f->val_int(key + offset); + const char *t_f; + int t_f_len; + + if (f->is_null_in_record(key)) + goto append_null; + + if (v_int) + { + t_f= "true"; + t_f_len= 4; + } + else + { + t_f= "false"; + t_f_len= 5; + } + + return str->append(t_f, t_f_len); + } + { + String *sv= f->val_str(tmp_val, key + offset); + if (f->is_null_in_record(key)) + goto append_null; + if (i->is_json_type()) + return str->append(sv->ptr(), sv->length()); + + if (i->result_type() == STRING_RESULT) + { + return str->append("\"", 1) || + st_append_escaped(str, sv) || + str->append("\"", 1); + } + return st_append_escaped(str, sv); + } + +append_null: + return str->append("null", 4); +} + + static int append_json_keyname(String *str, Item *item, String *tmp_val) { String *sv= item->val_str(tmp_val); @@ -3621,12 +3702,43 @@ int Arg_comparator::compare_e_json_str_basic(Item *j, Item *s) } -String* Item_func_json_arrayagg::convert_to_json(Item *item, String *res) +String *Item_func_json_arrayagg::get_str_from_item(Item *i, String *tmp) { - String tmp; - res->length(0); - append_json_value(res, item, &tmp); - return res; + m_tmp_json.length(0); + if (append_json_value(&m_tmp_json, i, tmp)) + return NULL; + return &m_tmp_json; +} + + +String *Item_func_json_arrayagg::get_str_from_field(Item *i,Field *f, + String *tmp, const uchar *key, size_t offset) +{ + m_tmp_json.length(0); + + if (append_json_value_from_field(&m_tmp_json, i, f, key, offset, tmp)) + return NULL; + + return &m_tmp_json; + +} + + +void Item_func_json_arrayagg::cut_max_length(String *result, + uint old_length, uint max_length) const +{ + if (result->length() == 0) + return; + + if (result->ptr()[result->length() - 1] != '"' || + max_length == 0) + { + Item_func_group_concat::cut_max_length(result, old_length, max_length); + return; + } + + Item_func_group_concat::cut_max_length(result, old_length, max_length-1); + result->append('"'); } @@ -3648,6 +3760,7 @@ Item_func_json_objectagg:: Item_func_json_objectagg(THD *thd, Item_func_json_objectagg *item) :Item_sum(thd, item) { + quick_group= FALSE; result.set_charset(collation.collation); result.append("{"); } diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index f1afaf6cc31..6bd2a81afc6 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -91,6 +91,7 @@ public: } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } + enum Functype functype() const { return JSON_VALID_FUNC; } }; @@ -240,6 +241,7 @@ public: String *val_str(String *); longlong val_int(); double val_real(); + my_decimal *val_decimal(my_decimal *); uint get_n_paths() const { return arg_count - 1; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -537,7 +539,19 @@ public: class Item_func_json_arrayagg : public Item_func_group_concat { +protected: + /* + Overrides Item_func_group_concat::skip_nulls() + NULL-s should be added to the result as JSON null value. + */ + bool skip_nulls() const { return false; } + String *get_str_from_item(Item *i, String *tmp); + String *get_str_from_field(Item *i, Field *f, String *tmp, + const uchar *key, size_t offset); + void cut_max_length(String *result, + uint old_length, uint max_length) const; public: + String m_tmp_json; /* Used in get_str_from_*.. */ Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List *is_select, const SQL_I_List &is_order, String *is_separator, @@ -552,14 +566,8 @@ public: const char *func_name() const { return "json_arrayagg("; } enum Sumfunctype sum_func() const {return JSON_ARRAYAGG_FUNC;} - String* convert_to_json(Item *item, String *str); String* val_str(String *str); - /* Overrides Item_func_group_concat::add() */ - bool add() - { - return Item_func_group_concat::add(false); - } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; @@ -572,6 +580,7 @@ public: Item_func_json_objectagg(THD *thd, Item *key, Item *value) : Item_sum(thd, key, value) { + quick_group= FALSE; result.append("{"); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4bbb33d4eb7..1690ec96e65 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -661,6 +661,40 @@ bool Item_subselect::is_expensive() } +bool Item_subselect::unknown_splocal_processor(void *argument) +{ + SELECT_LEX *sl= unit->first_select(); + if (sl->top_join_list.elements) + return 0; + if (sl->tvc && sl->tvc->walk_values(&Item::unknown_splocal_processor, + false, argument)) + return true; + for (SELECT_LEX *lex= unit->first_select(); lex; lex= lex->next_select()) + { + /* + TODO: walk through GROUP BY and ORDER yet eventually. + This will require checking aliases in SELECT list: + SELECT 1 AS a GROUP BY a; + SELECT 1 AS a ORDER BY a; + */ + List_iterator li(lex->item_list); + Item *item; + if (lex->where && (lex->where)->walk(&Item::unknown_splocal_processor, + false, argument)) + return true; + if (lex->having && (lex->having)->walk(&Item::unknown_splocal_processor, + false, argument)) + return true; + while ((item=li++)) + { + if (item->walk(&Item::unknown_splocal_processor, false, argument)) + return true; + } + } + return false; +} + + bool Item_subselect::walk(Item_processor processor, bool walk_subquery, void *argument) { @@ -728,8 +762,8 @@ bool Item_subselect::exec() QT_WITHOUT_INTRODUCERS)); push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_UNKNOWN_ERROR, "DBUG: Item_subselect::exec %.*s", - print.length(),print.c_ptr()); + ER_UNKNOWN_ERROR, "DBUG: Item_subselect::exec %.*b", + print.length(),print.ptr()); ); /* Do not execute subselect in case of a fatal error @@ -2070,7 +2104,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) The swap is needed for expressions of type 'f1 < ALL ( SELECT ....)' where we want to evaluate the sub query even if f1 would be null. */ - subs= func->create_swap(thd, *(optimizer->get_cache()), subs); + subs= func->create_swap(thd, expr, subs); thd->change_item_tree(place, subs); if (subs->fix_fields(thd, &subs)) DBUG_RETURN(true); @@ -2192,10 +2226,13 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, } else { + /* + No need to use real_item for the item, as the ref items that are possible + in the subquery either belong to views or to the parent select. + For such case we need to refer to the reference and not to the original + item. + */ Item *item= (Item*) select_lex->item_list.head(); - if (item->type() != REF_ITEM || - ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF) - item= item->real_item(); if (select_lex->table_list.elements) { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index dc8417495c5..8f6e4836ac7 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -234,6 +234,7 @@ public: virtual void reset_value_registration() {} enum_parsing_place place() { return parsing_place; } bool walk(Item_processor processor, bool walk_subquery, void *arg); + bool unknown_splocal_processor(void *arg); bool mark_as_eliminated_processor(void *arg); bool eliminate_subselect_processor(void *arg); bool set_fake_select_as_master_processor(void *arg); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 052ac173747..5573cc132f0 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1387,10 +1387,12 @@ Item_sum_sp::execute() bool res; uint old_server_status= thd->server_status; - /* We set server status so we can send a signal to exit from the - function with the return value. */ + /* + We set server status so we can send a signal to exit from the + function with the return value. + */ - thd->server_status= SERVER_STATUS_LAST_ROW_SENT; + thd->server_status|= SERVER_STATUS_LAST_ROW_SENT; res= Item_sp::execute(thd, &null_value, args, arg_count); thd->server_status= old_server_status; return res; @@ -3518,7 +3520,7 @@ String *Item_sum_udf_str::val_str(String *str) */ extern "C" -int group_concat_key_cmp_with_distinct(void* arg, const void* key1, +int group_concat_key_cmp_with_distinct(void* arg, const void* key1, const void* key2) { Item_func_group_concat *item_func= (Item_func_group_concat*)arg; @@ -3552,6 +3554,63 @@ int group_concat_key_cmp_with_distinct(void* arg, const void* key1, } +/* + @brief + Comparator function for DISTINCT clause taking into account NULL values. + + @note + Used for JSON_ARRAYAGG function +*/ + +int group_concat_key_cmp_with_distinct_with_nulls(void* arg, + const void* key1_arg, + const void* key2_arg) +{ + Item_func_group_concat *item_func= (Item_func_group_concat*)arg; + + uchar *key1= (uchar*)key1_arg + item_func->table->s->null_bytes; + uchar *key2= (uchar*)key2_arg + item_func->table->s->null_bytes; + + /* + JSON_ARRAYAGG function only accepts one argument. + */ + + Item *item= item_func->args[0]; + /* + If item is a const item then either get_tmp_table_field returns 0 + or it is an item over a const table. + */ + if (item->const_item()) + return 0; + /* + We have to use get_tmp_table_field() instead of + real_item()->get_tmp_table_field() because we want the field in + the temporary table, not the original field + */ + Field *field= item->get_tmp_table_field(); + + if (!field) + return 0; + + if (field->is_null_in_record((uchar*)key1_arg) && + field->is_null_in_record((uchar*)key2_arg)) + return 0; + + if (field->is_null_in_record((uchar*)key1_arg)) + return -1; + + if (field->is_null_in_record((uchar*)key2_arg)) + return 1; + + uint offset= (field->offset(field->table->record[0]) - + field->table->s->null_bytes); + int res= field->cmp(key1 + offset, key2 + offset); + if (res) + return res; + return 0; +} + + /** function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... ) */ @@ -3608,6 +3667,106 @@ int group_concat_key_cmp_with_order(void* arg, const void* key1, } +/* + @brief + Comparator function for ORDER BY clause taking into account NULL values. + + @note + Used for JSON_ARRAYAGG function +*/ + +int group_concat_key_cmp_with_order_with_nulls(void *arg, const void *key1_arg, + const void *key2_arg) +{ + Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; + ORDER **order_item, **end; + + uchar *key1= (uchar*)key1_arg + grp_item->table->s->null_bytes; + uchar *key2= (uchar*)key2_arg + grp_item->table->s->null_bytes; + + for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order; + order_item < end; + order_item++) + { + Item *item= *(*order_item)->item; + /* + If field_item is a const item then either get_tmp_table_field returns 0 + or it is an item over a const table. + */ + if (item->const_item()) + continue; + /* + We have to use get_tmp_table_field() instead of + real_item()->get_tmp_table_field() because we want the field in + the temporary table, not the original field + + Note that for the case of ROLLUP, field may point to another table + tham grp_item->table. This is however ok as the table definitions are + the same. + */ + Field *field= item->get_tmp_table_field(); + if (!field) + continue; + + if (field->is_null_in_record((uchar*)key1_arg) && + field->is_null_in_record((uchar*)key2_arg)) + continue; + + if (field->is_null_in_record((uchar*)key1_arg)) + return ((*order_item)->direction == ORDER::ORDER_ASC) ? -1 : 1; + + if (field->is_null_in_record((uchar*)key2_arg)) + return ((*order_item)->direction == ORDER::ORDER_ASC) ? 1 : -1; + + uint offset= (field->offset(field->table->record[0]) - + field->table->s->null_bytes); + int res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset); + if (res) + return ((*order_item)->direction == ORDER::ORDER_ASC) ? res : -res; + } + /* + We can't return 0 because in that case the tree class would remove this + item as double value. This would cause problems for case-changes and + if the returned values are not the same we do the sort on. + */ + return 1; +} + + +static void report_cut_value_error(THD *thd, uint row_count, const char *fname) +{ + size_t fn_len= strlen(fname); + char *fname_upper= (char *) my_alloca(fn_len + 1); + if (!fname_upper) + fname_upper= (char*) fname; // Out of memory + else + memcpy(fname_upper, fname, fn_len+1); + my_caseup_str(&my_charset_latin1, fname_upper); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_CUT_VALUE_GROUP_CONCAT, + ER_THD(thd, ER_CUT_VALUE_GROUP_CONCAT), + row_count, fname_upper); + my_afree(fname_upper); +} + + +void Item_func_group_concat::cut_max_length(String *result, + uint old_length, uint max_length) const +{ + const char *ptr= result->ptr(); + /* + It's ok to use item->result.length() as the fourth argument + as this is never used to limit the length of the data. + Cut is done with the third argument. + */ + size_t add_length= Well_formed_prefix(collation.collation, + ptr + old_length, + ptr + max_length, + result->length()).length(); + result->length(old_length + add_length); +} + + /** Append data from current leaf to item->result. */ @@ -3630,23 +3789,25 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), ulonglong *offset_limit= &item->copy_offset_limit; ulonglong *row_limit = &item->copy_row_limit; if (item->limit_clause && !(*row_limit)) + { + item->result_finalized= true; return 1; - - if (item->no_appended) - item->no_appended= FALSE; - else - result->append(*item->separator); + } tmp.length(0); if (item->limit_clause && (*offset_limit)) { item->row_count++; - item->no_appended= TRUE; (*offset_limit)--; return 0; } + if (!item->result_finalized) + item->result_finalized= true; + else + result->append(*item->separator); + for (; arg < arg_end; arg++) { String *res; @@ -3658,7 +3819,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), because it contains both order and arg list fields. */ if ((*arg)->const_item()) - res= (*arg)->val_str(&tmp); + res= item->get_str_from_item(*arg, &tmp); else { Field *field= (*arg)->get_tmp_table_field(); @@ -3667,25 +3828,15 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); DBUG_ASSERT(offset < table->s->reclength); - res= field->val_str(&tmp, key + offset); + res= item->get_str_from_field(*arg, field, &tmp, key, + offset + item->get_null_bytes()); } else - res= (*arg)->val_str(&tmp); + res= item->get_str_from_item(*arg, &tmp); } - if (res) - { - if (item->sum_func() == Item_sum::JSON_ARRAYAGG_FUNC) - { - /* - JSON_ARRAYAGG needs to convert the type into valid JSON before - appending it to the result - */ - Item_func_json_arrayagg *arrayagg= (Item_func_json_arrayagg *) item_arg; - res= arrayagg->convert_to_json(*arg, res); - } + if (res) result->append(*res); - } } if (item->limit_clause) @@ -3695,24 +3846,10 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), /* stop if length of result more than max_length */ if (result->length() > max_length) { - CHARSET_INFO *cs= item->collation.collation; - const char *ptr= result->ptr(); THD *thd= current_thd; - /* - It's ok to use item->result.length() as the fourth argument - as this is never used to limit the length of the data. - Cut is done with the third argument. - */ - size_t add_length= Well_formed_prefix(cs, - ptr + old_length, - ptr + max_length, - result->length()).length(); - result->length(old_length + add_length); + item->cut_max_length(result, old_length, max_length); item->warning_for_row= TRUE; - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_CUT_VALUE_GROUP_CONCAT, - ER_THD(thd, ER_CUT_VALUE_GROUP_CONCAT), - item->row_count); + report_cut_value_error(thd, item->row_count, item->func_name()); /** To avoid duplicated warnings in Item_func_group_concat::val_str() @@ -3913,7 +4050,7 @@ void Item_func_group_concat::clear() result.copy(); null_value= TRUE; warning_for_row= FALSE; - no_appended= TRUE; + result_finalized= false; if (offset_limit) copy_offset_limit= offset_limit->val_int(); if (row_limit) @@ -3963,7 +4100,7 @@ bool Item_func_group_concat::repack_tree(THD *thd) init_tree(&st.tree, (size_t) MY_MIN(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - size, group_concat_key_cmp_with_order, NULL, + size, get_comparator_function_for_order_by(), NULL, (void*) this, MYF(MY_THREAD_SPECIFIC)); DBUG_ASSERT(tree->size_of_element == st.tree.size_of_element); st.table= table; @@ -3981,6 +4118,7 @@ bool Item_func_group_concat::repack_tree(THD *thd) return 0; } + /* Repacking the tree is expensive. But it keeps the tree small, and inserting into an unnecessary large tree is also waste of time. @@ -4017,6 +4155,14 @@ bool Item_func_group_concat::add(bool exclude_nulls) if (tree && (res= field->val_str(&buf))) row_str_len+= res->length(); } + else + { + /* + should not reach here, we create temp table for all the arguments of + the group_concat function + */ + DBUG_ASSERT(0); + } } null_value= FALSE; @@ -4026,7 +4172,7 @@ bool Item_func_group_concat::add(bool exclude_nulls) { /* Filter out duplicate rows. */ uint count= unique_filter->elements_in_tree(); - unique_filter->unique_add(table->record[0] + table->s->null_bytes); + unique_filter->unique_add(get_record_pointer()); if (count == unique_filter->elements_in_tree()) row_eligible= FALSE; } @@ -4040,21 +4186,19 @@ bool Item_func_group_concat::add(bool exclude_nulls) && tree->elements_in_tree > 1) if (repack_tree(thd)) return 1; - el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0, - tree->custom_arg); + el= tree_insert(tree, get_record_pointer(), 0, tree->custom_arg); /* check if there was enough memory to insert the row */ if (!el) return 1; tree_len+= row_str_len; } + /* - If the row is not a duplicate (el->count == 1) - we can dump the row here in case of GROUP_CONCAT(DISTINCT...) - instead of doing tree traverse later. + In case of GROUP_CONCAT with DISTINCT or ORDER BY (or both) don't dump the + row to the output buffer here. That will be done in val_str. */ - if (row_eligible && !warning_for_row && - (!tree || (el->count == 1 && distinct && !arg_count_order))) - dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this); + if (row_eligible && !warning_for_row && (!tree && !distinct)) + dump_leaf_key(get_record_pointer(), 1, this); return 0; } @@ -4149,13 +4293,10 @@ bool Item_func_group_concat::setup(THD *thd) Item *item= args[i]; if (list.push_back(item, thd->mem_root)) DBUG_RETURN(TRUE); - if (item->const_item()) + if (item->const_item() && item->is_null() && skip_nulls()) { - if (item->is_null()) - { - always_null= 1; - DBUG_RETURN(FALSE); - } + always_null= 1; + DBUG_RETURN(FALSE); } } @@ -4250,16 +4391,16 @@ bool Item_func_group_concat::setup(THD *thd) */ init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - tree_key_length, - group_concat_key_cmp_with_order, NULL, (void*) this, + tree_key_length + get_null_bytes(), + get_comparator_function_for_order_by(), NULL, (void*) this, MYF(MY_THREAD_SPECIFIC)); tree_len= 0; } if (distinct) - unique_filter= new Unique(group_concat_key_cmp_with_distinct, + unique_filter= new Unique(get_comparator_function_for_distinct(), (void*)this, - tree_key_length, + tree_key_length + get_null_bytes(), ram_limitation(thd)); if ((row_limit && row_limit->cmp_type() != INT_RESULT) || (offset_limit && offset_limit->cmp_type() != INT_RESULT)) @@ -4289,26 +4430,93 @@ String* Item_func_group_concat::val_str(String* str) DBUG_ASSERT(fixed == 1); if (null_value) return 0; - if (no_appended && tree) - /* Tree is used for sorting as in ORDER BY */ - tree_walk(tree, &dump_leaf_key, this, left_root_right); + + if (!result_finalized) // Result yet to be written. + { + if (tree != NULL) // order by + tree_walk(tree, &dump_leaf_key, this, left_root_right); + else if (distinct) // distinct (and no order by). + unique_filter->walk(table, &dump_leaf_key, this); + else if (row_limit && copy_row_limit == (ulonglong)row_limit->val_int()) + return &result; + else + DBUG_ASSERT(false); // Can't happen + } if (table && table->blob_storage && table->blob_storage->is_truncated_value()) { warning_for_row= true; - push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, - ER_CUT_VALUE_GROUP_CONCAT, ER(ER_CUT_VALUE_GROUP_CONCAT), - row_count); + report_cut_value_error(current_thd, row_count, func_name()); } return &result; } +/* + @brief + Get the comparator function for DISTINT clause +*/ + +qsort_cmp2 Item_func_group_concat::get_comparator_function_for_distinct() +{ + return skip_nulls() ? + group_concat_key_cmp_with_distinct : + group_concat_key_cmp_with_distinct_with_nulls; +} + + +/* + @brief + Get the comparator function for ORDER BY clause +*/ + +qsort_cmp2 Item_func_group_concat::get_comparator_function_for_order_by() +{ + return skip_nulls() ? + group_concat_key_cmp_with_order : + group_concat_key_cmp_with_order_with_nulls; +} + + +/* + + @brief + Get the record pointer of the current row of the table + + @details + look at the comments for Item_func_group_concat::get_null_bytes +*/ + +uchar* Item_func_group_concat::get_record_pointer() +{ + return skip_nulls() ? + table->record[0] + table->s->null_bytes : + table->record[0]; +} + + +/* + @brief + Get the null bytes for the table if required. + + @details + This function is used for GROUP_CONCAT (or JSON_ARRAYAGG) implementation + where the Unique tree or the ORDER BY tree may store the null values, + in such case we also store the null bytes inside each node of the tree. + +*/ + +uint Item_func_group_concat::get_null_bytes() +{ + return skip_nulls() ? 0 : table->s->null_bytes; +} + + void Item_func_group_concat::print(String *str, enum_query_type query_type) { - str->append(STRING_WITH_LEN("group_concat(")); + str->append(func_name()); if (distinct) str->append(STRING_WITH_LEN("distinct ")); for (uint i= 0; i < arg_count_field; i++) @@ -4331,9 +4539,13 @@ void Item_func_group_concat::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN(" DESC")); } } - str->append(STRING_WITH_LEN(" separator \'")); - str->append_for_single_quote(separator->ptr(), separator->length()); - str->append(STRING_WITH_LEN("\'")); + + if (sum_func() == GROUP_CONCAT_FUNC) + { + str->append(STRING_WITH_LEN(" separator \'")); + str->append_for_single_quote(separator->ptr(), separator->length()); + str->append(STRING_WITH_LEN("\'")); + } if (limit_clause) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 77d1809d7bf..dc520ce2578 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1208,6 +1208,8 @@ public: const Type_handler *type_handler() const { return &type_handler_ulonglong; } bool fix_length_and_dec() { + if (args[0]->check_type_can_return_int(func_name())) + return true; decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; return FALSE; } @@ -1407,6 +1409,11 @@ public: return sp_result_field->val_decimal(dec_buf); } + bool val_native(THD *thd, Native *to) + { + return null_value= execute() || sp_result_field->val_native(to); + } + String *val_str(String *str) { String buf; @@ -1842,8 +1849,12 @@ public: C_MODE_START int group_concat_key_cmp_with_distinct(void* arg, const void* key1, const void* key2); +int group_concat_key_cmp_with_distinct_with_nulls(void* arg, const void* key1, + const void* key2); int group_concat_key_cmp_with_order(void* arg, const void* key1, const void* key2); +int group_concat_key_cmp_with_order_with_nulls(void *arg, const void *key1, + const void *key2); int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); @@ -1880,7 +1891,8 @@ protected: bool warning_for_row; bool always_null; bool force_copy_fields; - bool no_appended; + /** True if entire result of GROUP_CONCAT has been written to output buffer. */ + bool result_finalized; /** Limits the rows in the result */ Item *row_limit; /** Skips a particular number of rows in from the result*/ @@ -1905,14 +1917,32 @@ protected: friend int group_concat_key_cmp_with_distinct(void* arg, const void* key1, const void* key2); + friend int group_concat_key_cmp_with_distinct_with_nulls(void* arg, + const void* key1, + const void* key2); friend int group_concat_key_cmp_with_order(void* arg, const void* key1, const void* key2); + friend int group_concat_key_cmp_with_order_with_nulls(void *arg, + const void *key1, const void *key2); friend int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); bool repack_tree(THD *thd); + /* + Says whether the function should skip NULL arguments + or add them to the result. + Redefined in JSON_ARRAYAGG. + */ + virtual bool skip_nulls() const { return true; } + virtual String *get_str_from_item(Item *i, String *tmp) + { return i->val_str(tmp); } + virtual String *get_str_from_field(Item *i, Field *f, String *tmp, + const uchar *key, size_t offset) + { return f->val_str(tmp, key + offset); } + virtual void cut_max_length(String *result, + uint old_length, uint max_length) const; public: // Methods used by ColumnStore bool get_distinct() const { return distinct; } @@ -1942,7 +1972,7 @@ public: void clear(); bool add() { - return add(true); + return add(skip_nulls()); } void reset_field() { DBUG_ASSERT(0); } // not used void update_field() { DBUG_ASSERT(0); } // not used @@ -1985,6 +2015,11 @@ public: { context= (Name_resolution_context *)cntx; return FALSE; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } + qsort_cmp2 get_comparator_function_for_distinct(); + qsort_cmp2 get_comparator_function_for_order_by(); + uchar* get_record_pointer(); + uint get_null_bytes(); + }; #endif /* ITEM_SUM_INCLUDED */ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a1377af08e6..e47d4fa7f0e 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2109,6 +2109,21 @@ void Item_extract::print(String *str, enum_query_type query_type) str->append(')'); } + +bool Item_extract::check_arguments() const +{ + if (!args[0]->type_handler()->can_return_extract_source(int_type)) + { + char tmp[64]; + my_snprintf(tmp, sizeof(tmp), "extract(%s)", interval_names[int_type]); + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0), + args[0]->type_handler()->name().ptr(), tmp); + return true; + } + return false; +} + + bool Item_extract::fix_length_and_dec() { maybe_null=1; // If wrong date diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 5d5f3bd4681..c9a493f8efc 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -1002,6 +1002,7 @@ class Item_extract :public Item_int_func, longlong val_int(); enum Functype functype() const { return EXTRACT_FUNC; } const char *func_name() const { return "extract"; } + bool check_arguments() const; bool fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str, enum_query_type query_type); diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index f20d20c81d6..25e86c5d777 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2016,2017 MariaDB + Copyright (c) 2016, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -187,13 +187,6 @@ bool Item_window_func::check_result_type_of_order_item() case Item_sum::PERCENTILE_DISC_FUNC: { Item *src_item= window_spec->order_list->first->item[0]; - Item_result rtype= src_item->cmp_type(); - // TODO-10.5: Fix MDEV-20280 PERCENTILE_DISC() rejects temporal and string input - if (rtype != REAL_RESULT && rtype != INT_RESULT && rtype != DECIMAL_RESULT) - { - my_error(ER_WRONG_TYPE_FOR_PERCENTILE_FUNC, MYF(0), window_func()->func_name()); - return true; - } Item_sum_percentile_disc *func= static_cast(window_func()); func->set_handler(src_item->type_handler()); @@ -348,9 +341,9 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) for (uint i= 0; i < arg_count; i++) { - // 'item' can be changed during fix_fields if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i])) return TRUE; + with_window_func|= args[i]->with_window_func; } for (uint i= 0; i < arg_count && !m_with_subquery; i++) diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index f38209e4bb5..c3304122c1b 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -779,12 +779,23 @@ public: if (get_row_count() == 0 || get_arg(0)->is_null()) { null_value= true; - return 0; + return true; } null_value= false; return value->get_date(thd, ltime, fuzzydate); } + bool val_native(THD *thd, Native *to) + { + if (get_row_count() == 0 || get_arg(0)->is_null()) + { + null_value= true; + return true; + } + null_value= false; + return value->val_native(thd, to); + } + bool add() { Item *arg= get_arg(0); diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index b5eda985eb2..4e7757f71db 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -788,7 +788,6 @@ bool Item_nodeset_func_attributebyname::val_native(THD *thd, Native *nodeset) bool Item_nodeset_func_predicate::val_native(THD *thd, Native *str) { Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0]; - Item_func *comp_func= (Item_func*)args[1]; uint pos= 0, size; prepare(thd, str); size= (uint)(fltend - fltbeg); @@ -797,7 +796,7 @@ bool Item_nodeset_func_predicate::val_native(THD *thd, Native *str) nodeset_func->context_cache.length(0); MY_XPATH_FLT(flt->num, flt->pos, size). append_to(&nodeset_func->context_cache); - if (comp_func->val_int()) + if (args[1]->val_int()) MY_XPATH_FLT(flt->num, pos++).append_to(str); } return false; @@ -970,11 +969,16 @@ static Item *create_comparator(MY_XPATH *xpath, b->fixed_type_handler() == &type_handler_xpath_nodeset) { uint len= (uint)(xpath->query.end - context->beg); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, - "XPATH error: " - "comparison of two nodesets is not supported: '%.*s'", - MYF(0), len, context->beg); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.*s'", + MYF(0), len, context->beg); + else + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.32T'", + MYF(0), context->beg); return 0; // TODO: Comparison of two nodesets } @@ -2627,9 +2631,12 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath) xpath->item= NULL; DBUG_ASSERT(xpath->query.end > dollar_pos); uint len= (uint)(xpath->query.end - dollar_pos); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", - MYF(0), len, dollar_pos); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", + MYF(0), len, dollar_pos); + else + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.32T'", + MYF(0), dollar_pos); } } return xpath->item ? 1 : 0; @@ -2760,9 +2767,13 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) if (!rc) { uint clen= (uint)(xpath.query.end - xpath.lasttok.beg); - set_if_smaller(clen, 32); - my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", - MYF(0), clen, xpath.lasttok.beg); + if (clen <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", + MYF(0), clen, xpath.lasttok.beg); + else + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.32T'", + MYF(0), xpath.lasttok.beg); + return true; } diff --git a/sql/log.cc b/sql/log.cc index 731bb3e98f0..abf22e7897a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1701,7 +1701,10 @@ int binlog_init(void *p) // recover needs to be set to make xa{commit,rollback}_handlerton effective binlog_hton->recover= binlog_xa_recover_dummy; } - binlog_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; + binlog_hton->flags= (HTON_NOT_USER_SELECTABLE | + HTON_HIDDEN | + HTON_NO_ROLLBACK | + HTON_AUTOMATIC_DELETE_TABLE); return 0; } @@ -1774,7 +1777,7 @@ binlog_flush_cache(THD *thd, binlog_cache_mngr *cache_mngr, if ((using_stmt && !cache_mngr->stmt_cache.empty()) || (using_trx && !cache_mngr->trx_cache.empty()) || - thd->transaction.xid_state.is_explicit_XA()) + thd->transaction->xid_state.is_explicit_XA()) { if (using_stmt && thd->binlog_flush_pending_rows_event(TRUE, FALSE)) DBUG_RETURN(1); @@ -1879,11 +1882,11 @@ binlog_commit_flush_trx_cache(THD *thd, bool all, binlog_cache_mngr *cache_mngr) if (thd->lex->sql_command == SQLCOM_XA_COMMIT && thd->lex->xa_opt != XA_ONE_PHASE) { - DBUG_ASSERT(thd->transaction.xid_state.is_explicit_XA()); - DBUG_ASSERT(thd->transaction.xid_state.get_state_code() == + DBUG_ASSERT(thd->transaction->xid_state.is_explicit_XA()); + DBUG_ASSERT(thd->transaction->xid_state.get_state_code() == XA_PREPARED); - buflen= serialize_with_xid(thd->transaction.xid_state.get_xid(), + buflen= serialize_with_xid(thd->transaction->xid_state.get_xid(), buf, query, q_len); } Query_log_event end_evt(thd, buf, buflen, TRUE, TRUE, TRUE, 0); @@ -1910,11 +1913,11 @@ binlog_rollback_flush_trx_cache(THD *thd, bool all, char buf[q_len + ser_buf_size]= "ROLLBACK"; size_t buflen= sizeof("ROLLBACK") - 1; - if (thd->transaction.xid_state.is_explicit_XA()) + if (thd->transaction->xid_state.is_explicit_XA()) { /* for not prepared use plain ROLLBACK */ - if (thd->transaction.xid_state.get_state_code() == XA_PREPARED) - buflen= serialize_with_xid(thd->transaction.xid_state.get_xid(), + if (thd->transaction->xid_state.get_state_code() == XA_PREPARED) + buflen= serialize_with_xid(thd->transaction->xid_state.get_xid(), buf, query, q_len); } Query_log_event end_evt(thd, buf, buflen, TRUE, TRUE, TRUE, 0); @@ -1999,7 +2002,7 @@ binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all) inline bool is_preparing_xa(THD *thd) { return - thd->transaction.xid_state.is_explicit_XA() && + thd->transaction->xid_state.is_explicit_XA() && thd->lex->sql_command == SQLCOM_XA_PREPARE; } @@ -2039,15 +2042,15 @@ static int binlog_rollback_by_xid(handlerton *hton, XID *xid) (void) thd->binlog_setup_trx_data(); DBUG_ASSERT(thd->lex->sql_command == SQLCOM_XA_ROLLBACK || - (thd->transaction.xid_state.get_state_code() == XA_ROLLBACK_ONLY)); + (thd->transaction->xid_state.get_state_code() == XA_ROLLBACK_ONLY)); return binlog_rollback(hton, thd, TRUE); } inline bool is_prepared_xa(THD *thd) { - return thd->transaction.xid_state.is_explicit_XA() && - thd->transaction.xid_state.get_state_code() == XA_PREPARED; + return thd->transaction->xid_state.is_explicit_XA() && + thd->transaction->xid_state.get_state_code() == XA_PREPARED; } @@ -2084,7 +2087,7 @@ static bool trans_cannot_safely_rollback(THD *thd, bool all) static int binlog_commit_flush_xa_prepare(THD *thd, bool all, binlog_cache_mngr *cache_mngr) { - XID *xid= thd->transaction.xid_state.get_xid(); + XID *xid= thd->transaction->xid_state.get_xid(); { // todo assert wsrep_simulate || is_open() @@ -2155,8 +2158,8 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) ("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", all, YESNO(thd->in_multi_stmt_transaction_mode()), - YESNO(thd->transaction.all.modified_non_trans_table), - YESNO(thd->transaction.stmt.modified_non_trans_table))); + YESNO(thd->transaction->all.modified_non_trans_table), + YESNO(thd->transaction->stmt.modified_non_trans_table))); thd->backup_stage(&org_stage); @@ -2167,7 +2170,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) } if (cache_mngr->trx_cache.empty() && - thd->transaction.xid_state.get_state_code() != XA_PREPARED) + thd->transaction->xid_state.get_state_code() != XA_PREPARED) { /* we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() @@ -2227,8 +2230,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", YESNO(all), - YESNO(thd->transaction.all.modified_non_trans_table), - YESNO(thd->transaction.stmt.modified_non_trans_table))); + YESNO(thd->transaction->all.modified_non_trans_table), + YESNO(thd->transaction->stmt.modified_non_trans_table))); /* If an incident event is set we do not flush the content of the statement @@ -2245,7 +2248,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) } if (cache_mngr->trx_cache.empty() && - thd->transaction.xid_state.get_state_code() != XA_PREPARED) + thd->transaction->xid_state.get_state_code() != XA_PREPARED) { /* we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() @@ -2631,7 +2634,7 @@ static int find_uniq_filename(char *name, ulong min_log_number_to_use, char buff[FN_REFLEN], ext_buf[FN_REFLEN]; struct st_my_dir *dir_info; struct fileinfo *file_info; - ulong max_found, next, UNINIT_VAR(number); + ulong max_found= 0, next= 0, number= 0; size_t buf_length, length; char *start, *end; int error= 0; @@ -2667,7 +2670,7 @@ static int find_uniq_filename(char *name, ulong min_log_number_to_use, if (strncmp(file_info->name, start, length) == 0 && test_if_number(file_info->name+length, &number,0)) { - set_if_bigger(max_found,(ulong) number); + set_if_bigger(max_found, number); } } my_dirend(dir_info); @@ -3614,6 +3617,8 @@ bool MYSQL_BIN_LOG::open(const char *log_name, LOG_BIN, io_cache_type_arg)) { sql_print_error("MYSQL_BIN_LOG::open failed to generate new file name."); + if (!is_relay_log) + goto err; DBUG_RETURN(1); } @@ -3978,7 +3983,7 @@ err: purge_index_entry(NULL, NULL, need_mutex); close_purge_index_file(); #endif - sql_print_error(fatal_log_error, name, tmp_errno); + sql_print_error(fatal_log_error, (name) ? name : log_name, tmp_errno); if (new_xid_list_entry) delete new_xid_list_entry; if (file >= 0) @@ -5609,17 +5614,19 @@ trans_has_updated_trans_table(const THD* thd) @param thd The client thread that executed the current statement. @return - @c true if a transactional table was updated, @c false otherwise. + @c true if a transactional table with rollback was updated, + @c false otherwise. */ bool stmt_has_updated_trans_table(const THD *thd) { Ha_trx_info *ha_info; - for (ha_info= thd->transaction.stmt.ha_list; ha_info; + for (ha_info= thd->transaction->stmt.ha_list; ha_info; ha_info= ha_info->next()) { - if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) + if (ha_info->is_trx_read_write() && + !(ha_info->ht()->flags & HTON_NO_ROLLBACK)) return (TRUE); } return (FALSE); @@ -5695,8 +5702,8 @@ bool ending_single_stmt_trans(THD* thd, const bool all) */ bool trans_has_updated_non_trans_table(const THD* thd) { - return (thd->transaction.all.modified_non_trans_table || - thd->transaction.stmt.modified_non_trans_table); + return (thd->transaction->all.modified_non_trans_table || + thd->transaction->stmt.modified_non_trans_table); } /** @@ -5709,7 +5716,7 @@ bool trans_has_updated_non_trans_table(const THD* thd) */ bool stmt_has_updated_non_trans_table(const THD* thd) { - return (thd->transaction.stmt.modified_non_trans_table); + return (thd->transaction->stmt.modified_non_trans_table); } /* @@ -6489,12 +6496,15 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) (WSREP(thd) && !(thd->variables.option_bits & OPTION_BIN_LOG)))) DBUG_RETURN(0); - if (thd->variables.option_bits & OPTION_GTID_BEGIN) + if (thd->variables.option_bits & + (OPTION_GTID_BEGIN | OPTION_BIN_COMMIT_OFF)) { DBUG_PRINT("info", ("OPTION_GTID_BEGIN was set")); /* Wait for commit from binary log before we commit */ direct= 0; using_trans= 1; + /* Set cache_type to ensure we don't get checksums for this event */ + event_info->cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE; } if (thd->binlog_evt_union.do_union) @@ -6550,7 +6560,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) nodes. A check has been added to stop them from getting logged into binary log files. */ - if (WSREP(thd)) option_bin_log_flag= true; + if (WSREP(thd)) + option_bin_log_flag= true; if ((!(option_bin_log_flag)) || (thd->lex->sql_command != SQLCOM_ROLLBACK_TO_SAVEPOINT && @@ -7579,7 +7590,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, entry.using_stmt_cache= using_stmt_cache; entry.using_trx_cache= using_trx_cache; entry.need_unlog= is_preparing_xa(thd); - ha_info= all ? thd->transaction.all.ha_list : thd->transaction.stmt.ha_list; + ha_info= all ? thd->transaction->all.ha_list : thd->transaction->stmt.ha_list; for (; !entry.need_unlog && ha_info; ha_info= ha_info->next()) { @@ -8156,7 +8167,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) */ DBUG_ASSERT(!cache_mngr->stmt_cache.empty() || !cache_mngr->trx_cache.empty() || - current->thd->transaction.xid_state.is_explicit_XA()); + current->thd->transaction->xid_state.is_explicit_XA()); if (unlikely((current->error= write_transaction_or_stmt(current, commit_id)))) @@ -9106,7 +9117,7 @@ void TC_LOG::run_prepare_ordered(THD *thd, bool all) { Ha_trx_info *ha_info= - all ? thd->transaction.all.ha_list : thd->transaction.stmt.ha_list; + all ? thd->transaction->all.ha_list : thd->transaction->stmt.ha_list; mysql_mutex_assert_owner(&LOCK_prepare_ordered); for (; ha_info; ha_info= ha_info->next()) @@ -9123,7 +9134,7 @@ void TC_LOG::run_commit_ordered(THD *thd, bool all) { Ha_trx_info *ha_info= - all ? thd->transaction.all.ha_list : thd->transaction.stmt.ha_list; + all ? thd->transaction->all.ha_list : thd->transaction->stmt.ha_list; mysql_mutex_assert_owner(&LOCK_commit_ordered); for (; ha_info; ha_info= ha_info->next()) @@ -10123,14 +10134,31 @@ int TC_LOG_BINLOG::unlog_xa_prepare(THD *thd, bool all) uint rw_count= ha_count_rw_all(thd, &ha_info); bool rc= false; +#ifndef DBUG_OFF + if (rw_count > 1) + { + /* + There must be no binlog_hton used in a transaction consisting of more + than 1 engine, *when* (at this point) this transaction has not been + binlogged. The one exception is if there is an engine without a + prepare method, as in this case the engine doesn't support XA and + we have to ignore this check. + */ + bool binlog= false, exist_hton_without_prepare= false; + for (ha_info= thd->transaction->all.ha_list; ha_info; + ha_info= ha_info->next()) + { + if (ha_info->ht() == binlog_hton) + binlog= true; + if (!ha_info->ht()->prepare) + exist_hton_without_prepare= true; + } + DBUG_ASSERT(!binlog || exist_hton_without_prepare); + } +#endif if (rw_count > 0) { /* an empty XA-prepare event group is logged */ -#ifndef DBUG_OFF - for (ha_info= thd->transaction.all.ha_list; rw_count > 1 && ha_info; - ha_info= ha_info->next()) - DBUG_ASSERT(ha_info->ht() != binlog_hton); -#endif rc= write_empty_xa_prepare(thd, cache_mngr); // normally gains need_unlog trans_register_ha(thd, true, binlog_hton, 0); // do it for future commmit } diff --git a/sql/log_event.cc b/sql/log_event.cc index 1b273b19c33..d5ec2060c02 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3134,6 +3134,8 @@ const char *sql_ex_info::init(const char *buf, const char *buf_end, } else { + if (buf_end - buf < 7) + return 0; // Wrong data field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1; field_term = buf++; // Use first byte in string enclosed= buf++; diff --git a/sql/log_event.h b/sql/log_event.h index 639cbfbe7aa..b515036c5e8 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1232,7 +1232,7 @@ public: */ uint16 flags; - uint16 cache_type; + enum_event_cache_type cache_type; /** A storage to cache the global system variable's value. diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index b6c626e7735..fb75bee9f21 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -736,12 +736,15 @@ void Log_event::init_show_field_list(THD *thd, List* field_list) @note A side effect of the method is altering Log_event::checksum_alg it the latter was undefined at calling. - @return true (positive) or false (negative) + @return true Checksum should be used. Log_event::checksum_alg is set. + @return false No checksum */ + my_bool Log_event::need_checksum() { - DBUG_ENTER("Log_event::need_checksum"); my_bool ret; + DBUG_ENTER("Log_event::need_checksum"); + /* few callers of Log_event::write (incl FD::write, FD constructing code on the slave side, Rotate relay log @@ -1310,35 +1313,46 @@ bool Query_log_event::write() Calculate length of whole event The "1" below is the \0 in the db's length */ - event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len; + event_length= ((uint) (start-buf) + get_post_header_size_for_derived() + + db_len + 1 + q_len); return write_header(event_length) || write_data(buf, QUERY_HEADER_LEN) || write_post_header_for_derived() || - write_data(start_of_status, (uint) (start-start_of_status)) || - write_data(safe_str(db), db_len + 1) || + write_data(start_of_status, (uint) status_vars_len) || + write_data(db, db_len + 1) || write_data(query, q_len) || write_footer(); } bool Query_compressed_log_event::write() { - const char *query_tmp = query; - uint32 q_len_tmp = q_len; - uint32 alloc_size; - bool ret = true; - q_len = alloc_size = binlog_get_compress_len(q_len); - query = (char *)my_safe_alloca(alloc_size); - if(query && !binlog_buf_compress(query_tmp, (char *)query, q_len_tmp, &q_len)) + char *buffer; + uint32 alloc_size, compressed_size; + bool ret= true; + + compressed_size= alloc_size= binlog_get_compress_len(q_len); + buffer= (char*) my_safe_alloca(alloc_size); + if (buffer && + !binlog_buf_compress(query, buffer, q_len, &compressed_size)) { - ret = Query_log_event::write(); + /* + Write the compressed event. We have to temporarily store the event + in query and q_len as Query_log_event::write() uses these. + */ + const char *query_tmp= query; + uint32 q_len_tmp= q_len; + query= buffer; + q_len= compressed_size; + ret= Query_log_event::write(); + query= query_tmp; + q_len= q_len_tmp; } - my_safe_afree((void *)query, alloc_size); - query = query_tmp; - q_len = q_len_tmp; + my_safe_afree(buffer, alloc_size); return ret; } + /** The simplest constructor that could possibly work. This is used for creating static objects that have a special meaning and are invisible @@ -1377,7 +1391,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0), using_trans), data_buf(0), query(query_arg), catalog(thd_arg->catalog), - db(thd_arg->db.str), q_len((uint32) query_length), + q_len((uint32) query_length), thread_id(thd_arg->thread_id), /* save the original thread id; we already know the server id */ slave_proxy_id((ulong)thd_arg->variables.pseudo_thread_id), @@ -1390,6 +1404,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, table_map_for_update((ulonglong)thd_arg->table_map_for_update), master_data_written(0) { + /* status_vars_len is set just before writing the event */ + time_t end_time; #ifdef WITH_WSREP @@ -1408,7 +1424,6 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, memset(&user, 0, sizeof(user)); memset(&host, 0, sizeof(host)); - error_code= errcode; end_time= my_time(0); @@ -1418,8 +1433,10 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, as an existing catalog of length zero. is that safe? /sven */ catalog_len = (catalog) ? (uint32) strlen(catalog) : 0; - /* status_vars_len is set just before writing the event */ - db_len = (db) ? (uint32) strlen(db) : 0; + + if (!(db= thd->db.str)) + db= ""; + db_len= (uint32) strlen(db); if (thd_arg->variables.collation_database != thd_arg->db_charset) charset_database_number= thd_arg->variables.collation_database->number; @@ -2045,7 +2062,7 @@ compare_errors: DBUG_EXECUTE_IF("stop_slave_middle_group", if (!current_stmt_is_commit && is_begin() == 0) { - if (thd->transaction.all.modified_non_trans_table) + if (thd->transaction->all.modified_non_trans_table) const_cast(rli)->abort_slave= 1; };); } @@ -2366,7 +2383,7 @@ int Format_description_log_event::do_apply_event(rpl_group_info *rgi) original place when it comes to us; we'll know this by checking log_pos ("artificial" events have log_pos == 0). */ - if (!is_artificial_event() && created && thd->transaction.all.ha_list) + if (!is_artificial_event() && created && thd->transaction->all.ha_list) { /* This is not an error (XA is safe), just an information */ rli->report(INFORMATION_LEVEL, 0, NULL, @@ -3238,13 +3255,13 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg, { cache_type= Log_event::EVENT_NO_CACHE; bool is_tmp_table= thd_arg->lex->stmt_accessed_temp_table(); - if (thd_arg->transaction.stmt.trans_did_wait() || - thd_arg->transaction.all.trans_did_wait()) + if (thd_arg->transaction->stmt.trans_did_wait() || + thd_arg->transaction->all.trans_did_wait()) flags2|= FL_WAITED; - if (thd_arg->transaction.stmt.trans_did_ddl() || - thd_arg->transaction.stmt.has_created_dropped_temp_table() || - thd_arg->transaction.all.trans_did_ddl() || - thd_arg->transaction.all.has_created_dropped_temp_table()) + if (thd_arg->transaction->stmt.trans_did_ddl() || + thd_arg->transaction->stmt.has_created_dropped_temp_table() || + thd_arg->transaction->all.trans_did_ddl() || + thd_arg->transaction->all.has_created_dropped_temp_table()) flags2|= FL_DDL; else if (is_transactional && !is_tmp_table) flags2|= FL_TRANSACTIONAL; @@ -3254,7 +3271,7 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg, if (thd_arg->rgi_slave) flags2|= (thd_arg->rgi_slave->gtid_ev_flags2 & (FL_DDL|FL_WAITED)); - XID_STATE &xid_state= thd->transaction.xid_state; + XID_STATE &xid_state= thd->transaction->xid_state; if (is_transactional && xid_state.is_explicit_XA() && (thd->lex->sql_command == SQLCOM_XA_PREPARE || xid_state.get_state_code() == XA_PREPARED)) @@ -3925,7 +3942,7 @@ int Xid_apply_log_event::do_apply_event(rpl_group_info *rgi) sub_id= rgi->gtid_sub_id; gtid= rgi->current_gtid; - if (!thd->transaction.xid_state.is_explicit_XA()) + if (!thd->transaction->xid_state.is_explicit_XA()) { if ((err= do_record_gtid(thd, rgi, true /* in_trans */, &hton))) return err; @@ -3945,7 +3962,7 @@ int Xid_apply_log_event::do_apply_event(rpl_group_info *rgi) res= do_commit(); if (!res && rgi->gtid_pending) { - DBUG_ASSERT(!thd->transaction.xid_state.is_explicit_XA()); + DBUG_ASSERT(!thd->transaction->xid_state.is_explicit_XA()); if ((err= do_record_gtid(thd, rgi, false, &hton))) return err; @@ -3964,7 +3981,7 @@ int Xid_apply_log_event::do_apply_event(rpl_group_info *rgi) /* Increment the global status commit count variable */ - enum enum_sql_command cmd= !thd->transaction.xid_state.is_explicit_XA() ? + enum enum_sql_command cmd= !thd->transaction->xid_state.is_explicit_XA() ? SQLCOM_COMMIT : SQLCOM_XA_PREPARE; status_var_increment(thd->status_var.com_stat[cmd]); @@ -5337,8 +5354,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) has not yet modified anything. Note, all.modified is reset by THD::reset_for_next_command(). */ - thd->transaction.stmt.modified_non_trans_table= FALSE; - thd->transaction.stmt.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction->stmt.modified_non_trans_table= FALSE; + thd->transaction->stmt.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; /* This is a row injection, so we flag the "statement" as such. Note that this code is called both when the slave does row @@ -5569,7 +5586,9 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) if (table) { master_had_triggers= table->master_had_triggers; - bool transactional_table= table->file->has_transactions(); + bool transactional_table= table->file->has_transactions_and_rollback(); + table->file->prepare_for_insert(get_general_type_code() != WRITE_ROWS_EVENT); + /* table == NULL means that this table should not be replicated (this was set up by Table_map_log_event::do_apply_event() @@ -5699,8 +5718,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) m_curr_row= m_curr_row_end; if (likely(error == 0) && !transactional_table) - thd->transaction.all.modified_non_trans_table= - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->all.modified_non_trans_table= + thd->transaction->stmt.modified_non_trans_table= TRUE; } // row processing loop while (error == 0 && (m_curr_row != m_rows_end)); @@ -5716,7 +5735,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) to shutdown trying to finish incomplete events group. */ DBUG_EXECUTE_IF("stop_slave_middle_group", - if (thd->transaction.all.modified_non_trans_table) + if (thd->transaction->all.modified_non_trans_table) const_cast(rli)->abort_slave= 1;); } @@ -5869,8 +5888,8 @@ static int rows_event_stmt_cleanup(rpl_group_info *rgi, THD * thd) */ if (!thd->in_multi_stmt_transaction_mode()) { - thd->transaction.all.modified_non_trans_table= 0; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction->all.modified_non_trans_table= 0; + thd->transaction->all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; } rgi->cleanup_context(thd, 0); diff --git a/sql/mdl.cc b/sql/mdl.cc index 287e0cb5f65..6cdea8c3ebd 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2007, 2012, Oracle and/or its affiliates. + Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,6 +28,8 @@ #include #include #include +#include +#include static PSI_memory_key key_memory_MDL_context_acquire_locks; @@ -340,32 +343,24 @@ public: class Ticket_list { + using List= ilist; public: - typedef I_P_List, - I_P_List_null_counter, - I_P_List_fast_push_back > - List; - operator const List &() const { return m_list; } - Ticket_list() :m_bitmap(0) {} + Ticket_list() :m_bitmap(0) { m_type_counters.fill(0); } void add_ticket(MDL_ticket *ticket); void remove_ticket(MDL_ticket *ticket); - bool is_empty() const { return m_list.is_empty(); } + bool is_empty() const { return m_list.empty(); } bitmap_t bitmap() const { return m_bitmap; } - private: - void clear_bit_if_not_in_list(enum_mdl_type type); + List::const_iterator begin() const { return m_list.begin(); } + List::const_iterator end() const { return m_list.end(); } private: /** List of tickets. */ List m_list; /** Bitmap of types of tickets in this list. */ bitmap_t m_bitmap; + std::array m_type_counters; // hash table }; - typedef Ticket_list::List::Iterator Ticket_iterator; - /** Helper struct which defines how different types of locks are handled @@ -574,14 +569,12 @@ public: { return m_strategy->needs_notification(ticket); } void notify_conflicting_locks(MDL_context *ctx) { - Ticket_iterator it(m_granted); - MDL_ticket *conflicting_ticket; - while ((conflicting_ticket= it++)) + for (const auto &conflicting_ticket : m_granted) { - if (conflicting_ticket->get_ctx() != ctx && - m_strategy->conflicting_locks(conflicting_ticket)) + if (conflicting_ticket.get_ctx() != ctx && + m_strategy->conflicting_locks(&conflicting_ticket)) { - MDL_context *conflicting_ctx= conflicting_ticket->get_ctx(); + MDL_context *conflicting_ctx= conflicting_ticket.get_ctx(); ctx->get_owner()-> notify_shared_lock(conflicting_ctx->get_owner(), @@ -723,21 +716,21 @@ struct mdl_iterate_arg static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg) { - int res= FALSE; /* We can skip check for m_strategy here, becase m_granted must be empty for such locks anyway. */ mysql_prlock_rdlock(&lock->m_rwlock); - MDL_lock::Ticket_iterator granted_it(lock->m_granted); - MDL_lock::Ticket_iterator waiting_it(lock->m_waiting); - MDL_ticket *ticket; - while ((ticket= granted_it++) && !(res= arg->callback(ticket, arg->argument, true))) - /* no-op */; - while ((ticket= waiting_it++) && !(res= arg->callback(ticket, arg->argument, false))) - /* no-op */; + bool res= std::any_of(lock->m_granted.begin(), lock->m_granted.end(), + [arg](MDL_ticket &ticket) { + return arg->callback(&ticket, arg->argument, true); + }); + res= std::any_of(lock->m_waiting.begin(), lock->m_waiting.end(), + [arg](MDL_ticket &ticket) { + return arg->callback(&ticket, arg->argument, false); + }); mysql_prlock_unlock(&lock->m_rwlock); - return MY_TEST(res); + return res; } @@ -1203,27 +1196,6 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, } -/** - Clear bit corresponding to the type of metadata lock in bitmap representing - set of such types if list of tickets does not contain ticket with such type. - - @param[in,out] bitmap Bitmap representing set of types of locks. - @param[in] list List to inspect. - @param[in] type Type of metadata lock to look up in the list. -*/ - -void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type type) -{ - MDL_lock::Ticket_iterator it(m_list); - const MDL_ticket *ticket; - - while ((ticket= it++)) - if (ticket->get_type() == type) - return; - m_bitmap&= ~ MDL_BIT(type); -} - - /** Add ticket to MDL_lock's list of waiting requests and update corresponding bitmap of lock types. @@ -1241,30 +1213,15 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) if ((this == &(ticket->get_lock()->m_waiting)) && wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false)) { - Ticket_iterator itw(ticket->get_lock()->m_waiting); - MDL_ticket *waiting; - MDL_ticket *prev=NULL; - bool added= false; - DBUG_ASSERT(WSREP(ticket->get_ctx()->get_thd())); - while ((waiting= itw++) && !added) - { - if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true)) - { - WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", - thd_get_thread_id(waiting->get_ctx()->get_thd()), - wsrep_thd_query(waiting->get_ctx()->get_thd())); - /* Insert the ticket before the first non-BF waiting thd. */ - m_list.insert_after(prev, ticket); - added= true; - } - prev= waiting; - } - - /* Otherwise, insert the ticket at the back of the waiting list. */ - if (!added) - m_list.push_back(ticket); + m_list.insert(std::find_if(ticket->get_lock()->m_waiting.begin(), + ticket->get_lock()->m_waiting.end(), + [](const MDL_ticket &waiting) { + return !wsrep_thd_is_BF( + waiting.get_ctx()->get_thd(), true); + }), + *ticket); } else #endif /* WITH_WSREP */ @@ -1273,9 +1230,10 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) Add ticket to the *back* of the queue to ensure fairness among requests with the same priority. */ - m_list.push_back(ticket); + m_list.push_back(*ticket); } m_bitmap|= MDL_BIT(ticket->get_type()); + m_type_counters[ticket->get_type()]++; } @@ -1286,18 +1244,15 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) void MDL_lock::Ticket_list::remove_ticket(MDL_ticket *ticket) { - m_list.remove(ticket); + m_list.remove(*ticket); /* Check if waiting queue has another ticket with the same type as one which was removed. If there is no such ticket, i.e. we have removed last ticket of particular type, then we need to update bitmap of waiting ticket's types. - Note that in most common case, i.e. when shared lock is removed - from waiting queue, we are likely to find ticket of the same - type early without performing full iteration through the list. - So this method should not be too expensive. */ - clear_bit_if_not_in_list(ticket->get_type()); + if (--m_type_counters[ticket->get_type()] == 0) + m_bitmap&= ~MDL_BIT(ticket->get_type()); } @@ -1314,8 +1269,6 @@ void MDL_lock::Ticket_list::remove_ticket(MDL_ticket *ticket) void MDL_lock::reschedule_waiters() { - MDL_lock::Ticket_iterator it(m_waiting); - MDL_ticket *ticket; bool skip_high_priority= false; bitmap_t hog_lock_types= hog_lock_types_bitmap(); @@ -1370,20 +1323,20 @@ void MDL_lock::reschedule_waiters() grant SNRW lock and there are no pending S or SH locks. */ - while ((ticket= it++)) + for (auto it= m_waiting.begin(); it != m_waiting.end(); ++it) { /* Skip high-prio, strong locks if earlier we have decided to give way to low-prio, weaker locks. */ if (skip_high_priority && - ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)) + ((MDL_BIT(it->get_type()) & hog_lock_types) != 0)) continue; - if (can_grant_lock(ticket->get_type(), ticket->get_ctx(), + if (can_grant_lock(it->get_type(), it->get_ctx(), skip_high_priority)) { - if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED)) + if (!it->get_ctx()->m_wait.set_status(MDL_wait::GRANTED)) { /* Satisfy the found request by updating lock structures. @@ -1393,15 +1346,19 @@ void MDL_lock::reschedule_waiters() when manages to do so, already sees an updated state of the MDL_lock object. */ - m_waiting.remove_ticket(ticket); - m_granted.add_ticket(ticket); + auto prev_it= std::prev(it); // this might be begin()-- but the hack + // works because list is circular + m_waiting.remove_ticket(&*it); + m_granted.add_ticket(&*it); /* Increase counter of successively granted high-priority strong locks, if we have granted one. */ - if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0) + if ((MDL_BIT(it->get_type()) & hog_lock_types) != 0) m_hog_lock_count++; + + it= prev_it; } /* If we could not update the wait slot of the waiter, @@ -1774,14 +1731,13 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, if (m_granted.bitmap() & granted_incompat_map) { - Ticket_iterator it(m_granted); bool can_grant= true; /* Check that the incompatible lock belongs to some other context. */ - while (auto ticket= it++) + for (const auto &ticket : m_granted) { - if (ticket->get_ctx() != requestor_ctx && - ticket->is_incompatible_when_granted(type_arg)) + if (ticket.get_ctx() != requestor_ctx && + ticket.is_incompatible_when_granted(type_arg)) { can_grant= false; #ifdef WITH_WSREP @@ -1793,12 +1749,12 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, requestor_ctx->get_thd()->wsrep_cs().mode() == wsrep::client_state::m_rsu) { - wsrep_handle_mdl_conflict(requestor_ctx, ticket, &key); + wsrep_handle_mdl_conflict(requestor_ctx, &ticket, &key); if (wsrep_log_conflicts) { - auto key= ticket->get_key(); + auto key= ticket.get_key(); WSREP_INFO("MDL conflict db=%s table=%s ticket=%d solved by abort", - key->db_name(), key->name(), ticket->get_type()); + key->db_name(), key->name(), ticket.get_type()); } continue; } @@ -1820,12 +1776,10 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, inline unsigned long MDL_lock::get_lock_owner() const { - Ticket_iterator it(m_granted); - MDL_ticket *ticket; + if (m_granted.is_empty()) + return 0; - if ((ticket= it++)) - return ticket->get_ctx()->get_thread_id(); - return 0; + return m_granted.begin()->get_ctx()->get_thread_id(); } @@ -2234,18 +2188,16 @@ MDL_context::clone_ticket(MDL_request *mdl_request) #ifndef DBUG_OFF bool MDL_lock::check_if_conflicting_replication_locks(MDL_context *ctx) { - Ticket_iterator it(m_granted); - MDL_ticket *conflicting_ticket; rpl_group_info *rgi_slave= ctx->get_thd()->rgi_slave; if (!rgi_slave->gtid_sub_id) return 0; - while ((conflicting_ticket= it++)) + for (const auto &conflicting_ticket : m_granted) { - if (conflicting_ticket->get_ctx() != ctx) + if (conflicting_ticket.get_ctx() != ctx) { - MDL_context *conflicting_ctx= conflicting_ticket->get_ctx(); + MDL_context *conflicting_ctx= conflicting_ticket.get_ctx(); rpl_group_info *conflicting_rgi_slave; conflicting_rgi_slave= conflicting_ctx->get_thd()->rgi_slave; @@ -2622,16 +2574,11 @@ MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket, bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket, MDL_wait_for_graph_visitor *gvisitor) { - MDL_ticket *ticket; MDL_context *src_ctx= waiting_ticket->get_ctx(); bool result= TRUE; mysql_prlock_rdlock(&m_rwlock); - /* Must be initialized after taking a read lock. */ - Ticket_iterator granted_it(m_granted); - Ticket_iterator waiting_it(m_waiting); - /* MDL_lock's waiting and granted queues and MDL_context::m_waiting_for member are updated by different threads when the lock is granted @@ -2698,46 +2645,44 @@ bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket, node. In workloads that involve wait-for graph loops this has proven to be a more efficient strategy [citation missing]. */ - while ((ticket= granted_it++)) + for (const auto& ticket : m_granted) { /* Filter out edges that point to the same node. */ - if (ticket->get_ctx() != src_ctx && - ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && - gvisitor->inspect_edge(ticket->get_ctx())) + if (ticket.get_ctx() != src_ctx && + ticket.is_incompatible_when_granted(waiting_ticket->get_type()) && + gvisitor->inspect_edge(ticket.get_ctx())) { goto end_leave_node; } } - while ((ticket= waiting_it++)) + for (const auto &ticket : m_waiting) { /* Filter out edges that point to the same node. */ - if (ticket->get_ctx() != src_ctx && - ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && - gvisitor->inspect_edge(ticket->get_ctx())) + if (ticket.get_ctx() != src_ctx && + ticket.is_incompatible_when_waiting(waiting_ticket->get_type()) && + gvisitor->inspect_edge(ticket.get_ctx())) { goto end_leave_node; } } /* Recurse and inspect all adjacent nodes. */ - granted_it.rewind(); - while ((ticket= granted_it++)) + for (const auto &ticket : m_granted) { - if (ticket->get_ctx() != src_ctx && - ticket->is_incompatible_when_granted(waiting_ticket->get_type()) && - ticket->get_ctx()->visit_subgraph(gvisitor)) + if (ticket.get_ctx() != src_ctx && + ticket.is_incompatible_when_granted(waiting_ticket->get_type()) && + ticket.get_ctx()->visit_subgraph(gvisitor)) { goto end_leave_node; } } - waiting_it.rewind(); - while ((ticket= waiting_it++)) + for (const auto &ticket : m_waiting) { - if (ticket->get_ctx() != src_ctx && - ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) && - ticket->get_ctx()->visit_subgraph(gvisitor)) + if (ticket.get_ctx() != src_ctx && + ticket.is_incompatible_when_waiting(waiting_ticket->get_type()) && + ticket.get_ctx()->visit_subgraph(gvisitor)) { goto end_leave_node; } @@ -3286,7 +3231,7 @@ const char *wsrep_get_mdl_namespace_name(MDL_key::enum_mdl_namespace ns) return "UNKNOWN"; } -void MDL_ticket::wsrep_report(bool debug) +void MDL_ticket::wsrep_report(bool debug) const { if (!debug) return; diff --git a/sql/mdl.h b/sql/mdl.h index 4659238e9f2..dd10b3a45d0 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -1,6 +1,7 @@ #ifndef MDL_H #define MDL_H /* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +17,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "sql_plist.h" +#include "ilist.h" #include #include #include @@ -685,7 +687,7 @@ public: threads/contexts. */ -class MDL_ticket : public MDL_wait_for_subgraph +class MDL_ticket : public MDL_wait_for_subgraph, public ilist_node<> { public: /** @@ -694,15 +696,9 @@ public: */ MDL_ticket *next_in_context; MDL_ticket **prev_in_context; - /** - Pointers for participating in the list of satisfied/pending requests - for the lock. Externally accessible. - */ - MDL_ticket *next_in_lock; - MDL_ticket **prev_in_lock; public: #ifdef WITH_WSREP - void wsrep_report(bool debug); + void wsrep_report(bool debug) const; #endif /* WITH_WSREP */ bool has_pending_conflicting_lock() const; diff --git a/sql/my_decimal.h b/sql/my_decimal.h index a7f6fc9e88d..2db08bf01e3 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -195,6 +195,16 @@ public: return res; } longlong to_longlong(bool unsigned_flag) const; + /* + Return the value as a signed or unsigned longlong, depending on the sign. + - Positive values are returned as unsigned. + - Negative values are returned as signed. + This is used by bit SQL operators: | & ^ ~ + as well as by the SQL function BIT_COUNT(). + */ + longlong to_xlonglong() const + { return to_longlong(!sign()); } + // Convert to string returning decimal2string() error code int to_string_native(String *to, uint prec, uint dec, char filler, uint mask= E_DEC_FATAL_ERROR) const; diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index ca519981b27..3234b8f9995 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -180,9 +180,6 @@ void Json_writer::add_size(longlong val) void Json_writer::add_double(double val) { char buf[64]; -#if __has_feature(memory_sanitizer) // FIXME: remove this workaround for - __msan_unpoison(&val, sizeof val); // main.range_mrr_icp & many other tests -#endif size_t len= my_snprintf(buf, sizeof(buf), "%-.11lg", val); add_unquoted_str(buf, len); } diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 59a3368057a..04f3789bad4 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -576,8 +576,8 @@ static int register_service(const char *datadir, const char *user, const char *p static void clean_directory(const char *dir) { - char dir2[MAX_PATH+2]; - *(strmake_buf(dir2, dir)+1)= 0; + char dir2[MAX_PATH + 4]= {}; + snprintf(dir2, MAX_PATH+2, "%s\\*", dir); SHFILEOPSTRUCT fileop; fileop.hwnd= NULL; /* no status display */ @@ -706,7 +706,7 @@ static int create_db_instance(const char *datadir) DWORD cwd_len= MAX_PATH; char cmdline[3*MAX_PATH]; FILE *in; - bool cleanup_datadir= true; + bool created_datadir= false; DWORD last_error; bool service_created= false; std::string mysql_db_dir; @@ -717,7 +717,11 @@ static int create_db_instance(const char *datadir) /* Create datadir and datadir/mysql, if they do not already exist. */ - if (!CreateDirectory(datadir, NULL) && (GetLastError() != ERROR_ALREADY_EXISTS)) + if (CreateDirectory(datadir, NULL)) + { + created_datadir= true; + } + else if (GetLastError() != ERROR_ALREADY_EXISTS) { last_error = GetLastError(); switch(last_error) @@ -756,7 +760,8 @@ static int create_db_instance(const char *datadir) if (!PathIsDirectoryEmpty(datadir)) { - fprintf(stderr,"FATAL ERROR: data directory is not empty\n"); + fprintf(stderr, "ERROR : Data directory %s is not empty." + " Only new or empty existing directories are accepted for --datadir\n", datadir); exit(1); } @@ -900,7 +905,7 @@ end: return ret; /* Cleanup after error.*/ - if (cleanup_datadir) + if (created_datadir) { SetCurrentDirectory(cwd); clean_directory(datadir); @@ -926,6 +931,8 @@ end: { handle_user_privileges(service_user.c_str(), 0, false); } + if (created_datadir) + RemoveDirectory(opt_datadir); } return ret; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d4b979f15a7..d14d2a10ecb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -328,7 +328,6 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0, opt_silent_startup= 0; -bool my_disable_leak_check= false; ulong max_used_connections; static char *mysqld_user, *mysqld_chroot; @@ -3608,7 +3607,7 @@ static void get_win_tzname(char* buf, size_t size) {0,0} }; DYNAMIC_TIME_ZONE_INFORMATION tzinfo; - if (GetDynamicTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_UNKNOWN) + if (GetDynamicTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID) { strncpy(buf, "unknown", size); return; @@ -4573,6 +4572,22 @@ init_gtid_pos_auto_engines(void) return 0; } +#define MYSQL_COMPATIBILITY_OPTION(option) \ + { option, OPT_MYSQL_COMPATIBILITY, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + +#define MYSQL_TO_BE_IMPLEMENTED_OPTION(option) \ + { option, OPT_MYSQL_TO_BE_IMPLEMENTED, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + +#define MYSQL_SUGGEST_ANALOG_OPTION(option, str) \ + { option, OPT_MYSQL_COMPATIBILITY, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + +#define MARIADB_REMOVED_OPTION(option) \ + { option, OPT_REMOVED_OPTION, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + static int init_server_components() { DBUG_ENTER("init_server_components"); @@ -4925,26 +4940,54 @@ static int init_server_components() int ho_error; struct my_option removed_opts[]= { - /* All options in this list are accepted by the server for backwards - compatibility, but do not have any effect otherwise, they behave - as if supplied with --loose. Whenever a deprecated option is removed - it should be appended here. */ - {"multi-range-count", OPT_DEPRECATED_OPTION, "", - 0, 0, 0, GET_NO_ARG, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-bdb", OPT_DEPRECATED_OPTION, "", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"thread-concurrency", OPT_DEPRECATED_OPTION, "", - 0, 0, 0, GET_NO_ARG, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"timed-mutexes", OPT_DEPRECATED_OPTION, "", - 0, 0, 0, GET_NO_ARG, OPT_ARG, 0, 0, 0, 0, 0, 0}, + /* The following options exist in 5.6 but not in 10.0 */ + MYSQL_COMPATIBILITY_OPTION("log-raw"), + MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"), + MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"), + MYSQL_COMPATIBILITY_OPTION("master-info-repository"), + MYSQL_COMPATIBILITY_OPTION("relay-log-info-repository"), + MYSQL_SUGGEST_ANALOG_OPTION("binlog-rows-query-log-events", "--binlog-annotate-row-events"), + MYSQL_COMPATIBILITY_OPTION("binlog-order-commits"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("log-throttle-queries-not-using-indexes"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("end-markers-in-json"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-features"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-offset"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-limit"), // OPTIMIZER_TRACE + MYSQL_COMPATIBILITY_OPTION("server-id-bits"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-rows-search-algorithms"), // HAVE_REPLICATION + MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-allow-batching"), // HAVE_REPLICATION + MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-period"), // HAVE_REPLICATION + MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-group"), // HAVE_REPLICATION + MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"), // HAVE_REPLICATION + MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-private-key-path"), // HAVE_OPENSSL + MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-public-key-path"), // HAVE_OPENSSL + + /* The following options exist in 5.5 and 5.6 but not in 10.0 */ + MYSQL_SUGGEST_ANALOG_OPTION("abort-slave-event-count", "--debug-abort-slave-event-count"), + MYSQL_SUGGEST_ANALOG_OPTION("disconnect-slave-event-count", "--debug-disconnect-slave-event-count"), + MYSQL_SUGGEST_ANALOG_OPTION("exit-info", "--debug-exit-info"), + MYSQL_SUGGEST_ANALOG_OPTION("max-binlog-dump-events", "--debug-max-binlog-dump-events"), + MYSQL_SUGGEST_ANALOG_OPTION("sporadic-binlog-dump-fail", "--debug-sporadic-binlog-dump-fail"), + MYSQL_COMPATIBILITY_OPTION("new"), + MYSQL_COMPATIBILITY_OPTION("show_compatibility_56"), + + /* The following options were removed in 10.5 */ #if defined(__linux__) - /* - Linux was the only large page OS that we've now removed the (always) - unused super-large-pages (because its Solaris only). - */ - {"super-large-pages", OPT_DEPRECATED_OPTION, "", - 0, 0, 0, GET_NO_ARG, OPT_ARG, 0, 0, 0, 0, 0, 0}, + MARIADB_REMOVED_OPTION("super-large-pages"), #endif + MARIADB_REMOVED_OPTION("innodb-locks-unsafe-for-binlog"), + MARIADB_REMOVED_OPTION("innodb-rollback-segments"), + MARIADB_REMOVED_OPTION("innodb-stats-sample-pages"), + MARIADB_REMOVED_OPTION("max-long-data-size"), + MARIADB_REMOVED_OPTION("multi-range-count"), + MARIADB_REMOVED_OPTION("skip-bdb"), + MARIADB_REMOVED_OPTION("thread-concurrency"), + MARIADB_REMOVED_OPTION("timed-mutexes"), + + /* The following options were added after 5.6.10 */ + MYSQL_TO_BE_IMPLEMENTED_OPTION("rpl-stop-slave-timeout"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("validate-user-plugins"), // NO_EMBEDDED_ACCESS_CHECKS {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; /* @@ -5780,6 +5823,31 @@ default_service_handling(char **argv, return 1; } +/* Remove service name from the command line arguments, and pass +resulting command line to the service via opt_args.*/ +#include +static void service_init_cmdline_args(int argc, char **argv) +{ + start_mode= 1; + use_opt_args= 1; + + if(argc == 1) + { + opt_argc= argc; + opt_argv= argv; + } + else + { + static std::vector argv_no_service; + for (int i= 0; argv[i]; i++) + argv_no_service.push_back(argv[i]); + // Remove the last argument, service name + argv_no_service[argv_no_service.size() - 1]= 0; + opt_argc= (int)argv_no_service.size() - 1; + opt_argv= &argv_no_service[0]; + } + DBUG_ASSERT(!opt_argv[opt_argc]); +} int mysqld_main(int argc, char **argv) { @@ -5811,6 +5879,7 @@ int mysqld_main(int argc, char **argv) my_path(file_path, argv[0], ""); /* Find name in path */ fn_format(file_path,argv[0],file_path,"", MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS); + if (argc == 2) { if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME, @@ -5827,7 +5896,7 @@ int mysqld_main(int argc, char **argv) */ if (my_strcasecmp(system_charset_info, argv[1],"mysql")) load_default_groups[load_default_groups_sz-2]= argv[1]; - start_mode= 1; + service_init_cmdline_args(argc, argv); Service.Init(argv[1], mysql_service); return 0; } @@ -5843,12 +5912,9 @@ int mysqld_main(int argc, char **argv) mysqld was started as mysqld --defaults-file=my_path\my.ini service-name */ - use_opt_args=1; - opt_argc= 2; // Skip service-name - opt_argv=argv; - start_mode= 1; if (my_strcasecmp(system_charset_info, argv[2],"mysql")) load_default_groups[load_default_groups_sz-2]= argv[2]; + service_init_cmdline_args(argc, argv); Service.Init(argv[2], mysql_service); return 0; } @@ -5881,7 +5947,7 @@ int mysqld_main(int argc, char **argv) else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME)) { /* start the default service */ - start_mode= 1; + service_init_cmdline_args(argc, argv); Service.Init(MYSQL_SERVICENAME, mysql_service); return 0; } @@ -6275,24 +6341,6 @@ int handle_early_options() return ho_error; } - -#define MYSQL_COMPATIBILITY_OPTION(option) \ - { option, OPT_MYSQL_COMPATIBILITY, \ - 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } - -#define MYSQL_TO_BE_IMPLEMENTED_OPTION(option) \ - { option, OPT_MYSQL_TO_BE_IMPLEMENTED, \ - 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } - -#define MYSQL_SUGGEST_ANALOG_OPTION(option, str) \ - { option, OPT_MYSQL_COMPATIBILITY, \ - 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } - -#define MARIADB_REMOVED_OPTION(option) \ - { option, OPT_REMOVED_OPTION, \ - 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } - - /** System variables are automatically command-line options (few exceptions are documented in sys_var.h), so don't need @@ -6742,42 +6790,6 @@ struct my_option my_long_options[]= "start.", &wsrep_new_cluster, &wsrep_new_cluster, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - - /* The following options exist in 5.6 but not in 10.0 */ - MYSQL_COMPATIBILITY_OPTION("log-raw"), - MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"), - MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"), - MYSQL_COMPATIBILITY_OPTION("master-info-repository"), - MYSQL_COMPATIBILITY_OPTION("relay-log-info-repository"), - MYSQL_SUGGEST_ANALOG_OPTION("binlog-rows-query-log-events", "--binlog-annotate-row-events"), - MYSQL_COMPATIBILITY_OPTION("binlog-order-commits"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("log-throttle-queries-not-using-indexes"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("end-markers-in-json"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-features"), // OPTIMIZER_TRACE - MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-offset"), // OPTIMIZER_TRACE - MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-limit"), // OPTIMIZER_TRACE - MYSQL_COMPATIBILITY_OPTION("server-id-bits"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-rows-search-algorithms"), // HAVE_REPLICATION - MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-allow-batching"), // HAVE_REPLICATION - MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-period"), // HAVE_REPLICATION - MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-group"), // HAVE_REPLICATION - MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"), // HAVE_REPLICATION - MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-private-key-path"), // HAVE_OPENSSL - MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-public-key-path"), // HAVE_OPENSSL - - /* The following options exist in 5.5 and 5.6 but not in 10.0 */ - MYSQL_SUGGEST_ANALOG_OPTION("abort-slave-event-count", "--debug-abort-slave-event-count"), - MYSQL_SUGGEST_ANALOG_OPTION("disconnect-slave-event-count", "--debug-disconnect-slave-event-count"), - MYSQL_SUGGEST_ANALOG_OPTION("exit-info", "--debug-exit-info"), - MYSQL_SUGGEST_ANALOG_OPTION("max-binlog-dump-events", "--debug-max-binlog-dump-events"), - MYSQL_SUGGEST_ANALOG_OPTION("sporadic-binlog-dump-fail", "--debug-sporadic-binlog-dump-fail"), - MYSQL_COMPATIBILITY_OPTION("new"), - MYSQL_COMPATIBILITY_OPTION("show_compatibility_56"), - - /* The following options were added after 5.6.10 */ - MYSQL_TO_BE_IMPLEMENTED_OPTION("rpl-stop-slave-timeout"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("validate-user-plugins") // NO_EMBEDDED_ACCESS_CHECKS }; static int show_queries(THD *thd, SHOW_VAR *var, char *buff, @@ -7914,12 +7926,9 @@ mysqld_get_one_option(const struct my_option *opt, char *argument, sql_print_warning("'%s' is disabled in this build", opt->name); #endif break; - case OPT_DEPRECATED_OPTION: - sql_print_warning("'%s' is deprecated. It does nothing and exists only " - "for compatibility with old my.cnf files.", - opt->name); - break; case OPT_REMOVED_OPTION: + sql_print_warning("'%s' was removed. It does nothing now and exists only " + "for compatibility with old my.cnf files.", opt->name); break; case OPT_MYSQL_COMPATIBILITY: sql_print_warning("'%s' is MySQL 5.6 / 5.7 compatible option. Not used or " diff --git a/sql/mysqld.h b/sql/mysqld.h index c6e1b0946a5..db8d9b4b1aa 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -781,7 +781,6 @@ enum options_mysqld OPT_BOOTSTRAP, OPT_CONSOLE, OPT_DEBUG_SYNC_TIMEOUT, - OPT_DEPRECATED_OPTION, OPT_REMOVED_OPTION, OPT_IGNORE_DB_DIRECTORY, OPT_ISAM_LOG, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index be907a0c4b3..c674730d230 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -442,6 +442,13 @@ static void print_range(String *out, const KEY_PART_INFO *key_part, KEY_MULTI_RANGE *range, uint n_key_parts); +static +void print_range_for_non_indexed_field(String *out, Field *field, + KEY_MULTI_RANGE *range); + +static void print_min_range_operator(String *out, const ha_rkey_function flag); +static void print_max_range_operator(String *out, const ha_rkey_function flag); + /* SEL_IMERGE is a list of possible ways to do index merge, i.e. it is @@ -2592,10 +2599,10 @@ static int fill_used_fields_bitmap(PARAM *param) In the table struct the following information is updated: quick_keys - Which keys can be used quick_rows - How many rows the key matches - quick_condition_rows - E(# rows that will satisfy the table condition) + opt_range_condition_rows - E(# rows that will satisfy the table condition) IMPLEMENTATION - quick_condition_rows value is obtained as follows: + opt_range_condition_rows value is obtained as follows: It is a minimum of E(#output rows) for all considered table access methods (range and index_merge accesses over various indexes). @@ -2619,7 +2626,7 @@ static int fill_used_fields_bitmap(PARAM *param) which is currently produced. TODO - * Change the value returned in quick_condition_rows from a pessimistic + * Change the value returned in opt_range_condition_rows from a pessimistic estimate to true E(#rows that satisfy table condition). (we can re-use some of E(#rows) calcuation code from index_merge/intersection for this) @@ -2691,10 +2698,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, DBUG_PRINT("info",("Time to scan table: %g", read_time)); Json_writer_object table_records(thd); - if (head->reginfo.join_tab) - table_records.add_table_name(head->reginfo.join_tab); - else - table_records.add_table_name(head); + table_records.add_table_name(head); + Json_writer_object trace_range(thd, "range_analysis"); { Json_writer_object table_rec(thd, "table_scan"); @@ -2730,6 +2735,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.imerge_cost_buff_size= 0; param.using_real_indexes= TRUE; param.remove_jump_scans= TRUE; + param.max_key_parts= 0; param.remove_false_where_parts= remove_false_parts_of_where; param.force_default_mrr= ordered_output; param.possible_keys.clear_all(); @@ -2951,7 +2957,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { best_trp= intersect_trp; best_read_time= best_trp->read_cost; - set_if_smaller(param.table->quick_condition_rows, + set_if_smaller(param.table->opt_range_condition_rows, intersect_trp->records); } } @@ -2971,7 +2977,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); if (new_conj_trp) - set_if_smaller(param.table->quick_condition_rows, + set_if_smaller(param.table->opt_range_condition_rows, new_conj_trp->records); if (new_conj_trp && (!best_conj_trp || @@ -2998,7 +3004,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, restore_nonrange_trees(¶m, tree, backup_keys); if ((group_trp= get_best_group_min_max(¶m, tree, read_time))) { - param.table->quick_condition_rows= MY_MIN(group_trp->records, + param.table->opt_range_condition_rows= MY_MIN(group_trp->records, head->stat_records()); Json_writer_object grp_summary(thd, "best_group_range_summary"); @@ -3190,6 +3196,7 @@ static double records_in_column_ranges(PARAM *param, uint idx, SEL_ARG *tree) { + THD *thd= param->thd; SEL_ARG_RANGE_SEQ seq; KEY_MULTI_RANGE range; range_seq_t seq_it; @@ -3216,6 +3223,8 @@ double records_in_column_ranges(PARAM *param, uint idx, seq_it= seq_if.init((void *) &seq, 0, flags); + Json_writer_array range_trace(thd, "ranges"); + while (!seq_if.next(seq_it, &range)) { key_range *min_endp, *max_endp; @@ -3232,6 +3241,13 @@ double records_in_column_ranges(PARAM *param, uint idx, if (range.start_key.flag == HA_READ_BEFORE_KEY) range_flag |= NEAR_MAX; + if (unlikely(thd->trace_started())) + { + StringBuffer<128> range_info(system_charset_info); + print_range_for_non_indexed_field(&range_info, field, &range); + range_trace.add(range_info.c_ptr_safe(), range_info.length()); + } + rows= get_column_range_cardinality(field, min_endp, max_endp, range_flag); if (DBL_MAX == rows) { @@ -3324,8 +3340,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) for (keynr= 0; keynr < table->s->keys; keynr++) { - if (table->quick_keys.is_set(keynr)) - set_if_bigger(max_quick_key_parts, table->quick_key_parts[keynr]); + if (table->opt_range_keys.is_set(keynr)) + set_if_bigger(max_quick_key_parts, table->opt_range[keynr].key_parts); } /* @@ -3337,13 +3353,13 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) { for (keynr= 0; keynr < table->s->keys; keynr++) { - if (table->quick_keys.is_set(keynr) && - table->quick_key_parts[keynr] == quick_key_parts) + if (table->opt_range_keys.is_set(keynr) && + table->opt_range[keynr].key_parts == quick_key_parts) { uint i; - uint used_key_parts= table->quick_key_parts[keynr]; - double quick_cond_selectivity= table->quick_rows[keynr] / - table_records; + uint used_key_parts= table->opt_range[keynr].key_parts; + double quick_cond_selectivity= (table->opt_range[keynr].rows / + table_records); KEY *key_info= table->key_info + keynr; KEY_PART_INFO* key_part= key_info->key_part; /* @@ -3451,6 +3467,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) param.using_real_indexes= FALSE; param.real_keynr[0]= 0; param.alloced_sel_args= 0; + param.max_key_parts= 0; thd->no_errors=1; @@ -5760,7 +5777,7 @@ bool prepare_search_best_index_intersect(PARAM *param, continue; } - cost= table->quick_index_only_costs[(*index_scan)->keynr]; + cost= table->opt_range[(*index_scan)->keynr].index_only_cost; idx_scan.add("cost", cost); @@ -7171,7 +7188,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ha_rows best_rows = double2rows(intersect_best->out_rows); if (!best_rows) best_rows= 1; - set_if_smaller(param->table->quick_condition_rows, best_rows); + set_if_smaller(param->table->opt_range_condition_rows, best_rows); trp->records= best_rows; trp->index_scan_costs= intersect_best->index_scan_costs; trp->cpk_scan= cpk_scan; @@ -7340,7 +7357,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, trp->read_cost= total_cost; trp->records= records; trp->cpk_scan= NULL; - set_if_smaller(param->table->quick_condition_rows, records); + set_if_smaller(param->table->opt_range_condition_rows, records); DBUG_PRINT("info", ("Returning covering ROR-intersect plan: cost %g, records %lu", @@ -11066,11 +11083,11 @@ void SEL_ARG::test_use_count(SEL_ARG *root) about range scan we've evaluated. mrr_flags INOUT MRR access flags cost OUT Scan cost + is_ror_scan is set to reflect if the key scan is a ROR (see + is_key_scan_ror function for more info) NOTES - param->is_ror_scan is set to reflect if the key scan is a ROR (see - is_key_scan_ror function for more info) - param->table->quick_*, param->range_count (and maybe others) are + param->table->opt_range*, param->range_count (and maybe others) are updated with data of given key scan, see quick_range_seq_next for details. RETURN @@ -11140,6 +11157,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, if (param->table->pos_in_table_list->is_non_derived()) rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0, bufsize, mrr_flags, cost); + param->quick_rows[keynr]= rows; if (rows != HA_POS_ERROR) { ha_rows table_records= param->table->stat_records(); @@ -11147,30 +11165,30 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, { /* For any index the total number of records within all ranges - cannot be be bigger than the number of records in the table + cannot be be bigger than the number of records in the table. + This check is needed as sometimes that table statistics or range + estimates may be slightly out of sync. */ rows= table_records; set_if_bigger(rows, 1); + param->quick_rows[keynr]= rows; } - param->quick_rows[keynr]= rows; param->possible_keys.set_bit(keynr); if (update_tbl_stats) { - param->table->quick_keys.set_bit(keynr); - param->table->quick_key_parts[keynr]= param->max_key_parts; - param->table->quick_n_ranges[keynr]= param->range_count; - param->table->quick_condition_rows= - MY_MIN(param->table->quick_condition_rows, rows); - param->table->quick_rows[keynr]= rows; - param->table->quick_costs[keynr]= cost->total_cost(); + param->table->opt_range_keys.set_bit(keynr); + param->table->opt_range[keynr].key_parts= param->max_key_parts; + param->table->opt_range[keynr].ranges= param->range_count; + param->table->opt_range_condition_rows= + MY_MIN(param->table->opt_range_condition_rows, rows); + param->table->opt_range[keynr].rows= rows; + param->table->opt_range[keynr].cost= cost->total_cost(); if (param->table->file->is_clustering_key(keynr)) - param->table->quick_index_only_costs[keynr]= 0; + param->table->opt_range[keynr].index_only_cost= 0; else - param->table->quick_index_only_costs[keynr]= cost->index_only_cost(); + param->table->opt_range[keynr].index_only_cost= cost->index_only_cost(); } } - else - param->quick_rows[keynr]= HA_POS_ERROR; /* Figure out if the key scan is ROR (returns rows in ROWID order) or not */ enum ha_key_alg key_alg= param->table->key_info[seq.real_keyno].algorithm; @@ -15818,6 +15836,37 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) #endif /* !DBUG_OFF */ + +/* + @brief Print the comparison operator for the min range +*/ + +static void print_min_range_operator(String *out, const ha_rkey_function flag) +{ + if (flag == HA_READ_AFTER_KEY) + out->append(STRING_WITH_LEN(" < ")); + else if (flag == HA_READ_KEY_EXACT || flag == HA_READ_KEY_OR_NEXT) + out->append(STRING_WITH_LEN(" <= ")); + else + out->append(STRING_WITH_LEN(" ? ")); +} + + +/* + @brief Print the comparison operator for the max range +*/ + +static void print_max_range_operator(String *out, const ha_rkey_function flag) +{ + if (flag == HA_READ_BEFORE_KEY) + out->append(STRING_WITH_LEN(" < ")); + else if (flag == HA_READ_AFTER_KEY) + out->append(STRING_WITH_LEN(" <= ")); + else + out->append(STRING_WITH_LEN(" ? ")); +} + + static void print_range(String *out, const KEY_PART_INFO *key_part, KEY_MULTI_RANGE *range, uint n_key_parts) @@ -15846,30 +15895,55 @@ void print_range(String *out, const KEY_PART_INFO *key_part, { print_key_value(out, key_part, range->start_key.key, range->start_key.length); - if (range->start_key.flag == HA_READ_AFTER_KEY) - out->append(STRING_WITH_LEN(" < ")); - else if (range->start_key.flag == HA_READ_KEY_EXACT || - range->start_key.flag == HA_READ_KEY_OR_NEXT) - out->append(STRING_WITH_LEN(" <= ")); - else - out->append(STRING_WITH_LEN(" ? ")); + print_min_range_operator(out, range->start_key.flag); } print_keyparts_name(out, key_part, n_key_parts, keypart_map); if (range->end_key.length) { - if (range->end_key.flag == HA_READ_BEFORE_KEY) - out->append(STRING_WITH_LEN(" < ")); - else if (range->end_key.flag == HA_READ_AFTER_KEY) - out->append(STRING_WITH_LEN(" <= ")); - else - out->append(STRING_WITH_LEN(" ? ")); + print_max_range_operator(out, range->end_key.flag); print_key_value(out, key_part, range->end_key.key, range->end_key.length); } } + +/* + @brief Print range created for non-indexed columns + + @param + out output string + field field for which the range is printed + range range for the field +*/ + +static +void print_range_for_non_indexed_field(String *out, Field *field, + KEY_MULTI_RANGE *range) +{ + TABLE *table= field->table; + my_bitmap_map *old_sets[2]; + dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); + + if (range->start_key.length) + { + field->print_key_part_value(out, range->start_key.key, field->key_length()); + print_min_range_operator(out, range->start_key.flag); + } + + out->append(field->field_name); + + if (range->end_key.length) + { + print_max_range_operator(out, range->end_key.flag); + field->print_key_part_value(out, range->end_key.key, field->key_length()); + } + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); +} + + + /* Add ranges to the trace @@ -15940,40 +16014,9 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part, { field= key_part->field; store_length= key_part->store_length; - if (field->flags & BLOB_FLAG) - { - // Byte 0 of a nullable key is the null-byte. If set, key is NULL. - if (field->real_maybe_null() && *key) - { - out->append(STRING_WITH_LEN("NULL")); - goto next; - } - } - if (field->real_maybe_null()) - { - /* - Byte 0 of key is the null-byte. If set, key is NULL. - Otherwise, print the key value starting immediately after the - null-byte - */ - if (*key) - { - out->append(STRING_WITH_LEN("NULL")); - goto next; - } - key++; // Skip null byte - store_length--; - } + field->print_key_part_value(out, key, key_part->length); - field->set_key_image(key, key_part->length); - field->print_key_value(&tmp, key_part->length); - if (field->charset() == &my_charset_bin) - out->append(tmp.ptr(), tmp.length(), tmp.charset()); - else - tmp.print(out, system_charset_info); - - next: if (key + store_length < key_end) out->append(STRING_WITH_LEN(",")); } diff --git a/sql/opt_range.h b/sql/opt_range.h index a504e35bf45..664e821f8d1 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -673,6 +673,7 @@ public: bool statement_should_be_aborted() const { return + thd->killed || thd->is_fatal_error || thd->is_error() || alloced_sel_args > SEL_ARG::MAX_SEL_ARGS; diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc index 267d764bb3b..20413f5df63 100644 --- a/sql/opt_range_mrr.cc +++ b/sql/opt_range_mrr.cc @@ -79,6 +79,7 @@ range_seq_t sel_arg_range_seq_init(void *init_param, uint n_ranges, uint flags) SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param; seq->param->range_count=0; seq->at_start= TRUE; + seq->param->max_key_parts= 0; seq->stack[0].key_tree= NULL; seq->stack[0].min_key= seq->param->min_key; seq->stack[0].min_key_flag= 0; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 1e0a5398f6a..62f5964cd3c 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -2500,7 +2500,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) double rows= 1.0; while ((tableno = tm_it.next_bit()) != Table_map_iterator::BITMAP_END) rows= COST_MULT(rows, - join->map2table[tableno]->table->quick_condition_rows); + join->map2table[tableno]->table->opt_range_condition_rows); sjm->rows= MY_MIN(sjm->rows, rows); } memcpy((uchar*) sjm->positions, diff --git a/sql/partition_info.cc b/sql/partition_info.cc index e9dbf2b49c3..10f82242bca 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -415,6 +415,8 @@ bool partition_info::set_up_default_partitions(THD *thd, handler *file, const char *error_string; if (part_type == RANGE_PARTITION) error_string= "RANGE"; + else if (part_type == VERSIONING_PARTITION) + error_string= "SYSTEM_TIME"; else error_string= "LIST"; my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_string); diff --git a/sql/protocol.cc b/sql/protocol.cc index 1829294097d..d565a818f31 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1218,7 +1218,7 @@ bool Protocol_text::store(const char *from, size_t length, { CHARSET_INFO *tocs= this->thd->variables.character_set_results; #ifndef DBUG_OFF - DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos, + DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*b", field_pos, field_count, (int) length, (length == 0 ? "" : from))); DBUG_ASSERT(field_handlers == 0 || field_pos < field_count); DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_STRING)); diff --git a/sql/rowid_filter.cc b/sql/rowid_filter.cc index d8d0890e1f9..4a3746d72db 100644 --- a/sql/rowid_filter.cc +++ b/sql/rowid_filter.cc @@ -110,10 +110,12 @@ Range_rowid_filter_cost_info::set_adjusted_gain_param(double access_cost_factor) void Range_rowid_filter_cost_info::init(Rowid_filter_container_type cont_type, TABLE *tab, uint idx) { + DBUG_ASSERT(tab->opt_range_keys.is_set(idx)); + container_type= cont_type; table= tab; key_no= idx; - est_elements= (ulonglong) (table->quick_rows[key_no]); + est_elements= (ulonglong) table->opt_range[key_no].rows; b= build_cost(container_type); selectivity= est_elements/((double) table->stat_records()); a= avg_access_and_eval_gain_per_row(container_type); @@ -134,8 +136,9 @@ double Range_rowid_filter_cost_info::build_cost(Rowid_filter_container_type cont_type) { double cost= 0; + DBUG_ASSERT(table->opt_range_keys.is_set(key_no)); - cost+= table->quick_index_only_costs[key_no]; + cost+= table->opt_range[key_no].index_only_cost; switch (cont_type) { @@ -345,7 +348,7 @@ void TABLE::init_cost_info_for_usable_range_rowid_filters(THD *thd) uint key_no; key_map usable_range_filter_keys; usable_range_filter_keys.clear_all(); - key_map::Iterator it(quick_keys); + key_map::Iterator it(opt_range_keys); /* From all indexes that can be used for range accesses select only such that @@ -359,7 +362,7 @@ void TABLE::init_cost_info_for_usable_range_rowid_filters(THD *thd) continue; if (file->is_clustering_key(key_no)) // !2 continue; - if (quick_rows[key_no] > + if (opt_range[key_no].rows > get_max_range_rowid_filter_elems_for_table(thd, this, SORTED_ARRAY_CONTAINER)) // !3 continue; diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index 24b76cf7c42..5c4a4d9f58a 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -350,16 +350,22 @@ Rpl_filter::set_do_table(const char* table_spec) int status; if (do_table_inited) - my_hash_reset(&do_table); - - status= parse_filter_rule(table_spec, &Rpl_filter::add_do_table); - - if (!do_table.records) { my_hash_free(&do_table); do_table_inited= 0; } + status= parse_filter_rule(table_spec, &Rpl_filter::add_do_table); + + if (do_table_inited && status) + { + if (!do_table.records) + { + my_hash_free(&do_table); + do_table_inited= 0; + } + } + return status; } @@ -370,16 +376,22 @@ Rpl_filter::set_ignore_table(const char* table_spec) int status; if (ignore_table_inited) - my_hash_reset(&ignore_table); - - status= parse_filter_rule(table_spec, &Rpl_filter::add_ignore_table); - - if (!ignore_table.records) { my_hash_free(&ignore_table); ignore_table_inited= 0; } + status= parse_filter_rule(table_spec, &Rpl_filter::add_ignore_table); + + if (ignore_table_inited && status) + { + if (!ignore_table.records) + { + my_hash_free(&ignore_table); + ignore_table_inited= 0; + } + } + return status; } diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index c5f765f9cda..af0c4747d2b 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -507,7 +507,7 @@ rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) Ha_trx_info *ha_info; uint count = 0; - for (ha_info= thd->transaction.all.ha_list; ha_info; ha_info= ha_info->next()) + for (ha_info= thd->transaction->all.ha_list; ha_info; ha_info= ha_info->next()) { void *trx_hton= ha_info->ht(); auto table_entry= list; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index d33e26d2ecc..94882230682 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -93,18 +93,18 @@ handle_queued_pos_update(THD *thd, rpl_parallel_thread::queued_event *qev) /* Do not update position if an earlier event group caused an error abort. */ DBUG_ASSERT(qev->typ == rpl_parallel_thread::queued_event::QUEUED_POS_UPDATE); + rli= qev->rgi->rli; e= qev->entry_for_queued; - if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || e->force_abort) + if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || + (e->force_abort && !rli->stop_for_until)) return; - rli= qev->rgi->rli; mysql_mutex_lock(&rli->data_lock); cmp= strcmp(rli->group_relay_log_name, qev->event_relay_log_name); if (cmp < 0) { rli->group_relay_log_pos= qev->future_event_relay_log_pos; strmake_buf(rli->group_relay_log_name, qev->event_relay_log_name); - rli->notify_group_relay_log_name_update(); } else if (cmp == 0 && rli->group_relay_log_pos < qev->future_event_relay_log_pos) rli->group_relay_log_pos= qev->future_event_relay_log_pos; @@ -467,6 +467,7 @@ pool_mark_busy(rpl_parallel_thread_pool *pool, THD *thd) So we protect the infrequent operations of FLUSH TABLES WITH READ LOCK and pool size changes with this condition wait. */ + DBUG_EXECUTE_IF("mark_busy_mdev_22370",my_sleep(1000000);); mysql_mutex_lock(&pool->LOCK_rpl_thread_pool); if (thd) { @@ -2012,10 +2013,24 @@ rpl_parallel_thread_pool::init(uint32 size) void rpl_parallel_thread_pool::destroy() +{ + deactivate(); + destroy_cond_mutex(); +} + +void +rpl_parallel_thread_pool::deactivate() { if (!inited) return; rpl_parallel_change_thread_count(this, 0, 1); +} + +void +rpl_parallel_thread_pool::destroy_cond_mutex() +{ + if (!inited) + return; mysql_mutex_destroy(&LOCK_rpl_thread_pool); mysql_cond_destroy(&COND_rpl_thread_pool); inited= false; diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index 9d9fa63125c..b88e77d5427 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -244,6 +244,8 @@ struct rpl_parallel_thread_pool { rpl_parallel_thread_pool(); int init(uint32 size); void destroy(); + void deactivate(); + void destroy_cond_mutex(); struct rpl_parallel_thread *get_thread(rpl_parallel_thread **owner, rpl_parallel_entry *entry); void release_thread(rpl_parallel_thread *rpt); diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc index 738ae52782d..aa69168d44c 100644 --- a/sql/rpl_reporting.cc +++ b/sql/rpl_reporting.cc @@ -19,6 +19,7 @@ #include "rpl_reporting.h" #include "log.h" // sql_print_error, sql_print_warning, // sql_print_information +#include "sql_class.h" Slave_reporting_capability::Slave_reporting_capability(char const *thread_name) : m_thread_name(thread_name) @@ -70,7 +71,8 @@ Slave_reporting_capability::report(loglevel level, int err_code, va_end(args); /* If the msg string ends with '.', do not add a ',' it would be ugly */ - report_function("Slave %s: %s%s %s%sInternal MariaDB error code: %d", + report_function("%s %s: %s%s %s%sInternal MariaDB error code: %d", + (current_thd && current_thd->rgi_fake) ? "" : "Slave", m_thread_name, pbuff, (pbuff[0] && *(strend(pbuff)-1) == '.') ? "" : ",", (extra_info ? extra_info : ""), (extra_info ? ", " : ""), diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 1a0147f7d8d..11eccefdde9 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -46,8 +46,8 @@ gtid_waiting rpl_global_gtid_waiting; const char *const Relay_log_info::state_delaying_string = "Waiting until MASTER_DELAY seconds after master executed event"; -Relay_log_info::Relay_log_info(bool is_slave_recovery) - :Slave_reporting_capability("SQL"), +Relay_log_info::Relay_log_info(bool is_slave_recovery, const char* thread_name) + :Slave_reporting_capability(thread_name), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period), sync_counter(0), is_relay_log_recovery(is_slave_recovery), @@ -62,6 +62,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), executed_entries(0), sql_delay(0), sql_delay_end(0), + until_relay_log_names_defer(false), m_flags(0) { DBUG_ENTER("Relay_log_info::Relay_log_info"); @@ -505,6 +506,8 @@ void Relay_log_info::clear_until_condition() until_condition= Relay_log_info::UNTIL_NONE; until_log_name[0]= 0; until_log_pos= 0; + until_relay_log_names_defer= false; + DBUG_VOID_RETURN; } @@ -995,7 +998,6 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, { group_relay_log_pos= rgi->future_event_relay_log_pos; strmake_buf(group_relay_log_name, rgi->event_relay_log_name); - notify_group_relay_log_name_update(); } else if (cmp == 0 && group_relay_log_pos < rgi->future_event_relay_log_pos) group_relay_log_pos= rgi->future_event_relay_log_pos; @@ -1285,29 +1287,78 @@ err: autoincrement or if we have transactions). Should be called ONLY if until_condition != UNTIL_NONE ! + + In the parallel execution mode and UNTIL_MASTER_POS the file name is + presented by future_event_master_log_name which may be ahead of + group_master_log_name. Log_event::log_pos does relate to it nevertheless + so the pair comprises a correct binlog coordinate. + Internal group events and events that have zero log_pos also + produce the zero for the local log_pos which may not lead to the + function falsely return true. + In UNTIL_RELAY_POS the original caching and notification are simplified + to straightforward files comparison when the current event can't be + a part of an event group. + RETURN VALUE true - condition met or error happened (condition seems to have bad log file name) false - condition not met */ -bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool Relay_log_info::is_until_satisfied(Log_event *ev) { const char *log_name; ulonglong log_pos; + /* Prevents stopping within transaction; needed solely for Relay UNTIL. */ + bool in_trans= false; + DBUG_ENTER("Relay_log_info::is_until_satisfied"); if (until_condition == UNTIL_MASTER_POS) { log_name= (mi->using_parallel() ? future_event_master_log_name : group_master_log_name); - log_pos= master_beg_pos; + log_pos= (get_flag(Relay_log_info::IN_TRANSACTION) || !ev || !ev->log_pos) ? + (mi->using_parallel() ? 0 : group_master_log_pos) : + ev->log_pos - ev->data_written; } else { DBUG_ASSERT(until_condition == UNTIL_RELAY_POS); - log_name= group_relay_log_name; - log_pos= group_relay_log_pos; + if (!mi->using_parallel()) + { + log_name= group_relay_log_name; + log_pos= group_relay_log_pos; + } + else + { + log_name= event_relay_log_name; + log_pos= event_relay_log_pos; + in_trans= get_flag(Relay_log_info::IN_TRANSACTION); + /* + until_log_names_cmp_result is set to UNKNOWN either + - by a non-group event *and* only when it is in the middle of a group + - or by a group event when the preceding group made the above + non-group event to defer the resetting. + */ + if ((ev && !Log_event::is_group_event(ev->get_type_code()))) + { + if (in_trans) + { + until_relay_log_names_defer= true; + } + else + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } + else if (!in_trans && until_relay_log_names_defer) + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } } DBUG_PRINT("info", ("group_master_log_name='%s', group_master_log_pos=%llu", @@ -1361,8 +1412,8 @@ bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) } DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && - log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); + (log_pos >= until_log_pos && !in_trans)) || + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); } @@ -1422,8 +1473,14 @@ bool Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd, } DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE();); if (mi->using_gtid == Master_info::USE_GTID_NO) + { + if (rgi->is_parallel_exec) + mysql_mutex_lock(&data_lock); if (flush()) error= 1; + if (rgi->is_parallel_exec) + mysql_mutex_unlock(&data_lock); + } DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE();); } DBUG_RETURN(error); @@ -2232,7 +2289,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) trans_rollback above does not rollback XA transactions (todo/fixme consider to do so. */ - if (thd->transaction.xid_state.is_explicit_XA()) + if (thd->transaction->xid_state.is_explicit_XA()) xa_trans_force_rollback(thd); thd->mdl_context.release_transactional_locks(); diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fafe8ead63d..4223e015ecd 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -219,7 +219,7 @@ public: */ char future_event_master_log_name[FN_REFLEN]; - /* + /* Original log name and position of the group we're currently executing (whose coordinates are group_relay_log_name/pos in the relay log) in the master's binlog. These concern the *group*, because in the master's @@ -387,11 +387,11 @@ public: */ slave_connection_state restart_gtid_pos; - Relay_log_info(bool is_slave_recovery); + Relay_log_info(bool is_slave_recovery, const char* thread_name= "SQL"); ~Relay_log_info(); /* - Invalidate cached until_log_name and group_relay_log_name comparison + Invalidate cached until_log_name and group_relay_log_name comparison result. Should be called after any update of group_realy_log_name if there chances that sql_thread is running. */ @@ -419,7 +419,7 @@ public: void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t); + bool is_until_satisfied(Log_event *ev); inline ulonglong until_pos() { DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || @@ -427,7 +427,13 @@ public: return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : group_relay_log_pos); } - + inline char *until_name() + { + DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || + until_condition == UNTIL_RELAY_POS); + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_name : + group_relay_log_name); + } /** Helper function to do after statement completion. @@ -564,6 +570,15 @@ private: relay_log.info had 4 lines. Now it has 5 lines. */ static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5; + /* + Hint for when to stop event distribution by sql driver thread. + The flag is set ON by a non-group event when this event is in the middle + of a group (e.g a transaction group) so it's too early + to refresh the current-relay-log vs until-log cached comparison result. + And it is checked and to decide whether it's a right time to do so + when the being processed group has been fully scheduled. + */ + bool until_relay_log_names_defer; /* Holds the state of the data in the relay log. diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 79634d142eb..2480eebf8d7 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -682,7 +682,7 @@ int Repl_semi_sync_master::wait_after_commit(THD* thd, bool all) my_off_t log_pos; bool is_real_trans= - (all || thd->transaction.all.ha_list == 0); + (all || thd->transaction->all.ha_list == 0); /* The coordinates are propagated to this point having been computed in report_binlog_update diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index 013ec65d3f5..6b06bddd773 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -206,7 +206,15 @@ extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd, as RSU has paused the provider. */ if ((ret || !wsrep_on(victim_thd)) && signal) - victim_thd->awake(KILL_QUERY); + { + mysql_mutex_assert_not_owner(&victim_thd->LOCK_thd_data); + mysql_mutex_assert_not_owner(&victim_thd->LOCK_thd_kill); + mysql_mutex_lock(&victim_thd->LOCK_thd_data); + mysql_mutex_lock(&victim_thd->LOCK_thd_kill); + victim_thd->awake_no_mutex(KILL_QUERY); + mysql_mutex_unlock(&victim_thd->LOCK_thd_kill); + mysql_mutex_unlock(&victim_thd->LOCK_thd_data); + } return ret; } @@ -305,8 +313,10 @@ extern "C" void wsrep_commit_ordered(THD *thd) { thd->wsrep_last_written_gtid_seqno= thd->wsrep_current_gtid_seqno; } - if (!wsrep_commit_will_write_binlog(thd)) + if (thd->wsrep_trx().state() != wsrep::transaction::s_ordered_commit && + !wsrep_commit_will_write_binlog(thd)) { + DEBUG_SYNC(thd, "before_wsrep_ordered_commit"); thd->wsrep_cs().ordered_commit(); } } diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc index a0919d825bf..d94ecdc2b24 100644 --- a/sql/session_tracker.cc +++ b/sql/session_tracker.cc @@ -741,7 +741,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) if ((thd->variables.session_track_transaction_info == TX_TRACK_CHISTICS) && (tx_changed & TX_CHG_CHISTICS)) { - bool is_xa= thd->transaction.xid_state.is_explicit_XA(); + bool is_xa= thd->transaction->xid_state.is_explicit_XA(); size_t start; /* 2 length by 1 byte and code */ @@ -918,7 +918,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) if ((tx_curr_state & TX_EXPLICIT) && is_xa) { - XID *xid= thd->transaction.xid_state.get_xid(); + XID *xid= thd->transaction->xid_state.get_xid(); long glen, blen; buf->append(STRING_WITH_LEN("XA START")); @@ -1183,6 +1183,7 @@ bool Session_state_change_tracker::store(THD *thd, String *buf) return false; } +#ifdef USER_VAR_TRACKING bool User_variables_tracker::update(THD *thd, set_var *) { @@ -1195,19 +1196,22 @@ bool User_variables_tracker::store(THD *thd, String *buf) { for (ulong i= 0; i < m_changed_user_variables.size(); i++) { - auto var= m_changed_user_variables.at(i); + const user_var_entry *var= m_changed_user_variables.at(i); String value_str; bool null_value; + size_t length; var->val_str(&null_value, &value_str, DECIMAL_MAX_SCALE); - - size_t length= net_length_size(var->name.length) + var->name.length; + length= net_length_size(var->name.length) + var->name.length; if (!null_value) length+= net_length_size(value_str.length()) + value_str.length(); + else + length+= 1; if (buf->reserve(sizeof(char) + length + net_length_size(length))) return true; + // TODO: check max packet length MDEV-22709 buf->q_append(static_cast(SESSION_TRACK_USER_VARIABLES)); buf->q_net_store_length(length); buf->q_net_store_data(reinterpret_cast(var->name.str), @@ -1215,10 +1219,16 @@ bool User_variables_tracker::store(THD *thd, String *buf) if (!null_value) buf->q_net_store_data(reinterpret_cast(value_str.ptr()), value_str.length()); + else + { + char nullbuff[1]= { (char)251 }; + buf->q_append(nullbuff, sizeof(nullbuff)); + } } m_changed_user_variables.clear(); return false; } +#endif // USER_VAR_TRACKING /////////////////////////////////////////////////////////////////////////////// diff --git a/sql/session_tracker.h b/sql/session_tracker.h index 7db1feb1b1a..c78778ac73c 100644 --- a/sql/session_tracker.h +++ b/sql/session_tracker.h @@ -35,7 +35,9 @@ enum enum_session_tracker CURRENT_SCHEMA_TRACKER, /* Current schema */ SESSION_STATE_CHANGE_TRACKER, TRANSACTION_INFO_TRACKER, /* Transaction state */ +#ifdef USER_VAR_TRACKING USER_VARIABLES_TRACKER, +#endif // USER_VAR_TRACKING SESSION_TRACKER_END /* must be the last */ }; @@ -395,6 +397,7 @@ private: This is a tracker class that enables & manages the tracking of user variables. */ +#ifdef USER_VAR_TRACKING class User_variables_tracker: public State_tracker { Hash_set m_changed_user_variables; @@ -415,6 +418,7 @@ public: } void deinit() { m_changed_user_variables.~Hash_set(); } }; +#endif // USER_VAR_TRACKING /** @@ -445,7 +449,9 @@ public: Session_state_change_tracker state_change; Transaction_state_tracker transaction_info; Session_sysvars_tracker sysvars; +#ifdef USER_VAR_TRACKING User_variables_tracker user_variables; +#endif // USER_VAR_TRACKING Session_tracker() { @@ -453,7 +459,9 @@ public: m_trackers[CURRENT_SCHEMA_TRACKER]= ¤t_schema; m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change; m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info; +#ifdef USER_VAR_TRACKING m_trackers[USER_VARIABLES_TRACKER]= &user_variables; +#endif // USER_VAR_TRACKING } void enable(THD *thd) diff --git a/sql/set_var.cc b/sql/set_var.cc index 0ace4658be7..38c8d1f1775 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -994,8 +994,17 @@ int set_var_default_role::check(THD *thd) { #ifndef NO_EMBEDDED_ACCESS_CHECKS real_user= get_current_user(thd, user); - int status= acl_check_set_default_role(thd, real_user->host.str, real_user->user.str); - return status; + real_role= role.str; + if (role.str == current_role.str) + { + if (!thd->security_ctx->priv_role[0]) + real_role= "NONE"; + else + real_role= thd->security_ctx->priv_role; + } + + return acl_check_set_default_role(thd, real_user->host.str, + real_user->user.str, real_role); #else return 0; #endif @@ -1006,7 +1015,8 @@ int set_var_default_role::update(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; thd->m_reprepare_observer= 0; - int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, role.str); + int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, + real_role); thd->m_reprepare_observer= save_reprepare_observer; return res; #else diff --git a/sql/set_var.h b/sql/set_var.h index 41a0010acf2..18c4dbc664e 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -1,7 +1,7 @@ #ifndef SET_VAR_INCLUDED #define SET_VAR_INCLUDED /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -370,6 +370,7 @@ class set_var_default_role: public set_var_base { LEX_USER *user, *real_user; LEX_CSTRING role; + const char *real_role; public: set_var_default_role(LEX_USER *user_arg, LEX_CSTRING role_arg) : user(user_arg), role(role_arg) {} diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 250da9948a0..275dc1605d8 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1197,30 +1197,30 @@ ER_TABLE_EXISTS_ERROR 42S01 swe "Tabellen '%-.192s' finns redan" ukr "Таблиця '%-.192s' вже існує" ER_BAD_TABLE_ERROR 42S02 - cze "Neznámá tabulka '%-.100s'" - dan "Ukendt tabel '%-.100s'" - nla "Onbekende tabel '%-.100s'" - eng "Unknown table '%-.100s'" - est "Tundmatu tabel '%-.100s'" - fre "Table '%-.100s' inconnue" - ger "Unbekannte Tabelle '%-.100s'" - greek "Αγνωστος πίνακας '%-.100s'" - hindi "अज्ञात टेबल '%-.100s'" - hun "Ervenytelen tabla: '%-.100s'" - ita "Tabella '%-.100s' sconosciuta" - jpn "'%-.100s' は不明な表です。" - kor "테이블 '%-.100s'는 알수 없음" - nor "Ukjent tabell '%-.100s'" - norwegian-ny "Ukjent tabell '%-.100s'" - pol "Nieznana tabela '%-.100s'" - por "Tabela '%-.100s' desconhecida" - rum "Tabela '%-.100s' este invalida" - rus "Неизвестная таблица '%-.100s'" - serbian "Nepoznata tabela '%-.100s'" - slo "Neznáma tabuľka '%-.100s'" - spa "Tabla '%-.100s' desconocida" - swe "Okänd tabell '%-.100s'" - ukr "Невідома таблиця '%-.100s'" + cze "Neznámá tabulka '%-.100T'" + dan "Ukendt tabel '%-.100T'" + nla "Onbekende tabel '%-.100T'" + eng "Unknown table '%-.100T'" + est "Tundmatu tabel '%-.100T'" + fre "Table '%-.100T' inconnue" + ger "Unbekannte Tabelle '%-.100T'" + greek "Αγνωστος πίνακας '%-.100T'" + hindi "अज्ञात टेबल '%-.100T'" + hun "Ervenytelen tabla: '%-.100T'" + ita "Tabella '%-.100T' sconosciuta" + jpn "'%-.100T' は不明な表です。" + kor "테이블 '%-.100T'는 알수 없음" + nor "Ukjent tabell '%-.100T'" + norwegian-ny "Ukjent tabell '%-.100T'" + pol "Nieznana tabela '%-.100T'" + por "Tabela '%-.100T' desconhecida" + rum "Tabela '%-.100T' este invalida" + rus "Неизвестная таблица '%-.100T'" + serbian "Nepoznata tabela '%-.100T'" + slo "Neznáma tabuľka '%-.100T'" + spa "Tabla '%-.100T' desconocida" + swe "Okänd tabell '%-.100T'" + ukr "Невідома таблиця '%-.100T'" ER_NON_UNIQ_ERROR 23000 cze "Sloupec '%-.192s' v %-.192s není zcela jasný" dan "Felt: '%-.192s' i tabel %-.192s er ikke entydigt" @@ -1394,30 +1394,30 @@ ER_WRONG_VALUE_COUNT 21S01 swe "Antalet kolumner motsvarar inte antalet värden" ukr "Кількість стовбців не співпадає з кількістю значень" ER_TOO_LONG_IDENT 42000 S1009 - cze "Jméno identifikátoru '%-.100s' je příliš dlouhé" - dan "Navnet '%-.100s' er for langt" - nla "Naam voor herkenning '%-.100s' is te lang" - eng "Identifier name '%-.100s' is too long" - est "Identifikaatori '%-.100s' nimi on liiga pikk" - fre "Le nom de l'identificateur '%-.100s' est trop long" - ger "Name des Bezeichners '%-.100s' ist zu lang" - greek "Το identifier name '%-.100s' είναι πολύ μεγάλο" - hindi "पहचानकर्ता का नाम '%-.100s' बहुत लंबा है" - hun "A(z) '%-.100s' azonositonev tul hosszu" - ita "Il nome dell'identificatore '%-.100s' e` troppo lungo" - jpn "識別子名 '%-.100s' は長すぎます。" - kor "Identifier '%-.100s'는 너무 길군요." - nor "Identifikator '%-.100s' er for lang" - norwegian-ny "Identifikator '%-.100s' er for lang" - pol "Nazwa identyfikatora '%-.100s' jest zbyt długa" - por "Nome identificador '%-.100s' é longo demais" - rum "Numele indentificatorului '%-.100s' este prea lung" - rus "Слишком длинный идентификатор '%-.100s'" - serbian "Ime '%-.100s' je predugačko" - slo "Meno identifikátora '%-.100s' je príliš dlhé" - spa "El nombre del identificador '%-.100s' es demasiado grande" - swe "Kolumnnamn '%-.100s' är för långt" - ukr "Ім'я ідентифікатора '%-.100s' задовге" + cze "Jméno identifikátoru '%-.100T' je příliš dlouhé" + dan "Navnet '%-.100T' er for langt" + nla "Naam voor herkenning '%-.100T' is te lang" + eng "Identifier name '%-.100T' is too long" + est "Identifikaatori '%-.100T' nimi on liiga pikk" + fre "Le nom de l'identificateur '%-.100T' est trop long" + ger "Name des Bezeichners '%-.100T' ist zu lang" + greek "Το identifier name '%-.100T' είναι πολύ μεγάλο" + hindi "पहचानकर्ता का नाम '%-.100T' बहुत लंबा है" + hun "A(z) '%-.100T' azonositonev tul hosszu" + ita "Il nome dell'identificatore '%-.100T' e` troppo lungo" + jpn "識別子名 '%-.100T' は長すぎます。" + kor "Identifier '%-.100T'는 너무 길군요." + nor "Identifikator '%-.100T' er for lang" + norwegian-ny "Identifikator '%-.100T' er for lang" + pol "Nazwa identyfikatora '%-.100T' jest zbyt długa" + por "Nome identificador '%-.100T' é longo demais" + rum "Numele indentificatorului '%-.100T' este prea lung" + rus "Слишком длинный идентификатор '%-.100T'" + serbian "Ime '%-.100T' je predugačko" + slo "Meno identifikátora '%-.100T' je príliš dlhé" + spa "El nombre del identificador '%-.100T' es demasiado grande" + swe "Kolumnnamn '%-.100T' är för långt" + ukr "Ім'я ідентифікатора '%-.100T' задовге" ER_DUP_FIELDNAME 42S21 S1009 cze "Zdvojené jméno sloupce '%-.192s'" dan "Feltnavnet '%-.192s' findes allerede" @@ -1471,30 +1471,30 @@ ER_DUP_KEYNAME 42000 S1009 # When using this error code, please use ER(ER_DUP_ENTRY_WITH_KEY_NAME) # for the message string. See, for example, code in handler.cc. ER_DUP_ENTRY 23000 S1009 - cze "Zdvojený klíč '%-.192s' (číslo klíče %d)" - dan "Ens værdier '%-.192s' for indeks %d" - nla "Dubbele ingang '%-.192s' voor zoeksleutel %d" - eng "Duplicate entry '%-.192s' for key %d" - est "Kattuv väärtus '%-.192s' võtmele %d" - fre "Duplicata du champ '%-.192s' pour la clef %d" - ger "Doppelter Eintrag '%-.192s' für Schlüssel %d" - greek "Διπλή εγγραφή '%-.192s' για το κλειδί %d" - hindi "सामान प्रवेश '%-.192s' KEY %d के लिए" - hun "Duplikalt bejegyzes '%-.192s' a %d kulcs szerint" - ita "Valore duplicato '%-.192s' per la chiave %d" - jpn "'%-.192s' は索引 %d で重複しています。" - kor "중복된 입력 값 '%-.192s': key %d" - nor "Like verdier '%-.192s' for nøkkel %d" - norwegian-ny "Like verdiar '%-.192s' for nykkel %d" - pol "Powtórzone wystąpienie '%-.192s' dla klucza %d" - por "Entrada '%-.192s' duplicada para a chave %d" - rum "Cimpul '%-.192s' e duplicat pentru cheia %d" - rus "Дублирующаяся запись '%-.192s' по ключу %d" - serbian "Dupliran unos '%-.192s' za ključ '%d'" - slo "Opakovaný kľúč '%-.192s' (číslo kľúča %d)" - spa "Entrada duplicada '%-.192s' para la clave %d" - swe "Dublett '%-.192s' för nyckel %d" - ukr "Дублюючий запис '%-.192s' для ключа %d" + cze "Zdvojený klíč '%-.192T' (číslo klíče %d)" + dan "Ens værdier '%-.192T' for indeks %d" + nla "Dubbele ingang '%-.192T' voor zoeksleutel %d" + eng "Duplicate entry '%-.192T' for key %d" + est "Kattuv väärtus '%-.192T' võtmele %d" + fre "Duplicata du champ '%-.192T' pour la clef %d" + ger "Doppelter Eintrag '%-.192T' für Schlüssel %d" + greek "Διπλή εγγραφή '%-.192T' για το κλειδί %d" + hindi "सामान प्रवेश '%-.192T' KEY %d के लिए" + hun "Duplikalt bejegyzes '%-.192T' a %d kulcs szerint" + ita "Valore duplicato '%-.192T' per la chiave %d" + jpn "'%-.192T' は索引 %d で重複しています。" + kor "중복된 입력 값 '%-.192T': key %d" + nor "Like verdier '%-.192T' for nøkkel %d" + norwegian-ny "Like verdiar '%-.192T' for nykkel %d" + pol "Powtórzone wystąpienie '%-.192T' dla klucza %d" + por "Entrada '%-.192T' duplicada para a chave %d" + rum "Cimpul '%-.192T' e duplicat pentru cheia %d" + rus "Дублирующаяся запись '%-.192T' по ключу %d" + serbian "Dupliran unos '%-.192T' za ključ '%d'" + slo "Opakovaný kľúč '%-.192T' (číslo kľúča %d)" + spa "Entrada duplicada '%-.192T' para la clave %d" + swe "Dublett '%-.192T' för nyckel %d" + ukr "Дублюючий запис '%-.192T' для ключа %d" ER_WRONG_FIELD_SPEC 42000 S1009 cze "Chybná specifikace sloupce '%-.192s'" dan "Forkert kolonnespecifikaton for felt '%-.192s'" @@ -1521,30 +1521,30 @@ ER_WRONG_FIELD_SPEC 42000 S1009 swe "Felaktigt kolumntyp för kolumn '%-.192s'" ukr "Невірний специфікатор стовбця '%-.192s'" ER_PARSE_ERROR 42000 s1009 - cze "%s blízko '%-.80s' na řádku %d" - dan "%s nær '%-.80s' på linje %d" - nla "%s bij '%-.80s' in regel %d" - eng "%s near '%-.80s' at line %d" - est "%s '%-.80s' ligidal real %d" - fre "%s près de '%-.80s' à la ligne %d" - ger "%s bei '%-.80s' in Zeile %d" - greek "%s πλησίον '%-.80s' στη γραμμή %d" - hindi "%s के पास '%-.80s' लाइन %d में" - hun "A %s a '%-.80s'-hez kozeli a %d sorban" - ita "%s vicino a '%-.80s' linea %d" - jpn "%s : '%-.80s' 付近 %d 行目" - kor "'%s' 에러 같읍니다. ('%-.80s' 명령어 라인 %d)" - nor "%s nær '%-.80s' på linje %d" - norwegian-ny "%s attmed '%-.80s' på line %d" - pol "%s obok '%-.80s' w linii %d" - por "%s próximo a '%-.80s' na linha %d" - rum "%s linga '%-.80s' pe linia %d" - rus "%s около '%-.80s' на строке %d" - serbian "'%s' u iskazu '%-.80s' na liniji %d" - slo "%s blízko '%-.80s' na riadku %d" - spa "%s cerca '%-.80s' en la linea %d" - swe "%s nära '%-.80s' på rad %d" - ukr "%s біля '%-.80s' в строці %d" + cze "%s blízko '%-.80T' na řádku %d" + dan "%s nær '%-.80T' på linje %d" + nla "%s bij '%-.80T' in regel %d" + eng "%s near '%-.80T' at line %d" + est "%s '%-.80T' ligidal real %d" + fre "%s près de '%-.80T' à la ligne %d" + ger "%s bei '%-.80T' in Zeile %d" + greek "%s πλησίον '%-.80T' στη γραμμή %d" + hindi "%s के पास '%-.80T' लाइन %d में" + hun "A %s a '%-.80T'-hez kozeli a %d sorban" + ita "%s vicino a '%-.80T' linea %d" + jpn "%s : '%-.80T' 付近 %d 行目" + kor "'%s' 에러 같읍니다. ('%-.80T' 명령어 라인 %d)" + nor "%s nær '%-.80T' på linje %d" + norwegian-ny "%s attmed '%-.80T' på line %d" + pol "%s obok '%-.80T' w linii %d" + por "%s próximo a '%-.80T' na linha %d" + rum "%s linga '%-.80T' pe linia %d" + rus "%s около '%-.80T' на строке %d" + serbian "'%s' u iskazu '%-.80T' na liniji %d" + slo "%s blízko '%-.80T' na riadku %d" + spa "%s cerca '%-.80T' en la linea %d" + swe "%s nära '%-.80T' på rad %d" + ukr "%s біля '%-.80T' в строці %d" ER_EMPTY_QUERY 42000 cze "Výsledek dotazu je prázdný" dan "Forespørgsel var tom" @@ -2380,30 +2380,30 @@ ER_TABLE_NOT_LOCKED ER_UNUSED_17 eng "You should never see it" ER_WRONG_DB_NAME 42000 - cze "Nepřípustné jméno databáze '%-.100s'" - dan "Ugyldigt database navn '%-.100s'" - nla "Databasenaam '%-.100s' is niet getoegestaan" - eng "Incorrect database name '%-.100s'" - est "Vigane andmebaasi nimi '%-.100s'" - fre "Nom de base de donnée illégal: '%-.100s'" - ger "Unerlaubter Datenbankname '%-.100s'" - greek "Λάθος όνομα βάσης δεδομένων '%-.100s'" - hindi "डेटाबेस नाम '%-.100s' गलत है" - hun "Hibas adatbazisnev: '%-.100s'" - ita "Nome database errato '%-.100s'" - jpn "データベース名 '%-.100s' は不正です。" - kor "'%-.100s' 데이타베이스의 이름이 부정확합니다." - nor "Ugyldig database navn '%-.100s'" - norwegian-ny "Ugyldig database namn '%-.100s'" - pol "Niedozwolona nazwa bazy danych '%-.100s'" - por "Nome de banco de dados '%-.100s' incorreto" - rum "Numele bazei de date este incorect '%-.100s'" - rus "Некорректное имя базы данных '%-.100s'" - serbian "Pogrešno ime baze '%-.100s'" - slo "Neprípustné meno databázy '%-.100s'" - spa "Nombre de base de datos ilegal '%-.100s'" - swe "Felaktigt databasnamn '%-.100s'" - ukr "Невірне ім'я бази данних '%-.100s'" + cze "Nepřípustné jméno databáze '%-.100T'" + dan "Ugyldigt database navn '%-.100T'" + nla "Databasenaam '%-.100T' is niet getoegestaan" + eng "Incorrect database name '%-.100T'" + est "Vigane andmebaasi nimi '%-.100T'" + fre "Nom de base de donnée illégal: '%-.100T'" + ger "Unerlaubter Datenbankname '%-.100T'" + greek "Λάθος όνομα βάσης δεδομένων '%-.100T'" + hindi "डेटाबेस नाम '%-.100T' गलत है" + hun "Hibas adatbazisnev: '%-.100T'" + ita "Nome database errato '%-.100T'" + jpn "データベース名 '%-.100T' は不正です。" + kor "'%-.100T' 데이타베이스의 이름이 부정확합니다." + nor "Ugyldig database navn '%-.100T'" + norwegian-ny "Ugyldig database namn '%-.100T'" + pol "Niedozwolona nazwa bazy danych '%-.100T'" + por "Nome de banco de dados '%-.100T' incorreto" + rum "Numele bazei de date este incorect '%-.100T'" + rus "Некорректное имя базы данных '%-.100T'" + serbian "Pogrešno ime baze '%-.100T'" + slo "Neprípustné meno databázy '%-.100T'" + spa "Nombre de base de datos ilegal '%-.100T'" + swe "Felaktigt databasnamn '%-.100T'" + ukr "Невірне ім'я бази данних '%-.100T'" ER_WRONG_TABLE_NAME 42000 cze "Nepřípustné jméno tabulky '%-.100s'" dan "Ugyldigt tabel navn '%-.100s'" @@ -4688,15 +4688,15 @@ ER_NO_DEFAULT 42000 spa "Variable '%-.64s' no tiene un valor patrón" swe "Variabel '%-.64s' har inte ett DEFAULT-värde" ER_WRONG_VALUE_FOR_VAR 42000 - nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200s'" - eng "Variable '%-.64s' can't be set to the value of '%-.200s'" - ger "Variable '%-.64s' kann nicht auf '%-.200s' gesetzt werden" - ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200s'" - jpn "変数 '%-.64s' に値 '%-.200s' を設定できません。" - por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200s'" - rus "Переменная '%-.64s' не может быть установлена в значение '%-.200s'" - spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200s'" - swe "Variabel '%-.64s' kan inte sättas till '%-.200s'" + nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200T'" + eng "Variable '%-.64s' can't be set to the value of '%-.200T'" + ger "Variable '%-.64s' kann nicht auf '%-.200T' gesetzt werden" + ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200T'" + jpn "変数 '%-.64s' に値 '%-.200T' を設定できません。" + por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200T'" + rus "Переменная '%-.64s' не может быть установлена в значение '%-.200T'" + spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200T'" + swe "Variabel '%-.64s' kan inte sättas till '%-.200T'" ER_WRONG_TYPE_FOR_VAR 42000 nla "Foutief argumenttype voor variabele '%-.64s'" eng "Incorrect argument type to variable '%-.64s'" @@ -4940,7 +4940,7 @@ ER_ZLIB_Z_DATA_ERROR por "ZLIB: Dados de entrada está corrupto" spa "ZLIB: Dato de entrada fué corrompido para zlib" ER_CUT_VALUE_GROUP_CONCAT - eng "Row %u was cut by GROUP_CONCAT()" + eng "Row %u was cut by %s)" ER_WARN_TOO_FEW_RECORDS 01000 eng "Row %lu doesn't contain data for all columns" ger "Zeile %lu enthält nicht für alle Felder Daten" @@ -5140,11 +5140,11 @@ ER_DUPLICATED_VALUE_IN_TYPE por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s" spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s" ER_TRUNCATED_WRONG_VALUE 22007 - eng "Truncated incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert gekürzt: '%-.128s'" - jpn "不正な %-.32s の値が切り捨てられました。: '%-.128s'" - por "Truncado errado %-.32s valor: '%-.128s'" - spa "Equivocado truncado %-.32s valor: '%-.128s'" + eng "Truncated incorrect %-.32T value: '%-.128T'" + ger "Falscher %-.32T-Wert gekürzt: '%-.128T'" + jpn "不正な %-.32T の値が切り捨てられました。: '%-.128T'" + por "Truncado errado %-.32T valor: '%-.128T'" + spa "Equivocado truncado %-.32T valor: '%-.128T'" ER_TOO_MUCH_AUTO_TIMESTAMP_COLS eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" ger "Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben" @@ -5181,8 +5181,8 @@ ER_WARN_INVALID_TIMESTAMP eng "Invalid TIMESTAMP value in column '%s' at row %lu" ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %lu" ER_INVALID_CHARACTER_STRING - eng "Invalid %s character string: '%.64s'" - ger "Ungültiger %s-Zeichen-String: '%.64s'" + eng "Invalid %s character string: '%.64T'" + ger "Ungültiger %s-Zeichen-String: '%.64T'" ER_WARN_ALLOWED_PACKET_OVERFLOWED eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated" ger "Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt" @@ -5426,11 +5426,11 @@ ER_DIVISION_BY_ZERO 22012 ger "Division durch 0" hindi "0 से विभाजन" ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 22007 - eng "Incorrect %-.32s value: '%-.128s' for column `%.192s`.`%.192s`.`%.192s` at row %lu" - ger "Falscher %-.32s-Wert: '%-.128s' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" + eng "Incorrect %-.32s value: '%-.128T' for column `%.192s`.`%.192s`.`%.192s` at row %lu" + ger "Falscher %-.32s-Wert: '%-.128T' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" ER_ILLEGAL_VALUE_FOR_TYPE 22007 - eng "Illegal %s '%-.192s' value found during parsing" - ger "Nicht zulässiger %s-Wert '%-.192s' beim Parsen gefunden" + eng "Illegal %s '%-.192T' value found during parsing" + ger "Nicht zulässiger %s-Wert '%-.192T' beim Parsen gefunden" ER_VIEW_NONUPD_CHECK eng "CHECK OPTION on non-updatable view %`-.192s.%`-.192s" ger "CHECK OPTION auf nicht-aktualisierbarem View %`-.192s.%`-.192s" @@ -5576,8 +5576,8 @@ ER_CANT_CREATE_USER_WITH_GRANT 42000 eng "You are not allowed to create a user with GRANT" ger "Sie dürfen keinen Benutzer mit GRANT anlegen" ER_WRONG_VALUE_FOR_TYPE - eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" - ger "Falscher %-.32s-Wert: '%-.128s' für Funktion %-.32s" + eng "Incorrect %-.32s value: '%-.128T' for function %-.32s" + ger "Falscher %-.32s-Wert: '%-.128T' für Funktion %-.32s" ER_TABLE_DEF_CHANGED eng "Table definition has changed, please retry transaction" ger "Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu" @@ -5756,8 +5756,8 @@ ER_HOSTNAME ger "Hostname" hindi "होस्ट का नाम" ER_WRONG_STRING_LENGTH - eng "String '%-.70s' is too long for %s (should be no longer than %d)" - ger "String '%-.70s' ist zu lang für %s (sollte nicht länger sein als %d)" + eng "String '%-.70T' is too long for %s (should be no longer than %d)" + ger "String '%-.70T' ist zu lang für %s (sollte nicht länger sein als %d)" ER_NON_INSERTABLE_TABLE eng "The target table %-.100s of the %s is not insertable-into" ger "Die Zieltabelle %-.100s von %s ist nicht einfügbar" @@ -5962,8 +5962,8 @@ ER_PLUGIN_IS_NOT_LOADED eng "Plugin '%-.192s' is not loaded" ger "Plugin '%-.192s' ist nicht geladen" ER_WRONG_VALUE - eng "Incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert: '%-.128s'" + eng "Incorrect %-.32s value: '%-.128T'" + ger "Falscher %-.32s-Wert: '%-.128T'" ER_NO_PARTITION_FOR_GIVEN_VALUE eng "Table has no partition for value %-.64s" ger "Tabelle hat für den Wert %-.64s keine Partition" @@ -6106,8 +6106,8 @@ ER_WRONG_PARTITION_NAME ER_CANT_CHANGE_TX_CHARACTERISTICS 25001 eng "Transaction characteristics can't be changed while a transaction is in progress" ER_DUP_ENTRY_AUTOINCREMENT_CASE - eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'" - ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192s' für Schlüssel '%-.192s' auftritt" + eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192T' for key '%-.192s'" + ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192T' für Schlüssel '%-.192s' auftritt" ER_EVENT_MODIFY_QUEUE_ERROR eng "Internal scheduler error %d" ger "Interner Scheduler-Fehler %d" @@ -6162,29 +6162,29 @@ ER_NATIVE_FCT_NAME_COLLISION # When using this error message, use the ER_DUP_ENTRY error code. See, for # example, code in handler.cc. ER_DUP_ENTRY_WITH_KEY_NAME 23000 S1009 - cze "Zvojený klíč '%-.64s' (číslo klíče '%-.192s')" - dan "Ens værdier '%-.64s' for indeks '%-.192s'" - nla "Dubbele ingang '%-.64s' voor zoeksleutel '%-.192s'" - eng "Duplicate entry '%-.64s' for key '%-.192s'" - est "Kattuv väärtus '%-.64s' võtmele '%-.192s'" - fre "Duplicata du champ '%-.64s' pour la clef '%-.192s'" - ger "Doppelter Eintrag '%-.64s' für Schlüssel '%-.192s'" - greek "Διπλή εγγραφή '%-.64s' για το κλειδί '%-.192s'" - hun "Duplikalt bejegyzes '%-.64s' a '%-.192s' kulcs szerint" - ita "Valore duplicato '%-.64s' per la chiave '%-.192s'" - jpn "'%-.64s' は索引 '%-.192s' で重複しています。" - kor "중복된 입력 값 '%-.64s': key '%-.192s'" - nor "Like verdier '%-.64s' for nøkkel '%-.192s'" - norwegian-ny "Like verdiar '%-.64s' for nykkel '%-.192s'" - pol "Powtórzone wystąpienie '%-.64s' dla klucza '%-.192s'" - por "Entrada '%-.64s' duplicada para a chave '%-.192s'" - rum "Cimpul '%-.64s' e duplicat pentru cheia '%-.192s'" - rus "Дублирующаяся запись '%-.64s' по ключу '%-.192s'" - serbian "Dupliran unos '%-.64s' za ključ '%-.192s'" - slo "Opakovaný kľúč '%-.64s' (číslo kľúča '%-.192s')" - spa "Entrada duplicada '%-.64s' para la clave '%-.192s'" - swe "Dublett '%-.64s' för nyckel '%-.192s'" - ukr "Дублюючий запис '%-.64s' для ключа '%-.192s'" + cze "Zvojený klíč '%-.64T' (číslo klíče '%-.192s')" + dan "Ens værdier '%-.64T' for indeks '%-.192s'" + nla "Dubbele ingang '%-.64T' voor zoeksleutel '%-.192s'" + eng "Duplicate entry '%-.64T' for key '%-.192s'" + est "Kattuv väärtus '%-.64T' võtmele '%-.192s'" + fre "Duplicata du champ '%-.64T' pour la clef '%-.192s'" + ger "Doppelter Eintrag '%-.64T' für Schlüssel '%-.192s'" + greek "Διπλή εγγραφή '%-.64T' για το κλειδί '%-.192s'" + hun "Duplikalt bejegyzes '%-.64T' a '%-.192s' kulcs szerint" + ita "Valore duplicato '%-.64T' per la chiave '%-.192s'" + jpn "'%-.64T' は索引 '%-.192s' で重複しています。" + kor "중복된 입력 값 '%-.64T': key '%-.192s'" + nor "Like verdier '%-.64T' for nøkkel '%-.192s'" + norwegian-ny "Like verdiar '%-.64T' for nykkel '%-.192s'" + pol "Powtórzone wystąpienie '%-.64T' dla klucza '%-.192s'" + por "Entrada '%-.64T' duplicada para a chave '%-.192s'" + rum "Cimpul '%-.64T' e duplicat pentru cheia '%-.192s'" + rus "Дублирующаяся запись '%-.64T' по ключу '%-.192s'" + serbian "Dupliran unos '%-.64T' za ključ '%-.192s'" + slo "Opakovaný kľúč '%-.64T' (číslo kľúča '%-.192s')" + spa "Entrada duplicada '%-.64T' para la clave '%-.192s'" + swe "Dublett '%-.64T' för nyckel '%-.192s'" + ukr "Дублюючий запис '%-.64T' для ключа '%-.192s'" ER_BINLOG_PURGE_EMFILE eng "Too many files opened, please execute the command again" ger "Zu viele offene Dateien, bitte führen Sie den Befehl noch einmal aus" @@ -6465,8 +6465,8 @@ ER_SLAVE_CANT_CREATE_CONVERSION ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT eng "Cannot modify @@session.binlog_format inside a transaction" ER_PATH_LENGTH - eng "The path specified for %.64s is too long" - hindi "%.64s के लिए निर्दिष्ट पथ बहुत लंबा है" + eng "The path specified for %.64T is too long" + hindi "%.64T के लिए निर्दिष्ट पथ बहुत लंबा है" ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT eng "'%s' is deprecated and will be removed in a future release" ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden" @@ -7166,8 +7166,8 @@ ER_UNKNOWN_OPTION eng "Unknown option '%-.64s'" hindi "अज्ञात विकल्प '%-.64s'" ER_BAD_OPTION_VALUE - eng "Incorrect value '%-.64s' for option '%-.64s'" - hindi "गलत मान '%-.64s' विकल्प '%-.64s' के लिए" + eng "Incorrect value '%-.64T' for option '%-.64s'" + hindi "गलत मान '%-.64T' विकल्प '%-.64s' के लिए" ER_UNUSED_6 eng "You should never see it" ER_UNUSED_7 @@ -7324,8 +7324,8 @@ ER_ROLE_DROP_EXISTS ER_CANNOT_CONVERT_CHARACTER eng "Cannot convert '%s' character 0x%-.64s to '%s'" ER_INVALID_DEFAULT_VALUE_FOR_FIELD 22007 - eng "Incorrect default value '%-.128s' for column '%.192s'" - hindi "गलत डिफ़ॉल्ट मान '%-.128s' कॉलम '%.192s' के लिए" + eng "Incorrect default value '%-.128T' for column '%.192s'" + hindi "गलत डिफ़ॉल्ट मान '%-.128T' कॉलम '%.192s' के लिए" ER_KILL_QUERY_DENIED_ERROR eng "You are not owner of query %lu" ger "Sie sind nicht Eigentümer von Abfrage %lu" @@ -7961,3 +7961,7 @@ ER_KEY_CONTAINS_PERIOD_FIELDS eng "Key %`s cannot explicitly include column %`s" ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS eng "Key %`s cannot have WITHOUT OVERLAPS" +ER_NOT_ALLOWED_IN_THIS_CONTEXT + eng "'%-.128s' is not allowed in this context" +ER_DATA_WAS_COMMITED_UNDER_ROLLBACK + eng "Engine %s does not support rollback. Changes where commited during rollback call" diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 467985c1270..5e3f32eae4e 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -52,8 +52,9 @@ static inline void output_core_info() char buff[PATH_MAX]; ssize_t len; int fd; - if ((len= readlink("/proc/self/cwd", buff, sizeof(buff))) >= 0) + if ((len= readlink("/proc/self/cwd", buff, sizeof(buff)-1)) >= 0) { + buff[len]= 0; my_safe_printf_stderr("Writing a core file...\nWorking directory at %.*s\n", (int) len, buff); } @@ -278,7 +279,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) } my_safe_printf_stderr("%s", "The manual page at " - "http://dev.mysql.com/doc/mysql/en/crashing.html contains\n" + "https://mariadb.com/kb/en/how-to-produce-a-full-stack-trace-for-mysqld/ contains\n" "information that should help you find out what is causing the crash.\n"); #endif /* HAVE_STACKTRACE */ diff --git a/sql/slave.cc b/sql/slave.cc index 9b9400bd7bc..bd3bab224d3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1448,7 +1448,7 @@ void slave_prepare_for_shutdown() mysql_mutex_unlock(&LOCK_active_mi); // It's safe to destruct worker pool now when // all driver threads are gone. - global_rpl_thread_pool.destroy(); + global_rpl_thread_pool.deactivate(); stop_slave_background_thread(); } @@ -1535,7 +1535,7 @@ static bool sql_slave_killed(rpl_group_info *rgi) rli->is_in_group(). */ - if ((thd->transaction.all.modified_non_trans_table || + if ((thd->transaction->all.modified_non_trans_table || (thd->variables.option_bits & OPTION_KEEP_LOG)) && rli->is_in_group()) { @@ -1549,7 +1549,7 @@ static bool sql_slave_killed(rpl_group_info *rgi) DBUG_PRINT("info", ("modified_non_trans_table: %d OPTION_BEGIN: %d " "OPTION_KEEP_LOG: %d is_in_group: %d", - thd->transaction.all.modified_non_trans_table, + thd->transaction->all.modified_non_trans_table, MY_TEST(thd->variables.option_bits & OPTION_BEGIN), MY_TEST(thd->variables.option_bits & OPTION_KEEP_LOG), rli->is_in_group())); @@ -4355,12 +4355,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && (ev->server_id != global_system_variables.server_id || rli->replicate_same_server_id) && - rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) - ? rli->group_master_log_pos - : ev->log_pos - ev->data_written)) + rli->is_until_satisfied(ev)) { - sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. @@ -4386,7 +4382,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, (LOG_EVENT_IS_QUERY(typ) && strcmp("COMMIT", ((Query_log_event *) ev)->query) == 0)) { - DBUG_ASSERT(thd->transaction.all.modified_non_trans_table); + DBUG_ASSERT(thd->transaction->all.modified_non_trans_table); rli->abort_slave= 1; mysql_mutex_unlock(&rli->data_lock); delete ev; @@ -5607,10 +5603,14 @@ pthread_handler_t handle_slave_sql(void *arg) } if ((rli->until_condition == Relay_log_info::UNTIL_MASTER_POS || rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(NULL)) { sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); mysql_mutex_unlock(&rli->data_lock); goto err; } @@ -5689,7 +5689,24 @@ pthread_handler_t handle_slave_sql(void *arg) err: if (mi->using_parallel()) rli->parallel.wait_for_done(thd, rli); + /* Gtid_list_log_event::do_apply_event has already reported the GTID until */ + if (rli->stop_for_until && rli->until_condition != Relay_log_info::UNTIL_GTID) + { + if (global_system_variables.log_warnings > 2) + sql_print_information("Slave SQL thread UNTIL stop was requested at position " + "%llu in %s %s file", + rli->until_log_pos, rli->until_log_name, + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + sql_print_information("Slave SQL thread stopped because it reached its" + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + }; /* Thread stopped. Print the current replication position to the log */ { StringBuffer<100> tmp; diff --git a/sql/sp.cc b/sql/sp.cc index 51bbeeef368..971aa4a143f 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -30,6 +30,7 @@ #include "sql_table.h" // write_bin_log #include "sp_head.h" #include "sp_cache.h" +#include "transaction.h" #include "lock.h" // lock_object_name #include @@ -470,27 +471,31 @@ static Proc_table_intact proc_table_intact; currently open tables will be saved, and from which will be restored when we will end work with mysql.proc. + NOTES + On must have a start_new_trans object active when calling this function + @retval 0 Error @retval \# Pointer to TABLE object of mysql.proc */ -TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup) +TABLE *open_proc_table_for_read(THD *thd) { TABLE_LIST table; - DBUG_ENTER("open_proc_table_for_read"); + DBUG_ASSERT(thd->internal_transaction()); + table.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROC_NAME, NULL, TL_READ); - if (open_system_tables_for_read(thd, &table, backup)) + if (open_system_tables_for_read(thd, &table)) DBUG_RETURN(NULL); if (!proc_table_intact.check(table.table, &proc_table_def)) DBUG_RETURN(table.table); - close_system_tables(thd, backup); + thd->commit_whole_transaction_and_close_tables(); DBUG_RETURN(NULL); } @@ -504,6 +509,10 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup) @note Table opened with this call should closed using close_thread_tables(). + We don't need to use the start_new_transaction object when calling this + as there can't be any active transactions when we create or alter + stored procedures + @retval 0 Error @retval @@ -517,7 +526,10 @@ static TABLE *open_proc_table_for_update(THD *thd) MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); DBUG_ENTER("open_proc_table_for_update"); - table_list.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROC_NAME, NULL, TL_WRITE); + DBUG_ASSERT(!thd->internal_transaction()); + + table_list.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROC_NAME, NULL, + TL_WRITE); if (!(table= open_system_table_for_update(thd, &table_list))) DBUG_RETURN(NULL); @@ -525,7 +537,7 @@ static TABLE *open_proc_table_for_update(THD *thd) if (!proc_table_intact.check(table, &proc_table_def)) DBUG_RETURN(table); - close_thread_tables(thd); + thd->commit_whole_transaction_and_close_tables(); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); DBUG_RETURN(NULL); @@ -683,23 +695,26 @@ Sp_handler::db_find_routine(THD *thd, longlong modified; Sp_chistics chistics; bool saved_time_zone_used= thd->time_zone_used; + bool trans_commited= 0; sql_mode_t sql_mode; - Open_tables_backup open_tables_state_backup; Stored_program_creation_ctx *creation_ctx; AUTHID definer; - DBUG_ENTER("db_find_routine"); DBUG_PRINT("enter", ("type: %s name: %.*s", type_str(), (int) name->m_name.length, name->m_name.str)); *sphp= 0; // In case of errors - if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) - DBUG_RETURN(SP_OPEN_TABLE_FAILED); - /* Reset sql_mode during data dictionary operations. */ + start_new_trans new_trans(thd); Sql_mode_instant_set sms(thd, 0); + if (!(table= open_proc_table_for_read(thd))) + { + ret= SP_OPEN_TABLE_FAILED; + goto done; + } + if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK) goto done; @@ -741,8 +756,9 @@ Sp_handler::db_find_routine(THD *thd, creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table); - close_system_tables(thd, &open_tables_state_backup); - table= 0; + trans_commited= 1; + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); ret= db_load_routine(thd, name, sphp, sql_mode, params, returns, body, chistics, definer, @@ -753,8 +769,12 @@ Sp_handler::db_find_routine(THD *thd, does not affect replication. */ thd->time_zone_used= saved_time_zone_used; - if (table) - close_system_tables(thd, &open_tables_state_backup); + if (!trans_commited) + { + if (table) + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + } DBUG_RETURN(ret); } @@ -1727,7 +1747,6 @@ bool lock_db_routines(THD *thd, const char *db) { TABLE *table; uint key_len; - Open_tables_backup open_tables_state_backup; MDL_request_list mdl_requests; Lock_db_routines_error_handler err_handler; uchar keybuf[MAX_KEY_LENGTH]; @@ -1735,13 +1754,15 @@ bool lock_db_routines(THD *thd, const char *db) DBUG_SLOW_ASSERT(ok_for_lower_case_names(db)); + start_new_trans new_trans(thd); + /* mysql.proc will be re-opened during deletion, so we can ignore errors when opening the table here. The error handler is used to avoid getting the same warning twice. */ thd->push_internal_handler(&err_handler); - table= open_proc_table_for_read(thd, &open_tables_state_backup); + table= open_proc_table_for_read(thd); thd->pop_internal_handler(); if (!table) { @@ -1750,6 +1771,7 @@ bool lock_db_routines(THD *thd, const char *db) or is outdated. We therefore only abort mysql_rm_db() if we have errors not handled by the error handler. */ + new_trans.restore_old_transaction(); DBUG_RETURN(thd->is_error() || thd->killed); } @@ -1760,11 +1782,10 @@ bool lock_db_routines(THD *thd, const char *db) if (nxtres) { table->file->print_error(nxtres, MYF(0)); - close_system_tables(thd, &open_tables_state_backup); - DBUG_RETURN(true); + goto error; } - if (! table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1, + if (!table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1, HA_READ_KEY_EXACT)) { do @@ -1789,10 +1810,10 @@ bool lock_db_routines(THD *thd, const char *db) if (nxtres != 0 && nxtres != HA_ERR_END_OF_FILE) { table->file->print_error(nxtres, MYF(0)); - close_system_tables(thd, &open_tables_state_backup); - DBUG_RETURN(true); + goto error; } - close_system_tables(thd, &open_tables_state_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); /* We should already hold a global IX lock and a schema X lock. */ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", @@ -1801,6 +1822,10 @@ bool lock_db_routines(THD *thd, const char *db) MDL_EXCLUSIVE)); DBUG_RETURN(thd->mdl_context.acquire_locks(&mdl_requests, thd->variables.lock_wait_timeout)); +error: + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + DBUG_RETURN(true); } @@ -1879,6 +1904,7 @@ sp_drop_db_routines(THD *thd, const char *db) table->file->ha_index_end(); err_idx_init: + trans_commit_stmt(thd); close_thread_tables(thd); /* Make sure to only release the MDL lock on mysql.proc, not other diff --git a/sql/sp.h b/sql/sp.h index 72485632261..e92525e1930 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -655,7 +655,7 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, Routines which allow open/lock and close mysql.proc table even when we already have some tables open and locked. */ -TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup); +TABLE *open_proc_table_for_read(THD *thd); bool load_charset(MEM_ROOT *mem_root, Field *field, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f840904def3..49c8229c277 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1212,6 +1212,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) backup_arena; query_id_t old_query_id; TABLE *old_derived_tables; + TABLE *old_rec_tables; LEX *old_lex; Item_change_list old_change_list; String old_packet; @@ -1292,6 +1293,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success) old_query_id= thd->query_id; old_derived_tables= thd->derived_tables; thd->derived_tables= 0; + old_rec_tables= thd->rec_tables; + thd->rec_tables= 0; save_sql_mode= thd->variables.sql_mode; thd->variables.sql_mode= m_sql_mode; save_abort_on_warning= thd->abort_on_warning; @@ -1566,6 +1569,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) thd->set_query_id(old_query_id); DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; + thd->rec_tables= old_rec_tables; thd->variables.sql_mode= save_sql_mode; thd->abort_on_warning= save_abort_on_warning; thd->m_reprepare_observer= save_reprepare_observer; @@ -3426,8 +3430,8 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, It's reset further in the common code part. It's merged with the saved parent's value at the exit of this func. */ - bool parent_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; - thd->transaction.stmt.modified_non_trans_table= FALSE; + bool parent_modified_non_trans_table= thd->transaction->stmt.modified_non_trans_table; + thd->transaction->stmt.modified_non_trans_table= FALSE; DBUG_ASSERT(!thd->derived_tables); DBUG_ASSERT(thd->Item_change_list::is_empty()); /* @@ -3550,7 +3554,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, Merge here with the saved parent's values what is needed from the substatement gained */ - thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table; + thd->transaction->stmt.modified_non_trans_table |= parent_modified_non_trans_table; TRANSACT_TRACKER(add_trx_state_from_thd(thd)); @@ -4648,7 +4652,7 @@ sp_instr_agg_cfetch::execute(THD *thd, uint *nextp) else { thd->spcont->pause_state= FALSE; - if (thd->server_status == SERVER_STATUS_LAST_ROW_SENT) + if (thd->server_status & SERVER_STATUS_LAST_ROW_SENT) { my_message(ER_SP_FETCH_NO_DATA, ER_THD(thd, ER_SP_FETCH_NO_DATA), MYF(0)); @@ -5164,6 +5168,9 @@ sp_head::set_local_variable(THD *thd, sp_pcontext *spcont, if (!(val= adjust_assignment_source(thd, val, spv->default_value))) return true; + if (val->walk(&Item::unknown_splocal_processor, false, NULL)) + return true; + sp_instr_set *sp_set= new (thd->mem_root) sp_instr_set(instructions(), spcont, rh, spv->offset, val, lex, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4271340340b..d94016b7815 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB Corporation. + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3124,8 +3124,33 @@ bool acl_getroot(Security_context *sctx, const char *user, const char *host, DBUG_RETURN(res); } -static int check_user_can_set_role(const char *user, const char *host, - const char *ip, const char *rolename, privilege_t *access) +static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data) +{ + LEX_CSTRING *rolename= static_cast(data); + if (rolename->length == grantee->user.length && + !strcmp(rolename->str, grantee->user.str)) + return -1; // End search, we've found our role. + + /* Keep looking, we haven't found our role yet. */ + return 0; +} + +/* + unlike find_user_exact and find_user_wild, + this function finds anonymous users too, it's when a + user is not empty, but priv_user (acl_user->user) is empty. +*/ +static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip) +{ + return find_by_username_or_anon + (reinterpret_cast(acl_users.buffer), acl_users.elements, + user, host, ip, NULL, FALSE, NULL); +} + + +static int check_user_can_set_role(THD *thd, const char *user, + const char *host, const char *ip, + const char *rolename, privilege_t *access) { ACL_ROLE *role; ACL_USER_BASE *acl_user_base; @@ -3142,10 +3167,7 @@ static int check_user_can_set_role(const char *user, const char *host, /* get the current user */ acl_user= find_user_wild(host, user, ip); if (acl_user == NULL) - { - my_error(ER_INVALID_CURRENT_USER, MYF(0)); - result= -1; - } + result= ER_INVALID_CURRENT_USER; else if (access) *access= acl_user->access; @@ -3155,9 +3177,9 @@ static int check_user_can_set_role(const char *user, const char *host, role= find_acl_role(rolename); /* According to SQL standard, the same error message must be presented */ - if (role == NULL) { - my_error(ER_INVALID_ROLE, MYF(0), rolename); - result= -1; + if (role == NULL) + { + result= ER_INVALID_ROLE; goto end; } @@ -3178,7 +3200,6 @@ static int check_user_can_set_role(const char *user, const char *host, /* According to SQL standard, the same error message must be presented */ if (!is_granted) { - my_error(ER_INVALID_ROLE, MYF(0), rolename); result= 1; goto end; } @@ -3187,17 +3208,66 @@ static int check_user_can_set_role(const char *user, const char *host, { *access = acl_user->access | role->access; } + end: mysql_mutex_unlock(&acl_cache->lock); - return result; + /* We present different error messages depending if the user has sufficient + privileges to know if the INVALID_ROLE exists. */ + switch (result) + { + case ER_INVALID_CURRENT_USER: + my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename); + break; + case ER_INVALID_ROLE: + /* Role doesn't exist at all */ + my_error(ER_INVALID_ROLE, MYF(0), rolename); + break; + case 1: + StringBuffer<1024> c_usr; + LEX_CSTRING role_lex; + /* First, check if current user can see mysql database. */ + bool read_access= !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); + + role_lex.str= rolename; + role_lex.length= strlen(rolename); + mysql_mutex_lock(&acl_cache->lock); + ACL_USER *cur_user= find_user_or_anon(thd->security_ctx->priv_host, + thd->security_ctx->priv_user, + thd->security_ctx->ip); + + /* If the current user does not have select priv to mysql database, + see if the current user can discover the role if it was granted to him. + */ + if (cur_user && (read_access || + traverse_role_graph_down(cur_user, &role_lex, + check_role_is_granted_callback, + NULL) == -1)) + { + /* Role is not granted but current user can see the role */ + c_usr.append(user, strlen(user)); + c_usr.append('@'); + c_usr.append(host, strlen(host)); + my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted role %`s", + MYF(0), c_usr.c_ptr(), rolename); + } + else + { + /* Role is not granted and current user cannot see the role */ + my_error(ER_INVALID_ROLE, MYF(0), rolename); + } + mysql_mutex_unlock(&acl_cache->lock); + break; + } + + return result; } + int acl_check_setrole(THD *thd, const char *rolename, privilege_t *access) { - /* Yes! priv_user@host. Don't ask why - that's what check_access() does. */ - return check_user_can_set_role(thd->security_ctx->priv_user, - thd->security_ctx->host, thd->security_ctx->ip, rolename, access); + return check_user_can_set_role(thd, thd->security_ctx->priv_user, + thd->security_ctx->host, thd->security_ctx->ip, rolename, access); } @@ -3936,9 +4006,12 @@ wsrep_error_label: DBUG_RETURN(result); } -int acl_check_set_default_role(THD *thd, const char *host, const char *user) +int acl_check_set_default_role(THD *thd, const char *host, const char *user, + const char *role) { - return check_alter_user(thd, host, user); + DBUG_ENTER("acl_check_set_default_role"); + DBUG_RETURN(check_alter_user(thd, host, user) || + check_user_can_set_role(thd, user, host, NULL, role, NULL)); } int acl_set_default_role(THD *thd, const char *host, const char *user, @@ -3958,16 +4031,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'", user, safe_str(host), safe_str(rolename))); - if (rolename == current_role.str) { - if (!thd->security_ctx->priv_role[0]) - rolename= "NONE"; - else - rolename= thd->security_ctx->priv_role; - } - - if (check_user_can_set_role(user, host, host, rolename, NULL)) - DBUG_RETURN(result); - if (!strcasecmp(rolename, "NONE")) clear_role= TRUE; @@ -4122,19 +4185,6 @@ bool is_acl_user(const char *host, const char *user) } -/* - unlike find_user_exact and find_user_wild, - this function finds anonymous users too, it's when a - user is not empty, but priv_user (acl_user->user) is empty. -*/ -static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip) -{ - return find_by_username_or_anon - (reinterpret_cast(acl_users.buffer), acl_users.elements, - user, host, ip, NULL, FALSE, NULL); -} - - /* Find first entry that matches the specified user@host pair */ @@ -4420,7 +4470,7 @@ static bool test_if_create_new_users(THD *thd) if (!(db_access & INSERT_ACL)) { if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE)) - create_new_users=0; + create_new_users=0; } } return create_new_users; @@ -8054,6 +8104,8 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, switch(access->check(orig_want_access, &t_ref->grant.privilege)) { case ACL_INTERNAL_ACCESS_GRANTED: + t_ref->grant.privilege|= orig_want_access; + t_ref->grant.want_privilege= NO_ACL; continue; case ACL_INTERNAL_ACCESS_DENIED: goto err; @@ -8406,7 +8458,8 @@ bool check_grant_all_columns(THD *thd, privilege_t want_access_arg, grant_table= grant->grant_table_user; grant_table_role= grant->grant_table_role; - DBUG_ASSERT (grant_table || grant_table_role); + if (!grant_table && !grant_table_role) + goto err; } } @@ -9725,17 +9778,6 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) mysql_mutex_unlock(&acl_cache->lock); } -static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data) -{ - LEX_CSTRING *rolename= static_cast(data); - if (rolename->length == grantee->user.length && - !strcmp(rolename->str, grantee->user.str)) - return -1; // End search, we've found our role. - - /* Keep looking, we haven't found our role yet. */ - return 0; -} - /* Modify a privilege table. @@ -11607,7 +11649,7 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, Security context in THD contains two pairs of (user,host): 1. (user,host) pair referring to inbound connection. 2. (priv_user,priv_host) pair obtained from mysql.user table after doing - authnetication of incoming connection. + authentication of incoming connection. Privileges should be checked wrt (priv_user, priv_host) tuple, because (user,host) pair obtained from inbound connection may have different values than what is actually stored in mysql.user table and while granting @@ -12171,7 +12213,7 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr) #ifndef NO_EMBEDDED_ACCESS_CHECKS -static bool update_schema_privilege(THD *thd, TABLE *table, char *buff, +static bool update_schema_privilege(THD *thd, TABLE *table, const char *buff, const char* db, const char* t_name, const char* column, uint col_length, const char *priv, uint priv_length, @@ -12195,13 +12237,27 @@ static bool update_schema_privilege(THD *thd, TABLE *table, char *buff, #endif +#ifndef NO_EMBEDDED_ACCESS_CHECKS +class Grantee_str +{ + char m_buff[USER_HOST_BUFF_SIZE + 6 /* 4 quotes, @, '\0' */]; +public: + Grantee_str(const char *user, const char *host) + { + DBUG_ASSERT(strlen(user) + strlen(host) + 6 < sizeof(m_buff)); + strxmov(m_buff, "'", user, "'@'", host, "'", NullS); + } + operator const char *() const { return m_buff; } +}; +#endif + + int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { #ifndef NO_EMBEDDED_ACCESS_CHECKS int error= 0; uint counter; ACL_USER *acl_user; - char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); @@ -12226,10 +12282,10 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) if (!(want_access & GRANT_ACL)) is_grantable= "NO"; - strxmov(buff,"'",user,"'@'",host,"'",NullS); + Grantee_str grantee(user, host); if (!(want_access & ~GRANT_ACL)) { - if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0, + if (update_schema_privilege(thd, table, grantee, 0, 0, 0, 0, STRING_WITH_LEN("USAGE"), is_grantable)) { error= 1; @@ -12243,9 +12299,9 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) privilege_t test_access(want_access & ~GRANT_ACL); for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1) { - if (test_access & j) + if (test_access & j) { - if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0, + if (update_schema_privilege(thd, table, grantee, 0, 0, 0, 0, command_array[priv_id], command_lengths[priv_id], is_grantable)) { @@ -12272,7 +12328,6 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) int error= 0; uint counter; ACL_DB *acl_db; - char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); @@ -12301,10 +12356,10 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { is_grantable= "NO"; } - strxmov(buff,"'",user,"'@'",host,"'",NullS); + Grantee_str grantee(user, host); if (!(want_access & ~GRANT_ACL)) { - if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0, + if (update_schema_privilege(thd, table, grantee, acl_db->db, 0, 0, 0, STRING_WITH_LEN("USAGE"), is_grantable)) { error= 1; @@ -12319,7 +12374,8 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1) if (test_access & j) { - if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0, 0, + if (update_schema_privilege(thd, table, + grantee, acl_db->db, 0, 0, 0, command_array[cnt], command_lengths[cnt], is_grantable)) { @@ -12345,7 +12401,6 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) #ifndef NO_EMBEDDED_ACCESS_CHECKS int error= 0; uint index; - char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); @@ -12378,10 +12433,11 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) if (!(table_access & GRANT_ACL)) is_grantable= "NO"; - strxmov(buff, "'", user, "'@'", host, "'", NullS); + Grantee_str grantee(user, host); if (!test_access) { - if (update_schema_privilege(thd, table, buff, grant_table->db, + if (update_schema_privilege(thd, table, + grantee, grant_table->db, grant_table->tname, 0, 0, STRING_WITH_LEN("USAGE"), is_grantable)) { @@ -12397,7 +12453,8 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { if (test_access & j) { - if (update_schema_privilege(thd, table, buff, grant_table->db, + if (update_schema_privilege(thd, table, + grantee, grant_table->db, grant_table->tname, 0, 0, command_array[cnt], command_lengths[cnt], is_grantable)) @@ -12425,7 +12482,6 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) #ifndef NO_EMBEDDED_ACCESS_CHECKS int error= 0; uint index; - char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1); @@ -12452,7 +12508,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) is_grantable= "NO"; privilege_t test_access(table_access & ~GRANT_ACL); - strxmov(buff, "'", user, "'@'", host, "'", NullS); + Grantee_str grantee(user, host); if (!test_access) continue; else @@ -12471,7 +12527,9 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) my_hash_element(&grant_table->hash_columns,col_index); if ((grant_column->rights & j) && (table_access & j)) { - if (update_schema_privilege(thd, table, buff, grant_table->db, + if (update_schema_privilege(thd, table, + grantee, + grant_table->db, grant_table->tname, grant_column->column, grant_column->key_length, diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 2cf1637c8db..570da144b46 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -2,7 +2,7 @@ #define SQL_ACL_INCLUDED /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2017, MariaDB Corporation. + Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -280,7 +280,8 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user, bool with_grant); int acl_setrole(THD *thd, const char *rolename, privilege_t access); int acl_check_setrole(THD *thd, const char *rolename, privilege_t *access); -int acl_check_set_default_role(THD *thd, const char *host, const char *user); +int acl_check_set_default_role(THD *thd, const char *host, const char *user, + const char *role); int acl_set_default_role(THD *thd, const char *host, const char *user, const char *rolename); diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 0274a51ff26..71939936da0 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1089,7 +1089,7 @@ send_result_message: } /* Make sure this table instance is not reused after the operation. */ if (table->table) - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); } result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; table->next_local= save_next_local; @@ -1141,6 +1141,13 @@ send_result_message: } if (table->table && !table->view) { + /* + Don't skip flushing if we are collecting EITS statistics. + */ + const bool skip_flush= + (operator_func == &handler::ha_analyze) && + (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE) && + !collect_eis; if (table->table->s->tmp_table) { /* @@ -1150,7 +1157,7 @@ send_result_message: if (open_for_modify && !open_error) table->table->file->info(HA_STATUS_CONST); } - else if (open_for_modify || fatal_error) + else if ((!skip_flush && open_for_modify) || fatal_error) { table->table->s->tdc->flush_unused(true); /* @@ -1213,7 +1220,7 @@ err: trans_rollback(thd); if (table && table->table) { - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); table->table= 0; } close_thread_tables(thd); // Shouldn't be needed diff --git a/sql/sql_alter.h b/sql/sql_alter.h index 88873477c7c..ca343f36569 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -95,11 +95,6 @@ public: List alter_rename_key_list; // List of columns, used by both CREATE and ALTER TABLE. List create_list; - - enum flags_bits - { - CHECK_CONSTRAINT_IF_NOT_EXISTS= 1 - }; List check_constraint_list; // Type of ALTER TABLE operation. alter_table_operations flags; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b5064fe9fd9..88a28c470c0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -598,12 +598,15 @@ bool flush_tables(THD *thd, flush_tables_type flag) else { /* - HA_OPEN_FOR_ALTER is used to allow us to open the table even if - TABLE_SHARE::incompatible_version is set. + HA_OPEN_FOR_FLUSH is used to allow us to open the table even if + TABLE_SHARE::incompatible_version is set. It also will tell + SEQUENCE engine that we don't have to read the sequence information + (which may cause deadlocks with concurrently running ALTER TABLE or + ALTER SEQUENCE) as we will close the table at once. */ if (!open_table_from_share(thd, share, &empty_clex_str, HA_OPEN_KEYFILE, 0, - HA_OPEN_FOR_ALTER, + HA_OPEN_FOR_ALTER | HA_OPEN_FOR_FLUSH, tmp_table, FALSE, NULL)) { @@ -793,7 +796,7 @@ int close_thread_tables(THD *thd) DEBUG_SYNC(thd, "before_close_thread_tables"); #endif - DBUG_ASSERT(thd->transaction.stmt.is_empty() || thd->in_sub_stmt || + DBUG_ASSERT(thd->transaction->stmt.is_empty() || thd->in_sub_stmt || (thd->state_flags & Open_tables_state::BACKUPS_AVAIL)); for (table= thd->open_tables; table; table= table->next) @@ -1765,6 +1768,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) { table= best_table; table->query_id= thd->query_id; + table->init(thd, table_list); DBUG_PRINT("info",("Using locked table")); #ifdef WITH_PARTITION_STORAGE_ENGINE part_names_error= set_partitions_as_used(table_list, table); @@ -2084,12 +2088,13 @@ retry_share: } table->mdl_ticket= mdl_ticket; + table->reginfo.lock_type=TL_READ; /* Assume read */ + + table->init(thd, table_list); table->next= thd->open_tables; /* Link into simple list */ thd->set_open_tables(table); - table->reginfo.lock_type=TL_READ; /* Assume read */ - reset: /* Check that there is no reference to a condition from an earlier query @@ -2121,16 +2126,15 @@ retry_share: my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db.str, table_list->alias.str); DBUG_RETURN(true); } - table->init(thd, table_list); - DBUG_ASSERT(thd->locked_tables_mode || table->file->row_logging == 0); - DBUG_RETURN(FALSE); + DBUG_ASSERT(thd->locked_tables_mode || table->file->row_logging == 0); + DBUG_RETURN(false); err_lock: tdc_release_share(share); DBUG_PRINT("exit", ("failed")); - DBUG_RETURN(TRUE); + DBUG_RETURN(true); } @@ -2296,9 +2300,9 @@ Locked_tables_list::init_locked_tables(THD *thd) in reopen_tables(). reopen_tables() is a critical path and we don't want to complicate it with extra allocations. */ - m_reopen_array= (TABLE**)alloc_root(&m_locked_tables_root, - sizeof(TABLE*) * - (m_locked_tables_count+1)); + m_reopen_array= (TABLE_LIST**)alloc_root(&m_locked_tables_root, + sizeof(TABLE_LIST*) * + (m_locked_tables_count+1)); if (m_reopen_array == NULL) { reset(); @@ -2351,7 +2355,7 @@ Locked_tables_list::unlock_locked_tables(THD *thd) TRANSACT_TRACKER(clear_trx_state(thd, TX_LOCKED_TABLES)); - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); error= close_thread_tables(thd); /* @@ -2411,6 +2415,7 @@ void Locked_tables_list::reset() m_locked_tables_last= &m_locked_tables; m_reopen_array= NULL; m_locked_tables_count= 0; + some_table_marked_for_reopen= 0; } @@ -2506,7 +2511,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) in reopen_tables() always links the opened table to the beginning of the open_tables list. */ - DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]); + DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]->table); thd->open_tables->pos_in_locked_tables->table= NULL; thd->open_tables->pos_in_locked_tables= NULL; @@ -2536,10 +2541,36 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) } +/* + Mark all instances of the table to be reopened + + This is only needed when LOCK TABLES is active +*/ + +void Locked_tables_list::mark_table_for_reopen(THD *thd, TABLE *table) +{ + TABLE_SHARE *share= table->s; + + for (TABLE_LIST *table_list= m_locked_tables; + table_list; table_list= table_list->next_global) + { + if (table_list->table->s == share) + table_list->table->internal_set_needs_reopen(true); + } + /* This is needed in the case where lock tables where not used */ + table->internal_set_needs_reopen(true); + some_table_marked_for_reopen= 1; +} + + /** Reopen the tables locked with LOCK TABLES and temporarily closed by a DDL statement or FLUSH TABLES. + @param need_reopen If set, reopen open tables that are marked with + for reopen. + If not set, reopen tables that where closed. + @note This function is a no-op if we're not under LOCK TABLES. @return TRUE if an error reopening the tables. May happen in @@ -2557,6 +2588,13 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) MYSQL_LOCK *merged_lock; DBUG_ENTER("Locked_tables_list::reopen_tables"); + DBUG_ASSERT(some_table_marked_for_reopen || !need_reopen); + + + /* Reset flag that some table was marked for reopen */ + if (need_reopen) + some_table_marked_for_reopen= 0; + for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= table_list->next_global) { @@ -2580,24 +2618,32 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) else { if (table_list->table) /* The table was not closed */ - continue; + continue; } - /* Links into thd->open_tables upon success */ - if (open_table(thd, table_list, &ot_ctx)) - { - unlink_all_closed_tables(thd, 0, reopen_count); - DBUG_RETURN(TRUE); - } - table_list->table->pos_in_locked_tables= table_list; - /* See also the comment on lock type in init_locked_tables(). */ - table_list->table->reginfo.lock_type= table_list->lock_type; - DBUG_ASSERT(reopen_count < m_locked_tables_count); - m_reopen_array[reopen_count++]= table_list->table; + m_reopen_array[reopen_count++]= table_list; } if (reopen_count) { + TABLE **tables= (TABLE**) my_alloca(reopen_count * sizeof(TABLE*)); + + for (uint i= 0 ; i < reopen_count ; i++) + { + TABLE_LIST *table_list= m_reopen_array[i]; + /* Links into thd->open_tables upon success */ + if (open_table(thd, table_list, &ot_ctx)) + { + unlink_all_closed_tables(thd, 0, i); + my_afree((void*) tables); + DBUG_RETURN(TRUE); + } + tables[i]= table_list->table; + table_list->table->pos_in_locked_tables= table_list; + /* See also the comment on lock type in init_locked_tables(). */ + table_list->table->reginfo.lock_type= table_list->lock_type; + } + thd->in_lock_tables= 1; /* We re-lock all tables with mysql_lock_tables() at once rather @@ -2610,7 +2656,7 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) works fine. Patching legacy code of thr_lock.c is risking to break something else. */ - lock= mysql_lock_tables(thd, m_reopen_array, reopen_count, + lock= mysql_lock_tables(thd, tables, reopen_count, MYSQL_OPEN_REOPEN | MYSQL_LOCK_USE_MALLOC); thd->in_lock_tables= 0; if (lock == NULL || (merged_lock= @@ -2619,9 +2665,11 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) unlink_all_closed_tables(thd, lock, reopen_count); if (! thd->killed) my_error(ER_LOCK_DEADLOCK, MYF(0)); + my_afree((void*) tables); DBUG_RETURN(TRUE); } thd->lock= merged_lock; + my_afree((void*) tables); } DBUG_RETURN(FALSE); } @@ -4117,7 +4165,7 @@ bool open_tables(THD *thd, const DDL_options_st &options, DBUG_ENTER("open_tables"); /* Data access in XA transaction is only allowed when it is active. */ - if (*start && thd->transaction.xid_state.check_has_uncommitted_xa()) + if (*start && thd->transaction->xid_state.check_has_uncommitted_xa()) DBUG_RETURN(true); thd->current_tablenr= 0; @@ -4259,7 +4307,7 @@ restart: list, we still need to call open_and_process_routine() to take MDL locks on the routines. */ - if (thd->locked_tables_mode <= LTM_LOCK_TABLES) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && *sroutine_to_open) { /* Process elements of the prelocking set which are present there @@ -5186,7 +5234,7 @@ end: table on the fly, and thus mustn't manipulate with the transaction of the enclosing statement. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty() || + DBUG_ASSERT(thd->transaction->stmt.is_empty() || (thd->state_flags & Open_tables_state::BACKUPS_AVAIL)); close_thread_tables(thd); /* Don't keep locks for a failed statement. */ @@ -5583,7 +5631,7 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, table on the fly, and thus mustn't manipulate with the transaction of the enclosing statement. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty() || + DBUG_ASSERT(thd->transaction->stmt.is_empty() || (thd->state_flags & Open_tables_state::BACKUPS_AVAIL)); close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(start_of_statement_svp); @@ -8375,11 +8423,9 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, if (table->next_number_field && rfield->field_index == table->next_number_field->field_index) table->auto_increment_field_not_null= TRUE; - Item::Type type= value->type(); const bool skip_sys_field= rfield->vers_sys_field(); // TODO: && !thd->vers_modify_history() [MDEV-16546] if ((rfield->vcol_info || skip_sys_field) && - type != Item::DEFAULT_VALUE_ITEM && - type != Item::NULL_ITEM && + !value->vcol_assignment_allowed_value() && table->s->table_category != TABLE_CATEGORY_TEMPORARY) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -8660,20 +8706,16 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List &values, if (field->field_index == autoinc_index) table->auto_increment_field_not_null= TRUE; - if (unlikely(field->vcol_info) || (vers_sys_field && !ignore_errors)) + if ((unlikely(field->vcol_info) || (vers_sys_field && !ignore_errors)) && + !value->vcol_assignment_allowed_value() && + table->s->table_category != TABLE_CATEGORY_TEMPORARY) { - Item::Type type= value->type(); - if (type != Item::DEFAULT_VALUE_ITEM && - type != Item::NULL_ITEM && - table->s->table_category != TABLE_CATEGORY_TEMPORARY) - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN, - ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN), - field->field_name.str, table->s->table_name.str); - if (vers_sys_field) - continue; - } + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN, + ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN), + field->field_name.str, table->s->table_name.str); + if (vers_sys_field) + continue; } if (use_value) @@ -8887,17 +8929,16 @@ bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b) open_system_tables_for_read() thd Thread context. table_list List of tables to open. - backup Pointer to Open_tables_state instance where - information about currently open tables will be - saved, and from which will be restored when we will - end work with system tables. NOTES + Caller should have used start_new_trans object to start a new + transcation when reading system tables. + Thanks to restrictions which we put on opening and locking of system tables for writing, we can open and lock them for reading - even when we already have some other tables open and locked. One - must call close_system_tables() to close systems tables opened - with this call. + even when we already have some other tables open and locked. + One should call thd->commit_whole_transaction_and_close_tables() + to close systems tables opened with this call. NOTES In some situations we use this function to open system tables for @@ -8911,22 +8952,20 @@ bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b) */ bool -open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, - Open_tables_backup *backup) +open_system_tables_for_read(THD *thd, TABLE_LIST *table_list) { Query_tables_list query_tables_list_backup; LEX *lex= thd->lex; DBUG_ENTER("open_system_tables_for_read"); + DBUG_ASSERT(thd->internal_transaction()); /* Besides using new Open_tables_state for opening system tables, we also have to backup and reset/and then restore part of LEX which is accessed by open_tables() in order to determine if prelocking is needed and what tables should be added for it. - close_system_tables() doesn't require such treatment. */ lex->reset_n_backup_query_tables_list(&query_tables_list_backup); - thd->reset_n_backup_open_tables_state(backup); thd->lex->sql_command= SQLCOM_SELECT; /* @@ -8941,7 +8980,6 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, MYSQL_LOCK_IGNORE_TIMEOUT : 0)))) { lex->restore_backup_query_tables_list(&query_tables_list_backup); - thd->restore_backup_open_tables_state(backup); DBUG_RETURN(TRUE); } @@ -8956,33 +8994,6 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(FALSE); } - -/* - Close system tables, opened with open_system_tables_for_read(). - - SYNOPSIS - close_system_tables() - thd Thread context - backup Pointer to Open_tables_backup instance which holds - information about tables which were open before we - decided to access system tables. -*/ - -void -close_system_tables(THD *thd, Open_tables_backup *backup) -{ - /* - Inform the transaction handler that we are closing the - system tables and we don't need the read view anymore. - */ - for (TABLE *table= thd->open_tables ; table ; table= table->next) - table->file->extra(HA_EXTRA_PREPARE_FOR_FORCED_CLOSE); - - close_thread_tables(thd); - thd->restore_backup_open_tables_state(backup); -} - - /** A helper function to close a mysql.* table opened in an auxiliary THD during bootstrap or in the main @@ -9091,9 +9102,17 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup) @param thd The current thread @param backup [in] the context to restore. */ + void close_log_table(THD *thd, Open_tables_backup *backup) { - close_system_tables(thd, backup); + /* + Inform the transaction handler that we are closing the + system tables and we don't need the read view anymore. + */ + for (TABLE *table= thd->open_tables ; table ; table= table->next) + table->file->extra(HA_EXTRA_PREPARE_FOR_FORCED_CLOSE); + close_thread_tables(thd); + thd->restore_backup_open_tables_state(backup); } diff --git a/sql/sql_base.h b/sql/sql_base.h index 0fdb2599ce4..ccfacaf9086 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -294,9 +294,8 @@ bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b); class Open_tables_backup; /* Functions to work with system tables. */ -bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, - Open_tables_backup *backup); -void close_system_tables(THD *thd, Open_tables_backup *backup); +bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list); +void close_system_tables(THD *thd); void close_mysql_tables(THD *thd); TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table); TABLE *open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup); diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index ea91f68f360..0011487f1dc 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -158,8 +158,9 @@ int binlog_defragment(THD *thd) memcpy(const_cast(thd->lex->comment.str) + gathered_length, entry[k]->value, entry[k]->length); gathered_length += entry[k]->length; - update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0); } + for (uint k=0; k < 2; k++) + update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0); DBUG_ASSERT(gathered_length == thd->lex->comment.length); @@ -210,7 +211,7 @@ void mysql_client_binlog_statement(THD* thd) size_t coded_len= 0, decoded_len= 0; rli= thd->rli_fake; - if (!rli && (rli= thd->rli_fake= new Relay_log_info(FALSE))) + if (!rli && (rli= thd->rli_fake= new Relay_log_info(FALSE, "BINLOG_BASE64_EVENT"))) rli->sql_driver_thd= thd; if (!(rgi= thd->rgi_fake)) rgi= thd->rgi_fake= new rpl_group_info(rli); diff --git a/sql/sql_bootstrap.cc b/sql/sql_bootstrap.cc index a8c930820a7..dbeb971cd5a 100644 --- a/sql/sql_bootstrap.cc +++ b/sql/sql_bootstrap.cc @@ -29,6 +29,7 @@ int read_bootstrap_query(char *query, int *query_length, int fgets_error= 0; *error= 0; + *query_length= 0; for ( ; ; ) { line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input, &fgets_error); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 00681ba8e2a..35e3a7c5608 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -3410,7 +3410,7 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used, if (!insert_table(thd, key_length, key, (*block_table), tables_used->view_db.length, 0, HA_CACHE_TBL_NONTRANSACT, 0, 0, TRUE)) - DBUG_RETURN(0); + goto err_cleanup; /* We do not need to register view tables here because they are already present in the global list. @@ -3434,7 +3434,7 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used, tables_used->callback_func, tables_used->engine_data, TRUE)) - DBUG_RETURN(0); + goto err_cleanup; if (tables_used->table->file-> register_query_cache_dependant_tables(thd, this, block_table, &n)) @@ -3442,6 +3442,11 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used, } } DBUG_RETURN(n - counter); +err_cleanup: + // Mark failed + (*block_table)->next= (*block_table)->prev= NULL; + (*block_table)->parent= NULL; + DBUG_RETURN(0); } /* @@ -3475,7 +3480,12 @@ my_bool Query_cache::register_all_tables(THD *thd, for (Query_cache_block_table *tmp = block->table(0) ; tmp != block_table; tmp++) - unlink_table(tmp); + { + if (tmp->prev) // not marked as failed and unuseable + unlink_table(tmp); + else + break; + } if (block_table->parent) unlink_table(block_table); } @@ -3493,7 +3503,8 @@ my_bool Query_cache::register_all_tables(THD *thd, my_bool Query_cache::insert_table(THD *thd, size_t key_len, const char *key, - Query_cache_block_table *node, size_t db_length, uint8 suffix_length_arg, + Query_cache_block_table *node, size_t db_length, + uint8 suffix_length_arg, uint8 cache_type, qc_engine_callback callback, ulonglong engine_data, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d63cbb7a7a2..0b142a22f59 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -72,6 +72,7 @@ #include "wsrep_trans_observer.h" #endif /* WITH_WSREP */ #include "opt_trace.h" +#include #ifdef HAVE_SYS_SYSCALL_H #include @@ -813,12 +814,14 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) system_thread= NON_SYSTEM_THREAD; cleanup_done= free_connection_done= abort_on_warning= 0; peer_port= 0; // For SHOW PROCESSLIST - transaction.m_pending_rows_event= 0; - transaction.on= 1; - wt_thd_lazy_init(&transaction.wt, &variables.wt_deadlock_search_depth_short, - &variables.wt_timeout_short, - &variables.wt_deadlock_search_depth_long, - &variables.wt_timeout_long); + transaction= &default_transaction; + transaction->m_pending_rows_event= 0; + transaction->on= 1; + wt_thd_lazy_init(&transaction->wt, + &variables.wt_deadlock_search_depth_short, + &variables.wt_timeout_short, + &variables.wt_deadlock_search_depth_long, + &variables.wt_timeout_long); #ifdef SIGNAL_WITH_VIO_CLOSE active_vio = 0; #endif @@ -1262,10 +1265,10 @@ void THD::init() if (variables.sql_mode & MODE_ANSI_QUOTES) server_status|= SERVER_STATUS_ANSI_QUOTES; - transaction.all.modified_non_trans_table= - transaction.stmt.modified_non_trans_table= FALSE; - transaction.all.m_unsafe_rollback_flags= - transaction.stmt.m_unsafe_rollback_flags= 0; + transaction->all.modified_non_trans_table= + transaction->stmt.modified_non_trans_table= FALSE; + transaction->all.m_unsafe_rollback_flags= + transaction->stmt.m_unsafe_rollback_flags= 0; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? @@ -1396,11 +1399,11 @@ void THD::init_for_queries() reset_root_defaults(mem_root, variables.query_alloc_block_size, variables.query_prealloc_size); - reset_root_defaults(&transaction.mem_root, + reset_root_defaults(&transaction->mem_root, variables.trans_alloc_block_size, variables.trans_prealloc_size); - DBUG_ASSERT(!transaction.xid_state.is_explicit_XA()); - DBUG_ASSERT(transaction.implicit_xid.is_null()); + DBUG_ASSERT(!transaction->xid_state.is_explicit_XA()); + DBUG_ASSERT(transaction->implicit_xid.is_null()); } @@ -1539,7 +1542,7 @@ void THD::cleanup(void) delete_dynamic(&user_var_events); close_temporary_tables(); - if (transaction.xid_state.is_explicit_XA()) + if (transaction->xid_state.is_explicit_XA()) trans_xa_detach(this); else trans_rollback(this); @@ -1565,7 +1568,7 @@ void THD::cleanup(void) decrease_user_connections(user_connect); user_connect= 0; // Safety } - wt_thd_destroy(&transaction.wt); + wt_thd_destroy(&transaction->wt); my_hash_free(&user_vars); my_hash_free(&sequences); @@ -1697,7 +1700,7 @@ THD::~THD() #endif mdl_context.destroy(); - free_root(&transaction.mem_root,MYF(0)); + transaction->free(); mysql_cond_destroy(&COND_wakeup_ready); mysql_mutex_destroy(&LOCK_wakeup_ready); mysql_mutex_destroy(&LOCK_thd_data); @@ -1736,7 +1739,9 @@ THD::~THD() /* trick to make happy memory accounting system */ #ifndef EMBEDDED_LIBRARY session_tracker.sysvars.deinit(); +#ifdef USER_VAR_TRACKING session_tracker.user_variables.deinit(); +#endif // USER_VAR_TRACKING #endif //EMBEDDED_LIBRARY if (status_var.local_memory_used != 0) @@ -2587,7 +2592,8 @@ void THD::add_changed_table(TABLE *table) { DBUG_ENTER("THD::add_changed_table(table)"); - DBUG_ASSERT(in_multi_stmt_transaction_mode() && table->file->has_transactions()); + DBUG_ASSERT(in_multi_stmt_transaction_mode() && + table->file->has_transactions()); add_changed_table(table->s->table_cache_key.str, (long) table->s->table_cache_key.length); DBUG_VOID_RETURN; @@ -2597,8 +2603,8 @@ void THD::add_changed_table(TABLE *table) void THD::add_changed_table(const char *key, size_t key_length) { DBUG_ENTER("THD::add_changed_table(key)"); - CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables; - CHANGED_TABLE_LIST *curr = transaction.changed_tables; + CHANGED_TABLE_LIST **prev_changed = &transaction->changed_tables; + CHANGED_TABLE_LIST *curr = transaction->changed_tables; for (; curr; prev_changed = &(curr->next), curr = curr->next) { @@ -4712,7 +4718,8 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen, DBUG_ASSERT(thd->open_tables == NULL); DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED); - Open_table_context ot_ctx(thd, 0); + /* Purge already hold the MDL for the table */ + Open_table_context ot_ctx(thd, MYSQL_OPEN_HAS_MDL_LOCK); TABLE_LIST *tl= (TABLE_LIST*)thd->alloc(sizeof(TABLE_LIST)); LEX_CSTRING db_name= {db, dblen }; LEX_CSTRING table_name= { tb, tblen }; @@ -5050,7 +5057,7 @@ thd_rpl_deadlock_check(MYSQL_THD thd, MYSQL_THD other_thd) if (!thd) return 0; DEBUG_SYNC(thd, "thd_report_wait_for"); - thd->transaction.stmt.mark_trans_did_wait(); + thd->transaction->stmt.mark_trans_did_wait(); if (!other_thd) return 0; binlog_report_wait_for(thd, other_thd); @@ -5153,7 +5160,7 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd) extern "C" int thd_non_transactional_update(const MYSQL_THD thd) { - return(thd->transaction.all.modified_non_trans_table); + return(thd->transaction->all.modified_non_trans_table); } extern "C" int thd_binlog_format(const MYSQL_THD thd) @@ -5362,7 +5369,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->limit_found_rows= limit_found_rows; backup->cuted_fields= cuted_fields; backup->client_capabilities= client_capabilities; - backup->savepoints= transaction.savepoints; + backup->savepoints= transaction->savepoints; backup->first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_prev_stmt; backup->first_successful_insert_id_in_cur_stmt= @@ -5384,7 +5391,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, client_capabilities &= ~CLIENT_MULTI_RESULTS; in_sub_stmt|= new_state; cuted_fields= 0; - transaction.savepoints= 0; + transaction->savepoints= 0; first_successful_insert_id_in_cur_stmt= 0; reset_slow_query_state(); } @@ -5410,16 +5417,16 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) level. It is enough to release first savepoint set on this level since all later savepoints will be released automatically. */ - if (transaction.savepoints) + if (transaction->savepoints) { SAVEPOINT *sv; - for (sv= transaction.savepoints; sv->prev; sv= sv->prev) + for (sv= transaction->savepoints; sv->prev; sv= sv->prev) {} /* ha_release_savepoint() never returns error. */ (void)ha_release_savepoint(this, sv); } count_cuted_fields= backup->count_cuted_fields; - transaction.savepoints= backup->savepoints; + transaction->savepoints= backup->savepoints; variables.option_bits= backup->option_bits; in_sub_stmt= backup->in_sub_stmt; enable_slow_log= backup->enable_slow_log; @@ -5740,6 +5747,95 @@ void THD::mark_transaction_to_rollback(bool all) } +/** + Commit the whole transaction (both statment and all) + + This is used mainly to commit an independent transaction, + like reading system tables. + + @return 0 0k + @return <>0 error code. my_error() has been called() +*/ + +int THD::commit_whole_transaction_and_close_tables() +{ + int error, error2; + DBUG_ENTER("THD::commit_whole_transaction_and_close_tables"); + + /* + This can only happened if we failed to open any table in the + new transaction + */ + DBUG_ASSERT(open_tables); + + if (!open_tables) // Safety for production usage + DBUG_RETURN(0); + + /* + Ensure table was locked (opened with open_and_lock_tables()). If not + the THD can't be part of any transactions and doesn't have to call + this function. + */ + DBUG_ASSERT(lock); + + error= ha_commit_trans(this, FALSE); + /* This will call external_lock to unlock all tables */ + if ((error2= mysql_unlock_tables(this, lock))) + { + my_error(ER_ERROR_DURING_COMMIT, MYF(0), error2); + error= error2; + } + lock= 0; + if ((error2= ha_commit_trans(this, TRUE))) + error= error2; + close_thread_tables(this); + DBUG_RETURN(error); +} + +/** + Start a new independent transaction +*/ + +start_new_trans::start_new_trans(THD *thd) +{ + org_thd= thd; + mdl_savepoint= thd->mdl_context.mdl_savepoint(); + memcpy(old_ha_data, thd->ha_data, sizeof(old_ha_data)); + thd->reset_n_backup_open_tables_state(&open_tables_state_backup); + bzero(thd->ha_data, sizeof(thd->ha_data)); + old_transaction= thd->transaction; + thd->transaction= &new_transaction; + new_transaction.on= 1; + in_sub_stmt= thd->in_sub_stmt; + thd->in_sub_stmt= 0; + server_status= thd->server_status; + m_transaction_psi= thd->m_transaction_psi; + thd->m_transaction_psi= 0; + wsrep_on= thd->variables.wsrep_on; + thd->variables.wsrep_on= 0; + thd->server_status&= ~(SERVER_STATUS_IN_TRANS | + SERVER_STATUS_IN_TRANS_READONLY); + thd->server_status|= SERVER_STATUS_AUTOCOMMIT; +} + + +void start_new_trans::restore_old_transaction() +{ + org_thd->transaction= old_transaction; + org_thd->restore_backup_open_tables_state(&open_tables_state_backup); + ha_close_connection(org_thd); + memcpy(org_thd->ha_data, old_ha_data, sizeof(old_ha_data)); + org_thd->mdl_context.rollback_to_savepoint(mdl_savepoint); + org_thd->in_sub_stmt= in_sub_stmt; + org_thd->server_status= server_status; + if (org_thd->m_transaction_psi) + MYSQL_COMMIT_TRANSACTION(org_thd->m_transaction_psi); + org_thd->m_transaction_psi= m_transaction_psi; + org_thd->variables.wsrep_on= wsrep_on; + org_thd= 0; +} + + /** Decide on logging format to use for the statement and issue errors or warnings as needed. The decision depends on the following @@ -5853,7 +5949,9 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ #ifdef WITH_WSREP - if (WSREP_CLIENT_NNULL(this) && wsrep_thd_is_local(this) && + if (WSREP_CLIENT_NNULL(this) && + wsrep_thd_is_local(this) && + wsrep_is_active(this) && variables.wsrep_trx_fragment_size > 0) { if (!is_current_stmt_binlog_format_row()) @@ -5866,11 +5964,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) } #endif /* WITH_WSREP */ - if ((WSREP_EMULATE_BINLOG_NNULL(this) || - (mysql_bin_log.is_open() && - (variables.option_bits & OPTION_BIN_LOG))) && - !(wsrep_binlog_format() == BINLOG_FORMAT_STMT && - !binlog_filter->db_ok(db.str))) + if (WSREP_EMULATE_BINLOG_NNULL(this) || + binlog_table_should_be_logged(&db)) { if (is_bulk_op()) { @@ -6394,6 +6489,21 @@ exit:; } #ifndef MYSQL_CLIENT +/** + Check if we should log a table DDL to the binlog + + @@return true yes + @@return false no +*/ + +bool THD::binlog_table_should_be_logged(const LEX_CSTRING *db) +{ + return (mysql_bin_log.is_open() && + (variables.option_bits & OPTION_BIN_LOG) && + (wsrep_binlog_format() != BINLOG_FORMAT_STMT || + binlog_filter->db_ok(db->str))); +} + /* Template member function for ensuring that there is an rows log event of the apropriate type before proceeding. @@ -7270,7 +7380,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, log event is written to the binary log, we pretend that no table maps were written. */ - if(binlog_should_compress(query_len)) + if (binlog_should_compress(query_len)) { Query_compressed_log_event qinfo(this, query_arg, query_len, is_trans, direct, suppress_use, errcode); diff --git a/sql/sql_class.h b/sql/sql_class.h index 1069b49790a..58a786ed33c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -793,7 +793,9 @@ typedef struct system_variables ulong session_track_transaction_info; my_bool session_track_schema; my_bool session_track_state_change; +#ifdef USER_VAR_TRACKING my_bool session_track_user_variables; +#endif // USER_VAR_TRACKING my_bool tcp_nodelay; ulong threadpool_priority; @@ -1951,20 +1953,23 @@ private: TABLE_LIST *m_locked_tables; TABLE_LIST **m_locked_tables_last; /** An auxiliary array used only in reopen_tables(). */ - TABLE **m_reopen_array; + TABLE_LIST **m_reopen_array; /** Count the number of tables in m_locked_tables list. We can't rely on thd->lock->table_count because it excludes non-transactional temporary tables. We need to know an exact number of TABLE objects. */ - size_t m_locked_tables_count; + uint m_locked_tables_count; public: + bool some_table_marked_for_reopen; + Locked_tables_list() :m_locked_tables(NULL), m_locked_tables_last(&m_locked_tables), m_reopen_array(NULL), - m_locked_tables_count(0) + m_locked_tables_count(0), + some_table_marked_for_reopen(0) { init_sql_alloc(key_memory_locked_table_list, &m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); @@ -1987,6 +1992,7 @@ public: bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table, MYSQL_LOCK *lock); void add_back_last_deleted_lock(TABLE_LIST *dst_table_list); + void mark_table_for_reopen(THD *thd, TABLE *table); }; @@ -2693,6 +2699,7 @@ public: { binlog_table_maps= 0; } + bool binlog_table_should_be_logged(const LEX_CSTRING *db); #endif /* MYSQL_CLIENT */ @@ -2733,6 +2740,10 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_VOID_RETURN; } + void free() + { + free_root(&mem_root,MYF(0)); + } my_bool is_active() { return (all.ha_list != NULL); @@ -2744,7 +2755,7 @@ public: init_sql_alloc(key_memory_thd_transactions, &mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); } - } transaction; + } default_transaction, *transaction; Global_read_lock global_read_lock; Field *dup_field; #ifndef __WIN__ @@ -3582,8 +3593,8 @@ public: timeval transaction_time() { if (!in_multi_stmt_transaction_mode()) - transaction.start_time.reset(this); - return transaction.start_time; + transaction->start_time.reset(this); + return transaction->start_time; } inline void set_start_time() @@ -3737,6 +3748,8 @@ public: { return server_status & SERVER_STATUS_IN_TRANS; } + /* Commit both statement and full transaction */ + int commit_whole_transaction_and_close_tables(); void give_protection_error(); inline bool has_read_only_protection() { @@ -3756,7 +3769,7 @@ public: } inline void* trans_alloc(size_t size) { - return alloc_root(&transaction.mem_root,size); + return alloc_root(&transaction->mem_root,size); } LEX_CSTRING strmake_lex_cstring(const char *str, size_t length) @@ -4140,7 +4153,8 @@ public: The worst things that can happen is that we get a suboptimal error message. */ - if (likely((killed_err= (err_info*) alloc(sizeof(*killed_err))))) + killed_err= (err_info*) alloc_root(&main_mem_root, sizeof(*killed_err)); + if (likely(killed_err)) { killed_err->no= killed_errno_arg; ::strmake((char*) killed_err->msg, killed_err_msg_arg, @@ -4172,7 +4186,7 @@ public: inline bool really_abort_on_warning() { return (abort_on_warning && - (!transaction.stmt.modified_non_trans_table || + (!transaction->stmt.modified_non_trans_table || (variables.sql_mode & MODE_STRICT_ALL_TABLES))); } void set_status_var_init(); @@ -4761,6 +4775,7 @@ public: } void mark_transaction_to_rollback(bool all); + bool internal_transaction() { return transaction != &default_transaction; } private: /** The current internal error handler for this thread, or NULL. */ @@ -4838,9 +4853,9 @@ public: if (!wsrep_xid.is_null()) return &wsrep_xid; #endif /* WITH_WSREP */ - return transaction.xid_state.is_explicit_XA() ? - transaction.xid_state.get_xid() : - &transaction.implicit_xid; + return (transaction->xid_state.is_explicit_XA() ? + transaction->xid_state.get_xid() : + &transaction->implicit_xid); } /* Members related to temporary tables. */ @@ -5084,10 +5099,10 @@ public: /* Copy relevant `stmt` transaction flags to `all` transaction. */ void merge_unsafe_rollback_flags() { - if (transaction.stmt.modified_non_trans_table) - transaction.all.modified_non_trans_table= TRUE; - transaction.all.m_unsafe_rollback_flags|= - (transaction.stmt.m_unsafe_rollback_flags & + if (transaction->stmt.modified_non_trans_table) + transaction->all.modified_non_trans_table= TRUE; + transaction->all.m_unsafe_rollback_flags|= + (transaction->stmt.m_unsafe_rollback_flags & (THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE | THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL)); } @@ -5097,7 +5112,7 @@ public: { if (in_active_multi_stmt_transaction()) { - if (transaction.all.is_trx_read_write()) + if (transaction->all.is_trx_read_write()) { if (variables.idle_write_transaction_timeout > 0) return variables.idle_write_transaction_timeout; @@ -5145,6 +5160,41 @@ public: }; + +/* + Start a new independent transaction for the THD. + The old one is stored in this object and restored when calling + restore_old_transaction() or when the object is freed +*/ + +class start_new_trans +{ + /* container for handler's private per-connection data */ + Ha_data old_ha_data[MAX_HA]; + struct THD::st_transactions *old_transaction, new_transaction; + Open_tables_backup open_tables_state_backup; + MDL_savepoint mdl_savepoint; + PSI_transaction_locker *m_transaction_psi; + THD *org_thd; + uint in_sub_stmt; + uint server_status; + my_bool wsrep_on; + +public: + start_new_trans(THD *thd); + ~start_new_trans() + { + destroy(); + } + void destroy() + { + if (org_thd) // Safety + restore_old_transaction(); + new_transaction.free(); + } + void restore_old_transaction(); +}; + /** A short cut for thd->get_stmt_da()->set_ok_status(). */ inline void @@ -7284,13 +7334,13 @@ class Sp_eval_expr_state { m_thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; m_thd->abort_on_warning= m_thd->is_strict_mode(); - m_thd->transaction.stmt.modified_non_trans_table= false; + m_thd->transaction->stmt.modified_non_trans_table= false; } void stop() { m_thd->count_cuted_fields= m_count_cuted_fields; m_thd->abort_on_warning= m_abort_on_warning; - m_thd->transaction.stmt.modified_non_trans_table= + m_thd->transaction->stmt.modified_non_trans_table= m_stmt_modified_non_trans_table; } public: @@ -7298,7 +7348,7 @@ public: :m_thd(thd), m_count_cuted_fields(thd->count_cuted_fields), m_abort_on_warning(thd->abort_on_warning), - m_stmt_modified_non_trans_table(thd->transaction.stmt. + m_stmt_modified_non_trans_table(thd->transaction->stmt. modified_non_trans_table) { start(); diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 1d3226fef34..5bf9930ef21 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1163,6 +1163,7 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem) { derived= with_elem->spec; if (derived != select_lex->master_unit() && + !with_elem->is_recursive && !is_with_table_recursive_reference()) { derived->move_as_slave(select_lex); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 039ed417078..7280236e43f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -492,7 +492,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, set_statistics_for_table(thd, table); table->covering_keys.clear_all(); - table->quick_keys.clear_all(); // Can't use 'only index' + table->opt_range_keys.clear_all(); select=make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (unlikely(error)) @@ -518,7 +518,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, } /* If running in safe sql mode, don't allow updates without keys */ - if (table->quick_keys.is_clear_all()) + if (table->opt_range_keys.is_clear_all()) { thd->set_status_no_index_used(); if (safe_update && !using_limit) @@ -875,14 +875,14 @@ cleanup: deltempfile=NULL; delete select; select= NULL; - transactional_table= table->file->has_transactions(); + transactional_table= table->file->has_transactions_and_rollback(); if (!transactional_table && deleted > 0) - thd->transaction.stmt.modified_non_trans_table= - thd->transaction.all.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= + thd->transaction->all.modified_non_trans_table= TRUE; /* See similar binlogging code in sql_update.cc, for comments */ - if (likely((error < 0) || thd->transaction.stmt.modified_non_trans_table)) + if (likely((error < 0) || thd->transaction->stmt.modified_non_trans_table)) { if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) { @@ -911,7 +911,7 @@ cleanup: } } } - DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); + DBUG_ASSERT(transactional_table || !deleted || thd->transaction->stmt.modified_non_trans_table); if (likely(error < 0) || (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error)) @@ -1332,7 +1332,7 @@ int multi_delete::send_data(List &values) { deleted++; if (!table->file->has_transactions()) - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) @@ -1368,17 +1368,17 @@ void multi_delete::abort_result_set() /* the error was handled or nothing deleted and no side effects return */ if (error_handled || - (!thd->transaction.stmt.modified_non_trans_table && !deleted)) + (!thd->transaction->stmt.modified_non_trans_table && !deleted)) DBUG_VOID_RETURN; /* Something already deleted so we have to invalidate cache */ if (deleted) query_cache_invalidate3(thd, delete_tables, 1); - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); /* If rows from the first table only has been deleted and it is @@ -1388,7 +1388,7 @@ void multi_delete::abort_result_set() */ if (do_delete && normal_tables && (table_being_deleted != delete_tables || - !table_being_deleted->table->file->has_transactions())) + !table_being_deleted->table->file->has_transactions_and_rollback())) { /* We have to execute the recorded do_deletes() and write info into the @@ -1400,7 +1400,7 @@ void multi_delete::abort_result_set() DBUG_VOID_RETURN; } - if (thd->transaction.stmt.modified_non_trans_table) + if (thd->transaction->stmt.modified_non_trans_table) { /* there is only side effects; to binlog with the error @@ -1537,8 +1537,8 @@ int multi_delete::do_table_deletes(TABLE *table, SORT_INFO *sort_info, table->file->print_error(local_error, MYF(0)); } } - if (last_deleted != deleted && !table->file->has_transactions()) - thd->transaction.stmt.modified_non_trans_table= TRUE; + if (last_deleted != deleted && !table->file->has_transactions_and_rollback()) + thd->transaction->stmt.modified_non_trans_table= TRUE; end_read_record(&info); @@ -1566,10 +1566,10 @@ bool multi_delete::send_eof() /* reset used flags */ THD_STAGE_INFO(thd, stage_end); - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); /* We must invalidate the query cache before binlog writing and @@ -1580,7 +1580,7 @@ bool multi_delete::send_eof() query_cache_invalidate3(thd, delete_tables, 1); } if (likely((local_error == 0) || - thd->transaction.stmt.modified_non_trans_table)) + thd->transaction->stmt.modified_non_trans_table)) { if(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) { diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 7d09c85a7c7..428e7b1d261 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1197,7 +1197,6 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_ASSERT(derived->table && derived->table->is_created()); select_unit *derived_result= derived->derived_result; SELECT_LEX *save_current_select= lex->current_select; - bool derived_recursive_is_filled= false; if (derived->pushdown_derived) { @@ -1238,7 +1237,6 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { /* In this case all iteration are performed */ res= derived->fill_recursive(thd); - derived_recursive_is_filled= true; } } else if (unit->is_unit_op()) @@ -1293,8 +1291,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) } } err: - if (res || (!lex->describe && !unit->uncacheable && - (!derived_is_recursive || derived_recursive_is_filled))) + if (res || (!derived_is_recursive && !lex->describe && !unit->uncacheable)) unit->cleanup(); lex->current_select= save_current_select; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index e3e08444f84..a6f93f6dfee 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -480,7 +480,7 @@ err: If called with reopen flag, no need to rollback either, it will be done at statement end. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); thd->set_open_tables(backup_open_tables); diff --git a/sql/sql_help.cc b/sql/sql_help.cc index c9307b578fc..3ccab553bfe 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -709,8 +709,9 @@ static bool mysqld_help_internal(THD *thd, const char *mask) Reset and backup the current open tables state to make it possible. */ - Open_tables_backup open_tables_state_backup; - if (open_system_tables_for_read(thd, tables, &open_tables_state_backup)) + start_new_trans new_trans(thd); + + if (open_system_tables_for_read(thd, tables)) goto error2; /* @@ -843,11 +844,13 @@ static bool mysqld_help_internal(THD *thd, const char *mask) } my_eof(thd); - close_system_tables(thd, &open_tables_state_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_RETURN(FALSE); error: - close_system_tables(thd, &open_tables_state_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); error2: DBUG_RETURN(TRUE); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0914b4ac497..31badbe2aba 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -77,7 +77,6 @@ #include "sql_audit.h" #include "sql_derived.h" // mysql_handle_derived #include "sql_prepare.h" -#include "rpl_filter.h" // binlog_filter #include #include "debug_sync.h" @@ -1144,7 +1143,7 @@ values_loop_end: table->file->ha_rnd_end(); } - transactional_table= table->file->has_transactions(); + transactional_table= table->file->has_transactions_and_rollback(); if (likely(changed= (info.copied || info.deleted || info.updated))) { @@ -1156,13 +1155,13 @@ values_loop_end: query_cache_invalidate3(thd, table_list, 1); } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); if (error <= 0 || - thd->transaction.stmt.modified_non_trans_table || + thd->transaction->stmt.modified_non_trans_table || was_insert_delayed) { if(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) @@ -1225,7 +1224,7 @@ values_loop_end: } } DBUG_ASSERT(transactional_table || !changed || - thd->transaction.stmt.modified_non_trans_table); + thd->transaction->stmt.modified_non_trans_table); } THD_STAGE_INFO(thd, stage_end); /* @@ -2055,8 +2054,8 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) info->deleted++; else info->updated++; - if (!table->file->has_transactions()) - thd->transaction.stmt.modified_non_trans_table= TRUE; + if (!table->file->has_transactions_and_rollback()) + thd->transaction->stmt.modified_non_trans_table= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, TRUE)) @@ -2121,8 +2120,8 @@ ok: after_trg_or_ignored_err: if (key) my_safe_afree(key,table->s->max_unique_length); - if (!table->file->has_transactions()) - thd->transaction.stmt.modified_non_trans_table= TRUE; + if (!table->file->has_transactions_and_rollback()) + thd->transaction->stmt.modified_non_trans_table= TRUE; DBUG_RETURN(trg_error); err: @@ -2538,7 +2537,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, end_create: mysql_mutex_unlock(&LOCK_delayed_create); - DBUG_PRINT("exit", ("is_error: %d", thd->is_error())); + DBUG_PRINT("exit", ("is_error(): %d", thd->is_error())); DBUG_RETURN(thd->is_error()); } @@ -4104,13 +4103,13 @@ void select_insert::store_values(List &values) bool select_insert::prepare_eof() { int error; - bool const trans_table= table->file->has_transactions(); + bool const trans_table= table->file->has_transactions_and_rollback(); bool changed; bool binary_logged= 0; killed_state killed_status= thd->killed; DBUG_ENTER("select_insert::prepare_eof"); - DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", + DBUG_PRINT("enter", ("trans_table: %d, table_type: '%s'", trans_table, table->file->table_type())); #ifdef WITH_WSREP @@ -4139,13 +4138,13 @@ bool select_insert::prepare_eof() query_cache_invalidate3(thd, table, 1); } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); DBUG_ASSERT(trans_table || !changed || - thd->transaction.stmt.modified_non_trans_table); + thd->transaction->stmt.modified_non_trans_table); /* Write to binlog before commiting transaction. No statement will @@ -4154,7 +4153,7 @@ bool select_insert::prepare_eof() ha_autocommit_or_rollback() is issued below. */ if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) && - (likely(!error) || thd->transaction.stmt.modified_non_trans_table)) + (likely(!error) || thd->transaction->stmt.modified_non_trans_table)) { int errcode= 0; int res; @@ -4273,12 +4272,12 @@ void select_insert::abort_result_set() zero, so no check for that is made. */ changed= (info.copied || info.deleted || info.updated); - transactional_table= table->file->has_transactions(); - if (thd->transaction.stmt.modified_non_trans_table || + transactional_table= table->file->has_transactions_and_rollback(); + if (thd->transaction->stmt.modified_non_trans_table || thd->log_current_statement) { if (!can_rollback_data()) - thd->transaction.all.modified_non_trans_table= TRUE; + thd->transaction->all.modified_non_trans_table= TRUE; if(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) { @@ -4294,7 +4293,7 @@ void select_insert::abort_result_set() query_cache_invalidate3(thd, table, 1); } DBUG_ASSERT(transactional_table || !changed || - thd->transaction.stmt.modified_non_trans_table); + thd->transaction->stmt.modified_non_trans_table); table->s->table_creation_was_logged|= binary_logged; table->file->ha_release_auto_increment(); @@ -4796,16 +4795,17 @@ static int binlog_show_create_table(THD *thd, TABLE *table, to a not shared table. */ -bool binlog_create_table(THD *thd, TABLE *table) +bool binlog_create_table(THD *thd, TABLE *table, bool replace) { + Table_specification_st create_info; + bool result; + ulonglong save_option_bits; + /* Don't log temporary tables in row format */ if (thd->variables.binlog_format == BINLOG_FORMAT_ROW && table->s->tmp_table) return 0; - if (!mysql_bin_log.is_open() || - !(thd->variables.option_bits & OPTION_BIN_LOG) || - (thd->wsrep_binlog_format() == BINLOG_FORMAT_STMT && - !binlog_filter->db_ok(table->s->db.str))) + if (!thd->binlog_table_should_be_logged(&table->s->db)) return 0; /* @@ -4814,7 +4814,19 @@ bool binlog_create_table(THD *thd, TABLE *table) */ thd->set_current_stmt_binlog_format_row(); table->file->prepare_for_row_logging(); - return binlog_show_create_table(thd, table, 0) != 0; + + create_info.lex_start(); + save_option_bits= thd->variables.option_bits; + if (replace) + create_info.set(DDL_options_st::OPT_OR_REPLACE); + /* Ensure we write ENGINE=xxx and CHARSET=... to binary log */ + create_info.used_fields|= (HA_CREATE_USED_ENGINE | + HA_CREATE_USED_DEFAULT_CHARSET); + /* Ensure we write all engine options to binary log */ + create_info.used_fields|= HA_CREATE_PRINT_ALL_OPTIONS; + result= binlog_show_create_table(thd, table, &create_info) != 0; + thd->variables.option_bits= save_option_bits; + return result; } @@ -4834,10 +4846,7 @@ bool binlog_drop_table(THD *thd, TABLE *table) /* Don't log temporary tables in row format */ if (!table->s->table_creation_was_logged) return 0; - if (!mysql_bin_log.is_open() || - !(thd->variables.option_bits & OPTION_BIN_LOG) || - (thd->wsrep_binlog_format() == BINLOG_FORMAT_STMT && - !binlog_filter->db_ok(table->s->db.str))) + if (!thd->binlog_table_should_be_logged(&table->s->db)) return 0; query.append("DROP "); @@ -4874,7 +4883,7 @@ bool select_create::send_eof() mark the flag at this point. */ if (table->s->tmp_table) - thd->transaction.stmt.mark_created_temp_table(); + thd->transaction->stmt.mark_created_temp_table(); if (thd->slave_thread) thd->variables.binlog_annotate_row_events= 0; @@ -5039,7 +5048,7 @@ void select_create::abort_result_set() save_option_bits= thd->variables.option_bits; thd->variables.option_bits&= ~OPTION_BIN_LOG; select_insert::abort_result_set(); - thd->transaction.stmt.modified_non_trans_table= FALSE; + thd->transaction->stmt.modified_non_trans_table= FALSE; thd->variables.option_bits= save_option_bits; /* possible error of writing binary log is ignored deliberately */ diff --git a/sql/sql_insert.h b/sql/sql_insert.h index 3f741640c1c..14041976973 100644 --- a/sql/sql_insert.h +++ b/sql/sql_insert.h @@ -43,7 +43,7 @@ int check_duplic_insert_without_overlaps(THD *thd, TABLE *table, int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *returning= NULL); void kill_delayed_threads(void); -bool binlog_create_table(THD *thd, TABLE *table); +bool binlog_create_table(THD *thd, TABLE *table, bool replace); bool binlog_drop_table(THD *thd, TABLE *table); #ifdef EMBEDDED_LIBRARY diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 12c3d0a153d..f39f88fe843 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3146,7 +3146,7 @@ st_select_lex_node *st_select_lex_node:: insert_chain_before( { end_chain_node->link_next= *ptr_pos_to_insert; (*ptr_pos_to_insert)->link_prev= &end_chain_node->link_next; - this->link_prev= ptr_pos_to_insert; + link_prev= ptr_pos_to_insert; return this; } @@ -3332,7 +3332,7 @@ bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, return TRUE; } while ((s= s->outer_select()) != last && s != 0); is_correlated= TRUE; - this->master_unit()->item->is_correlated= TRUE; + master_unit()->item->is_correlated= TRUE; return FALSE; } @@ -3565,8 +3565,11 @@ void LEX::print(String *str, enum_query_type query_type) value->print(str, query_type); } - str->append(STRING_WITH_LEN(" WHERE ")); - sel->where->print(str, query_type); + if (sel->where) + { + str->append(STRING_WITH_LEN(" WHERE ")); + sel->where->print(str, query_type); + } if (sel->order_list.elements) { @@ -4491,7 +4494,7 @@ void LEX::reset_n_backup_query_tables_list(Query_tables_list *backup) We have to perform full initialization here since otherwise we will damage backed up state. */ - this->reset_query_tables_list(TRUE); + reset_query_tables_list(TRUE); } @@ -4505,8 +4508,8 @@ void LEX::reset_n_backup_query_tables_list(Query_tables_list *backup) void LEX::restore_backup_query_tables_list(Query_tables_list *backup) { - this->destroy_query_tables_list(); - this->set_query_tables_list(backup); + destroy_query_tables_list(); + set_query_tables_list(backup); } @@ -6295,7 +6298,7 @@ bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars, bool last= i + 1 == (uint) nvars; spvar->default_value= dflt_value_item; /* The last instruction is responsible for freeing LEX. */ - sp_instr_set *is= new (this->thd->mem_root) + sp_instr_set *is= new (thd->mem_root) sp_instr_set(sphead->instructions(), spcont, &sp_rcontext_handler_local, spvar->offset, dflt_value_item, @@ -6595,7 +6598,7 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name, return NULL; spvar->default_value= value; - sp_instr_set *is= new (this->thd->mem_root) + sp_instr_set *is= new (thd->mem_root) sp_instr_set(sphead->instructions(), spcont, &sp_rcontext_handler_local, spvar->offset, value, @@ -11393,3 +11396,36 @@ bool LEX::stmt_revoke_proxy(THD *thd, LEX_USER *user) return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command, NO_ACL)); } + + +LEX_USER *LEX::current_user_for_set_password(THD *thd) +{ + LEX_CSTRING pw= { STRING_WITH_LEN("password") }; + if (unlikely(spcont && spcont->find_variable(&pw, false))) + { + my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str); + return NULL; + } + LEX_USER *res; + if (unlikely(!(res= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))) + return NULL; + res->user= current_user; + return res; +} + + +bool LEX::sp_create_set_password_instr(THD *thd, + LEX_USER *user, + USER_AUTH *auth, + bool no_lookahead) +{ + user->auth= auth; + set_var_password *var= new (thd->mem_root) set_var_password(user); + if (unlikely(var == NULL) || + unlikely(var_list.push_back(var, thd->mem_root))) + return true; + autocommit= true; + if (sphead) + sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; + return sp_create_assignment_instr(thd, no_lookahead); +} diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 0a802b9652c..b6dcb49ed08 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB Corporation. + Copyright (c) 2010, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1015,7 +1015,7 @@ public: int save_union_explain_part2(Explain_query *output); unit_common_op common_op(); - bool explainable() + bool explainable() const { /* EXPLAIN/ANALYZE unit, when: @@ -3864,6 +3864,21 @@ public: const Column_definition &ref, Row_definition_list *fields, Item *def); + + LEX_USER *current_user_for_set_password(THD *thd); + bool sp_create_set_password_instr(THD *thd, + LEX_USER *user, + USER_AUTH *auth, + bool no_lookahead); + bool sp_create_set_password_instr(THD *thd, + USER_AUTH *auth, + bool no_lookahead) + { + LEX_USER *user; + return !(user= current_user_for_set_password(thd)) || + sp_create_set_password_instr(thd, user, auth, no_lookahead); + } + bool sp_handler_declaration_init(THD *thd, int type); bool sp_handler_declaration_finalize(THD *thd, int type); @@ -4316,8 +4331,7 @@ public: bool if_not_exists) { constr->name= name; - constr->flags= if_not_exists ? - Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS : 0; + constr->flags= if_not_exists ? VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS : 0; alter_info.check_constraint_list.push_back(constr); return false; } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 3ce37170b48..c3e301cd39d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -436,7 +436,7 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, } table= table_list->table; - transactional_table= table->file->has_transactions(); + transactional_table= table->file->has_transactions_and_rollback(); #ifndef EMBEDDED_LIBRARY is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT); #endif @@ -739,7 +739,7 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, /* since there is already an error, the possible error of writing binary log will be ignored */ - if (thd->transaction.stmt.modified_non_trans_table) + if (thd->transaction->stmt.modified_non_trans_table) (void) write_execute_load_query_log_event(thd, ex, table_list->db.str, table_list->table_name.str, @@ -764,10 +764,10 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, (ulong) (info.records - info.copied), (long) thd->get_stmt_da()->current_statement_warn_count()); - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); #ifndef EMBEDDED_LIBRARY if (mysql_bin_log.is_open()) { @@ -816,7 +816,7 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, my_ok(thd, info.copied + info.deleted, 0L, name); err: DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) || - thd->transaction.stmt.modified_non_trans_table); + thd->transaction->stmt.modified_non_trans_table); table->file->ha_release_auto_increment(); table->auto_increment_field_not_null= FALSE; thd->abort_on_warning= 0; @@ -1212,7 +1212,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, bool no_trans_update_stmt; DBUG_ENTER("read_xml_field"); - no_trans_update_stmt= !table->file->has_transactions(); + no_trans_update_stmt= !table->file->has_transactions_and_rollback(); for ( ; ; it.rewind()) { @@ -1300,7 +1300,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. */ - thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt; + thd->transaction->stmt.modified_non_trans_table= no_trans_update_stmt; thd->get_stmt_da()->inc_current_row_for_warning(); continue_loop:; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 872dc8ce840..167aefee7a6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -437,16 +437,13 @@ bool stmt_causes_implicit_commit(THD *thd, uint mask) DBUG_RETURN(FALSE); switch (lex->sql_command) { - case SQLCOM_DROP_TABLE: - case SQLCOM_DROP_SEQUENCE: - skip= (lex->tmp_table() || - (thd->variables.option_bits & OPTION_GTID_BEGIN)); - break; case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_SEQUENCE: /* If ALTER TABLE of non-temporary table, do implicit commit */ skip= (lex->tmp_table()); break; + case SQLCOM_DROP_TABLE: + case SQLCOM_DROP_SEQUENCE: case SQLCOM_CREATE_TABLE: case SQLCOM_CREATE_SEQUENCE: /* @@ -945,11 +942,6 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, char *buf= thd->strmake(init_command->str, len); mysql_rwlock_unlock(var_lock); -#if defined(ENABLED_PROFILING) - thd->profiling.start_new_query(); - thd->profiling.set_query_source(buf, len); -#endif - THD_STAGE_INFO(thd, stage_execution_of_init_command); save_client_capabilities= thd->client_capabilities; thd->client_capabilities|= CLIENT_MULTI_QUERIES; @@ -964,9 +956,6 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; -#if defined(ENABLED_PROFILING) - thd->profiling.finish_current_query(); -#endif } @@ -1104,7 +1093,7 @@ int bootstrap(MYSQL_FILE *file) thd->reset_kill_query(); /* Ensure that killed_errmsg is released */ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); - free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC)); + thd->transaction->free(); thd->lex->restore_set_statement_var(); } delete thd; @@ -1291,7 +1280,7 @@ bool do_command(THD *thd) Aborted by background rollbacker thread. Handle error here and jump straight to out */ - if (wsrep_before_command(thd)) + if (unlikely(wsrep_service_started) && wsrep_before_command(thd)) { thd->store_globals(); WSREP_LOG_THD(thd, "enter found BF aborted"); @@ -1368,7 +1357,8 @@ out: if (packet_length != packet_error) { /* there was a command to process, and before_command() has been called */ - wsrep_after_command_after_result(thd); + if (unlikely(wsrep_service_started)) + wsrep_after_command_after_result(thd); } #endif /* WITH_WSREP */ DBUG_RETURN(return_value); @@ -1507,6 +1497,31 @@ uint maria_multi_check(THD *thd, char *packet, size_t packet_length) } +#if defined(WITH_ARIA_STORAGE_ENGINE) +class Silence_all_errors : public Internal_error_handler +{ + char m_message[MYSQL_ERRMSG_SIZE]; + int error; +public: + Silence_all_errors():error(0) {} + virtual ~Silence_all_errors() {} + + virtual bool handle_condition(THD *thd, + uint sql_errno, + const char* sql_state, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) + { + error= sql_errno; + *cond_hdl= NULL; + strmake_buf(m_message, msg); + return true; // Error handled + } +}; +#endif + + /** Perform one connection-level (COM_XXXX) command. @@ -1659,14 +1674,20 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { thd->status_var.com_other++; #ifdef WITH_WSREP - wsrep_after_command_ignore_result(thd); - wsrep_close(thd); + if (unlikely(wsrep_service_started)) + { + wsrep_after_command_ignore_result(thd); + wsrep_close(thd); + } #endif /* WITH_WSREP */ thd->change_user(); thd->clear_error(); // if errors from rollback #ifdef WITH_WSREP - wsrep_open(thd); - wsrep_before_command(thd); + if (unlikely(wsrep_service_started)) + { + wsrep_open(thd); + wsrep_before_command(thd); + } #endif /* WITH_WSREP */ /* Restore original charset from client authentication packet.*/ if(thd->org_charset) @@ -1680,13 +1701,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd, status_var_increment(thd->status_var.com_other); #ifdef WITH_WSREP - wsrep_after_command_ignore_result(thd); - wsrep_close(thd); + if (unlikely(wsrep_service_started)) + { + wsrep_after_command_ignore_result(thd); + wsrep_close(thd); + } #endif /* WITH_WSREP */ thd->change_user(); #ifdef WITH_WSREP - wsrep_open(thd); - wsrep_before_command(thd); + if (unlikely(wsrep_service_started)) + { + wsrep_open(thd); + wsrep_before_command(thd); + } #endif /* WITH_WSREP */ thd->clear_error(); // if errors from rollback @@ -1847,10 +1874,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ char *beginning_of_next_stmt= (char*) parser_state.m_lip.found_semicolon; -#ifdef WITH_ARIA_STORAGE_ENGINE - ha_maria::implicit_commit(thd, FALSE); -#endif - /* Finalize server status flags after executing a statement. */ thd->update_server_status(); thd->protocol->end_statement(); @@ -2046,7 +2069,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysqld_list_fields(thd,&table_list,fields); thd->lex->unit.cleanup(); /* No need to rollback statement transaction, it's not started. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); @@ -2376,46 +2399,52 @@ com_multi_end: } dispatch_end: + do_end_of_statement= true; #ifdef WITH_WSREP /* - BF aborted before sending response back to client + Next test should really be WSREP(thd), but that causes a failure when doing + 'set WSREP_ON=0' */ - if (thd->killed == KILL_QUERY) - { - WSREP_DEBUG("THD is killed at dispatch_end"); - } - wsrep_after_command_before_result(thd); - if (wsrep_current_error(thd) && - !(command == COM_STMT_PREPARE || - command == COM_STMT_FETCH || - command == COM_STMT_SEND_LONG_DATA || - command == COM_STMT_CLOSE - )) - { - /* todo: Pass wsrep client state current error to override */ - wsrep_override_error(thd, wsrep_current_error(thd), - wsrep_current_error_status(thd)); - WSREP_LOG_THD(thd, "leave"); - } - if (WSREP(thd)) + if (unlikely(wsrep_service_started)) { /* - MDEV-10812 - In the case of COM_QUIT/COM_STMT_CLOSE thread status should be disabled. + BF aborted before sending response back to client */ - DBUG_ASSERT((command != COM_QUIT && command != COM_STMT_CLOSE) + if (thd->killed == KILL_QUERY) + { + WSREP_DEBUG("THD is killed at dispatch_end"); + } + wsrep_after_command_before_result(thd); + if (wsrep_current_error(thd) && + !(command == COM_STMT_PREPARE || + command == COM_STMT_FETCH || + command == COM_STMT_SEND_LONG_DATA || + command == COM_STMT_CLOSE + )) + { + /* todo: Pass wsrep client state current error to override */ + wsrep_override_error(thd, wsrep_current_error(thd), + wsrep_current_error_status(thd)); + WSREP_LOG_THD(thd, "leave"); + } + if (WSREP(thd)) + { + /* + MDEV-10812 + In the case of COM_QUIT/COM_STMT_CLOSE thread status should be disabled. + */ + DBUG_ASSERT((command != COM_QUIT && command != COM_STMT_CLOSE) || thd->get_stmt_da()->is_disabled()); - DBUG_ASSERT(thd->wsrep_trx().state() != wsrep::transaction::s_replaying); - /* wsrep BF abort in query exec phase */ - mysql_mutex_lock(&thd->LOCK_thd_kill); - do_end_of_statement= thd_is_connection_alive(thd); - mysql_mutex_unlock(&thd->LOCK_thd_kill); + DBUG_ASSERT(thd->wsrep_trx().state() != wsrep::transaction::s_replaying); + /* wsrep BF abort in query exec phase */ + mysql_mutex_lock(&thd->LOCK_thd_kill); + do_end_of_statement= thd_is_connection_alive(thd); + mysql_mutex_unlock(&thd->LOCK_thd_kill); + } } - else - do_end_of_statement= true; - #endif /* WITH_WSREP */ + if (do_end_of_statement) { DBUG_ASSERT(thd->derived_tables == NULL && @@ -3092,14 +3121,13 @@ mysql_create_routine(THD *thd, LEX *lex) statement takes metadata locks should be detected by a deadlock detector in MDL subsystem and reported as errors. - No need to commit/rollback statement transaction, it's not started. - TODO: Long-term we should either ensure that implicit GRANT statement is written into binary log as a separate statement or make both creation of routine and implicit GRANT parts of one fully atomic statement. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + if (trans_commit_stmt(thd)) + goto wsrep_error_label; close_thread_tables(thd); /* Check if the definer exists on slave, @@ -3143,7 +3171,9 @@ mysql_create_routine(THD *thd, LEX *lex) #endif return false; } -#ifdef WITH_WSREP + (void) trans_commit_stmt(thd); + +#if !defined(NO_EMBEDDED_ACCESS_CHECKS) || defined(WITH_WSREP) wsrep_error_label: #endif return true; @@ -3320,7 +3350,7 @@ mysql_execute_command(THD *thd) DBUG_RETURN(1); } - DBUG_ASSERT(thd->transaction.stmt.is_empty() || thd->in_sub_stmt); + DBUG_ASSERT(thd->transaction->stmt.is_empty() || thd->in_sub_stmt); /* Each statement or replication event which might produce deadlock should handle transaction rollback on its own. So by the start of @@ -3547,7 +3577,7 @@ mysql_execute_command(THD *thd) thd->progress.report_to_client= MY_TEST(sql_command_flags[lex->sql_command] & CF_REPORT_PROGRESS); - DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE); + DBUG_ASSERT(thd->transaction->stmt.modified_non_trans_table == FALSE); /* store old value of binlog format */ enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format; @@ -3704,7 +3734,7 @@ mysql_execute_command(THD *thd) */ DBUG_ASSERT(! thd->in_sub_stmt); /* Statement transaction still should not be started. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); if (!(thd->variables.option_bits & OPTION_GTID_BEGIN)) { /* Commit the normal transaction if one is active. */ @@ -3718,7 +3748,7 @@ mysql_execute_command(THD *thd) goto error; } } - thd->transaction.stmt.mark_trans_did_ddl(); + thd->transaction->stmt.mark_trans_did_ddl(); #ifdef WITH_WSREP /* Clean up the previous transaction on implicit commit */ if (wsrep_thd_is_local(thd) && wsrep_after_statement(thd)) @@ -4852,6 +4882,8 @@ mysql_execute_command(THD *thd) } else { + if (thd->transaction->xid_state.check_has_uncommitted_xa()) + goto error; status_var_decrement(thd->status_var.com_stat[lex->sql_command]); status_var_increment(thd->status_var.com_drop_tmp_table); @@ -5007,6 +5039,7 @@ mysql_execute_command(THD *thd) res= 1; thd->mdl_context.release_transactional_locks(); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + thd->reset_binlog_for_next_statement(); } if (thd->global_read_lock.is_acquired() && thd->current_backup_stage == BACKUP_FINISHED) @@ -5910,7 +5943,7 @@ mysql_execute_command(THD *thd) lex->create_info.set(DDL_options_st::OPT_IF_EXISTS); DBUG_ASSERT(lex->m_sql_cmd != NULL); res= lex->m_sql_cmd->execute(thd); - DBUG_PRINT("result", ("res: %d killed: %d is_error: %d", + DBUG_PRINT("result", ("res: %d killed: %d is_error(): %d", res, thd->killed, thd->is_error())); break; default: @@ -5941,7 +5974,8 @@ finish: lex->unit.cleanup(); /* close/reopen tables that were marked to need reopen under LOCK TABLES */ - if (! thd->lex->requires_prelocking()) + if (unlikely(thd->locked_tables_list.some_table_marked_for_reopen) && + !thd->lex->requires_prelocking()) thd->locked_tables_list.reopen_tables(thd, true); if (! thd->in_sub_stmt) @@ -5971,9 +6005,6 @@ finish: trans_commit_stmt(thd); thd->get_stmt_da()->set_overwrite_status(false); } -#ifdef WITH_ARIA_STORAGE_ENGINE - ha_maria::implicit_commit(thd, FALSE); -#endif } /* Free tables. Set stage 'closing tables' */ @@ -6495,14 +6526,13 @@ drop_routine(THD *thd, LEX *lex) statement takes metadata locks should be detected by a deadlock detector in MDL subsystem and reported as errors. - No need to commit/rollback statement transaction, it's not started. - TODO: Long-term we should either ensure that implicit REVOKE statement is written into binary log as a separate statement or make both dropping of routine and implicit REVOKE parts of one fully atomic statement. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + if (trans_commit_stmt(thd)) + sp_result= SP_INTERNAL_ERROR; close_thread_tables(thd); if (sp_result != SP_KEY_NOT_FOUND && @@ -7505,7 +7535,7 @@ void THD::reset_for_next_command(bool do_clear_error) if (!in_multi_stmt_transaction_mode()) { variables.option_bits&= ~OPTION_KEEP_LOG; - transaction.all.reset(); + transaction->all.reset(); } DBUG_ASSERT(security_ctx== &main_security_ctx); thread_specific_used= FALSE; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index bf93047885e..9051484b6b8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4936,7 +4936,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, { *fast_alter_table= true; /* Force table re-open for consistency with the main case. */ - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -4984,7 +4984,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, must be reopened. */ *fast_alter_table= true; - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -5034,7 +5034,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), "LIST", "IN"); } - else if (thd->work_part_info->part_type == VERSIONING_PARTITION) + else if (thd->work_part_info->part_type == VERSIONING_PARTITION || + tab_part_info->part_type == VERSIONING_PARTITION) { my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME"); } @@ -5885,6 +5886,37 @@ the generated partition syntax in a correct manner. *partition_changed= TRUE; } } + /* + Prohibit inplace when partitioned by primary key and the primary key is changed. + */ + if (!*partition_changed && + tab_part_info->part_field_array && + !tab_part_info->part_field_list.elements && + table->s->primary_key != MAX_KEY) + { + + if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | + ALTER_ADD_SYSTEM_VERSIONING)) + { + *partition_changed= true; + } + else + { + KEY *primary_key= table->key_info + table->s->primary_key; + List_iterator_fast drop_it(alter_info->drop_list); + const char *primary_name= primary_key->name.str; + const Alter_drop *drop; + drop_it.rewind(); + while ((drop= drop_it++)) + { + if (drop->type == Alter_drop::KEY && + 0 == my_strcasecmp(system_charset_info, primary_name, drop->name)) + break; + } + if (drop) + *partition_changed= TRUE; + } + } } if (thd->work_part_info) { @@ -5917,23 +5949,6 @@ the generated partition syntax in a correct manner. } } - // In case of PARTITION BY KEY(), check if primary key has changed - // System versioning also implicitly adds/removes primary key parts - if (alter_info->partition_flags == 0 && part_info->list_of_part_fields - && part_info->part_field_list.elements == 0) - { - if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | - ALTER_ADD_SYSTEM_VERSIONING)) - *partition_changed= true; - - List_iterator it(alter_info->key_list); - Key *key; - while((key= it++) && !*partition_changed) - { - if (key->type == Key::PRIMARY) - *partition_changed= true; - } - } /* Set up partition default_engine_type either from the create_info or from the previus table @@ -6834,7 +6849,7 @@ static void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, partition_info *part_info= lpt->part_info->get_clone(thd); TABLE *table= lpt->table; DBUG_ENTER("handle_alter_part_error"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); /* All instances of this table needs to be closed. @@ -7050,7 +7065,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, /* option_bits is used to mark if we should log the query with IF EXISTS */ ulonglong save_option_bits= thd->variables.option_bits; DBUG_ENTER("fast_alter_partition_table"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); part_info= table->part_info; lpt->thd= thd; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0ccabf87ff5..4750be99d30 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1897,7 +1897,7 @@ static void plugin_load(MEM_ROOT *tmp_root) sql_print_error(ER_THD(new_thd, ER_GET_ERRNO), my_errno, table->file->table_type()); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + table->mark_table_for_reopen(); close_mysql_tables(new_thd); end: new_thd->db= null_clex_str; // Avoid free on thd->db diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 98ffc842196..93bef049d28 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -853,6 +853,8 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ + + param->sync_clones(); } if (acc.finalize()) DBUG_RETURN(1); @@ -3130,7 +3132,10 @@ static void reset_stmt_params(Prepared_statement *stmt) Item_param **item= stmt->param_array; Item_param **end= item + stmt->param_count; for (;item < end ; ++item) + { (**item).reset(); + (**item).sync_clones(); + } } @@ -4087,7 +4092,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) lex->unit.cleanup(); /* No need to commit statement transaction, it's not started. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 493313da90a..07f07a7150f 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -182,6 +182,8 @@ #define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern #define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern #define OPTION_BIN_TMP_LOG_OFF (1ULL << 42) // disable binlog, intern +/* Disable commit of binlog. Used to combine many DDL's and DML's as one */ +#define OPTION_BIN_COMMIT_OFF (1ULL << 43) #define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 55e5e940b19..3ed0e288870 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2006,7 +2006,7 @@ send_event_to_slave(binlog_send_info *info, Log_event_type event_type, pos= my_b_tell(log); if (repl_semisync_master.update_sync_header(info->thd, - (uchar*) packet->ptr(), + (uchar*) packet->c_ptr_safe(), info->log_file_name + info->dirlen, pos, &need_sync)) { @@ -2030,7 +2030,8 @@ send_event_to_slave(binlog_send_info *info, Log_event_type event_type, } } - if (need_sync && repl_semisync_master.flush_net(info->thd, packet->c_ptr())) + if (need_sync && repl_semisync_master.flush_net(info->thd, + packet->c_ptr_safe())) { info->error= ER_UNKNOWN_ERROR; return "Failed to run hook 'after_send_event'"; @@ -2120,9 +2121,13 @@ static int init_binlog_sender(binlog_send_info *info, }); if (global_system_variables.log_warnings > 1) + { sql_print_information( - "Start binlog_dump to slave_server(%lu), pos(%s, %lu)", - thd->variables.server_id, log_ident, (ulong)*pos); + "Start binlog_dump to slave_server(%lu), pos(%s, %lu), " + "using_gtid(%d), gtid('%s')", thd->variables.server_id, + log_ident, (ulong)*pos, info->using_gtid_state, + connect_gtid_state.c_ptr_quick()); + } #ifndef DBUG_OFF if (opt_sporadic_binlog_dump_fail && (binlog_dump_count++ % 2)) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0774dc15ef8..896e7fdf5e7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -428,7 +428,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, setup_tables_done_option, result, unit, select_lex); } - DBUG_PRINT("info",("res: %d report_error: %d", res, + DBUG_PRINT("info",("res: %d is_error(): %d", res, thd->is_error())); res|= thd->is_error(); if (unlikely(res)) @@ -982,9 +982,12 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) } bool is_select= false; + bool use_sysvar= false; switch (thd->lex->sql_command) { case SQLCOM_SELECT: + use_sysvar= true; + /* fall through */ case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE_SELECT: case SQLCOM_DELETE_MULTI: @@ -1028,7 +1031,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) } // propagate system_time from sysvar - if (!vers_conditions.is_set() && is_select) + if (!vers_conditions.is_set() && use_sysvar) { if (vers_conditions.init_from_sysvar(thd)) DBUG_RETURN(-1); @@ -1036,10 +1039,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) if (vers_conditions.is_set()) { + if (vers_conditions.was_set() && + table->lock_type > TL_READ_NO_INSERT && + !vers_conditions.delete_history) + { + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table->alias.str); + DBUG_RETURN(-1); + } + if (vers_conditions.type == SYSTEM_TIME_ALL) continue; - - lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway } bool timestamps_only= table->table->versioned(VERS_TIMESTAMP); @@ -1588,6 +1597,9 @@ int JOIN::optimize() join_optimization_state init_state= optimization_state; if (select_lex->pushdown_select) { + // Do same as JOIN::optimize_inner does: + fields= &select_lex->item_list; + if (!(select_options & SELECT_DESCRIBE)) { /* Prepare to execute the query pushed into a foreign engine */ @@ -1749,36 +1761,6 @@ JOIN::init_range_rowid_filters() } -int JOIN::init_join_caches() -{ - JOIN_TAB *tab; - - for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); - tab; - tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) - { - TABLE *table= tab->table; - if (table->file->keyread_enabled()) - { - if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX)) - table->mark_columns_used_by_index(table->file->keyread, table->read_set); - } - else if ((tab->read_first_record == join_read_first || - tab->read_first_record == join_read_last) && - !tab->filesort && table->covering_keys.is_set(tab->index) && - !table->no_keyread) - { - table->prepare_for_keyread(tab->index, table->read_set); - } - if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE)) - revise_cache_usage(tab); - else - tab->remove_redundant_bnl_scan_conds(); - } - return 0; -} - - /** global select optimisation. @@ -2768,11 +2750,16 @@ int JOIN::optimize_stage2() } need_tmp= test_if_need_tmp_table(); - //TODO this could probably go in test_if_need_tmp_table. - if (this->select_lex->window_specs.elements > 0) { - need_tmp= TRUE; + + /* + If window functions are present then we can't have simple_order set to + TRUE as the window function needs a temp table for computation. + ORDER BY is computed after the window function computation is done, so + the sort will be done on the temp table. + */ + if (select_lex->have_window_funcs()) simple_order= FALSE; - } + /* If the hint FORCE INDEX FOR ORDER BY/GROUP BY is used for the table @@ -2996,8 +2983,7 @@ int JOIN::optimize_stage2() if (make_aggr_tables_info()) DBUG_RETURN(1); - if (init_join_caches()) - DBUG_RETURN(1); + init_join_cache_and_keyread(); if (init_range_rowid_filters()) DBUG_RETURN(1); @@ -4757,6 +4743,10 @@ void mark_join_nest_as_const(JOIN *join, { List_iterator it(join_nest->nested_join->join_list); TABLE_LIST *tbl; + Json_writer_object emb_obj(join->thd); + Json_writer_object trace_obj(join->thd, "mark_join_nest_as_const"); + Json_writer_array trace_array(join->thd, "members"); + while ((tbl= it++)) { if (tbl->nested_join) @@ -4776,6 +4766,8 @@ void mark_join_nest_as_const(JOIN *join, *found_const_table_map|= tab->table->map; set_position(join,(*const_count)++,tab,(KEYUSE*) 0); mark_as_null_row(tab->table); // All fields are NULL + + trace_array.add_table_name(tab->table); } } } @@ -4905,7 +4897,7 @@ make_join_statistics(JOIN *join, List &tables_list, table->file->print_error(error, MYF(0)); goto error; } - table->quick_keys.clear_all(); + table->opt_range_keys.clear_all(); table->intersect_keys.clear_all(); table->reginfo.join_tab=s; table->reginfo.not_exists_optimize=0; @@ -4917,7 +4909,7 @@ make_join_statistics(JOIN *join, List &tables_list, s->dependent= tables->dep_tables; if (tables->schema_table) table->file->stats.records= table->used_stat_records= 2; - table->quick_condition_rows= table->stat_records(); + table->opt_range_condition_rows= table->stat_records(); s->on_expr_ref= &tables->on_expr; if (*s->on_expr_ref) @@ -5384,7 +5376,7 @@ make_join_statistics(JOIN *join, List &tables_list, get_delayed_table_estimates(s->table, &s->records, &s->read_time, &s->startup_cost); s->found_records= s->records; - table->quick_condition_rows=s->records; + table->opt_range_condition_rows=s->records; } else s->scan_time(); @@ -6953,6 +6945,7 @@ void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) uint n_tables= my_count_bits(map); if (n_tables == 1) // Only one table { + DBUG_ASSERT(!(map & PSEUDO_TABLE_BITS)); // Must be a real table Table_map_iterator it(map); int tablenr= it.next_bit(); DBUG_ASSERT(tablenr != Table_map_iterator::BITMAP_END); @@ -7224,8 +7217,8 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, If applicable, get a more accurate estimate. Don't use the two heuristics at once. */ - if (s->table->quick_condition_rows != s->found_records) - records= s->table->quick_condition_rows; + if (s->table->opt_range_condition_rows != s->found_records) + records= s->table->opt_range_condition_rows; dbl_records= (double)records; return dbl_records; @@ -7513,8 +7506,8 @@ best_access_path(JOIN *join, type= JT_EQ_REF; trace_access_idx.add("access_type", join_type_str[type]) .add("index", keyinfo->name); - if (!found_ref && table->quick_keys.is_set(key)) - tmp= adjust_quick_cost(table->quick_costs[key], 1); + if (!found_ref && table->opt_range_keys.is_set(key)) + tmp= adjust_quick_cost(table->opt_range[key].cost, 1); else tmp= table->file->avg_io_cost(); tmp*= prev_record_reads(join_positions, idx, found_ref); @@ -7544,12 +7537,12 @@ best_access_path(JOIN *join, quick_cond is equivalent to ref_const_cond (if it was an empty interval we wouldn't have got here). */ - if (table->quick_keys.is_set(key)) + if (table->opt_range_keys.is_set(key)) { - records= (double) table->quick_rows[key]; + records= (double) table->opt_range[key].rows; trace_access_idx.add("used_range_estimates", true); - tmp= adjust_quick_cost(table->quick_costs[key], - table->quick_rows[key]); + tmp= adjust_quick_cost(table->opt_range[key].cost, + table->opt_range[key].rows); goto got_cost; } else @@ -7582,19 +7575,19 @@ best_access_path(JOIN *join, can make an adjustment is a special case of the criteria used in ReuseRangeEstimateForRef-3. */ - if (table->quick_keys.is_set(key) && + if (table->opt_range_keys.is_set(key) && (const_part & - (((key_part_map)1 << table->quick_key_parts[key])-1)) == - (((key_part_map)1 << table->quick_key_parts[key])-1) && - table->quick_n_ranges[key] == 1 && - records > (double) table->quick_rows[key]) + (((key_part_map)1 << table->opt_range[key].key_parts)-1)) == + (((key_part_map)1 << table->opt_range[key].key_parts)-1) && + table->opt_range[key].ranges == 1 && + records > (double) table->opt_range[key].rows) { - records= (double) table->quick_rows[key]; + records= (double) table->opt_range[key].rows; trace_access_idx.add("used_range_estimates", true); } else { - if (table->quick_keys.is_set(key)) + if (table->opt_range_keys.is_set(key)) { trace_access_idx.add("used_range_estimates",false) .add("cause", @@ -7668,13 +7661,13 @@ best_access_path(JOIN *join, (C3) "range optimizer used (have ref_or_null?2:1) intervals" */ - if (table->quick_keys.is_set(key) && !found_ref && //(C1) - table->quick_key_parts[key] == max_key_part && //(C2) - table->quick_n_ranges[key] == 1 + MY_TEST(ref_or_null_part)) //(C3) + if (table->opt_range_keys.is_set(key) && !found_ref && //(C1) + table->opt_range[key].key_parts == max_key_part && //(C2) + table->opt_range[key].ranges == 1 + MY_TEST(ref_or_null_part)) //(C3) { - records= (double) table->quick_rows[key]; - tmp= adjust_quick_cost(table->quick_costs[key], - table->quick_rows[key]); + records= (double) table->opt_range[key].rows; + tmp= adjust_quick_cost(table->opt_range[key].cost, + table->opt_range[key].rows); trace_access_idx.add("used_range_estimates", true); goto got_cost2; } @@ -7699,15 +7692,16 @@ best_access_path(JOIN *join, cheaper in some cases ? TODO: figure this out and adjust the plan choice if needed. */ - if (table->quick_keys.is_set(key)) + if (table->opt_range_keys.is_set(key)) { - if (table->quick_key_parts[key] >= max_key_part) // (2) + if (table->opt_range[key].key_parts >= max_key_part) // (2) { + double rows= (double) table->opt_range[key].rows; if (!found_ref && // (1) - records < (double) table->quick_rows[key]) // (3) + records < rows) // (3) { trace_access_idx.add("used_range_estimates", true); - records= (double) table->quick_rows[key]; + records= rows; } } else /* (table->quick_key_parts[key] < max_key_part) */ @@ -7773,15 +7767,16 @@ best_access_path(JOIN *join, optimizer is the same as in ReuseRangeEstimateForRef-3, applied to first table->quick_key_parts[key] key parts. */ - if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] <= max_key_part && + if (table->opt_range_keys.is_set(key) && + table->opt_range[key].key_parts <= max_key_part && const_part & - ((key_part_map)1 << table->quick_key_parts[key]) && - table->quick_n_ranges[key] == 1 + MY_TEST(ref_or_null_part & - const_part) && - records > (double) table->quick_rows[key]) + ((key_part_map)1 << table->opt_range[key].key_parts) && + table->opt_range[key].ranges == (1 + + MY_TEST(ref_or_null_part & + const_part)) && + records > (double) table->opt_range[key].rows) { - records= (double) table->quick_rows[key]; + records= (double) table->opt_range[key].rows; } } @@ -7820,7 +7815,7 @@ best_access_path(JOIN *join, tmp-= filter->get_adjusted_gain(rows) - filter->get_cmp_gain(rows); DBUG_ASSERT(tmp >= 0); trace_access_idx.add("rowid_filter_key", - s->table->key_info[filter->key_no].name); + table->key_info[filter->key_no].name); } } trace_access_idx.add("rows", records).add("cost", tmp); @@ -7935,7 +7930,7 @@ best_access_path(JOIN *join, if ((records >= s->found_records || best > s->read_time) && // (1) !(best_key && best_key->key == MAX_KEY) && // (2) !(s->quick && best_key && s->quick->index == best_key->key && // (2) - best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2) + best_max_key_part >= s->table->opt_range[best_key->key].key_parts) &&// (2) !((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3) ! s->table->covering_keys.is_clear_all() && best_key && !s->quick) &&// (3) !(s->table->force_index && best_key && !s->quick) && // (4) @@ -9200,10 +9195,11 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, /* Check if we have a prefix of key=const that matches a quick select. */ - if (!is_hash_join_key_no(key)) + if (!is_hash_join_key_no(key) && table->opt_range_keys.is_set(key)) { - key_part_map quick_key_map= (key_part_map(1) << table->quick_key_parts[key]) - 1; - if (table->quick_rows[key] && + key_part_map quick_key_map= (key_part_map(1) << + table->opt_range[key].key_parts) - 1; + if (table->opt_range[key].rows && !(quick_key_map & ~table->const_key_parts[key])) { /* @@ -9230,7 +9226,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, However if sel becomes greater than 2 then with high probability something went wrong. */ - sel /= (double)table->quick_rows[key] / (double) table->stat_records(); + sel /= (double)table->opt_range[key].rows / (double) table->stat_records(); set_if_smaller(sel, 1.0); used_range_selectivity= true; } @@ -9520,9 +9516,9 @@ best_extension_by_limited_search(JOIN *join, for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) { table_map real_table_bit= s->table->map; - if ((remaining_tables & real_table_bit) && + if ((remaining_tables & real_table_bit) && (allowed_tables & real_table_bit) && - !(remaining_tables & s->dependent) && + !(remaining_tables & s->dependent) && (!idx || !check_interleaving_with_nj(s))) { double current_record_count, current_read_time; @@ -9643,12 +9639,15 @@ best_extension_by_limited_search(JOIN *join, if (join->sort_by_table && join->sort_by_table != join->positions[join->const_tables].table->table) + { /* We may have to make a temp table, note that this is only a heuristic since we cannot know for sure at this point. Hence it may be wrong. */ + trace_one_table.add("cost_for_sorting", current_record_count); current_read_time= COST_ADD(current_read_time, current_record_count); + } trace_one_table.add("estimated_join_cardinality", partial_join_cardinality); if (current_read_time < join->best_read) @@ -11725,7 +11724,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { sel->needed_reg=tab->needed_reg; } - sel->quick_keys= tab->table->quick_keys; + sel->quick_keys= tab->table->opt_range_keys; if (!sel->quick_keys.is_subset(tab->checked_keys) || !sel->needed_reg.is_subset(tab->checked_keys)) { @@ -13123,17 +13122,15 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) /* Only happens with outer joins */ tab->read_first_record= tab->type == JT_SYSTEM ? join_read_system : join_read_const; - if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) - table->file->ha_start_keyread(tab->ref.key); - else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) + if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) && + (!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); break; case JT_EQ_REF: tab->read_record.unlock_row= join_read_key_unlock_row; /* fall through */ - if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) - table->file->ha_start_keyread(tab->ref.key); - else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) + if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) && + (!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); break; case JT_REF_OR_NULL: @@ -13145,9 +13142,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) } delete tab->quick; tab->quick=0; - if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) - table->file->ha_start_keyread(tab->ref.key); - else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered()) + if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) && + (!jcl || jcl > 4) && !tab->ref.is_access_triggered()) push_index_cond(tab, tab->ref.key); break; case JT_ALL: @@ -13206,12 +13202,11 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) } if (!table->no_keyread) { - if (tab->select && tab->select->quick && - tab->select->quick->index != MAX_KEY && //not index_merge - table->covering_keys.is_set(tab->select->quick->index)) - table->file->ha_start_keyread(tab->select->quick->index); - else if (!table->covering_keys.is_clear_all() && - !(tab->select && tab->select->quick)) + if (!(tab->select && tab->select->quick && + tab->select->quick->index != MAX_KEY && //not index_merge + table->covering_keys.is_set(tab->select->quick->index)) && + (!table->covering_keys.is_clear_all() && + !(tab->select && tab->select->quick))) { // Only read index tree if (tab->loosescan_match_tab) tab->index= tab->loosescan_key; @@ -13238,7 +13233,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) } if (tab->select && tab->select->quick && tab->select->quick->index != MAX_KEY && - !tab->table->file->keyread_enabled()) + !tab->table->covering_keys.is_set(tab->select->quick->index)) push_index_cond(tab, tab->select->quick->index); } break; @@ -13491,14 +13486,14 @@ double JOIN_TAB::scan_time() get_delayed_table_estimates(table, &records, &read_time, &startup_cost); found_records= records; - table->quick_condition_rows= records; + table->opt_range_condition_rows= records; } else { found_records= records= table->stat_records(); read_time= table->file->scan_time(); /* - table->quick_condition_rows has already been set to + table->opt_range_condition_rows has already been set to table->file->stats.records */ } @@ -16622,10 +16617,15 @@ static uint build_bitmap_for_nested_joins(List *join_list, /** - Set NESTED_JOIN::counter=0 in all nested joins in passed list. + Set NESTED_JOIN::counter and n_tables in all nested joins in passed list. - Recursively set NESTED_JOIN::counter=0 for all nested joins contained in - the passed join_list. + For all nested joins contained in the passed join_list (including its + children), set: + - nested_join->counter=0 + - nested_join->n_tables= {number of non-degenerate direct children}. + + Non-degenerate means non-const base table or a join nest that has a + non-degenerate child. @param join_list List of nested joins to process. It may also contain base tables which will be ignored. @@ -16648,8 +16648,11 @@ static uint reset_nj_counters(JOIN *join, List *join_list) if (!nested_join->n_tables) is_eliminated_nest= TRUE; } - if ((table->nested_join && !is_eliminated_nest) || - (!table->nested_join && (table->table->map & ~join->eliminated_tables))) + const table_map removed_tables= join->eliminated_tables | + join->const_table_map; + + if ((table->nested_join && !is_eliminated_nest) || + (!table->nested_join && (table->table->map & ~removed_tables))) n++; } DBUG_RETURN(n); @@ -18262,6 +18265,7 @@ TABLE *Create_tmp_table::start(THD *thd, char *tmpname,path[FN_REFLEN]; Field **reg_field; uint *blob_field; + key_part_map *const_key_parts; /* Treat sum functions as normal ones when loose index scan is used. */ m_save_sum_fields|= param->precomputed_group_by; DBUG_ENTER("Create_tmp_table::start"); @@ -18358,6 +18362,7 @@ TABLE *Create_tmp_table::start(THD *thd, &m_group_buff, (m_group && ! m_using_unique_constraint ? param->group_length : 0), &m_bitmaps, bitmap_buffer_size(field_count)*6, + &const_key_parts, sizeof(*const_key_parts), NullS)) { DBUG_RETURN(NULL); /* purecov: inspected */ @@ -18375,12 +18380,15 @@ TABLE *Create_tmp_table::start(THD *thd, bzero((char*) reg_field, sizeof(Field*) * (field_count+1)); bzero((char*) m_default_field, sizeof(Field*) * (field_count)); bzero((char*) m_from_field, sizeof(Field*) * field_count); + /* const_key_parts is used in sort_and_filter_keyuse */ + bzero((char*) const_key_parts, sizeof(*const_key_parts)); table->mem_root= own_root; mem_root_save= thd->mem_root; thd->mem_root= &table->mem_root; table->field=reg_field; + table->const_key_parts= const_key_parts; table->alias.set(table_alias->str, table_alias->length, table_alias_charset); table->reginfo.lock_type=TL_WRITE; /* Will be updated */ @@ -20596,7 +20604,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) } join->thd->get_stmt_da()->reset_current_row_for_warning(); - if (rc != NESTED_LOOP_NO_MORE_ROWS && + if (rc != NESTED_LOOP_NO_MORE_ROWS && (rc= join_tab_execution_startup(join_tab)) < 0) DBUG_RETURN(rc); @@ -20692,8 +20700,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, DBUG_ENTER("evaluate_join_record"); DBUG_PRINT("enter", - ("evaluate_join_record join: %p join_tab: %p" - " cond: %p error: %d alias %s", + ("evaluate_join_record join: %p join_tab: %p " + "cond: %p abort: %d alias %s", join, join_tab, select_cond, error, join_tab->table->alias.ptr())); @@ -23403,9 +23411,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, Otherwise, construct a ref access (todo: it's not clear what is the win in using ref access when we could use quick select also?) */ - if ((table->quick_keys.is_set(new_ref_key) && - table->quick_key_parts[new_ref_key] > ref_key_parts) || - !(tab->ref.key >= 0)) + if ((table->opt_range_keys.is_set(new_ref_key) && + table->opt_range[new_ref_key].key_parts > ref_key_parts) || + !(tab->ref.key >= 0)) { /* The range optimizer constructed QUICK_RANGE for ref_key, and @@ -23508,7 +23516,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, goto use_filesort; if (select && // psergey: why doesn't this use a quick? - table->quick_keys.is_set(best_key) && best_key != ref_key) + table->opt_range_keys.is_set(best_key) && best_key != ref_key) { key_map tmp_map; tmp_map.clear_all(); // Force the creation of quick select @@ -23590,15 +23598,6 @@ check_reverse_order: bool quick_created= (select && select->quick && select->quick!=save_quick); - /* - If ref_key used index tree reading only ('Using index' in EXPLAIN), - and best_key doesn't, then revert the decision. - */ - if (table->covering_keys.is_set(best_key) && !table->no_keyread) - table->file->ha_start_keyread(best_key); - else - table->file->ha_end_keyread(); - if (!quick_created) { if (select) // Throw any existing quick select @@ -23639,7 +23638,6 @@ check_reverse_order: tab->ref.key_parts= 0; if (select_limit < table->stat_records()) tab->limit= select_limit; - table->file->ha_end_keyread(); } } else if (tab->type != JT_ALL || tab->select->quick) @@ -23740,14 +23738,6 @@ skipped_filesort: { delete save_quick; save_quick= NULL; - - /* - 'delete save_quick' disabled key reads. Enable key read if the new - index is an covering key - */ - if (select->quick && !select->head->no_keyread && - select->head->covering_keys.is_set(select->quick->index)) - select->head->file->ha_start_keyread(select->quick->index); } if (orig_cond_saved && !changed_key) tab->set_cond(orig_cond); @@ -23762,9 +23752,6 @@ use_filesort: { delete select->quick; select->quick= save_quick; - if (select->quick && !select->head->no_keyread && - select->head->covering_keys.is_set(select->quick->index)) - select->head->file->ha_start_keyread(select->quick->index); } if (orig_cond_saved) tab->set_cond(orig_cond); @@ -27095,13 +27082,18 @@ int JOIN::save_explain_data_intern(Explain_query *output, output->add_node(xpl_sel); } - for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit(); - tmp_unit; - tmp_unit= tmp_unit->next_unit()) - { - if (tmp_unit->explainable()) - explain->add_child(tmp_unit->first_select()->select_number); - } + /* + Don't try to add query plans for child selects if this select was pushed + down into a Smart Storage Engine: + - the entire statement was pushed down ("PUSHED SELECT"), or + - this derived table was pushed down ("PUSHED DERIVED") + */ + if (!select_lex->pushdown_select && select_lex->type != pushed_derived_text) + for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit(); + tmp_unit; + tmp_unit= tmp_unit->next_unit()) + if (tmp_unit->explainable()) + explain->add_child(tmp_unit->first_select()->select_number); if (select_lex->is_top_level_node()) output->query_plan_ready(); @@ -27132,7 +27124,16 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, THD *thd=join->thd; select_result *result=join->result; DBUG_ENTER("select_describe"); - + + if (join->select_lex->pushdown_select) + { + /* + The whole statement was pushed down to a Smart Storage Engine. Do not + attempt to produce a query plan locally. + */ + DBUG_VOID_RETURN; + } + /* Update the QPF with latest values of using_temporary, using_filesort */ for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit(); unit; @@ -28071,14 +28072,14 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, We need to adjust the estimates if we had a quick select (or ref(const)) on index keynr. */ - if (table->quick_keys.is_set(keynr)) + if (table->opt_range_keys.is_set(keynr)) { /* Start from quick select's rows and cost. These are always cheaper than full index scan/cost. */ - double best_rows= (double)table->quick_rows[keynr]; - double best_cost= (double)table->quick_costs[keynr]; + double best_rows= (double) table->opt_range[keynr].rows; + double best_cost= (double) table->opt_range[keynr].cost; /* Check if ref(const) access was possible on this index. @@ -28105,8 +28106,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, 2. ref(const) uses fewer key parts, becasue there is a range_cond(key_part+1). */ - if (kp == table->quick_key_parts[keynr]) - ref_rows= table->quick_rows[keynr]; + if (kp == table->opt_range[keynr].key_parts) + ref_rows= table->opt_range[keynr].rows; else ref_rows= (ha_rows) table->key_info[keynr].actual_rec_per_key(kp-1); @@ -28192,7 +28193,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, value for further use in QUICK_SELECT_DESC @note - This function takes into account table->quick_condition_rows statistic + This function takes into account table->opt_range_condition_rows statistic (that is calculated by the make_join_statistics function). However, single table procedures such as mysql_update() and mysql_delete() never call make_join_statistics, so they have to update it manually @@ -28227,7 +28228,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, double fanout= 1; ha_rows table_records= table->stat_records(); bool group= join && join->group && order == join->group_list; - ha_rows refkey_rows_estimate= table->quick_condition_rows; + ha_rows refkey_rows_estimate= table->opt_range_condition_rows; const bool has_limit= (select_limit_arg != HA_POS_ERROR); THD* thd= join ? join->thd : table->in_use; @@ -28281,7 +28282,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, trace_cheaper_ordering.add("read_time", read_time); /* Calculate the selectivity of the ref_key for REF_ACCESS. For - RANGE_ACCESS we use table->quick_condition_rows. + RANGE_ACCESS we use table->opt_range_condition_rows. */ if (ref_key >= 0 && ref_key != MAX_KEY && tab->type == JT_REF) { @@ -28292,9 +28293,9 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, */ if (tab->ref.const_ref_part_map == make_prev_keypart_map(tab->ref.key_parts) && - table->quick_keys.is_set(ref_key) && - table->quick_key_parts[ref_key] == tab->ref.key_parts) - refkey_rows_estimate= table->quick_rows[ref_key]; + table->opt_range_keys.is_set(ref_key) && + table->opt_range[ref_key].key_parts == tab->ref.key_parts) + refkey_rows_estimate= table->opt_range[ref_key].rows; else { const KEY *ref_keyinfo= table->key_info + ref_key; @@ -28508,8 +28509,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, possible_key.add("cause", "ref estimates better"); continue; } - if (table->quick_keys.is_set(nr)) - quick_records= table->quick_rows[nr]; + if (table->opt_range_keys.is_set(nr)) + quick_records= table->opt_range[nr].rows; possible_key.add("records", quick_records); if (best_key < 0 || (select_limit <= MY_MIN(quick_records,best_records) ? @@ -28579,7 +28580,6 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, *new_select_limit= has_limit ? best_select_limit : table_records; if (new_used_key_parts != NULL) *new_used_key_parts= best_key_parts; - table->file->ha_end_keyread(); DBUG_RETURN(TRUE); } @@ -28605,7 +28605,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, @note Side effects: - may deallocate or deallocate and replace select->quick; - - may set table->quick_condition_rows and table->quick_rows[...] + - may set table->opt_range_condition_rows and table->quick_rows[...] to table->file->stats.records. */ @@ -28670,10 +28670,10 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, { // check if some index scan & LIMIT is more efficient than filesort /* - Update quick_condition_rows since single table UPDATE/DELETE procedures + Update opt_range_condition_rows since single table UPDATE/DELETE procedures don't call make_join_statistics() and leave this variable uninitialized. */ - table->quick_condition_rows= table->stat_records(); + table->opt_range_condition_rows= table->stat_records(); int key, direction; if (test_if_cheaper_ordering(NULL, order, table, @@ -29313,6 +29313,103 @@ void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join, } +/* + @brief + Initialize join cache and enable keyread +*/ +void JOIN::init_join_cache_and_keyread() +{ + JOIN_TAB *tab; + for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); + tab; + tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) + { + TABLE *table= tab->table; + switch (tab->type) { + case JT_SYSTEM: + case JT_CONST: + case JT_FT: + case JT_UNKNOWN: + case JT_MAYBE_REF: + break; + case JT_EQ_REF: + case JT_REF_OR_NULL: + case JT_REF: + if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) + table->file->ha_start_keyread(tab->ref.key); + break; + case JT_HASH: + case JT_ALL: + SQL_SELECT *select; + select= tab->select ? tab->select : + (tab->filesort ? tab->filesort->select : NULL); + if (select && select->quick && select->quick->index != MAX_KEY && + table->covering_keys.is_set(select->quick->index) && + !table->no_keyread) + table->file->ha_start_keyread(select->quick->index); + break; + case JT_HASH_NEXT: + case JT_NEXT: + if ((tab->read_first_record == join_read_first || + tab->read_first_record == join_read_last) && + table->covering_keys.is_set(tab->index) && + !table->no_keyread) + { + DBUG_ASSERT(!tab->filesort); + table->file->ha_start_keyread(tab->index); + } + break; + default: + break; + /* purecov: end */ + } + + if (table->file->keyread_enabled()) + { + /* + Here we set the read_set bitmap for all covering keys + except CLUSTERED indexes, with all the key-parts inside the key. + This is needed specifically for an index that contains virtual column. + + Example: + Lets say we have this query + SELECT b FROM t1; + + and the table definition is like + CREATE TABLE t1( + a varchar(10) DEFAULT NULL, + b varchar(255) GENERATED ALWAYS AS (a) VIRTUAL, + KEY key1 (b)); + + So we a virtual column b and an index key1 defined on the virtual + column. So if a query uses a vcol, base columns that it + depends on are automatically added to the read_set - because they're + needed to calculate the vcol. + But if we're doing keyread, vcol is taken + from the index, not calculated, and base columns do not need to be + in the read set. To ensure this we try to set the read_set to only + the key-parts of the indexes. + + Another side effect of this is + Lets say you have a query + select a, b from t1 + and there is an index key1 (a,b,c) + then as key1 is covering and we would have the keyread enable for + this key, so the below call will also set the read_set for column + c, which is not a problem as we read all the columns from the index + tuple. + */ + if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX)) + table->mark_columns_used_by_index(table->file->keyread, table->read_set); + } + if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE)) + revise_cache_usage(tab); + else + tab->remove_redundant_bnl_scan_conds(); + } +} + + /** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 46c84b9df7b..545db41798c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1642,7 +1642,6 @@ public: bool flatten_subqueries(); bool optimize_unflattened_subqueries(); bool optimize_constant_subqueries(); - int init_join_caches(); bool make_range_rowid_filters(); bool init_range_rowid_filters(); bool make_sum_func_list(List &all_fields, List &send_fields, @@ -1748,6 +1747,7 @@ public: - We are using an ORDER BY or GROUP BY on fields not in the first table - We are using different ORDER BY and GROUP BY orders - The user wants us to buffer the result. + - We are using WINDOW functions. When the WITH ROLLUP modifier is present, we cannot skip temporary table creation for the DISTINCT clause just because there are only const tables. */ @@ -1757,7 +1757,8 @@ public: ((select_distinct || !simple_order || !simple_group) || (group_list && order) || MY_TEST(select_options & OPTION_BUFFER_RESULT))) || - (rollup.state != ROLLUP::STATE_NONE && select_distinct)); + (rollup.state != ROLLUP::STATE_NONE && select_distinct) || + select_lex->have_window_funcs()); } bool choose_subquery_plan(table_map join_tables); void get_partial_cost_and_fanout(int end_tab_idx, @@ -1824,6 +1825,7 @@ private: bool add_having_as_table_cond(JOIN_TAB *tab); bool make_aggr_tables_info(); bool add_fields_for_current_rowid(JOIN_TAB *cur, List *fields); + void init_join_cache_and_keyread(); }; enum enum_with_bush_roots { WITH_BUSH_ROOTS, WITHOUT_BUSH_ROOTS}; diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index f41221e11de..c0925da59e1 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -203,6 +203,16 @@ bool check_sequence_fields(LEX *lex, List *fields) reason= "Sequence tables cannot have any keys"; goto err; } + if (lex->alter_info.check_constraint_list.elements > 0) + { + reason= "Sequence tables cannot have any constraints"; + goto err; + } + if (lex->alter_info.flags & ALTER_ORDER) + { + reason= "ORDER BY"; + goto err; + } for (field_no= 0; (field= it++); field_no++) { @@ -210,7 +220,8 @@ bool check_sequence_fields(LEX *lex, List *fields) if (my_strcasecmp(system_charset_info, field_def->field_name, field->field_name.str) || field->flags != field_def->flags || - field->type_handler() != field_def->type_handler) + field->type_handler() != field_def->type_handler || + field->check_constraint || field->vcol_info) { reason= field->field_name.str; goto err; @@ -301,8 +312,7 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list) if (!temporary_table) { /* - The following code works like open_system_tables_for_read() and - close_system_tables() + The following code works like open_system_tables_for_read() The idea is: - Copy the table_list object for the sequence that was created - Backup the current state of open tables and create a new @@ -355,8 +365,10 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list) seq->reserved_until= seq->start; error= seq->write_initial_sequence(table); - trans_commit_stmt(thd); - trans_commit_implicit(thd); + if (trans_commit_stmt(thd)) + error= 1; + if (trans_commit_implicit(thd)) + error= 1; if (!temporary_table) { @@ -437,11 +449,11 @@ int SEQUENCE::read_initial_values(TABLE *table) MYSQL_LOCK *lock; bool mdl_lock_used= 0; THD *thd= table->in_use; - bool has_active_transaction= !thd->transaction.stmt.is_empty(); + bool has_active_transaction= !thd->transaction->stmt.is_empty(); /* There is already a mdl_ticket for this table. However, for list_fields the MDL lock is of type MDL_SHARED_HIGH_PRIO which is not usable - for doing a able lock. Get a proper read lock to solve this. + for doing a table lock. Get a proper read lock to solve this. */ if (table->mdl_ticket == 0) { @@ -490,7 +502,7 @@ int SEQUENCE::read_initial_values(TABLE *table) But we also don't want to commit the stmt transaction while in a substatement, see MDEV-15977. */ - if (!has_active_transaction && !thd->transaction.stmt.is_empty() && + if (!has_active_transaction && !thd->transaction->stmt.is_empty() && !thd->in_sub_stmt) trans_commit_stmt(thd); } @@ -917,6 +929,8 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) table= first_table->table; seq= table->s->sequence; + + seq->write_lock(table); new_seq->reserved_until= seq->reserved_until; /* Copy from old sequence those fields that the user didn't specified */ @@ -949,18 +963,18 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) first_table->db.str, first_table->table_name.str); error= 1; + seq->write_unlock(table); goto end; } - table->s->sequence->write_lock(table); if (likely(!(error= new_seq->write(table, 1)))) { /* Store the sequence values in table share */ - table->s->sequence->copy(new_seq); + seq->copy(new_seq); } else table->file->print_error(error, MYF(0)); - table->s->sequence->write_unlock(table); + seq->write_unlock(table); if (trans_commit_stmt(thd)) error= 1; if (trans_commit_implicit(thd)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2528134f4ee..5eb2d911926 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1753,7 +1753,7 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, @param thd thread handler @param packet string to append @param opt list of options - @param check_options only print known options + @param check_options print all used options @param rules list of known options */ @@ -1812,7 +1812,9 @@ static void add_table_options(THD *thd, TABLE *table, handlerton *hton; HA_CREATE_INFO create_info; bool check_options= (!(sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) && - !create_info_arg); + (!create_info_arg || + create_info_arg->used_fields & + HA_CREATE_PRINT_ALL_OPTIONS)); #ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info) @@ -5273,6 +5275,29 @@ bool store_schema_schemata(THD* thd, TABLE *table, LEX_CSTRING *db_name, } +/* + Check if the specified database exists on disk. + + @param dbname - the database name + @retval true - on error, the database directory does not exists + @retval false - on success, the database directory exists +*/ +static bool verify_database_directory_exists(const LEX_CSTRING &dbname) +{ + DBUG_ENTER("verify_database_directory_exists"); + char path[FN_REFLEN + 16]; + uint path_len; + MY_STAT stat_info; + if (!dbname.str[0]) + DBUG_RETURN(true); // Empty database name: does not exist. + path_len= build_table_filename(path, sizeof(path) - 1, dbname.str, "", "", 0); + path[path_len - 1]= 0; + if (!mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) + DBUG_RETURN(true); // The database directory was not found: does not exist. + DBUG_RETURN(false); // The database directory was found. +} + + int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) { /* @@ -5301,19 +5326,10 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) If we have lookup db value we should check that the database exists */ if(lookup_field_vals.db_value.str && !lookup_field_vals.wild_db_value && - db_names.at(0) != &INFORMATION_SCHEMA_NAME) - { - char path[FN_REFLEN+16]; - uint path_len; - MY_STAT stat_info; - if (!lookup_field_vals.db_value.str[0]) - DBUG_RETURN(0); - path_len= build_table_filename(path, sizeof(path) - 1, - lookup_field_vals.db_value.str, "", "", 0); - path[path_len-1]= 0; - if (!mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) - DBUG_RETURN(0); - } + (!db_names.elements() /* The database name was too long */|| + (db_names.at(0) != &INFORMATION_SCHEMA_NAME && + verify_database_directory_exists(lookup_field_vals.db_value)))) + DBUG_RETURN(0); for (size_t i=0; i < db_names.elements(); i++) { @@ -5504,10 +5520,25 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, str.qs_append(STRING_WITH_LEN(" partitioned")); #endif - if (share->transactional != HA_CHOICE_UNDEF) + /* + Write transactional=0|1 for tables where the user has specified the + option or for tables that supports both transactional and non + transactional tables + */ + if (share->transactional != HA_CHOICE_UNDEF || + (share->db_type() && + share->db_type()->flags & HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL && + file)) { + uint choice= share->transactional; + if (choice == HA_CHOICE_UNDEF) + choice= ((file->ha_table_flags() & + (HA_NO_TRANSACTIONS | HA_CRASH_SAFE)) == + HA_NO_TRANSACTIONS ? + HA_CHOICE_NO : HA_CHOICE_YES); + str.qs_append(STRING_WITH_LEN(" transactional=")); - str.qs_append(ha_choice_values[(uint) share->transactional]); + str.qs_append(ha_choice_values[choice]); } append_create_options(thd, &str, share->option_list, false, 0); @@ -6105,7 +6136,7 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, table->field[1]->store(option_name, strlen(option_name), scs); table->field[2]->store(plugin_decl(plugin)->descr, strlen(plugin_decl(plugin)->descr), scs); - tmp= &yesno[MY_TEST(hton->commit)]; + tmp= &yesno[MY_TEST(hton->commit && !(hton->flags & HTON_NO_ROLLBACK))]; table->field[3]->store(tmp->str, tmp->length, scs); table->field[3]->set_notnull(); tmp= &yesno[MY_TEST(hton->prepare)]; @@ -6492,7 +6523,6 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; bool full_access; char definer[USER_HOST_BUFF_SIZE]; - Open_tables_backup open_tables_state_backup; enum enum_schema_tables schema_table_idx= get_schema_table_idx(tables->schema_table); DBUG_ENTER("fill_schema_proc"); @@ -6507,8 +6537,12 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) proc_tables.lock_type= TL_READ; full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE, 1, TRUE); - if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup))) + + start_new_trans new_trans(thd); + + if (!(proc_table= open_proc_table_for_read(thd))) { + new_trans.restore_old_transaction(); DBUG_RETURN(1); } @@ -6550,7 +6584,9 @@ err: if (proc_table->file->inited) (void) proc_table->file->ha_index_end(); - close_system_tables(thd, &open_tables_state_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + thd->variables.sql_mode = sql_mode_was; DBUG_RETURN(res); } diff --git a/sql/sql_sort.h b/sql/sql_sort.h index 5b3f5a67d17..40f0c5ede5f 100644 --- a/sql/sql_sort.h +++ b/sql/sql_sort.h @@ -536,7 +536,7 @@ public: uchar *unique_buff; bool not_killable; - char* tmp_buffer; + String tmp_buffer; // The fields below are used only by Unique class. qsort2_cmp compare; BUFFPEK_COMPARE_CONTEXT cmp_context; @@ -544,6 +544,12 @@ public: Sort_param() { memset(reinterpret_cast(this), 0, sizeof(*this)); + tmp_buffer.set_thread_specific(); + /* + Fix memset() clearing the charset. + TODO: The constructor should be eventually rewritten not to use memset(). + */ + tmp_buffer.set_charset(&my_charset_bin); } void init_for_filesort(uint sortlen, TABLE *table, ha_rows maxrows, bool sort_positions); diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 55e8e52c052..879955af723 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2009 MySQL AB - Copyright (c) 2019, MariaDB Corporation. + Copyright (c) 2019, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -230,17 +230,17 @@ index_stat_def= {INDEX_STAT_N_FIELDS, index_stat_fields, 4, index_stat_pk_col}; Open all statistical tables and lock them */ -static int open_stat_tables(THD *thd, TABLE_LIST *tables, - Open_tables_backup *backup, bool for_write) +static int open_stat_tables(THD *thd, TABLE_LIST *tables, bool for_write) { int rc; - Dummy_error_handler deh; // suppress errors + DBUG_ASSERT(thd->internal_transaction()); + thd->push_internal_handler(&deh); init_table_list_for_stat_tables(tables, for_write); init_mdl_requests(tables); thd->in_sub_stmt|= SUB_STMT_STAT_TABLES; - rc= open_system_tables_for_read(thd, tables, backup); + rc= open_system_tables_for_read(thd, tables); thd->in_sub_stmt&= ~SUB_STMT_STAT_TABLES; thd->pop_internal_handler(); @@ -253,7 +253,7 @@ static int open_stat_tables(THD *thd, TABLE_LIST *tables, stat_table_intact.check(tables[COLUMN_STAT].table, &column_stat_def) || stat_table_intact.check(tables[INDEX_STAT].table, &index_stat_def))) { - close_system_tables(thd, backup); + close_thread_tables(thd); rc= 1; } @@ -270,13 +270,12 @@ static int open_stat_tables(THD *thd, TABLE_LIST *tables, stat tables need to be adjusted accordingly. */ static inline int open_stat_table_for_ddl(THD *thd, TABLE_LIST *table, - const LEX_CSTRING *stat_tab_name, - Open_tables_backup *backup) + const LEX_CSTRING *stat_tab_name) { table->init_one_table(&MYSQL_SCHEMA_NAME, stat_tab_name, NULL, TL_WRITE); No_such_table_error_handler nst_handler; thd->push_internal_handler(&nst_handler); - int res= open_system_tables_for_read(thd, table, backup); + int res= open_system_tables_for_read(thd, table); thd->pop_internal_handler(); return res; } @@ -1037,27 +1036,31 @@ public: stat_field->set_notnull(); switch (i) { case COLUMN_STAT_MIN_VALUE: + { + /* + TODO varun: After MDEV-22583 is fixed, add a function in Field_bit + and move this implementation there + */ if (table_field->type() == MYSQL_TYPE_BIT) stat_field->store(table_field->collected_stats->min_value->val_int(),true); else { - table_field->collected_stats->min_value->val_str(&val); - size_t length= Well_formed_prefix(val.charset(), val.ptr(), - MY_MIN(val.length(), stat_field->field_length)).length(); - stat_field->store(val.ptr(), length, &my_charset_bin); + Field *field= table_field->collected_stats->min_value; + field->store_to_statistical_minmax_field(stat_field, &val); } break; + } case COLUMN_STAT_MAX_VALUE: + { if (table_field->type() == MYSQL_TYPE_BIT) stat_field->store(table_field->collected_stats->max_value->val_int(),true); else { - table_field->collected_stats->max_value->val_str(&val); - size_t length= Well_formed_prefix(val.charset(), val.ptr(), - MY_MIN(val.length(), stat_field->field_length)).length(); - stat_field->store(val.ptr(), length, &my_charset_bin); + Field *field= table_field->collected_stats->max_value; + field->store_to_statistical_minmax_field(stat_field, &val); } break; + } case COLUMN_STAT_NULLS_RATIO: stat_field->store(table_field->collected_stats->get_nulls_ratio()); break; @@ -1134,17 +1137,19 @@ public: switch (i) { case COLUMN_STAT_MIN_VALUE: - table_field->read_stats->min_value->set_notnull(); - stat_field->val_str(&val); - table_field->read_stats->min_value->store(val.ptr(), val.length(), - &my_charset_bin); + { + Field *field= table_field->read_stats->min_value; + field->set_notnull(); + field->store_from_statistical_minmax_field(stat_field, &val); break; + } case COLUMN_STAT_MAX_VALUE: - table_field->read_stats->max_value->set_notnull(); - stat_field->val_str(&val); - table_field->read_stats->max_value->store(val.ptr(), val.length(), - &my_charset_bin); + { + Field *field= table_field->read_stats->max_value; + field->set_notnull(); + field->store_from_statistical_minmax_field(stat_field, &val); break; + } case COLUMN_STAT_NULLS_RATIO: table_field->read_stats->set_nulls_ratio(stat_field->val_real()); break; @@ -1671,6 +1676,7 @@ public: */ virtual bool add() { + table_field->mark_unused_memory_as_defined(); return tree->unique_add(table_field->ptr); } @@ -2225,27 +2231,13 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share) DBUG_ENTER("alloc_statistics_for_table_share"); - DEBUG_SYNC(thd, "statistics_mem_alloc_start1"); - DEBUG_SYNC(thd, "statistics_mem_alloc_start2"); - - mysql_mutex_lock(&table_share->LOCK_share); - - if (stats_cb->stats_can_be_read) - { - mysql_mutex_unlock(&table_share->LOCK_share); - DBUG_RETURN(0); - } - Table_statistics *table_stats= stats_cb->table_stats; if (!table_stats) { table_stats= (Table_statistics *) alloc_root(&stats_cb->mem_root, sizeof(Table_statistics)); if (!table_stats) - { - mysql_mutex_unlock(&table_share->LOCK_share); DBUG_RETURN(1); - } memset(table_stats, 0, sizeof(Table_statistics)); stats_cb->table_stats= table_stats; } @@ -2311,88 +2303,10 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share) } } } - - if (column_stats && index_stats && idx_avg_frequency) - stats_cb->stats_can_be_read= TRUE; - - mysql_mutex_unlock(&table_share->LOCK_share); - - DBUG_RETURN(0); + DBUG_RETURN(column_stats && index_stats && idx_avg_frequency ? 0 : 1); } -/** - @brief - Allocate memory for the histogram used by a table share - - @param - thd Thread handler - @param - table_share Table share for which the memory for histogram data is allocated - @param - is_safe TRUE <-> at any time only one thread can perform the function - - @note - The function allocates the memory for the histogram built for a table in the - table's share memory with the intention to read the data there from the - system persistent statistical table mysql.column_stats, - The memory is allocated in the table_share's mem_root. - If the parameter is_safe is TRUE then it is guaranteed that at any given time - only one thread is executed the code of the function. - - @retval - 0 If the memory for all statistical data has been successfully allocated - @retval - 1 Otherwise - - @note - Currently the function always is called with the parameter is_safe set - to FALSE. -*/ - -static -int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share, - bool is_safe) -{ - TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb; - - DBUG_ENTER("alloc_histograms_for_table_share"); - - if (!is_safe) - mysql_mutex_lock(&table_share->LOCK_share); - - if (stats_cb->histograms_can_be_read) - { - if (!is_safe) - mysql_mutex_unlock(&table_share->LOCK_share); - DBUG_RETURN(0); - } - - Table_statistics *table_stats= stats_cb->table_stats; - ulong total_hist_size= table_stats->total_hist_size; - - if (total_hist_size && !table_stats->histograms) - { - uchar *histograms= (uchar *) alloc_root(&stats_cb->mem_root, - total_hist_size); - if (!histograms) - { - if (!is_safe) - mysql_mutex_unlock(&table_share->LOCK_share); - DBUG_RETURN(1); - } - memset(histograms, 0, total_hist_size); - table_stats->histograms= histograms; - stats_cb->histograms_can_be_read= TRUE; - } - - if (!is_safe) - mysql_mutex_unlock(&table_share->LOCK_share); - - DBUG_RETURN(0); - -} - /** @brief Initialize the aggregation fields to collect statistics on a column @@ -2874,18 +2788,18 @@ int collect_statistics_for_table(THD *thd, TABLE *table) int update_statistics_for_table(THD *thd, TABLE *table) { TABLE_LIST tables[STATISTICS_TABLES]; - Open_tables_backup open_tables_backup; uint i; int err; enum_binlog_format save_binlog_format; int rc= 0; TABLE *stat_table; - DBUG_ENTER("update_statistics_for_table"); DEBUG_SYNC(thd, "statistics_update_start"); - if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) + start_new_trans new_trans(thd); + + if (open_stat_tables(thd, tables, TRUE)) DBUG_RETURN(rc); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -2935,8 +2849,9 @@ int update_statistics_for_table(THD *thd, TABLE *table) } thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + if (thd->commit_whole_transaction_and_close_tables()) + rc= 1; + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -2984,15 +2899,26 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) Field **field_ptr; KEY *key_info, *key_info_end; TABLE_SHARE *table_share= table->s; - Table_statistics *read_stats= table_share->stats_cb.table_stats; enum_check_fields old_check_level= thd->count_cuted_fields; DBUG_ENTER("read_statistics_for_table"); + DEBUG_SYNC(thd, "statistics_mem_alloc_start1"); + DEBUG_SYNC(thd, "statistics_mem_alloc_start2"); + + if (!table_share->stats_cb.start_stats_load()) + DBUG_RETURN(table_share->stats_cb.stats_are_ready() ? 0 : 1); + + if (alloc_statistics_for_table_share(thd, table_share)) + { + table_share->stats_cb.abort_stats_load(); + DBUG_RETURN(1); + } /* Don't write warnings for internal field conversions */ thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* Read statistics from the statistical table table_stats */ + Table_statistics *read_stats= table_share->stats_cb.table_stats; stat_table= stat_tables[TABLE_STAT].table; Table_stat table_stat(stat_table, table); table_stat.set_key_fields(); @@ -3009,7 +2935,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) column_stat.get_stat_values(); total_hist_size+= table_field->read_stats->histogram.get_size(); } - read_stats->total_hist_size= total_hist_size; + table_share->stats_cb.total_hist_size= total_hist_size; /* Read statistics from the statistical table index_stats */ stat_table= stat_tables[INDEX_STAT].table; @@ -3071,9 +2997,8 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) } } - table->stats_is_read= TRUE; thd->count_cuted_fields= old_check_level; - + table_share->stats_cb.end_stats_load(); DBUG_RETURN(0); } @@ -3111,71 +3036,6 @@ void delete_stat_values_for_table_share(TABLE_SHARE *table_share) } -/** - @brief - Check whether any statistics is to be read for tables from a table list - - @param - thd The thread handle - @param - tables The tables list for whose tables the check is to be done - - @details - The function checks whether for any of the tables opened and locked for - a statement statistics from statistical tables is needed to be read. - - @retval - TRUE statistics for any of the tables is needed to be read - @retval - FALSE Otherwise -*/ - -static -bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables) -{ - if (!tables) - return FALSE; - - /* - Do not read statistics for any query that explicity involves - statistical tables, failure to to do so we may end up - in a deadlock. - */ - - for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) - { - if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) - { - TABLE_SHARE *table_share= tl->table->s; - if (table_share && - table_share->table_category != TABLE_CATEGORY_USER - && is_stat_table(&tl->db, &tl->alias)) - return FALSE; - } - } - - for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) - { - if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) - { - TABLE_SHARE *table_share= tl->table->s; - if (table_share && - table_share->stats_cb.stats_can_be_read && - (!table_share->stats_cb.stats_is_read || - (!table_share->stats_cb.histograms_are_read && - thd->variables.optimizer_use_condition_selectivity > 3))) - return TRUE; - if (table_share->stats_cb.stats_is_read) - tl->table->stats_is_read= TRUE; - if (table_share->stats_cb.histograms_are_read) - tl->table->histograms_are_read= TRUE; - } - } - - return FALSE; -} - - /** @brief Read histogram for a table from the persistent statistical tables @@ -3211,26 +3071,25 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables) static int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) { - TABLE_SHARE *table_share= table->s; - + TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb; DBUG_ENTER("read_histograms_for_table"); - if (!table_share->stats_cb.histograms_can_be_read) + if (stats_cb->start_histograms_load()) { - (void) alloc_histograms_for_table_share(thd, table_share, FALSE); - } - if (table_share->stats_cb.histograms_can_be_read && - !table_share->stats_cb.histograms_are_read) - { - Field **field_ptr; - uchar *histogram= table_share->stats_cb.table_stats->histograms; - TABLE *stat_table= stat_tables[COLUMN_STAT].table; - Column_stat column_stat(stat_table, table); - for (field_ptr= table_share->field; *field_ptr; field_ptr++) + uchar *histogram= (uchar *) alloc_root(&stats_cb->mem_root, + stats_cb->total_hist_size); + if (!histogram) + { + stats_cb->abort_histograms_load(); + DBUG_RETURN(1); + } + memset(histogram, 0, stats_cb->total_hist_size); + + Column_stat column_stat(stat_tables[COLUMN_STAT].table, table); + for (Field **field_ptr= table->s->field; *field_ptr; field_ptr++) { Field *table_field= *field_ptr; - uint hist_size= table_field->read_stats->histogram.get_size(); - if (hist_size) + if (uint hist_size= table_field->read_stats->histogram.get_size()) { column_stat.set_key_fields(table_field); table_field->read_stats->histogram.set_values(histogram); @@ -3238,8 +3097,9 @@ int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) histogram+= hist_size; } } + stats_cb->end_histograms_load(); } - + table->histograms_are_read= true; DBUG_RETURN(0); } @@ -3287,83 +3147,96 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) } +static void dump_stats_from_share_to_table(TABLE *table) +{ + TABLE_SHARE *table_share= table->s; + KEY *key_info= table_share->key_info; + KEY *key_info_end= key_info + table_share->keys; + KEY *table_key_info= table->key_info; + for ( ; key_info < key_info_end; key_info++, table_key_info++) + table_key_info->read_stats= key_info->read_stats; + + Field **field_ptr= table_share->field; + Field **table_field_ptr= table->field; + for ( ; *field_ptr; field_ptr++, table_field_ptr++) + (*table_field_ptr)->read_stats= (*field_ptr)->read_stats; + table->stats_is_read= true; +} + + int read_statistics_for_tables(THD *thd, TABLE_LIST *tables) { TABLE_LIST stat_tables[STATISTICS_TABLES]; - Open_tables_backup open_tables_backup; DBUG_ENTER("read_statistics_for_tables"); if (thd->bootstrap || thd->variables.use_stat_tables == NEVER) DBUG_RETURN(0); + bool found_stat_table= false; + bool statistics_for_tables_is_needed= false; + for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { - if (tl->table) + TABLE_SHARE *table_share; + if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) && + table_share->tmp_table == NO_TMP_TABLE) { - TABLE_SHARE *table_share= tl->table->s; - if (table_share && table_share->table_category == TABLE_CATEGORY_USER && - table_share->tmp_table == NO_TMP_TABLE) + if (table_share->table_category == TABLE_CATEGORY_USER) { - if (table_share->stats_cb.stats_can_be_read || - !alloc_statistics_for_table_share(thd, table_share)) + if (table_share->stats_cb.stats_are_ready()) { - if (table_share->stats_cb.stats_can_be_read) - { - KEY *key_info= table_share->key_info; - KEY *key_info_end= key_info + table_share->keys; - KEY *table_key_info= tl->table->key_info; - for ( ; key_info < key_info_end; key_info++, table_key_info++) - table_key_info->read_stats= key_info->read_stats; - Field **field_ptr= table_share->field; - Field **table_field_ptr= tl->table->field; - for ( ; *field_ptr; field_ptr++, table_field_ptr++) - (*table_field_ptr)->read_stats= (*field_ptr)->read_stats; - tl->table->stats_is_read= table_share->stats_cb.stats_is_read; - } + if (!tl->table->stats_is_read) + dump_stats_from_share_to_table(tl->table); + tl->table->histograms_are_read= + table_share->stats_cb.histograms_are_ready(); + if (table_share->stats_cb.histograms_are_ready() || + thd->variables.optimizer_use_condition_selectivity <= 3) + continue; } + statistics_for_tables_is_needed= true; } + else if (is_stat_table(&tl->db, &tl->alias)) + found_stat_table= true; } } DEBUG_SYNC(thd, "statistics_read_start"); - if (!statistics_for_tables_is_needed(thd, tables)) + /* + Do not read statistics for any query that explicity involves + statistical tables, failure to to do so we may end up + in a deadlock. + */ + if (found_stat_table || !statistics_for_tables_is_needed) DBUG_RETURN(0); - if (open_stat_tables(thd, stat_tables, &open_tables_backup, FALSE)) + start_new_trans new_trans(thd); + + if (open_stat_tables(thd, stat_tables, FALSE)) DBUG_RETURN(1); for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { - if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) - { - TABLE_SHARE *table_share= tl->table->s; - if (table_share && !(table_share->table_category == TABLE_CATEGORY_USER)) - continue; - - if (table_share && - table_share->stats_cb.stats_can_be_read && - !table_share->stats_cb.stats_is_read) + TABLE_SHARE *table_share; + if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) && + table_share->tmp_table == NO_TMP_TABLE && + table_share->table_category == TABLE_CATEGORY_USER) + { + if (!tl->table->stats_is_read) { - (void) read_statistics_for_table(thd, tl->table, stat_tables); - table_share->stats_cb.stats_is_read= TRUE; + if (!read_statistics_for_table(thd, tl->table, stat_tables)) + dump_stats_from_share_to_table(tl->table); + else + continue; } - if (table_share->stats_cb.stats_is_read) - tl->table->stats_is_read= TRUE; - if (thd->variables.optimizer_use_condition_selectivity > 3 && - table_share && table_share->stats_cb.stats_can_be_read && - !table_share->stats_cb.histograms_are_read) - { + if (thd->variables.optimizer_use_condition_selectivity > 3) (void) read_histograms_for_table(thd, tl->table, stat_tables); - table_share->stats_cb.histograms_are_read= TRUE; - } - if (table_share->stats_cb.histograms_are_read) - tl->table->histograms_are_read= TRUE; } - } + } - close_system_tables(thd, &open_tables_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_RETURN(0); } @@ -3403,8 +3276,10 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, Open_tables_backup open_tables_backup; int rc= 0; DBUG_ENTER("delete_statistics_for_table"); + + start_new_trans new_trans(thd); - if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) + if (open_stat_tables(thd, tables, TRUE)) DBUG_RETURN(0); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3447,8 +3322,8 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, rc= 1; thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3480,12 +3355,12 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) enum_binlog_format save_binlog_format; TABLE *stat_table; TABLE_LIST tables; - Open_tables_backup open_tables_backup; int rc= 0; DBUG_ENTER("delete_statistics_for_column"); - if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1], - &open_tables_backup)) + start_new_trans new_trans(thd); + + if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1])) DBUG_RETURN(0); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3501,8 +3376,9 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) } thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + if (thd->commit_whole_transaction_and_close_tables()) + rc= 1; + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3537,12 +3413,12 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, enum_binlog_format save_binlog_format; TABLE *stat_table; TABLE_LIST tables; - Open_tables_backup open_tables_backup; int rc= 0; DBUG_ENTER("delete_statistics_for_index"); - if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[2], - &open_tables_backup)) + start_new_trans new_trans(thd); + + if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[2])) DBUG_RETURN(0); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3578,8 +3454,9 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, rc= 1; thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + if (thd->commit_whole_transaction_and_close_tables()) + rc= 1; + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3621,14 +3498,13 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, enum_binlog_format save_binlog_format; TABLE *stat_table; TABLE_LIST tables[STATISTICS_TABLES]; - Open_tables_backup open_tables_backup; int rc= 0; DBUG_ENTER("rename_table_in_stat_tables"); - if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) - { + start_new_trans new_trans(thd); + + if (open_stat_tables(thd, tables, TRUE)) DBUG_RETURN(0); // not an error - } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3677,8 +3553,9 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, } thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + if (thd->commit_whole_transaction_and_close_tables()) + rc= 1; + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } @@ -3711,15 +3588,15 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, enum_binlog_format save_binlog_format; TABLE *stat_table; TABLE_LIST tables; - Open_tables_backup open_tables_backup; int rc= 0; DBUG_ENTER("rename_column_in_stat_tables"); if (tab->s->tmp_table != NO_TMP_TABLE) DBUG_RETURN(0); - if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1], - &open_tables_backup)) + start_new_trans new_trans(thd); + + if (open_stat_table_for_ddl(thd, &tables, &stat_table_name[1])) DBUG_RETURN(rc); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3736,8 +3613,9 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, } thd->restore_stmt_binlog_format(save_binlog_format); - - close_system_tables(thd, &open_tables_backup); + if (thd->commit_whole_transaction_and_close_tables()) + rc= 1; + new_trans.restore_old_transaction(); DBUG_RETURN(rc); } diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 5fc9d7b5c75..b90c614b74f 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -295,7 +295,6 @@ public: Column_statistics *column_stats; /* Array of statistical data for columns */ Index_statistics *index_stats; /* Array of statistical data for indexes */ ulong *idx_avg_frequency; /* Array of records per key for index prefixes */ - ulong total_hist_size; /* Total size of all histograms */ uchar *histograms; /* Sequence of histograms */ }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index afc397850d4..f091fd29303 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -75,6 +75,9 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *, ha_rows *, ha_rows *, Alter_info::enum_enable_or_disable, Alter_table_ctx *); +static bool append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info, + Alter_info *alter_info, KEY **key_info, + uint key_count); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, uint *, handler *, KEY **, uint *, int); static uint blob_length_by_type(enum_field_types type); @@ -1104,7 +1107,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) LEX_CSTRING handler_name; handler *file= NULL; MEM_ROOT mem_root; - int error= TRUE; + int error= 1; char to_path[FN_REFLEN]; char from_path[FN_REFLEN]; handlerton *hton; @@ -1154,28 +1157,27 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) { strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); if (unlikely((error= mysql_file_delete(key_file_frm, to_path, - MYF(MY_WME))))) - { - if (my_errno != ENOENT) - break; - } + MYF(MY_WME | + MY_IGNORE_ENOENT))))) + break; #ifdef WITH_PARTITION_STORAGE_ENGINE strxmov(to_path, ddl_log_entry->name, PAR_EXT, NullS); - (void) mysql_file_delete(key_file_partition_ddl_log, to_path, MYF(MY_WME)); + (void) mysql_file_delete(key_file_partition_ddl_log, to_path, + MYF(0)); #endif } else { if (unlikely((error= file->ha_delete_table(ddl_log_entry->name)))) { - if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE) + if (!non_existing_table_error(error)) break; } } if ((deactivate_ddl_log_entry_no_lock(ddl_log_entry->entry_pos))) break; (void) sync_ddl_log_no_lock(); - error= FALSE; + error= 0; if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION) break; } @@ -1821,6 +1823,10 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) strxmov(shadow_frm_name, shadow_path, reg_ext, NullS); if (flags & WFRM_WRITE_SHADOW) { + if (append_system_key_parts(lpt->thd, lpt->create_info, lpt->alter_info, + &lpt->key_info_buffer, 0)) + DBUG_RETURN(true); + if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info, &lpt->db_options, lpt->table->file, &lpt->key_info_buffer, &lpt->key_count, @@ -2230,11 +2236,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, bool dont_free_locks) { TABLE_LIST *table; - char path[FN_REFLEN + 1], wrong_tables_buff[160]; + char path[FN_REFLEN + 1], unknown_tables_buff[160]; LEX_CSTRING alias= null_clex_str; - String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1, + String unknown_tables(unknown_tables_buff, sizeof(unknown_tables_buff)-1, system_charset_info); - uint path_length= 0, errors= 0; + uint not_found_errors= 0; int error= 0; int non_temp_tables_count= 0; bool non_tmp_error= 0; @@ -2247,7 +2253,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, String built_trans_tmp_query, built_non_trans_tmp_query; DBUG_ENTER("mysql_rm_table_no_locks"); - wrong_tables.length(0); + unknown_tables.length(0); /* Prepares the drop statements that will be written into the binary log as follows: @@ -2301,11 +2307,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, for (table= tables; table; table= table->next_local) { - bool is_trans= 0; - bool table_creation_was_logged= 0; + bool is_trans= 0, frm_was_deleted= 0, temporary_table_was_dropped= 0; + bool table_creation_was_logged= 0, trigger_drop_executed= 0; + bool local_non_tmp_error= 0, frm_exists= 0, wrong_drop_sequence= 0; + bool table_dropped= 0; LEX_CSTRING db= table->db; handlerton *table_type= 0; + size_t path_length= 0; + char *path_end= 0; + error= 0; DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", table->db.str, table->table_name.str, table->table, table->table ? table->table->s : NULL)); @@ -2320,36 +2331,42 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, thd->find_temporary_table(table) && table->mdl_request.ticket != NULL)); - if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || - (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) - error= 1; - else + /* First try to delete temporary tables and temporary sequences */ + if ((table->open_type != OT_BASE_ONLY && is_temporary_table(table)) && + (!drop_sequence || table->table->s->table_type == TABLE_TYPE_SEQUENCE)) { table_creation_was_logged= table->table->s->table_creation_was_logged; if (thd->drop_temporary_table(table->table, &is_trans, true)) { + /* + This is a very unlikely scenaro as dropping a temporary table + should always work. Would be better if we tried to drop all + temporary tables before giving the error. + */ error= 1; goto err; } - error= 0; table->table= 0; + temporary_table_was_dropped= 1; } - if ((drop_temporary && if_exists) || !error) + if ((drop_temporary && if_exists) || temporary_table_was_dropped) { /* This handles the case of temporary tables. We have the following cases: - . "DROP TEMPORARY" was executed and a temporary table was affected - (i.e. drop_temporary && !error) or the if_exists was specified (i.e. - drop_temporary && if_exists). - - . "DROP" was executed but a temporary table was affected (.i.e - !error). + - "DROP TEMPORARY" was executed and table was dropped + temporary_table_was_dropped == 1 + - "DROP TEMPORARY IF EXISTS" was specified but no temporary table + existed + temporary_table_was_dropped == 0 */ if (!dont_log_query && table_creation_was_logged) { /* + DROP TEMPORARY succeded. For the moment when we only come + here on success (error == 0) + If there is an error, we don't know the type of the engine at this point. So, we keep it in the trx-cache. */ @@ -2380,7 +2397,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, is no need to proceed with the code that tries to drop a regular table. */ - if (!error) continue; + if (temporary_table_was_dropped) + continue; } else if (!drop_temporary) { @@ -2394,55 +2412,37 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, /* remove .frm file and engine files */ path_length= build_table_filename(path, sizeof(path) - 1, db.str, alias.str, reg_ext, 0); + path_end= path + path_length - reg_ext_length; } + DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); error= 0; - if (drop_temporary || - (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && - table_type == 0) || - (!drop_view && (was_view= (table_type == view_pseudo_hton))) || - (drop_sequence && !is_sequence)) + if (drop_temporary) + { + /* "DROP TEMPORARY" but a temporary table was not found */ + error= ENOENT; + } + else if (((frm_exists= ha_table_exists(thd, &db, &alias, &table_type, + &is_sequence)) == 0 && + table_type == 0) || + (!drop_view && (was_view= (table_type == view_pseudo_hton))) || + (drop_sequence && !is_sequence)) { /* One of the following cases happened: - . "DROP TEMPORARY" but a temporary table was not found. . "DROP" but table was not found . "DROP TABLE" statement, but it's a view. . "DROP SEQUENCE", but it's not a sequence */ - was_table= drop_sequence && table_type; - if (if_exists) - { - char buff[FN_REFLEN]; - int err= (drop_sequence ? ER_UNKNOWN_SEQUENCES : - ER_BAD_TABLE_ERROR); - String tbl_name(buff, sizeof(buff), system_charset_info); - tbl_name.length(0); - tbl_name.append(&db); - tbl_name.append('.'); - tbl_name.append(&table->table_name); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - err, ER_THD(thd, err), - tbl_name.c_ptr_safe()); - - /* - Our job is done here. This statement was added to avoid executing - unnecessary code farther below which in some strange corner cases - caused the server to crash (see MDEV-17896). - */ - goto log_query; - } - else - { - non_tmp_error = (drop_temporary ? non_tmp_error : TRUE); - error= 1; - } + wrong_drop_sequence= drop_sequence && table_type; + was_table|= wrong_drop_sequence; + local_non_tmp_error= 1; + error= -1; + if ((!frm_exists && !table_type)) // no .frm + error= ENOENT; } else { - char *end; - int frm_delete_error= 0; - #ifdef WITH_WSREP if (WSREP(thd) && !wsrep_should_replicate_ddl(thd, table_type->db_type)) @@ -2486,15 +2486,21 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, MDL_EXCLUSIVE)); // Remove extension for delete - *(end= path + path_length - reg_ext_length)= '\0'; + *path_end= '\0'; if (table_type && table_type != view_pseudo_hton && table_type->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE) log_if_exists= 1; thd->replication_flags= 0; - if ((error= ha_delete_table(thd, table_type, path, &db, - &table->table_name, !dont_log_query))) + error= ha_delete_table(thd, table_type, path, &db, + &table->table_name, !dont_log_query); + + if (!error) + table_dropped= 1; + else if (error < 0) + error= 0; // Table didn't exists + else if (error) { if (thd->is_killed()) { @@ -2502,70 +2508,173 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, goto err; } } - else + /* This may be set by the storage engine in handler::delete_table() */ + if (thd->replication_flags & OPTION_IF_EXISTS) + log_if_exists= 1; + + /* + Delete the .frm file if we managed to delete the table from the + engine or the table didn't exists in the engine + */ + strmov(path_end, reg_ext); + if ((likely(!error) || non_existing_table_error(error)) && + !access(path, F_OK)) { + int frm_delete_error= 0; /* Delete the table definition file */ - strmov(end,reg_ext); if (table_type && table_type != view_pseudo_hton && - table_type->discover_table) + (table_type->discover_table || error)) { /* - Table type is using discovery and may not need a .frm file. + Table type is using discovery and may not need a .frm file + or the .frm file existed but no table in engine. Delete it silently if it exists */ - (void) mysql_file_delete(key_file_frm, path, MYF(0)); + if (mysql_file_delete(key_file_frm, path, + MYF(MY_WME | MY_IGNORE_ENOENT))) + frm_delete_error= my_errno; } else if (unlikely(mysql_file_delete(key_file_frm, path, - MYF(MY_WME)))) + !error ? MYF(MY_WME) : + MYF(MY_WME | MY_IGNORE_ENOENT)))) { frm_delete_error= my_errno; DBUG_ASSERT(frm_delete_error); } - } - if (thd->replication_flags & OPTION_IF_EXISTS) - log_if_exists= 1; + frm_was_deleted= 1; // We tried to delete .frm - if (likely(!error)) - { - int trigger_drop_error= 0; - - if (likely(!frm_delete_error)) + if (frm_delete_error) { - non_tmp_table_deleted= TRUE; - trigger_drop_error= - Table_triggers_list::drop_all_triggers(thd, &db, - &table->table_name); + /* Remember unexpected error from dropping the .frm file */ + error= frm_delete_error; + } + else + { + error= 0; // We succeeded to delete the frm + table_dropped= 1; } - - if (unlikely(trigger_drop_error) || - (frm_delete_error && frm_delete_error != ENOENT)) - error= 1; - else if (frm_delete_error && if_exists) - thd->clear_error(); } - non_tmp_error|= MY_TEST(error); + if (likely(!error) || non_existing_table_error(error)) + { + trigger_drop_executed= 1; + + if (Table_triggers_list::drop_all_triggers(thd, &db, + &table->table_name, + MYF(MY_WME | + MY_IGNORE_ENOENT))) + error= error ? error : -1; + } + local_non_tmp_error|= MY_TEST(error); + } + + /* + If there was no .frm file and the table is not temporary, + scan all engines try to drop the table from there. + This is to ensure we don't have any partial table files left. + + We check for trigger_drop_executed to ensure we don't again try + to drop triggers when it failed above (after sucecssfully dropping + the table). + */ + if (non_existing_table_error(error) && !drop_temporary && + table_type != view_pseudo_hton && !trigger_drop_executed && + !wrong_drop_sequence) + { + int ferror= 0; + + /* Remove extension for delete */ + *path_end= '\0'; + ferror= ha_delete_table_force(thd, path, &db, &table->table_name); + if (!ferror) + { + /* Table existed and was deleted */ + local_non_tmp_error= 0; + table_dropped= 1; + error= 0; + } + if (ferror <= 0) + { + ferror= 0; // Ignore table not found + + /* Delete the table definition file */ + if (!frm_was_deleted) + { + strmov(path_end, reg_ext); + if (mysql_file_delete(key_file_frm, path, + MYF(MY_WME | MY_IGNORE_ENOENT))) + ferror= my_errno; + } + if (Table_triggers_list::drop_all_triggers(thd, &db, + &table->table_name, + MYF(MY_WME | + MY_IGNORE_ENOENT))) + ferror= -1; + } + if (!error) + error= ferror; } if (error) { - if (wrong_tables.length()) - wrong_tables.append(','); - wrong_tables.append(&db); - wrong_tables.append('.'); - wrong_tables.append(&table->table_name); - errors++; + char buff[FN_REFLEN]; + String tbl_name(buff, sizeof(buff), system_charset_info); + uint is_note= (if_exists && (was_view || wrong_drop_sequence) ? + ME_NOTE : 0); + + tbl_name.length(0); + tbl_name.append(&db); + tbl_name.append('.'); + tbl_name.append(&table->table_name); + + if (!non_existing_table_error(error) || is_note) + { + /* + Error from engine already given. Here we only have to take + care about errors for trying to drop view or sequence + */ + if (was_view) + my_error(ER_IT_IS_A_VIEW, MYF(is_note), tbl_name.c_ptr_safe()); + else if (wrong_drop_sequence) + my_error(ER_NOT_SEQUENCE2, MYF(is_note), tbl_name.c_ptr_safe()); + if (is_note) + error= ENOENT; + } + else + { + not_found_errors++; + if (unknown_tables.append(tbl_name) || unknown_tables.append(',')) + { + error= 1; + goto err; + } + } } - else + + /* + Don't give an error if we are using IF EXISTS for a table that + didn't exists + */ + if (if_exists && non_existing_table_error(error)) { - PSI_CALL_drop_table_share(false, table->db.str, (uint)table->db.length, - table->table_name.str, (uint)table->table_name.length); + error= 0; + local_non_tmp_error= 0; + } + + non_tmp_error|= local_non_tmp_error; + + if (!error && table_dropped) + { + PSI_CALL_drop_table_share(temporary_table_was_dropped, + table->db.str, (uint)table->db.length, + table->table_name.str, + (uint)table->table_name.length); mysql_audit_drop_table(thd, table); } -log_query: - if (!dont_log_query && !drop_temporary) + if (!dont_log_query && !drop_temporary && + (!error || table_dropped || non_existing_table_error(error))) { - non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted); + non_tmp_table_deleted|= (if_exists || table_dropped); /* Don't write the database name if it is the current one (or if thd->db is NULL). @@ -2585,20 +2694,16 @@ log_query: DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog"); thd->thread_specific_used= TRUE; error= 0; + err: - if (wrong_tables.length()) + if (unknown_tables.length() > 1) { - DBUG_ASSERT(errors); - if (errors == 1 && was_view) - my_error(ER_IT_IS_A_VIEW, MYF(0), wrong_tables.c_ptr_safe()); - else if (errors == 1 && drop_sequence && was_table) - my_error(ER_NOT_SEQUENCE2, MYF(0), wrong_tables.c_ptr_safe()); - else if (errors > 1 || !thd->is_error()) - my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES : - ER_BAD_TABLE_ERROR), - MYF(0), wrong_tables.c_ptr_safe()); - error= 1; + uint is_note= if_exists ? ME_NOTE : 0; + unknown_tables.chop(); + my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES : ER_BAD_TABLE_ERROR), + MYF(is_note), unknown_tables.c_ptr_safe()); } + error= thd->is_error(); /* We are always logging drop of temporary tables. @@ -2616,7 +2721,7 @@ err: trans_tmp_table_deleted || non_tmp_table_deleted) { if (non_trans_tmp_table_deleted || trans_tmp_table_deleted) - thd->transaction.stmt.mark_dropped_temp_table(); + thd->transaction->stmt.mark_dropped_temp_table(); query_cache_invalidate3(thd, tables, 0); if (!dont_log_query && mysql_bin_log.is_open()) @@ -2720,9 +2825,10 @@ err: } end: - DBUG_RETURN(error); + DBUG_RETURN(error || thd->is_error()); } + /** Log the drop of a table. @@ -2802,7 +2908,8 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db, delete file; } if (!(flags & (FRM_ONLY|NO_HA_TABLE))) - error|= ha_delete_table(thd, base, path, db, table_name, 0); + if (ha_delete_table(thd, base, path, db, table_name, 0) > 0) + error= 1; if (likely(error == 0)) { @@ -4214,6 +4321,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY)) unique_key=1; key_info->key_length=(uint16) key_length; + if (key_info->key_length > max_key_length && key->type == Key::UNIQUE) + is_hash_field_needed= true; if (key_length > max_key_length && key->type != Key::FULLTEXT && !is_hash_field_needed) { @@ -4279,11 +4388,35 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_info->without_overlaps= key->without_overlaps; if (key_info->without_overlaps) { - if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) + if (key_info->algorithm == HA_KEY_ALG_HASH || + key_info->algorithm == HA_KEY_ALG_LONG_HASH) + { +without_overlaps_err: my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key_info->name.str); DBUG_RETURN(true); } + key_iterator2.rewind(); + while ((key2 = key_iterator2++)) + { + if (key2->type != Key::FOREIGN_KEY) + continue; + DBUG_ASSERT(key != key2); + Foreign_key *fk= (Foreign_key*) key2; + if (fk->update_opt != FK_OPTION_CASCADE) + continue; + for (Key_part_spec& kp: key->columns) + { + for (Key_part_spec& kp2: fk->columns) + { + if (!lex_string_cmp(system_charset_info, &kp.field_name, + &kp2.field_name)) + { + goto without_overlaps_err; + } + } + } + } create_info->period_info.unique_keys++; } @@ -4331,6 +4464,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && + !sql_field->vers_sys_field() && sql_field->is_timestamp_type() && !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && @@ -4371,7 +4505,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, while ((check= c_it++)) { if (!check->name.length || check->automatic_name) + { + if (check_expression(check, &check->name, VCOL_CHECK_TABLE, alter_info)) + DBUG_RETURN(TRUE); continue; + } { /* Check that there's no repeating table CHECK constraint names. */ @@ -4470,6 +4608,21 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, Well_formed_prefix(system_charset_info, *comment, max_len).length(); if (tmp_len < comment->length) { + if (comment->length <= max_len) + { + if (thd->is_strict_mode()) + { + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + system_charset_info->csname, comment->str); + DBUG_RETURN(true); + } + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_INVALID_CHARACTER_STRING, + ER_THD(thd, ER_INVALID_CHARACTER_STRING), + system_charset_info->csname, comment->str); + comment->length= tmp_len; + DBUG_RETURN(false); + } if (thd->is_strict_mode()) { my_error(err_code, MYF(0), name, static_cast(max_len)); @@ -5002,7 +5155,8 @@ int create_table_impl(THD *thd, const LEX_CSTRING &orig_db, If a table exists, it must have been pre-opened. Try looking for one in-use in THD::all_temp_tables list of TABLE_SHAREs. */ - TABLE *tmp_table= thd->find_temporary_table(db.str, table_name.str); + TABLE *tmp_table= thd->find_temporary_table(db.str, table_name.str, + THD::TMP_TABLE_ANY); if (tmp_table) { @@ -5391,7 +5545,7 @@ err: } if (create_info->tmp_table()) - thd->transaction.stmt.mark_created_temp_table(); + thd->transaction->stmt.mark_created_temp_table(); /* Write log if no error or if we already deleted a table */ if (likely(!result) || thd->log_current_statement) @@ -5511,7 +5665,7 @@ static bool make_unique_constraint_name(THD *thd, LEX_CSTRING *name, if (!check) // Found unique name { name->length= (size_t) (real_end - buff); - name->str= thd->strmake(buff, name->length); + name->str= strmake_root(thd->stmt_arena->mem_root, buff, name->length); return (name->str == NULL); } } @@ -6009,7 +6163,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, res, create_info->tmp_table(), local_create_info.table)); if (create_info->tmp_table()) { - thd->transaction.stmt.mark_created_temp_table(); + thd->transaction->stmt.mark_created_temp_table(); if (!res && local_create_info.table) { /* @@ -6639,7 +6793,7 @@ remove_key: while ((check=it++)) { - if (!(check->flags & Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS) && + if (!(check->flags & VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS) && check->name.length) continue; check->flags= 0; @@ -8056,16 +8210,13 @@ blob_length_by_type(enum_field_types type) } -static void append_drop_column(THD *thd, bool dont, String *str, - Field *field) +static inline +void append_drop_column(THD *thd, String *str, Field *field) { - if (!dont) - { - if (str->length()) - str->append(STRING_WITH_LEN(", ")); - str->append(STRING_WITH_LEN("DROP COLUMN ")); - append_identifier(thd, str, &field->field_name); - } + if (str->length()) + str->append(STRING_WITH_LEN(", ")); + str->append(STRING_WITH_LEN("DROP COLUMN ")); + append_identifier(thd, str, &field->field_name); } @@ -8310,7 +8461,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->invisible < INVISIBLE_SYSTEM) { StringBuffer tmp; - append_drop_column(thd, false, &tmp, field); + append_drop_column(thd, &tmp, field); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8406,7 +8557,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->default_value->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); } - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } dropped_sys_vers_fields &= VERS_SYSTEM_FIELD; @@ -8416,10 +8568,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, !vers_system_invisible) { StringBuffer tmp; - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_START_FLAG, - &tmp, table->vers_start_field()); - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_END_FLAG, - &tmp, table->vers_end_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_START_FLAG)) + append_drop_column(thd, &tmp, table->vers_start_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_END_FLAG)) + append_drop_column(thd, &tmp, table->vers_end_field()); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8905,7 +9057,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { check->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } new_constraint_list.push_back(check, thd->mem_root); } @@ -9691,11 +9844,16 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, (!create_info->db_type || /* unknown engine */ !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) { + unsupported: my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0), hton_name(create_info->db_type)->str); DBUG_RETURN(true); } + if (create_info->db_type == maria_hton && + create_info->transactional != HA_CHOICE_NO) + goto unsupported; + #ifdef WITH_PARTITION_STORAGE_ENGINE if (alter_info->partition_flags & ALTER_PARTITION_INFO) { @@ -10055,7 +10213,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, { if ((table->key_info[n_key].flags & HA_NOSAME) && my_strcasecmp(system_charset_info, - drop->name, table->key_info[n_key].name.str) == 0) // Merge todo: review '.str' + drop->name, table->key_info[n_key].name.str) == 0) { drop->type= Alter_drop::KEY; alter_info->flags|= ALTER_DROP_INDEX; @@ -10555,11 +10713,10 @@ do_continue:; if ((table->file->partition_ht()->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE) && (table->file->partition_ht() != new_table->file->partition_ht()) && - (mysql_bin_log.is_open() && - (thd->variables.option_bits & OPTION_BIN_LOG))) + thd->binlog_table_should_be_logged(&new_table->s->db)) { /* - We new_table is marked as internal temp table, but we want to have + 'new_table' is marked as internal temp table, but we want to have the logging based on the original table type */ bool res; @@ -10568,9 +10725,11 @@ do_continue:; /* Force row logging, even if the table was created as 'temporary' */ new_table->s->can_do_row_logging= 1; - thd->binlog_start_trans_and_stmt(); - res= binlog_drop_table(thd, table) || binlog_create_table(thd, new_table); + thd->variables.option_bits|= OPTION_BIN_COMMIT_OFF; + res= (binlog_drop_table(thd, table) || + binlog_create_table(thd, new_table, 1)); + thd->variables.option_bits&= ~OPTION_BIN_COMMIT_OFF; new_table->s->tmp_table= org_tmp_table; if (res) goto err_new_table_cleanup; @@ -10931,7 +11090,7 @@ bool mysql_trans_commit_alter_copy_data(THD *thd) DBUG_ENTER("mysql_trans_commit_alter_copy_data"); /* Save flags as trans_commit_implicit are deleting them */ - save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags; + save_unsafe_rollback_flags= thd->transaction->stmt.m_unsafe_rollback_flags; DEBUG_SYNC(thd, "alter_table_copy_trans_commit"); @@ -10949,7 +11108,7 @@ bool mysql_trans_commit_alter_copy_data(THD *thd) if (trans_commit_implicit(thd)) error= TRUE; - thd->transaction.stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags; + thd->transaction->stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags; DBUG_RETURN(error); } @@ -10976,6 +11135,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, sql_mode_t save_sql_mode= thd->variables.sql_mode; ulonglong prev_insert_id, time_to_report_progress; Field **dfield_ptr= to->default_field; + uint save_to_s_default_fields= to->s->default_fields; bool make_versioned= !from->versioned() && to->versioned(); bool make_unversioned= from->versioned() && !to->versioned(); bool keep_versioned= from->versioned() && to->versioned(); @@ -11309,6 +11469,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, *copied= found_count; *deleted=delete_count; to->file->ha_release_auto_increment(); + to->s->default_fields= save_to_s_default_fields; if (!cleanup_done) { diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 726ba6d3cf2..677e6cfa510 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -558,7 +558,11 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* Later on we will need it to downgrade the lock */ mdl_ticket= table->mdl_ticket; - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + /* + RENAME ensures that table is flushed properly and locked tables will + be removed from the active transaction + */ + if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) goto end; lock_upgrade_done= TRUE; @@ -590,10 +594,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) table->triggers->create_trigger(thd, tables, &stmt_query): table->triggers->drop_trigger(thd, tables, &stmt_query)); - if (result) - goto end; - close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED, NULL); + /* Reopen the table if we were under LOCK TABLES. Ignore the return value for now. It's better to @@ -1031,10 +1033,10 @@ bool Trigger::add_to_file_list(void* param_arg) */ static bool rm_trigger_file(char *path, const LEX_CSTRING *db, - const LEX_CSTRING *table_name) + const LEX_CSTRING *table_name, myf MyFlags) { build_table_filename(path, FN_REFLEN-1, db->str, table_name->str, TRG_EXT, 0); - return mysql_file_delete(key_file_trg, path, MYF(MY_WME)); + return mysql_file_delete(key_file_trg, path, MyFlags); } @@ -1053,10 +1055,11 @@ static bool rm_trigger_file(char *path, const LEX_CSTRING *db, */ static bool rm_trigname_file(char *path, const LEX_CSTRING *db, - const LEX_CSTRING *trigger_name) + const LEX_CSTRING *trigger_name, myf MyFlags) { - build_table_filename(path, FN_REFLEN - 1, db->str, trigger_name->str, TRN_EXT, 0); - return mysql_file_delete(key_file_trn, path, MYF(MY_WME)); + build_table_filename(path, FN_REFLEN - 1, db->str, trigger_name->str, + TRN_EXT, 0); + return mysql_file_delete(key_file_trn, path, MyFlags); } @@ -1174,7 +1177,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, parse_file.cc functionality (because we will need it elsewhere). */ - if (rm_trigger_file(path, &tables->db, &tables->table_name)) + if (rm_trigger_file(path, &tables->db, &tables->table_name, MYF(MY_WME))) return 1; } else @@ -1183,7 +1186,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, return 1; } - if (rm_trigname_file(path, &tables->db, sp_name)) + if (rm_trigname_file(path, &tables->db, sp_name, MYF(MY_WME))) return 1; delete trigger; @@ -1324,9 +1327,9 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) This could be avoided if there is no triggers for UPDATE and DELETE. @retval - False success + False no triggers or triggers where correctly loaded @retval - True error + True error (wrong trigger file) */ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, @@ -1640,7 +1643,7 @@ err_with_lex_cleanup: } error: - if (unlikely(!thd->is_error())) + if (unlikely(!thd->is_error())) { /* We don't care about this error message much because .TRG files will @@ -1817,7 +1820,8 @@ bool add_table_for_trigger(THD *thd, */ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, - const LEX_CSTRING *name) + const LEX_CSTRING *name, + myf MyFlags) { TABLE table; char path[FN_REFLEN]; @@ -1826,11 +1830,13 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, table.reset(); init_sql_alloc(key_memory_Table_trigger_dispatcher, - &table.mem_root, 8192, 0, MYF(0)); + &table.mem_root, 8192, 0, MYF(MY_WME)); if (Table_triggers_list::check_n_load(thd, db, name, &table, 1)) { result= 1; + /* We couldn't parse trigger file, best to just remove it */ + rm_trigger_file(path, db, name, MyFlags); goto end; } if (table.triggers) @@ -1850,7 +1856,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, Such triggers have zero-length name and are skipped here. */ if (trigger->name.length && - rm_trigname_file(path, db, &trigger->name)) + rm_trigname_file(path, db, &trigger->name, MyFlags)) { /* Instead of immediately bailing out with error if we were unable @@ -1864,7 +1870,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, } } } - if (rm_trigger_file(path, db, name)) + if (rm_trigger_file(path, db, name, MyFlags)) result= 1; delete table.triggers; } @@ -1925,9 +1931,10 @@ change_table_name_in_triggers(THD *thd, if (save_trigger_file(thd, new_db_name, new_table_name)) return TRUE; - if (rm_trigger_file(path_buff, old_db_name, old_table_name)) + if (rm_trigger_file(path_buff, old_db_name, old_table_name, MYF(MY_WME))) { - (void) rm_trigger_file(path_buff, new_db_name, new_table_name); + (void) rm_trigger_file(path_buff, new_db_name, new_table_name, + MYF(MY_WME)); return TRUE; } return FALSE; @@ -2036,9 +2043,11 @@ bool Trigger::change_on_table_name(void* param_arg) /* Remove stale .TRN file in case of database upgrade */ if (param->old_db_name) { - if (rm_trigname_file(trigname_buff, param->old_db_name, &name)) + if (rm_trigname_file(trigname_buff, param->old_db_name, &name, + MYF(MY_WME))) { - (void) rm_trigname_file(trigname_buff, param->new_db_name, &name); + (void) rm_trigname_file(trigname_buff, param->new_db_name, &name, + MYF(MY_WME)); return 1; } } diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index ae3d1738b16..040d8eba989 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -231,7 +231,7 @@ public: static bool check_n_load(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, TABLE *table, bool names_only); static bool drop_all_triggers(THD *thd, const LEX_CSTRING *db, - const LEX_CSTRING *table_name); + const LEX_CSTRING *table_name, myf MyFlags); static bool change_table_name(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *old_alias, const LEX_CSTRING *old_table, diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index a745293ec31..8ed996c0a8d 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -246,7 +246,7 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref, inspite of errors. */ if (error == HA_ERR_WRONG_COMMAND || - table_ref->table->file->has_transactions()) + table_ref->table->file->has_transactions_and_rollback()) DBUG_RETURN(TRUNCATE_FAILED_SKIP_BINLOG); else DBUG_RETURN(TRUNCATE_FAILED_BUT_BINLOG); diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 678dd81709e..37f0f80e8a0 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -23,6 +23,36 @@ #include "sql_parse.h" #include "sql_cte.h" + +/** + @brief + Walk through all VALUES items. + @param + @param processor - the processor to call for each Item + @param walk_qubquery - if should dive into subquery items + @param argument - the argument to pass recursively + @retval + true on error + false on success +*/ +bool table_value_constr::walk_values(Item_processor processor, + bool walk_subquery, + void *argument) +{ + List_iterator_fast list_item_it(lists_of_values); + while (List_item *list= list_item_it++) + { + List_iterator_fast item_it(*list); + while (Item *item= item_it++) + { + if (item->walk(&Item::unknown_splocal_processor, false, argument)) + return true; + } + } + return false; +} + + /** @brief Fix fields for TVC values @@ -52,7 +82,15 @@ bool fix_fields_for_tvc(THD *thd, List_iterator_fast &li) while ((item= it++)) { - if (item->fix_fields(thd, 0)) + /* + Some items have already been fixed. + For example Item_splocal items get fixed in + Item_splocal::append_for_log(), which is called from subst_spvars() + while replacing their values to NAME_CONST()s. + So fix only those that have not been. + */ + if (item->fix_fields_if_needed(thd, 0) || + item->check_is_evaluable_expression_or_error()) DBUG_RETURN(true); } } diff --git a/sql/sql_tvc.h b/sql/sql_tvc.h index 594a77af65c..b5b8b979f43 100644 --- a/sql/sql_tvc.h +++ b/sql/sql_tvc.h @@ -18,6 +18,7 @@ #include "sql_type.h" typedef List List_item; +typedef bool (Item::*Item_processor) (void *arg); class select_result; class Explain_select; class Explain_query; @@ -65,6 +66,7 @@ public: bool exec(SELECT_LEX *sl); void print(THD *thd_arg, String *str, enum_query_type query_type); + bool walk_values(Item_processor processor, bool walk_subquery, void *arg); }; st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index cbf620e85d1..aee9b4c165c 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2015,2020 MariaDB + Copyright (c) 2015, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -6540,7 +6540,7 @@ bool Type_handler_decimal_result:: bool Type_handler_temporal_result:: Item_func_plus_fix_length_and_dec(Item_func_plus *item) const { - item->fix_length_and_dec_temporal(); + item->fix_length_and_dec_temporal(true); return false; } @@ -6589,7 +6589,7 @@ bool Type_handler_decimal_result:: bool Type_handler_temporal_result:: Item_func_minus_fix_length_and_dec(Item_func_minus *item) const { - item->fix_length_and_dec_temporal(); + item->fix_length_and_dec_temporal(true); return false; } @@ -6638,7 +6638,7 @@ bool Type_handler_decimal_result:: bool Type_handler_temporal_result:: Item_func_mul_fix_length_and_dec(Item_func_mul *item) const { - item->fix_length_and_dec_temporal(); + item->fix_length_and_dec_temporal(true); return false; } @@ -6687,7 +6687,7 @@ bool Type_handler_decimal_result:: bool Type_handler_temporal_result:: Item_func_div_fix_length_and_dec(Item_func_div *item) const { - item->fix_length_and_dec_temporal(); + item->fix_length_and_dec_temporal(false); return false; } @@ -6736,7 +6736,7 @@ bool Type_handler_decimal_result:: bool Type_handler_temporal_result:: Item_func_mod_fix_length_and_dec(Item_func_mod *item) const { - item->fix_length_and_dec_temporal(); + item->fix_length_and_dec_temporal(true); return false; } @@ -8994,6 +8994,11 @@ bool Type_handler::partition_field_append_value( } +bool Type_handler::can_return_extract_source(interval_type int_type) const +{ + return type_collection() == &type_collection_std; +} + /***************************************************************************/ LEX_CSTRING Charset::collation_specific_name() const diff --git a/sql/sql_type.h b/sql/sql_type.h index c3a6a5f4ff5..0850d08c5ae 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -338,6 +338,10 @@ public: double to_double() const { return m_ptr ? m_ptr->to_double() : 0.0; } longlong to_longlong(bool unsigned_flag) { return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; } + Longlong_null to_xlonglong_null() + { + return m_ptr ? Longlong_null(m_ptr->to_xlonglong()) : Longlong_null(); + } bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; } String *to_string(String *to) const { @@ -3616,6 +3620,7 @@ public: virtual bool can_return_text() const { return true; } virtual bool can_return_date() const { return true; } virtual bool can_return_time() const { return true; } + virtual bool can_return_extract_source(interval_type type) const; virtual bool is_bool_type() const { return false; } virtual bool is_general_purpose_string_type() const { return false; } virtual uint Item_time_precision(THD *thd, Item *item) const; diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h index d3e9d0318cf..9fd4f0c46a0 100644 --- a/sql/sql_type_int.h +++ b/sql/sql_type_int.h @@ -16,6 +16,8 @@ #ifndef SQL_TYPE_INT_INCLUDED #define SQL_TYPE_INT_INCLUDED +#include "my_bit.h" // my_count_bits() + class Null_flag { @@ -43,6 +45,58 @@ public: Longlong_null(longlong nr, bool is_null) :Longlong(nr), Null_flag(is_null) { } + explicit Longlong_null() + :Longlong(0), Null_flag(true) + { } + explicit Longlong_null(longlong nr) + :Longlong(nr), Null_flag(false) + { } + Longlong_null operator|(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null(value() | other.value()); + } + Longlong_null operator&(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null(value() & other.value()); + } + Longlong_null operator^(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null((longlong) (value() ^ other.value())); + } + Longlong_null operator~() const + { + if (is_null()) + return *this; + return Longlong_null((longlong) ~ (ulonglong) value()); + } + Longlong_null operator<<(const Longlong_null &llshift) const + { + if (is_null() || llshift.is_null()) + return Longlong_null(); + uint shift= (uint) llshift.value(); + ulonglong res= ((ulonglong) value()) << shift; + return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0); + } + Longlong_null operator>>(const Longlong_null &llshift) const + { + if (is_null() || llshift.is_null()) + return Longlong_null(); + uint shift= (uint) llshift.value(); + ulonglong res= ((ulonglong) value()) >> shift; + return Longlong_null(shift < sizeof(longlong) * 8 ? (longlong) res : 0); + } + Longlong_null bit_count() const + { + if (is_null()) + return *this; + return Longlong_null((longlong) my_count_bits((ulonglong) value())); + } }; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 4da85de7852..5df9e7dd47d 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -268,7 +268,9 @@ void udf_init() if (unlikely(error > 0)) sql_print_error("Got unknown error: %d", my_errno); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + + // Force close to free memory + table->mark_table_for_reopen(); end: close_mysql_tables(new_thd); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index bb2ab527754..3360c3c18cb 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -2712,6 +2712,19 @@ bool st_select_lex::cleanup() delete join; join= 0; } + for (TABLE_LIST *tbl= get_table_list(); tbl; tbl= tbl->next_local) + { + if (tbl->is_recursive_with_table() && + !tbl->is_with_table_recursive_reference()) + { + /* + If query is killed before open_and_process_table() for tbl + is called then 'with' is already set, but 'derived' is not. + */ + st_select_lex_unit *unit= tbl->with->spec; + error|= (bool) error | (uint) unit->cleanup(); + } + } for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; lex_unit= lex_unit->next_unit()) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8e6eb4c815a..fccc2a426c4 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -443,7 +443,7 @@ int mysql_update(THD *thd, /* Calculate "table->covering_keys" based on the WHERE */ table->covering_keys= table->s->keys_in_use; - table->quick_keys.clear_all(); + table->opt_range_keys.clear_all(); query_plan.select_lex= thd->lex->first_select_lex(); query_plan.table= table; @@ -577,7 +577,7 @@ int mysql_update(THD *thd, } /* If running in safe sql mode, don't allow updates without keys */ - if (table->quick_keys.is_clear_all()) + if (table->opt_range_keys.is_clear_all()) { thd->set_status_no_index_used(); if (safe_update && !using_limit) @@ -931,7 +931,7 @@ update_begin: thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; - transactional_table= table->file->has_transactions(); + transactional_table= table->file->has_transactions_and_rollback(); thd->abort_on_warning= !ignore && thd->is_strict_mode(); if (do_direct_update) @@ -1227,7 +1227,7 @@ update_end: table->file->try_semi_consistent_read(0); if (!transactional_table && updated > 0) - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= TRUE; end_read_record(&info); delete select; @@ -1246,10 +1246,10 @@ update_end: query_cache_invalidate3(thd, table_list, 1); } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); /* error < 0 means really no error at all: we processed all rows until the @@ -1260,7 +1260,7 @@ update_end: Sometimes we want to binlog even if we updated no rows, in case user used it to be sure master and slave are in same state. */ - if (likely(error < 0) || thd->transaction.stmt.modified_non_trans_table) + if (likely(error < 0) || thd->transaction->stmt.modified_non_trans_table) { if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) { @@ -1281,7 +1281,7 @@ update_end: } } } - DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table); + DBUG_ASSERT(transactional_table || !updated || thd->transaction->stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); delete file_sort; if (table->file->pushed_cond) @@ -2452,7 +2452,7 @@ multi_update::~multi_update() delete [] copy_field; thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting DBUG_ASSERT(trans_safe || !updated || - thd->transaction.all.modified_non_trans_table); + thd->transaction->all.modified_non_trans_table); } @@ -2572,12 +2572,12 @@ int multi_update::send_data(List ¬_used_values) } /* non-transactional or transactional table got modified */ /* either multi_update class' flag is raised in its branch */ - if (table->file->has_transactions()) + if (table->file->has_transactions_and_rollback()) transactional_tables= TRUE; else { trans_safe= FALSE; - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= TRUE; } } } @@ -2632,7 +2632,7 @@ void multi_update::abort_result_set() { /* the error was handled or nothing deleted and no side effects return */ if (unlikely(error_handled || - (!thd->transaction.stmt.modified_non_trans_table && !updated))) + (!thd->transaction->stmt.modified_non_trans_table && !updated))) return; /* Something already updated so we have to invalidate cache */ @@ -2645,14 +2645,14 @@ void multi_update::abort_result_set() if (! trans_safe) { - DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table); + DBUG_ASSERT(thd->transaction->stmt.modified_non_trans_table); if (do_update && table_count > 1) { /* Add warning here */ (void) do_updates(); } } - if (thd->transaction.stmt.modified_non_trans_table) + if (thd->transaction->stmt.modified_non_trans_table) { /* The query has to binlog because there's a modified non-transactional table @@ -2671,11 +2671,11 @@ void multi_update::abort_result_set() thd->query(), thd->query_length(), transactional_tables, FALSE, FALSE, errcode); } - thd->transaction.all.modified_non_trans_table= TRUE; + thd->transaction->all.modified_non_trans_table= TRUE; } - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); - DBUG_ASSERT(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table); + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + DBUG_ASSERT(trans_safe || !updated || thd->transaction->stmt.modified_non_trans_table); } @@ -2891,12 +2891,12 @@ int multi_update::do_updates() if (updated != org_updated) { - if (table->file->has_transactions()) + if (table->file->has_transactions_and_rollback()) transactional_tables= TRUE; else { trans_safe= FALSE; // Can't do safe rollback - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= TRUE; } } (void) table->file->ha_rnd_end(); @@ -2928,12 +2928,12 @@ err2: if (updated != org_updated) { - if (table->file->has_transactions()) + if (table->file->has_transactions_and_rollback()) transactional_tables= TRUE; else { trans_safe= FALSE; - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction->stmt.modified_non_trans_table= TRUE; } } DBUG_RETURN(1); @@ -2980,13 +2980,13 @@ bool multi_update::send_eof() either from the query's list or via a stored routine: bug#13270,23333 */ - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; - thd->transaction.all.m_unsafe_rollback_flags|= - (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); + if (thd->transaction->stmt.modified_non_trans_table) + thd->transaction->all.modified_non_trans_table= TRUE; + thd->transaction->all.m_unsafe_rollback_flags|= + (thd->transaction->stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT); if (likely(local_error == 0 || - thd->transaction.stmt.modified_non_trans_table)) + thd->transaction->stmt.modified_non_trans_table)) { if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) { @@ -3018,7 +3018,7 @@ bool multi_update::send_eof() } } DBUG_ASSERT(trans_safe || !updated || - thd->transaction.stmt.modified_non_trans_table); + thd->transaction->stmt.modified_non_trans_table); if (likely(local_error != 0)) error_handled= TRUE; // to force early leave from ::abort_result_set() diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 30fadcc63d2..617254244e1 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -432,7 +432,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (check_dependencies_in_with_clauses(lex->with_clauses_list)) { res= TRUE; - goto err; + goto err_no_relink; } WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); @@ -449,16 +449,15 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (thd->open_temporary_tables(lex->query_tables) || open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) { - view= lex->unlink_first_table(&link_to_local); res= TRUE; - goto err; + goto err_no_relink; } #ifdef WITH_WSREP if(!wsrep_should_replicate_ddl_iterate(thd, static_cast(tables))) { res= TRUE; - goto err; + goto err_no_relink; } #endif @@ -723,10 +722,12 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, #ifdef WITH_WSREP wsrep_error_label: res= true; + goto err_no_relink; #endif err: lex->link_first_table_back(view, link_to_local); +err_no_relink: unit->cleanup(); DBUG_RETURN(res || thd->is_error()); } @@ -1809,10 +1810,10 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) char path[FN_REFLEN + 1]; TABLE_LIST *view; String non_existant_views; - const char *wrong_object_db= NULL, *wrong_object_name= NULL; - bool error= FALSE; + bool delete_error= FALSE, wrong_object_name= FALSE; bool some_views_deleted= FALSE; bool something_wrong= FALSE; + uint not_exists_count= 0; DBUG_ENTER("mysql_drop_view"); /* @@ -1842,32 +1843,22 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) char name[FN_REFLEN]; my_snprintf(name, sizeof(name), "%s.%s", view->db.str, view->table_name.str); - if (thd->lex->if_exists()) + if (non_existant_views.length()) + non_existant_views.append(','); + non_existant_views.append(name); + + if (!not_exist) { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_UNKNOWN_VIEW, - ER_THD(thd, ER_UNKNOWN_VIEW), - name); - continue; - } - if (not_exist) - { - if (non_existant_views.length()) - non_existant_views.append(','); - non_existant_views.append(name); + wrong_object_name= 1; + my_error(ER_WRONG_OBJECT, MYF(ME_WARNING), view->db.str, + view->table_name.str, "VIEW"); } else - { - if (!wrong_object_name) - { - wrong_object_db= view->db.str; - wrong_object_name= view->table_name.str; - } - } + not_exists_count++; continue; } if (unlikely(mysql_file_delete(key_file_frm, path, MYF(MY_WME)))) - error= TRUE; + delete_error= TRUE; some_views_deleted= TRUE; @@ -1880,17 +1871,16 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) sp_cache_invalidate(); } - if (unlikely(wrong_object_name)) - { - my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, - "VIEW"); - } + something_wrong= (delete_error || + (!thd->lex->if_exists() && (not_exists_count || + wrong_object_name))); + if (unlikely(non_existant_views.length())) { - my_error(ER_UNKNOWN_VIEW, MYF(0), non_existant_views.c_ptr_safe()); + my_error(ER_UNKNOWN_VIEW, MYF(something_wrong ? 0 : ME_NOTE), + non_existant_views.c_ptr_safe()); } - something_wrong= error || wrong_object_name || non_existant_views.length(); if (some_views_deleted || !something_wrong) { /* if something goes wrong, bin-log with possible error code, diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 9e6ef6468e0..68a783341f3 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -3066,7 +3066,8 @@ bool Window_funcs_sort::setup(THD *thd, SQL_SELECT *sel, */ ORDER *order= (ORDER *)alloc_root(thd->mem_root, sizeof(ORDER)); memset(order, 0, sizeof(*order)); - Item *item= new (thd->mem_root) Item_field(thd, join_tab->table->field[0]); + Item *item= new (thd->mem_root) Item_temptable_field(thd, + join_tab->table->field[0]); order->item= (Item **)alloc_root(thd->mem_root, 2 * sizeof(Item *)); order->item[1]= NULL; order->item[0]= item; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b946b8a9ee0..d8ad3aef7c3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1543,6 +1543,7 @@ End SQL_MODE_ORACLE_SPECIFIC */ admin_option_for_role user_maybe_role %type opt_auth_str auth_expression auth_token + text_or_password %type opt_collate @@ -13047,13 +13048,13 @@ expr_or_default: expr { $$= $1;} | DEFAULT { - $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context()); + $$= new (thd->mem_root) Item_default_specification(thd); if (unlikely($$ == NULL)) MYSQL_YYABORT; } | IGNORE_SYM { - $$= new (thd->mem_root) Item_ignore_value(thd, Lex->current_context()); + $$= new (thd->mem_root) Item_ignore_specification(thd); if (unlikely($$ == NULL)) MYSQL_YYABORT; } @@ -16176,13 +16177,15 @@ set_stmt_option: ident_cli equal set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3))) + if (unlikely(!tmp.str) || + unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $3))) MYSQL_YYABORT; } | ident_cli '.' ident equal set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5))) + if (unlikely(!tmp.str) || + unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $5))) MYSQL_YYABORT; } | DEFAULT '.' ident equal set_expr_or_default @@ -16203,7 +16206,8 @@ option_value_following_option_type: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_system_variable(Lex->option_type, &tmp, $4)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) MYSQL_YYABORT; } @@ -16215,7 +16219,8 @@ option_value_following_option_type: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_system_variable(thd, Lex->option_type, &tmp, &$3, $6)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) MYSQL_YYABORT; } @@ -16242,7 +16247,8 @@ option_value_no_option_type: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_variable(&tmp, $4)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_variable(&tmp, $4)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) MYSQL_YYABORT; } @@ -16254,7 +16260,8 @@ option_value_no_option_type: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_variable(&tmp, &$3, $6)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_variable(&tmp, &$3, $6)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) MYSQL_YYABORT; } @@ -16422,29 +16429,35 @@ option_value_no_option_type: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_variable(&tmp, $4)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_variable(&tmp, $4)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) MYSQL_YYABORT; } - | PASSWORD_SYM opt_for_user text_or_password + | PASSWORD_SYM equal { if (sp_create_assignment_lex(thd, $1.pos())) MYSQL_YYABORT; - LEX *lex = Lex; - set_var_password *var= (new (thd->mem_root) - set_var_password(lex->definer)); - if (unlikely(var == NULL) || - unlikely(lex->var_list.push_back(var, thd->mem_root))) + } + text_or_password + { + if (unlikely(Lex->sp_create_set_password_instr(thd, $4, + yychar == YYEMPTY))) MYSQL_YYABORT; - lex->autocommit= TRUE; - if (lex->sphead) - lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; - if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY))) + } + | PASSWORD_SYM FOR_SYM + { + if (sp_create_assignment_lex(thd, $1.pos())) + MYSQL_YYABORT; + } + user equal text_or_password + { + if (unlikely(Lex->sp_create_set_password_instr(thd, $4, $6, + yychar == YYEMPTY))) MYSQL_YYABORT; } ; - transaction_characteristics: transaction_access_mode | isolation_level @@ -16501,42 +16514,25 @@ isolation_types: | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; } ; -opt_for_user: - equal - { - LEX *lex= thd->lex; - sp_pcontext *spc= lex->spcont; - LEX_CSTRING pw= { STRING_WITH_LEN("password") }; - - if (unlikely(spc && spc->find_variable(&pw, false))) - my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str)); - if (unlikely(!(lex->definer= (LEX_USER*) - thd->calloc(sizeof(LEX_USER))))) - MYSQL_YYABORT; - lex->definer->user= current_user; - lex->definer->auth= new (thd->mem_root) USER_AUTH(); - } - | FOR_SYM user equal { Lex->definer= $2; } - ; text_or_password: TEXT_STRING { - Lex->definer->auth= new (thd->mem_root) USER_AUTH(); - Lex->definer->auth->auth_str= $1; + $$= new (thd->mem_root) USER_AUTH(); + $$->auth_str= $1; } | PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->auth= new (thd->mem_root) USER_AUTH(); - Lex->definer->auth->pwtext= $3; + $$= new (thd->mem_root) USER_AUTH(); + $$->pwtext= $3; } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->auth= new (thd->mem_root) USER_AUTH(); - Lex->definer->auth->pwtext= $3; - Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd, + $$= new (thd->mem_root) USER_AUTH(); + $$->pwtext= $3; + $$->auth_str.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + $$->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -18150,14 +18146,16 @@ sp_statement: { // Direct procedure call (without the CALL keyword) Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->call_statement_start(thd, &tmp))) + if (unlikely(!tmp.str) || + unlikely(Lex->call_statement_start(thd, &tmp))) MYSQL_YYABORT; } opt_sp_cparam_list | ident_cli_directly_assignable '.' ident { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->call_statement_start(thd, &tmp, &$3))) + if (unlikely(!tmp.str) || + unlikely(Lex->call_statement_start(thd, &tmp, &$3))) MYSQL_YYABORT; } opt_sp_cparam_list @@ -18371,7 +18369,8 @@ set_assign: set_expr_or_default { Lex_ident_sys tmp(thd, &$1); - if (unlikely(Lex->set_variable(&tmp, $4)) || + if (unlikely(!tmp.str) || + unlikely(Lex->set_variable(&tmp, $4)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY, false))) MYSQL_YYABORT; @@ -18388,7 +18387,8 @@ set_assign: LEX *lex= Lex; DBUG_ASSERT(lex->var_list.is_empty()); Lex_ident_sys tmp(thd, &$1); - if (unlikely(lex->set_variable(&tmp, &$3, $6)) || + if (unlikely(!tmp.str) || + unlikely(lex->set_variable(&tmp, &$3, $6)) || unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY, false))) MYSQL_YYABORT; @@ -19070,7 +19070,7 @@ sp_labeled_block: { Lex->sp_block_init(thd, &$1); } - sp_decl_body_list + opt_sp_decl_body_list { if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd))) MYSQL_YYABORT; @@ -19112,7 +19112,7 @@ sp_unlabeled_block: MYSQL_YYABORT; Lex->sp_block_init(thd); } - sp_decl_body_list + opt_sp_decl_body_list { if (unlikely(Lex->sp_block_with_exceptions_finalize_declarations(thd))) MYSQL_YYABORT; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index df6f9933e36..1badca024fd 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2465,7 +2465,7 @@ static Sys_var_ulong Sys_max_sort_length( "the first max_sort_length bytes of each value are used; the rest " "are ignored)", SESSION_VAR(max_sort_length), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(4, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1)); + VALID_RANGE(8, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1)); static Sys_var_ulong Sys_max_sp_recursion_depth( "max_sp_recursion_depth", @@ -2999,7 +2999,7 @@ static Sys_var_charptr_fscs Sys_tmpdir( static bool fix_trans_mem_root(sys_var *self, THD *thd, enum_var_type type) { if (type != OPT_GLOBAL) - reset_root_defaults(&thd->transaction.mem_root, + reset_root_defaults(&thd->transaction->mem_root, thd->variables.trans_alloc_block_size, thd->variables.trans_prealloc_size); return false; @@ -4326,8 +4326,8 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG | OPTION_NOT_AUTOCOMMIT | OPTION_GTID_BEGIN); - thd->transaction.all.modified_non_trans_table= false; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction->all.modified_non_trans_table= false; + thd->transaction->all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; thd->server_status|= SERVER_STATUS_AUTOCOMMIT; return false; } @@ -4336,8 +4336,8 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) (OPTION_AUTOCOMMIT |OPTION_NOT_AUTOCOMMIT)) == 0) { // disabling autocommit - thd->transaction.all.modified_non_trans_table= false; - thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; + thd->transaction->all.modified_non_trans_table= false; + thd->transaction->all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT; thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT; thd->variables.option_bits|= OPTION_NOT_AUTOCOMMIT; return false; @@ -6647,6 +6647,7 @@ static Sys_var_mybool Sys_session_track_state_change( ON_UPDATE(update_session_track_state_change)); +#ifdef USER_VAR_TRACKING static bool update_session_track_user_variables(sys_var *self, THD *thd, enum_var_type type) { @@ -6661,6 +6662,7 @@ static Sys_var_mybool Sys_session_track_user_variables( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(update_session_track_user_variables)); +#endif // USER_VAR_TRACKING #endif //EMBEDDED_LIBRARY diff --git a/sql/table.cc b/sql/table.cc index 92e3d2e4800..9e7592e4b97 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -98,8 +98,11 @@ static std::atomic last_table_id; /* Functions defined in this file */ -static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, - uint types, char **names); +static bool fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *names, size_t names_length); + static uint find_field(Field **fields, uchar *record, uint start, uint length); inline bool is_system_table_name(const char *name, size_t length); @@ -462,10 +465,6 @@ void TABLE_SHARE::destroy() delete_stat_values_for_table_share(this); delete sequence; free_root(&stats_cb.mem_root, MYF(0)); - stats_cb.stats_can_be_read= FALSE; - stats_cb.stats_is_read= FALSE; - stats_cb.histograms_can_be_read= FALSE; - stats_cb.histograms_are_read= FALSE; /* The mutexes are initialized only for shares that are part of the TDC */ if (tmp_table == NO_TMP_TABLE) @@ -731,7 +730,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, uint keys, KEY *keyinfo, uint new_frm_ver, uint *ext_key_parts, TABLE_SHARE *share, uint len, - KEY *first_keyinfo, char** keynames) + KEY *first_keyinfo, + LEX_STRING *keynames) { uint i, j, n_length; KEY_PART_INFO *key_part= NULL; @@ -883,10 +883,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, share->ext_key_parts++; share->ext_key_parts+= keyinfo->ext_key_parts; } - *keynames=(char*) key_part; - strpos+= strnmov(*keynames, (char *) strpos, frm_image_end - strpos) - *keynames; + keynames->str= (char*) key_part; + keynames->length= strnmov(keynames->str, (char *) strpos, + frm_image_end - strpos) - keynames->str; + strpos+= keynames->length; if (*strpos++) // key names are \0-terminated return 1; + keynames->length++; // Include '\0', to make fix_type_pointers() happy. //reading index comments for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++) @@ -1698,11 +1701,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, TABLE_SHARE *share= this; uint new_frm_ver, field_pack_length, new_field_pack_flag; uint interval_count, interval_parts, read_length, int_length; + uint total_typelib_value_count; uint db_create_options, keys, key_parts, n_length; uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i, hash_fields= 0; bool use_hash, mysql57_null_bits= 0; - char *keynames, *names, *comment_pos; + LEX_STRING keynames= {NULL, 0}; + char *names, *comment_pos; const uchar *forminfo; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos); @@ -1714,6 +1719,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, KEY_PART_INFO *key_part= NULL; Field **field_ptr, *reg_field; const char **interval_array; + uint *typelib_value_lengths= NULL; enum legacy_db_type legacy_db_type; my_bitmap_map *bitmaps; bool null_bits_are_used; @@ -2133,11 +2139,34 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length)); + /* + We load the following things into TYPELIBs: + - One TYPELIB for field names + - interval_count TYPELIBs for ENUM/SET values + - One TYPELIB for key names + Every TYPELIB requires one extra value with a NULL pointer and zero length, + which is the end-of-values marker. + TODO-10.5+: + Note, we should eventually reuse this total_typelib_value_count + to allocate interval_array. The below code reserves less space + than total_typelib_value_count pointers. So it seems `interval_array` + and `names` overlap in the memory. Too dangerous to fix in 10.1. + */ + total_typelib_value_count= + (share->fields + 1/*end-of-values marker*/) + + (interval_parts + interval_count/*end-of-values markers*/) + + (keys + 1/*end-of-values marker*/); + if (!multi_alloc_root(&share->mem_root, &share->field, (uint)(share->fields+1)*sizeof(Field*), &share->intervals, (uint)interval_count*sizeof(TYPELIB), &share->check_constraints, (uint) share->table_check_constraints * sizeof(Virtual_column_info*), + /* + This looks wrong: shouldn't it be (+2+interval_count) + instread of (+3) ? + */ &interval_array, (uint) (share->fields+interval_parts+ keys+3)*sizeof(char *), + &typelib_value_lengths, total_typelib_value_count * sizeof(uint *), &names, (uint) (n_length+int_length), &comment_pos, (uint) com_length, &vcol_screen_pos, vcol_screen_length, @@ -2164,33 +2193,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length, vcol_screen_length); - fix_type_pointers(&interval_array, &share->fieldnames, 1, &names); - if (share->fieldnames.count != share->fields) + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->fieldnames, 1, names, n_length) || + share->fieldnames.count != share->fields) goto err; - fix_type_pointers(&interval_array, share->intervals, interval_count, &names); - { - /* Set ENUM and SET lengths */ - TYPELIB *interval; - for (interval= share->intervals; - interval < share->intervals + interval_count; - interval++) - { - uint count= (uint) (interval->count + 1) * sizeof(uint); - if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root, - count))) - goto err; - for (count= 0; count < interval->count; count++) - { - char *val= (char*) interval->type_names[count]; - interval->type_lengths[count]= (uint)strlen(val); - } - interval->type_lengths[count]= 0; - } - } + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + share->intervals, interval_count, + names + n_length, int_length)) + goto err; - if (keynames) - fix_type_pointers(&interval_array, &share->keynames, 1, &keynames); + if (keynames.length && + (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->keynames, 1, keynames.str, keynames.length) || + share->keynames.count != keys)) + goto err; /* Allocate handler */ if (!(handler_file= get_new_handler(share, thd->mem_root, @@ -3557,7 +3574,6 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table, to be part of the virtual column */ Item::vcol_func_processor_result res; - res.errors= 0; int error= func_expr->walk(&Item::check_vcol_func_processor, 0, &res); if (unlikely(error || (res.errors & VCOL_IMPOSSIBLE))) @@ -3875,7 +3891,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, outparam->write_row_record= NULL; if (share->incompatible_version && - !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR))) + !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR | + HA_OPEN_FOR_FLUSH))) { /* one needs to run mysql_upgrade on the table */ error= OPEN_FRM_NEEDS_REBUILD; @@ -3959,6 +3976,15 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, sizeof(Field*))))) goto err; /* purecov: inspected */ + /* Allocate storage for range optimizer */ + if (!multi_alloc_root(&outparam->mem_root, + &outparam->opt_range, + share->keys * sizeof(TABLE::OPT_RANGE), + &outparam->const_key_parts, + share->keys * sizeof(key_part_map), + NullS)) + goto err; + outparam->field= field_ptr; record= (uchar*) outparam->record[0]-1; /* Fieldstart = 1 */ @@ -4403,37 +4429,81 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error, ** with a '\0' */ -static void -fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, - char **names) +static bool +fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *ptr, size_t length) { - char *type_name, *ptr; - char chr; + const char *end= ptr + length; - ptr= *names; while (types--) { + char sep; point_to_type->name=0; - point_to_type->type_names= *array; + point_to_type->type_names= *typelib_value_names; + point_to_type->type_lengths= *typelib_value_lengths; - if ((chr= *ptr)) /* Test if empty type */ + /* + Typelib can be encoded as: + 1) 0x00 - empty typelib + 2) 0xFF 0x00 - empty typelib (index names) + 3) sep (value sep)... 0x00 - non-empty typelib (where sep is a separator) + */ + if (length == 2 && ptr[0] == (char) 0xFF && ptr[1] == '\0') { - while ((type_name=strchr(ptr+1,chr)) != NullS) - { - *((*array)++) = ptr+1; - *type_name= '\0'; /* End string */ - ptr=type_name; - } - ptr+=2; /* Skip end mark and last 0 */ + /* + This is a special case #2. + If there are no indexes at all, index names can be encoded + as a two byte sequence: 0xFF 0x00 + TODO: Check if it's a bug in the FRM packing routine. + It should probably write just 0x00 instead of 0xFF00. + */ + ptr+= 2; } - else - ptr++; - point_to_type->count= (uint) (*array - point_to_type->type_names); + else if ((sep= *ptr++)) // A non-empty typelib + { + for ( ; ptr < end; ) + { + // Now scan the next value+sep pair + char *vend= (char*) memchr(ptr, sep, end - ptr); + if (!vend) + return true; // Bad format + *((*typelib_value_names)++)= ptr; + *((*typelib_value_lengths)++)= (uint) (vend - ptr); + *vend= '\0'; // Change sep to '\0' + ptr= vend + 1; // Shift from sep to the next byte + /* + Now we can have either: + - the end-of-typelib marker (0x00) + - more value+sep pairs + */ + if (!*ptr) + { + /* + We have an ambiguity here. 0x00 can be an end-of-typelib marker, + but it can also be a part of the next value: + CREATE TABLE t1 (a ENUM(0x61, 0x0062) CHARACTER SET BINARY); + If this is the last ENUM/SET in the table and there is still more + packed data left after 0x00, then we know for sure that 0x00 + is a part of the next value. + TODO-10.5+: we should eventually introduce a new unambiguous + typelib encoding for FRM. + */ + if (!types && ptr + 1 < end) + continue; // A binary value starting with 0x00 + ptr++; // Consume the end-of-typelib marker + break; // End of the current typelib + } + } + } + point_to_type->count= (uint) (*typelib_value_names - + point_to_type->type_names); point_to_type++; - *((*array)++)= NullS; /* End of type */ + *((*typelib_value_names)++)= NullS; /* End of type */ + *((*typelib_value_lengths)++)= 0; /* End of type */ } - *names=ptr; /* Update end */ - return; + return ptr != end; } /* fix_type_pointers */ @@ -5313,6 +5383,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) fulltext_searched= 0; file->ft_handler= 0; reginfo.impossible_range= 0; + reginfo.join_tab= NULL; + reginfo.not_exists_optimize= FALSE; created= TRUE; cond_selectivity= 1.0; cond_selectivity_sampling_explain= NULL; @@ -5320,9 +5392,9 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) range_rowid_filter_cost_info_ptr= NULL; range_rowid_filter_cost_info= NULL; vers_write= s->versioned; - quick_condition_rows=0; + opt_range_condition_rows=0; no_cache= false; - initialize_quick_structures(); + initialize_opt_range_structures(); #ifdef HAVE_REPLICATION /* used in RBR Triggers */ master_had_triggers= 0; @@ -7190,7 +7262,6 @@ void TABLE::mark_columns_needed_for_update() DBUG_ENTER("TABLE::mark_columns_needed_for_update"); bool need_signal= false; - mark_columns_per_binlog_row_image(); if (triggers) triggers->mark_fields_used(TRG_EVENT_UPDATE); @@ -7219,6 +7290,12 @@ void TABLE::mark_columns_needed_for_update() } need_signal= true; } + else + { + if (found_next_number_field) + mark_auto_increment_column(); + } + if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) { /* @@ -7260,6 +7337,7 @@ void TABLE::mark_columns_needed_for_update() bitmap_union(read_set, write_set); need_signal= true; } + mark_columns_per_binlog_row_image(); if (need_signal) file->column_bitmaps_signal(); DBUG_VOID_RETURN; @@ -7276,7 +7354,6 @@ void TABLE::mark_columns_needed_for_update() void TABLE::mark_columns_needed_for_insert() { DBUG_ENTER("mark_columns_needed_for_insert"); - mark_columns_per_binlog_row_image(); if (triggers) { @@ -7296,6 +7373,7 @@ void TABLE::mark_columns_needed_for_insert() /* Mark virtual columns for insert */ if (vfield) mark_virtual_columns_for_write(TRUE); + mark_columns_per_binlog_row_image(); if (check_constraints) mark_check_constraint_columns_for_read(); DBUG_VOID_RETURN; @@ -7704,12 +7782,28 @@ void TABLE::restore_blob_values(String *blob_storage) bool TABLE::alloc_keys(uint key_count) { - key_info= (KEY*) alloc_root(&mem_root, sizeof(KEY)*(s->keys+key_count)); + KEY *new_key_info; + key_part_map *new_const_key_parts; + DBUG_ASSERT(s->tmp_table == INTERNAL_TMP_TABLE); + + if (!multi_alloc_root(&mem_root, + &new_key_info, sizeof(*key_info)*(s->keys+key_count), + &new_const_key_parts, + sizeof(*new_const_key_parts)*(s->keys+key_count), + NullS)) + return TRUE; if (s->keys) - memmove(key_info, s->key_info, sizeof(KEY)*s->keys); - s->key_info= key_info; + { + memmove(new_key_info, s->key_info, sizeof(*key_info) * s->keys); + memmove(new_const_key_parts, const_key_parts, + s->keys * sizeof(const_key_parts)); + } + s->key_info= key_info= new_key_info; + const_key_parts= new_const_key_parts; + bzero((char*) (const_key_parts + s->keys), + sizeof(*const_key_parts) * key_count); max_keys= s->keys+key_count; - return !(key_info); + return FALSE; } @@ -8517,9 +8611,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) int TABLE::update_virtual_field(Field *vf) { - DBUG_ASSERT(!in_use->is_error()); - Query_arena backup_arena; DBUG_ENTER("TABLE::update_virtual_field"); + Query_arena backup_arena; + Counting_error_handler count_errors; + in_use->push_internal_handler(&count_errors); in_use->set_n_backup_active_arena(expr_arena, &backup_arena); bitmap_clear_all(&tmp_set); vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); @@ -8527,7 +8622,8 @@ int TABLE::update_virtual_field(Field *vf) vf->vcol_info->expr->save_in_field(vf, 0); DBUG_RESTORE_WRITE_SET(vf); in_use->restore_active_arena(expr_arena, &backup_arena); - DBUG_RETURN(in_use->is_error()); + in_use->pop_internal_handler(); + DBUG_RETURN(count_errors.errors); } @@ -8690,7 +8786,8 @@ bool TABLE::check_period_overlaps(const KEY &key, if (key.key_part[part_nr].null_bit) if (f->is_null_in_record(lhs) || f->is_null_in_record(rhs)) return false; - if (f->cmp(f->ptr_in_record(lhs), f->ptr_in_record(rhs)) != 0) + uint kp_len= key.key_part[part_nr].length; + if (f->cmp_max(f->ptr_in_record(lhs), f->ptr_in_record(rhs), kp_len) != 0) return false; } @@ -8852,7 +8949,7 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const for (Field **fld= field; *fld; fld++) { if (!bitmap_is_set(write_set, (*fld)->field_index) && - !((*fld)->flags & NO_DEFAULT_VALUE_FLAG)) + !((*fld)->flags & (NO_DEFAULT_VALUE_FLAG | VERS_SYSTEM_FIELD))) { if (!(*fld)->is_null_in_record(s->default_values) && (*fld)->validate_value_in_record_with_warn(thd, s->default_values) && @@ -9826,18 +9923,27 @@ bool TABLE::export_structure(THD *thd, Row_definition_list *defs) /* @brief - Initialize all the quick structures that are used to stored the + Initialize all the opt_range structures that are used to stored the estimates when the range optimizer is run. - @details - This is specifically needed when we read the TABLE structure from the - table cache. There can be some garbage data from previous queries - that need to be reset here. + As these are initialized by the range optimizer for all index + marked in opt_range_keys, we only mark the memory as undefined + to be able to find wrong usage of data with valgrind or MSAN. */ -void TABLE::initialize_quick_structures() +void TABLE::initialize_opt_range_structures() { - bzero(quick_rows, sizeof(quick_rows)); - bzero(quick_key_parts, sizeof(quick_key_parts)); - bzero(quick_costs, sizeof(quick_costs)); - bzero(quick_n_ranges, sizeof(quick_n_ranges)); + TRASH_ALLOC((void*)&opt_range_keys, sizeof(opt_range_keys)); + TRASH_ALLOC(opt_range, s->keys * sizeof(*opt_range)); + TRASH_ALLOC(const_key_parts, s->keys * sizeof(*const_key_parts)); +} + +/* + Mark table to be reopened after query +*/ + +void TABLE::mark_table_for_reopen() +{ + THD *thd= in_use; + DBUG_ASSERT(thd); + thd->locked_tables_list.mark_table_for_reopen(thd, this); } diff --git a/sql/table.h b/sql/table.h index fd4e09dfa7f..c0397dd9590 100644 --- a/sql/table.h +++ b/sql/table.h @@ -25,6 +25,7 @@ #ifndef MYSQL_CLIENT +#include "my_cpu.h" /* LF_BACKOFF() */ #include "hash.h" /* HASH */ #include "handler.h" /* row_type, ha_choice, handler */ #include "mysql_com.h" /* enum_field_types */ @@ -607,15 +608,94 @@ enum open_frm_error { from persistent statistical tables */ -struct TABLE_STATISTICS_CB +class TABLE_STATISTICS_CB { + class Statistics_state + { + enum state_codes + { + EMPTY, /** data is not loaded */ + LOADING, /** data is being loaded in some connection */ + READY /** data is loaded and available for use */ + }; + int32 state; + + public: + /** No state copy */ + Statistics_state &operator=(const Statistics_state &) { return *this; } + + /** Checks if data loading have been completed */ + bool is_ready() const + { + return my_atomic_load32_explicit(const_cast(&state), + MY_MEMORY_ORDER_ACQUIRE) == READY; + } + + /** + Sets mutual exclusion for data loading + + If stats are in LOADING state, waits until state change. + + @return + @retval true atomic EMPTY -> LOADING transfer completed, ok to load + @retval false stats are in READY state, no need to load + */ + bool start_load() + { + for (;;) + { + int32 expected= EMPTY; + if (my_atomic_cas32_weak_explicit(&state, &expected, LOADING, + MY_MEMORY_ORDER_RELAXED, + MY_MEMORY_ORDER_RELAXED)) + return true; + if (expected == READY) + return false; + (void) LF_BACKOFF(); + } + } + + /** Marks data available for subsequent use */ + void end_load() + { + DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) == + LOADING); + my_atomic_store32_explicit(&state, READY, MY_MEMORY_ORDER_RELEASE); + } + + /** Restores empty state on error (e.g. OOM) */ + void abort_load() + { + DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) == + LOADING); + my_atomic_store32_explicit(&state, EMPTY, MY_MEMORY_ORDER_RELAXED); + } + }; + + class Statistics_state stats_state; + class Statistics_state hist_state; + +public: MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */ Table_statistics *table_stats; /* Structure to access the statistical data */ - bool stats_can_be_read; /* Memory for statistical data is allocated */ - bool stats_is_read; /* Statistical data for table has been read - from statistical tables */ - bool histograms_can_be_read; - bool histograms_are_read; + ulong total_hist_size; /* Total size of all histograms */ + + bool histograms_are_ready() const + { + return !total_hist_size || hist_state.is_ready(); + } + + bool start_histograms_load() + { + return total_hist_size && hist_state.start_load(); + } + + void end_histograms_load() { hist_state.end_load(); } + void abort_histograms_load() { hist_state.abort_load(); } + bool stats_are_ready() const { return stats_state.is_ready(); } + bool start_stats_load() { return stats_state.start_load(); } + void end_stats_load() { stats_state.end_load(); } + void abort_stats_load() { stats_state.abort_load(); } }; /** @@ -1177,8 +1257,7 @@ public: Map of keys that can be used to retrieve all data from this table needed by the query without reading the row. */ - key_map covering_keys; - key_map quick_keys, intersect_keys; + key_map covering_keys, intersect_keys; /* A set of keys that can be used in the query that references this table. @@ -1260,28 +1339,29 @@ public: /* The estimate of the number of records in the table used by optimizer */ ha_rows used_stat_records; + key_map opt_range_keys; /* - For each key that has quick_keys.is_set(key) == TRUE: estimate of #records - and max #key parts that range access would use. + The following structure is filled for each key that has + opt_range_keys.is_set(key) == TRUE */ - ha_rows quick_rows[MAX_KEY]; - uint quick_key_parts[MAX_KEY]; - - double quick_costs[MAX_KEY]; - /* - If there is a range access by i-th index then the cost of - index only access for it is stored in quick_index_only_costs[i] - */ - double quick_index_only_costs[MAX_KEY]; - + struct OPT_RANGE + { + uint key_parts; + uint ranges; + ha_rows rows; + double cost; + /* + If there is a range access by i-th index then the cost of + index only access for it is stored in index_only_costs[i] + */ + double index_only_cost; + } *opt_range; /* - Bitmaps of key parts that =const for the duration of join execution. If - we're in a subquery, then the constant may be different across subquery - re-executions. + Bitmaps of key parts that =const for the duration of join execution. If + we're in a subquery, then the constant may be different across subquery + re-executions. */ - key_part_map const_key_parts[MAX_KEY]; - - uint quick_n_ranges[MAX_KEY]; + key_part_map *const_key_parts; /* Estimate of number of records that satisfy SARGable part of the table @@ -1291,7 +1371,7 @@ public: that will pass the table condition (condition that depends on fields of this table and constants) */ - ha_rows quick_condition_rows; + ha_rows opt_range_condition_rows; double cond_selectivity; List *cond_selectivity_sampling_explain; @@ -1395,8 +1475,8 @@ public: bool insert_or_update; /* Can be used by the handler */ bool alias_name_used; /* true if table_name is alias */ bool get_fields_in_item_tree; /* Signal to fix_field */ - bool m_needs_reopen; private: + bool m_needs_reopen; bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: #ifdef HAVE_REPLICATION @@ -1507,6 +1587,16 @@ public: /** Should this instance of the table be reopened? */ inline bool needs_reopen() { return !db_stat || m_needs_reopen; } + /* + Mark that all current connection instances of the table should be + reopen at end of statement + */ + void mark_table_for_reopen(); + /* Should only be called from Locked_tables_list::mark_table_for_reopen() */ + void internal_set_needs_reopen(bool value) + { + m_needs_reopen= value; + } bool alloc_keys(uint key_count); bool check_tmp_key(uint key, uint key_parts, @@ -1547,7 +1637,7 @@ public: bool is_filled_at_execution(); bool update_const_key_parts(COND *conds); - void initialize_quick_structures(); + void initialize_opt_range_structures(); my_ptrdiff_t default_values_offset() const { return (my_ptrdiff_t) (s->default_values - record[0]); } @@ -2894,9 +2984,11 @@ typedef struct st_nested_join Before each use the counters are zeroed by reset_nj_counters. */ uint counter; + /* - Number of elements in join_list that were not (or contain table(s) that - weren't) removed by table elimination. + Number of elements in join_list that participate in the join plan choice: + - Base tables that were not removed by table elimination + - Join nests that were not removed by mark_join_nest_as_const */ uint n_tables; nested_join_map nj_map; /* Bit used to identify this nested join*/ diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index ef6f1c42434..a8d8113945b 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -698,10 +698,10 @@ bool THD::rm_temporary_table(handlerton *base, const char *path) char frm_path[FN_REFLEN + 1]; strxnmov(frm_path, sizeof(frm_path) - 1, path, reg_ext, NullS); - if (mysql_file_delete(key_file_frm, frm_path, MYF(0))) - { + if (mysql_file_delete(key_file_frm, frm_path, + MYF(MY_WME | MY_IGNORE_ENOENT))) error= true; - } + file= get_new_handler((TABLE_SHARE*) 0, current_thd->mem_root, base); if (file && file->ha_delete_table(path)) { @@ -1070,7 +1070,7 @@ TABLE *THD::find_temporary_table(const char *key, uint key_length, case TMP_TABLE_ANY: found= true; break; } } - if (table && unlikely(table->m_needs_reopen)) + if (table && unlikely(table->needs_reopen())) { share->all_tmp_tables.remove(table); free_temporary_table(table); @@ -1402,7 +1402,7 @@ bool THD::log_events_and_free_tmp_shares() variables.character_set_client= cs_save; get_stmt_da()->set_overwrite_status(true); - transaction.stmt.mark_dropped_temp_table(); + transaction->stmt.mark_dropped_temp_table(); bool error2= mysql_bin_log.write(&qinfo); if (unlikely(error|= error2)) { diff --git a/sql/threadpool.h b/sql/threadpool.h index 33949306ac3..285b46e3b27 100644 --- a/sql/threadpool.h +++ b/sql/threadpool.h @@ -64,9 +64,6 @@ extern void tp_set_threadpool_stall_limit(uint val); extern int tp_get_idle_thread_count(); extern int tp_get_thread_count(); -/* Activate threadpool scheduler */ -extern void tp_scheduler(void); - enum TP_PRIORITY { TP_PRIORITY_HIGH, @@ -141,7 +138,7 @@ struct TP_pool struct TP_pool_win:TP_pool { - TP_pool_win(); + TP_pool_win(); virtual int init(); virtual ~TP_pool_win(); virtual TP_connection *new_connection(CONNECT *c); diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index ed74236fb0b..c27f42b3d62 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -64,24 +64,24 @@ static inline TP_connection *get_TP_connection(THD *thd) /* Worker threads contexts, and THD contexts. ========================================= - - Both worker threads and connections have their sets of thread local variables - At the moment it is mysys_var (this has specific data for dbug, my_error and + + Both worker threads and connections have their sets of thread local variables + At the moment it is mysys_var (this has specific data for dbug, my_error and similar goodies), and PSI per-client structure. Whenever query is executed following needs to be done: 1. Save worker thread context. 2. Change TLS variables to connection specific ones using thread_attach(THD*). - This function does some additional work , e.g setting up + This function does some additional work , e.g setting up thread_stack/thread_ends_here pointers. 3. Process query 4. Restore worker thread context. - Connection login and termination follows similar schema w.r.t saving and - restoring contexts. + Connection login and termination follows similar schema w.r.t saving and + restoring contexts. - For both worker thread, and for the connection, mysys variables are created + For both worker thread, and for the connection, mysys variables are created using my_thread_init() and freed with my_thread_end(). */ @@ -158,7 +158,7 @@ static void thread_attach(THD* thd) } /* - Determine connection priority , using current + Determine connection priority , using current transaction state and 'threadpool_priority' variable value. */ static TP_PRIORITY get_priority(TP_connection *c) @@ -166,7 +166,7 @@ static TP_PRIORITY get_priority(TP_connection *c) DBUG_ASSERT(c->thd == current_thd); TP_PRIORITY prio= (TP_PRIORITY)c->thd->variables.threadpool_priority; if (prio == TP_PRIORITY_AUTO) - prio= c->thd->transaction.is_active() ? TP_PRIORITY_HIGH : TP_PRIORITY_LOW; + prio= c->thd->transaction->is_active() ? TP_PRIORITY_HIGH : TP_PRIORITY_LOW; return prio; } @@ -215,12 +215,11 @@ void tp_callback(TP_connection *c) error: c->thd= 0; - delete c; - if (thd) { threadpool_remove_connection(thd); } + delete c; worker_context.restore(); } @@ -248,9 +247,9 @@ static THD *threadpool_add_connection(CONNECT *connect, TP_connection *c) } delete connect; + thd->event_scheduler.data= c; server_threads.insert(thd); thd->set_mysys_var(mysys_var); - thd->event_scheduler.data = c; /* Login. */ thread_attach(thd); @@ -287,7 +286,6 @@ end: static void threadpool_remove_connection(THD *thd) { thread_attach(thd); - thd->event_scheduler.data= 0; thd->net.reading_or_writing = 0; end_connection(thd); close_connection(thd, 0); @@ -296,7 +294,7 @@ static void threadpool_remove_connection(THD *thd) delete thd; /* - Free resources associated with this connection: + Free resources associated with this connection: mysys thread_var and PSI thread. */ my_thread_end(); @@ -330,8 +328,8 @@ static int threadpool_process_request(THD *thd) if (thd->killed >= KILL_CONNECTION) { - /* - killed flag was set by timeout handler + /* + killed flag was set by timeout handler or KILL command. Return error. */ retval= 1; diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc index 8a4c7c94c9a..2a5587fa04a 100644 --- a/sql/threadpool_generic.cc +++ b/sql/threadpool_generic.cc @@ -83,7 +83,7 @@ static PSI_thread_info thread_list[] = {&key_timer_thread, "timer_thread", PSI_FLAG_GLOBAL} }; -/* Macro to simplify performance schema registration */ +/* Macro to simplify performance schema registration */ #define PSI_register(X) \ if(PSI_server) PSI_server->register_ ## X("threadpool", X ## _list, array_elements(X ## _list)) #else @@ -126,48 +126,47 @@ static void print_pool_blocked_message(bool); /** Asynchronous network IO. - - We use native edge-triggered network IO multiplexing facility. + + We use native edge-triggered network IO multiplexing facility. This maps to different APIs on different Unixes. - + Supported are currently Linux with epoll, Solaris with event ports, OSX and BSD with kevent, Windows with IOCP. All those API's are used with one-shot flags - (the event is signalled once client has written something into the socket, + (the event is signalled once client has written something into the socket, then socket is removed from the "poll-set" until the command is finished, and we need to re-arm/re-register socket) - + No implementation for poll/select is currently provided. - - The API closely resembles all of the above mentioned platform APIs - and consists of following functions. - + + The API closely resembles all of the above mentioned platform APIs + and consists of following functions. + - io_poll_create() - Creates an io_poll descriptor + Creates an io_poll descriptor On Linux: epoll_create() - + - io_poll_associate_fd(int poll_fd, TP_file_handle fd, void *data, void *opt) - Associate file descriptor with io poll descriptor + Associate file descriptor with io poll descriptor On Linux : epoll_ctl(..EPOLL_CTL_ADD)) - + - io_poll_disassociate_fd(TP_file_handle pollfd, TP_file_handle fd) - Associate file descriptor with io poll descriptor + Associate file descriptor with io poll descriptor On Linux: epoll_ctl(..EPOLL_CTL_DEL) - - + + - io_poll_start_read(int poll_fd,int fd, void *data, void *opt) - The same as io_poll_associate_fd(), but cannot be used before + The same as io_poll_associate_fd(), but cannot be used before io_poll_associate_fd() was called. On Linux : epoll_ctl(..EPOLL_CTL_MOD) - - - io_poll_wait (TP_file_handle pollfd, native_event *native_events, int maxevents, + + - io_poll_wait (TP_file_handle pollfd, native_event *native_events, int maxevents, int timeout_ms) - - wait until one or more descriptors added with io_poll_associate_fd() - or io_poll_start_read() becomes readable. Data associated with - descriptors can be retrieved from native_events array, using + + wait until one or more descriptors added with io_poll_associate_fd() + or io_poll_start_read() becomes readable. Data associated with + descriptors can be retrieved from native_events array, using native_event_get_userdata() function. - On Linux: epoll_wait() */ @@ -199,7 +198,7 @@ int io_poll_start_read(TP_file_handle pollfd, TP_file_handle fd, void *data, voi ev.data.u64= 0; /* Keep valgrind happy */ ev.data.ptr= data; ev.events= EPOLLIN|EPOLLET|EPOLLERR|EPOLLRDHUP|EPOLLONESHOT; - return epoll_ctl(pollfd, EPOLL_CTL_MOD, fd, &ev); + return epoll_ctl(pollfd, EPOLL_CTL_MOD, fd, &ev); } int io_poll_disassociate_fd(TP_file_handle pollfd, TP_file_handle fd) @@ -214,11 +213,11 @@ int io_poll_disassociate_fd(TP_file_handle pollfd, TP_file_handle fd) NOTE - in case of EINTR, it restarts with original timeout. Since we use either infinite or 0 timeouts, this is not critical */ -int io_poll_wait(TP_file_handle pollfd, native_event *native_events, int maxevents, +int io_poll_wait(TP_file_handle pollfd, native_event *native_events, int maxevents, int timeout_ms) { int ret; - do + do { ret = epoll_wait(pollfd, native_events, maxevents, timeout_ms); } @@ -234,9 +233,9 @@ static void *native_event_get_userdata(native_event *event) #elif defined(HAVE_KQUEUE) -/* +/* NetBSD is incompatible with other BSDs , last parameter in EV_SET macro - (udata, user data) needs to be intptr_t, whereas it needs to be void* + (udata, user data) needs to be intptr_t, whereas it needs to be void* everywhere else. */ @@ -255,18 +254,18 @@ TP_file_handle io_poll_create() int io_poll_start_read(TP_file_handle pollfd, TP_file_handle fd, void *data,void *) { struct kevent ke; - MY_EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, + MY_EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, 0, 0, data); - return kevent(pollfd, &ke, 1, 0, 0, 0); + return kevent(pollfd, &ke, 1, 0, 0, 0); } int io_poll_associate_fd(TP_file_handle pollfd, TP_file_handle fd, void *data,void *) { struct kevent ke; - MY_EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, + MY_EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, 0, 0, data); - return io_poll_start_read(pollfd,fd, data, 0); + return io_poll_start_read(pollfd,fd, data, 0); } @@ -289,7 +288,7 @@ int io_poll_wait(TP_file_handle pollfd, struct kevent *events, int maxevents, in } do { - ret= kevent(pollfd, 0, 0, events, maxevents, + ret= kevent(pollfd, 0, 0, events, maxevents, (timeout_ms >= 0)?&ts:NULL); } while (ret == -1 && errno == EINTR); @@ -367,15 +366,44 @@ int io_poll_start_read(TP_file_handle pollfd, TP_file_handle fd, void *, void *o static int io_poll_associate_fd(TP_file_handle pollfd, TP_file_handle fd, void *data, void *opt) { HANDLE h= CreateIoCompletionPort(fd, pollfd, (ULONG_PTR)data, 0); - if (!h) + if (!h) return -1; - return io_poll_start_read(pollfd,fd, 0, opt); + return io_poll_start_read(pollfd,fd, 0, opt); } +typedef LONG NTSTATUS; + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; + +struct FILE_COMPLETION_INFORMATION { + HANDLE Port; + PVOID Key; +}; + +enum FILE_INFORMATION_CLASS { + FileReplaceCompletionInformation = 0x3D +}; + + +typedef NTSTATUS(WINAPI* pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); + int io_poll_disassociate_fd(TP_file_handle pollfd, TP_file_handle fd) { - /* Not possible to unbind/rebind file descriptor in IOCP. */ + static pNtSetInformationFile my_NtSetInformationFile = (pNtSetInformationFile) + GetProcAddress(GetModuleHandle("ntdll"), "NtSetInformationFile"); + if (!my_NtSetInformationFile) + return -1; /* unexpected, we only support Windows 8.1+*/ + IO_STATUS_BLOCK iosb{}; + FILE_COMPLETION_INFORMATION fci{}; + if (my_NtSetInformationFile(fd,&iosb,&fci,sizeof(fci),FileReplaceCompletionInformation)) + return -1; return 0; } @@ -423,7 +451,7 @@ static TP_connection_generic *queue_get(thread_group_t *thread_group) if (c) DBUG_RETURN(c); } - DBUG_RETURN(0); + DBUG_RETURN(0); } static TP_connection_generic* queue_get(thread_group_t* group, operation_origin origin) @@ -466,8 +494,8 @@ static void queue_put(thread_group_t *thread_group, native_event *ev, int cnt) } } -/* - Handle wait timeout : +/* + Handle wait timeout : Find connections that have been idle for too long and kill them. Also, recalculate time when next timeout check should run. */ @@ -493,16 +521,16 @@ static my_bool timeout_check(THD *thd, pool_timer_t *timer) } -/* - Timer thread. - +/* + Timer thread. + Periodically, check if one of the thread groups is stalled. Stalls happen if - events are not being dequeued from the queue, or from the network, Primary - reason for stall can be a lengthy executing non-blocking request. It could - also happen that thread is waiting but wait_begin/wait_end is forgotten by - storage engine. Timer thread will create a new thread in group in case of + events are not being dequeued from the queue, or from the network, Primary + reason for stall can be a lengthy executing non-blocking request. It could + also happen that thread is waiting but wait_begin/wait_end is forgotten by + storage engine. Timer thread will create a new thread in group in case of a stall. - + Besides checking for stalls, timer thread is also responsible for terminating clients that have been idle for longer than wait_timeout seconds. @@ -537,14 +565,14 @@ static void* timer_thread(void *param) if (err == ETIMEDOUT) { timer->current_microtime= microsecond_interval_timer(); - + /* Check stalls in thread groups */ for (i= 0; i < threadpool_max_size; i++) { if(all_groups[i].connection_count) check_stall(&all_groups[i]); } - + /* Check if any client exceeded wait_timeout */ if (timer->next_timeout_check.load(std::memory_order_relaxed) <= timer->current_microtime) @@ -587,9 +615,9 @@ void check_stall(thread_group_t *thread_group) } /* - Check if listener is present. If not, check whether any IO - events were dequeued since last time. If not, this means - listener is either in tight loop or thd_wait_begin() + Check if listener is present. If not, check whether any IO + events were dequeued since last time. If not, this means + listener is either in tight loop or thd_wait_begin() was forgotten. Create a new worker(it will make itself listener). */ if (!thread_group->listener && !thread_group->io_event_count) @@ -598,16 +626,16 @@ void check_stall(thread_group_t *thread_group) mysql_mutex_unlock(&thread_group->mutex); return; } - + /* Reset io event count */ thread_group->io_event_count= 0; - /* + /* Check whether requests from the workqueue are being dequeued. The stall detection and resolution works as follows: - 1. There is a counter thread_group->queue_event_count for the number of + 1. There is a counter thread_group->queue_event_count for the number of events removed from the queue. Timer resets the counter to 0 on each run. 2. Timer determines stall if this counter remains 0 since last check and the queue is not empty. @@ -618,13 +646,13 @@ void check_stall(thread_group_t *thread_group) Q : Will this handling lead to an unbound growth of threads, if queue stalls permanently? A : No. If queue stalls permanently, it is an indication for many very long - simultaneous queries. The maximum number of simultanoues queries is + simultaneous queries. The maximum number of simultanoues queries is max_connections, further we have threadpool_max_threads limit, upon which no - worker threads are created. So in case there is a flood of very long + worker threads are created. So in case there is a flood of very long queries, threadpool would slowly approach thread-per-connection behavior. NOTE: If long queries never wait, creation of the new threads is done by timer, - so it is slower than in real thread-per-connection. However if long queries + so it is slower than in real thread-per-connection. However if long queries do wait and indicate that via thd_wait_begin/end callbacks, thread creation will be faster. */ @@ -634,10 +662,10 @@ void check_stall(thread_group_t *thread_group) TP_INCREMENT_GROUP_COUNTER(thread_group,stalls); wake_or_create_thread(thread_group,true); } - + /* Reset queue event count */ thread_group->queue_event_count= 0; - + mysql_mutex_unlock(&thread_group->mutex); } @@ -669,10 +697,10 @@ static void stop_timer(pool_timer_t *timer) /** Poll for socket events and distribute them to worker threads In many case current thread will handle single event itself. - + @return a ready connection, or NULL on shutdown */ -static TP_connection_generic * listener(worker_thread_t *current_thread, +static TP_connection_generic * listener(worker_thread_t *current_thread, thread_group_t *thread_group) { DBUG_ENTER("listener"); @@ -682,10 +710,10 @@ static TP_connection_generic * listener(worker_thread_t *current_thread, { native_event ev[MAX_EVENTS]; int cnt; - + if (thread_group->shutdown) break; - + cnt = io_poll_wait(thread_group->pollfd, ev, MAX_EVENTS, -1); TP_INCREMENT_GROUP_COUNTER(thread_group, polls[(int)operation_origin::LISTENER]); if (cnt <=0) @@ -693,7 +721,7 @@ static TP_connection_generic * listener(worker_thread_t *current_thread, DBUG_ASSERT(thread_group->shutdown); break; } - + mysql_mutex_lock(&thread_group->mutex); if (thread_group->shutdown) @@ -701,53 +729,52 @@ static TP_connection_generic * listener(worker_thread_t *current_thread, mysql_mutex_unlock(&thread_group->mutex); break; } - - thread_group->io_event_count += cnt; - - /* + + thread_group->io_event_count += cnt; + + /* We got some network events and need to make decisions : whether listener hould handle events and whether or not any wake worker threads so they can handle events. - - Q1 : Should listener handle an event itself, or put all events into + + Q1 : Should listener handle an event itself, or put all events into queue and let workers handle the events? - + Solution : - Generally, listener that handles events itself is preferable. We do not - want listener thread to change its state from waiting to running too + Generally, listener that handles events itself is preferable. We do not + want listener thread to change its state from waiting to running too often, Since listener has just woken from poll, it better uses its time slice and does some work. Besides, not handling events means they go to the queue, and often to wake another worker must wake up to handle the event. This is not good, as we want to avoid wakeups. - + The downside of listener that also handles queries is that we can - potentially leave thread group for long time not picking the new + potentially leave thread group for long time not picking the new network events. It is not a major problem, because this stall will be detected sooner or later by the timer thread. Still, relying on timer is not always good, because it may "tick" too slow (large timer_interval) - + We use following strategy to solve this problem - if queue was not empty - we suspect flood of network events and listener stays, Otherwise, it + we suspect flood of network events and listener stays, Otherwise, it handles a query. - - + Q2: If queue is not empty, how many workers to wake? - + Solution: - We generally try to keep one thread per group active (threads handling - queries are considered active, unless they stuck in inside some "wait") - Thus, we will wake only one worker, and only if there is not active - threads currently,and listener is not going to handle a query. When we - don't wake, we hope that currently active threads will finish fast and + We generally try to keep one thread per group active (threads handling + queries are considered active, unless they stuck in inside some "wait") + Thus, we will wake only one worker, and only if there is not active + threads currently,and listener is not going to handle a query. When we + don't wake, we hope that currently active threads will finish fast and handle the queue. If this does not happen, timer thread will detect stall and wake a worker. - - NOTE: Currently nothing is done to detect or prevent long queuing times. - A solution for the future would be to give up "one active thread per - group" principle, if events stay in the queue for too long, and just wake + + NOTE: Currently nothing is done to detect or prevent long queuing times. + A solution for the future would be to give up "one active thread per + group" principle, if events stay in the queue for too long, and just wake more workers. */ - + bool listener_picks_event=is_queue_empty(thread_group) && !threadpool_dedicated_listener; queue_put(thread_group, ev, cnt); if (listener_picks_event) @@ -763,19 +790,19 @@ static TP_connection_generic * listener(worker_thread_t *current_thread, /* We added some work items to queue, now wake a worker. */ if(wake_thread(thread_group, false)) { - /* + /* Wake failed, hence groups has no idle threads. Now check if there are any threads in the group except listener. - */ + */ if(thread_group->thread_count == 1) { /* Currently there is no worker thread in the group, as indicated by - thread_count == 1 (this means listener is the only one thread in + thread_count == 1 (this means listener is the only one thread in the group). The queue is not empty, and listener is not going to handle events. In order to drain the queue, we create a worker here. - Alternatively, we could just rely on timer to detect stall, and + Alternatively, we could just rely on timer to detect stall, and create thread, but waiting for timer would be an inefficient and pointless delay. */ @@ -790,7 +817,7 @@ static TP_connection_generic * listener(worker_thread_t *current_thread, } /** - Adjust thread counters in group or global + Adjust thread counters in group or global whenever thread is created or is about to exit @param thread_group @@ -808,8 +835,8 @@ static void add_thread_count(thread_group_t *thread_group, int32 count) /** - Creates a new worker thread. - thread_mutex must be held when calling this function + Creates a new worker thread. + thread_mutex must be held when calling this function NOTE: in rare cases, the number of threads can exceed threadpool_max_threads, because we need at least 2 threads @@ -821,7 +848,7 @@ static int create_worker(thread_group_t *thread_group, bool due_to_stall) pthread_t thread_id; bool max_threads_reached= false; int err; - + DBUG_ENTER("create_worker"); if (tp_stats.num_worker_threads >= threadpool_max_threads && thread_group->thread_count >= 2) @@ -831,8 +858,7 @@ static int create_worker(thread_group_t *thread_group, bool due_to_stall) goto end; } - - err= mysql_thread_create(key_worker_thread, &thread_id, + err= mysql_thread_create(key_worker_thread, &thread_id, thread_group->pthread_attr, worker_main, thread_group); if (!err) { @@ -855,18 +881,18 @@ end: print_pool_blocked_message(max_threads_reached); else pool_block_start= 0; /* Reset pool blocked timer, if it was set */ - + DBUG_RETURN(err); } /** Calculate microseconds throttling delay for thread creation. - + The value depends on how many threads are already in the group: small number of threads means no delay, the more threads the larger the delay. - + The actual values were not calculated using any scientific methods. They just look right, and behave well in practice. */ @@ -876,7 +902,7 @@ end: static ulonglong microsecond_throttling_interval(thread_group_t *thread_group) { int count= thread_group->thread_count; - + if (count < 1+ (int)threadpool_oversubscribe) return 0; @@ -891,15 +917,15 @@ static ulonglong microsecond_throttling_interval(thread_group_t *thread_group) /** - Wakes a worker thread, or creates a new one. - + Wakes a worker thread, or creates a new one. + Worker creation is throttled, so we avoid too many threads to be created during the short time. */ static int wake_or_create_thread(thread_group_t *thread_group, bool due_to_stall) { DBUG_ENTER("wake_or_create_thread"); - + if (thread_group->shutdown) DBUG_RETURN(0); @@ -911,13 +937,13 @@ static int wake_or_create_thread(thread_group_t *thread_group, bool due_to_stall if (thread_group->thread_count > thread_group->connection_count) DBUG_RETURN(-1); - + if (thread_group->active_thread_count == 0) { /* - We're better off creating a new thread here with no delay, either there - are no workers at all, or they all are all blocking and there was no - idle thread to wakeup. Smells like a potential deadlock or very slowly + We're better off creating a new thread here with no delay, either there + are no workers at all, or they all are all blocking and there was no + idle thread to wakeup. Smells like a potential deadlock or very slowly executing requests, e.g sleeps or user locks. */ DBUG_RETURN(create_worker(thread_group, due_to_stall)); @@ -926,8 +952,8 @@ static int wake_or_create_thread(thread_group_t *thread_group, bool due_to_stall ulonglong now = microsecond_interval_timer(); ulonglong time_since_last_thread_created = (now - thread_group->last_thread_creation_time); - - /* Throttle thread creation. */ + + /* Throttle thread creation. */ if (time_since_last_thread_created > microsecond_throttling_interval(thread_group)) { @@ -999,7 +1025,7 @@ static int wake_thread(thread_group_t *thread_group,bool due_to_stall) DBUG_RETURN(1); /* no thread in waiter list => missed wakeup */ } -/* +/* Wake listener thread (during shutdown) Self-pipe trick is used in most cases,except IOCP. */ @@ -1028,8 +1054,8 @@ static int wake_listener(thread_group_t *thread_group) /** Initiate shutdown for thread group. - The shutdown is asynchronous, we only care to wake all threads in here, so - they can finish. We do not wait here until threads terminate. Final cleanup + The shutdown is asynchronous, we only care to wake all threads in here, so + they can finish. We do not wait here until threads terminate. Final cleanup of the group (thread_group_destroy) will be done by the last exiting threads. */ @@ -1038,32 +1064,32 @@ static void thread_group_close(thread_group_t *thread_group) DBUG_ENTER("thread_group_close"); mysql_mutex_lock(&thread_group->mutex); - if (thread_group->thread_count == 0) + if (thread_group->thread_count == 0) { mysql_mutex_unlock(&thread_group->mutex); thread_group_destroy(thread_group); DBUG_VOID_RETURN; } - thread_group->shutdown= true; + thread_group->shutdown= true; thread_group->listener= NULL; wake_listener(thread_group); /* Wake all workers. */ - while(wake_thread(thread_group, false) == 0) - { + while(wake_thread(thread_group, false) == 0) + { } - + mysql_mutex_unlock(&thread_group->mutex); DBUG_VOID_RETURN; } -/* +/* Add work to the queue. Maybe wake a worker if they all sleep. - + Currently, this function is only used when new connections need to perform login (this is done in worker threads). @@ -1083,39 +1109,39 @@ static void queue_put(thread_group_t *thread_group, TP_connection_generic *conne } -/* - Prevent too many threads executing at the same time,if the workload is +/* + Prevent too many threads executing at the same time,if the workload is not CPU bound. */ static bool too_many_threads(thread_group_t *thread_group) { - return (thread_group->active_thread_count >= 1+(int)threadpool_oversubscribe + return (thread_group->active_thread_count >= 1+(int)threadpool_oversubscribe && !thread_group->stalled); } /** Retrieve a connection with pending event. - - Pending event in our case means that there is either a pending login request + + Pending event in our case means that there is either a pending login request (if connection is not yet logged in), or there are unread bytes on the socket. - If there are no pending events currently, thread will wait. + If there are no pending events currently, thread will wait. If timeout specified in abstime parameter passes, the function returns NULL. - + @param current_thread - current worker thread @param thread_group - current thread group @param abstime - absolute wait timeout - + @return - connection with pending event. + connection with pending event. NULL is returned if timeout has expired,or on shutdown. */ -TP_connection_generic *get_event(worker_thread_t *current_thread, +TP_connection_generic *get_event(worker_thread_t *current_thread, thread_group_t *thread_group, struct timespec *abstime) -{ +{ DBUG_ENTER("get_event"); TP_connection_generic *connection = NULL; @@ -1123,10 +1149,10 @@ TP_connection_generic *get_event(worker_thread_t *current_thread, mysql_mutex_lock(&thread_group->mutex); DBUG_ASSERT(thread_group->active_thread_count >= 0); - for(;;) + for(;;) { int err=0; - bool oversubscribed = too_many_threads(thread_group); + bool oversubscribed = too_many_threads(thread_group); if (thread_group->shutdown) break; @@ -1155,10 +1181,10 @@ TP_connection_generic *get_event(worker_thread_t *current_thread, thread_group->listener= NULL; break; } - - /* - Last thing we try before going to sleep is to + + /* + Last thing we try before going to sleep is to non-blocking event poll, i.e with timeout = 0. If this returns events, pick one */ @@ -1176,20 +1202,20 @@ TP_connection_generic *get_event(worker_thread_t *current_thread, } - /* And now, finally sleep */ + /* And now, finally sleep */ current_thread->woken = false; /* wake() sets this to true */ - /* + /* Add current thread to the head of the waiting list and wait. It is important to add thread to the head rather than tail as it ensures LIFO wakeup order (hot caches, working inactivity timeout) */ thread_group->waiting_threads.push_front(current_thread); - + thread_group->active_thread_count--; if (abstime) { - err = mysql_cond_timedwait(¤t_thread->cond, &thread_group->mutex, + err = mysql_cond_timedwait(¤t_thread->cond, &thread_group->mutex, abstime); } else @@ -1197,7 +1223,7 @@ TP_connection_generic *get_event(worker_thread_t *current_thread, err = mysql_cond_wait(¤t_thread->cond, &thread_group->mutex); } thread_group->active_thread_count++; - + if (!current_thread->woken) { /* @@ -1215,14 +1241,14 @@ TP_connection_generic *get_event(worker_thread_t *current_thread, thread_group->stalled= false; mysql_mutex_unlock(&thread_group->mutex); - + DBUG_RETURN(connection); } /** - Tells the pool that worker starts waiting on IO, lock, condition, + Tells the pool that worker starts waiting on IO, lock, condition, sleep() or similar. */ @@ -1231,20 +1257,20 @@ void wait_begin(thread_group_t *thread_group) DBUG_ENTER("wait_begin"); mysql_mutex_lock(&thread_group->mutex); thread_group->active_thread_count--; - + DBUG_ASSERT(thread_group->active_thread_count >=0); DBUG_ASSERT(thread_group->connection_count > 0); - if ((thread_group->active_thread_count == 0) && + if ((thread_group->active_thread_count == 0) && (!is_queue_empty(thread_group) || !thread_group->listener)) { - /* - Group might stall while this thread waits, thus wake + /* + Group might stall while this thread waits, thus wake or create a worker to prevent stall. */ wake_or_create_thread(thread_group); } - + mysql_mutex_unlock(&thread_group->mutex); DBUG_VOID_RETURN; } @@ -1263,15 +1289,13 @@ void wait_end(thread_group_t *thread_group) } - - TP_connection * TP_pool_generic::new_connection(CONNECT *c) { return new (std::nothrow) TP_connection_generic(c); } /** - Add a new connection to thread pool.. + Add a new connection to thread pool */ void TP_pool_generic::add(TP_connection *c) @@ -1281,7 +1305,7 @@ void TP_pool_generic::add(TP_connection *c) TP_connection_generic *connection=(TP_connection_generic *)c; thread_group_t *thread_group= connection->thread_group; /* - Add connection to the work queue.Actual logon + Add connection to the work queue.Actual logon will be done by a worker thread. */ mysql_mutex_lock(&thread_group->mutex); @@ -1312,8 +1336,8 @@ void TP_connection_generic::wait_begin(int type) MySQL scheduler callback: wait end */ -void TP_connection_generic::wait_end() -{ +void TP_connection_generic::wait_end() +{ DBUG_ENTER("wait_end"); DBUG_ASSERT(waiting); waiting--; @@ -1338,6 +1362,12 @@ static void set_next_timeout_check(ulonglong abstime) DBUG_VOID_RETURN; } +static size_t get_group_id(my_thread_id tid) +{ + return size_t(tid % group_count); +} + + TP_connection_generic::TP_connection_generic(CONNECT *c): TP_connection(c), thread_group(0), @@ -1345,7 +1375,8 @@ TP_connection_generic::TP_connection_generic(CONNECT *c): prev_in_queue(0), abs_wait_timeout(ULONGLONG_MAX), bound_to_poll_descriptor(false), - waiting(false) + waiting(false), + fix_group(false) { DBUG_ASSERT(c->vio_type != VIO_CLOSED); @@ -1358,8 +1389,7 @@ TP_connection_generic::TP_connection_generic(CONNECT *c): /* Assign connection to a group. */ thread_group_t *group= - &all_groups[c->thread_id%group_count]; - + &all_groups[get_group_id(c->thread_id)]; thread_group=group; mysql_mutex_lock(&group->mutex); @@ -1375,17 +1405,17 @@ TP_connection_generic::~TP_connection_generic() } /** - Set wait timeout for connection. + Set wait timeout for connection. */ void TP_connection_generic::set_io_timeout(int timeout_sec) { DBUG_ENTER("set_wait_timeout"); - /* + /* Calculate wait deadline for this connection. - Instead of using microsecond_interval_timer() which has a syscall - overhead, use pool_timer.current_microtime and take - into account that its value could be off by at most + Instead of using microsecond_interval_timer() which has a syscall + overhead, use pool_timer.current_microtime and take + into account that its value could be off by at most one tick interval. */ @@ -1398,17 +1428,16 @@ void TP_connection_generic::set_io_timeout(int timeout_sec) } -#ifndef HAVE_IOCP /** - Handle a (rare) special case,where connection needs to + Handle a (rare) special case,where connection needs to migrate to a different group because group_count has changed - after thread_pool_size setting. + after thread_pool_size setting. */ -static int change_group(TP_connection_generic *c, +static int change_group(TP_connection_generic *c, thread_group_t *old_group, thread_group_t *new_group) -{ +{ int ret= 0; DBUG_ASSERT(c->thread_group == old_group); @@ -1422,7 +1451,7 @@ static int change_group(TP_connection_generic *c, } c->thread_group->connection_count--; mysql_mutex_unlock(&old_group->mutex); - + /* Add connection to the new group. */ mysql_mutex_lock(&new_group->mutex); c->thread_group= new_group; @@ -1433,11 +1462,10 @@ static int change_group(TP_connection_generic *c, mysql_mutex_unlock(&new_group->mutex); return ret; } -#endif + int TP_connection_generic::start_io() { -#ifndef HAVE_IOCP /* Usually, connection will stay in the same group for the entire connection's life. However, we do allow group_count to @@ -1447,26 +1475,28 @@ int TP_connection_generic::start_io() So we recalculate in which group the connection should be, based on thread_id and current group count, and migrate if necessary. - */ - thread_group_t *group = - &all_groups[thd->thread_id%group_count]; - - if (group != thread_group) + */ + if (fix_group) { - if (change_group(this, thread_group, group)) - return -1; - } -#endif + fix_group = false; + thread_group_t *new_group= &all_groups[get_group_id(thd->thread_id)]; - /* - Bind to poll descriptor if not yet done. - */ + if (new_group != thread_group) + { + if (change_group(this, thread_group, new_group)) + return -1; + } + } + + /* + Bind to poll descriptor if not yet done. + */ if (!bound_to_poll_descriptor) { bound_to_poll_descriptor= true; return io_poll_associate_fd(thread_group->pollfd, fd, this, OPTIONAL_IO_POLL_READ_PARAM); } - + return io_poll_start_read(thread_group->pollfd, fd, this, OPTIONAL_IO_POLL_READ_PARAM); } @@ -1478,13 +1508,13 @@ int TP_connection_generic::start_io() static void *worker_main(void *param) { - + worker_thread_t this_thread; pthread_detach_this_thread(); my_thread_init(); - + DBUG_ENTER("worker_main"); - + thread_group_t *thread_group = (thread_group_t *)param; /* Init per-thread structure */ @@ -1543,7 +1573,7 @@ int TP_pool_generic::init() threadpool_started= true; for (uint i= 0; i < threadpool_max_size; i++) { - thread_group_init(&all_groups[i], get_connection_attrib()); + thread_group_init(&all_groups[i], get_connection_attrib()); } set_pool_size(threadpool_size); if(group_count == 0) @@ -1555,7 +1585,7 @@ int TP_pool_generic::init() PSI_register(mutex); PSI_register(cond); PSI_register(thread); - + pool_timer.tick_interval= threadpool_stall_limit; start_timer(&pool_timer); DBUG_RETURN(0); @@ -1564,7 +1594,7 @@ int TP_pool_generic::init() TP_pool_generic::~TP_pool_generic() { DBUG_ENTER("tp_end"); - + if (!threadpool_started) DBUG_VOID_RETURN; @@ -1579,11 +1609,19 @@ TP_pool_generic::~TP_pool_generic() } +static my_bool thd_reset_group(THD* thd, void*) +{ + auto c= (TP_connection_generic*)thd->event_scheduler.data; + if(c) + c->fix_group= true; + return FALSE; +} + /** Ensure that poll descriptors are created when threadpool_size changes */ int TP_pool_generic::set_pool_size(uint size) { bool success= true; - + for(uint i=0; i< size; i++) { thread_group_t *group= &all_groups[i]; @@ -1596,7 +1634,7 @@ int TP_pool_generic::set_pool_size(uint size) { sql_print_error("io_poll_create() failed, errno=%d", errno); } - } + } mysql_mutex_unlock(&group->mutex); if (!success) { @@ -1605,6 +1643,7 @@ int TP_pool_generic::set_pool_size(uint size) } } group_count= size; + server_threads.iterate(thd_reset_group); return 0; } @@ -1620,8 +1659,8 @@ int TP_pool_generic::set_stall_limit(uint limit) /** Calculate number of idle/waiting threads in the pool. - - Sum idle threads over all groups. + + Sum idle threads over all groups. Don't do any locking, it is not required for stats. */ @@ -1638,7 +1677,7 @@ int TP_pool_generic::get_idle_thread_count() /* Report threadpool problems */ -/** +/** Delay in microseconds, after which "pool blocked" message is printed. (30 sec == 30 Mio usec) */ @@ -1667,7 +1706,7 @@ static void print_pool_blocked_message(bool max_threads_reached) { ulonglong now; static bool msg_written; - + now= microsecond_interval_timer(); if (pool_block_start == 0) { @@ -1675,14 +1714,14 @@ static void print_pool_blocked_message(bool max_threads_reached) msg_written = false; return; } - + if (now > pool_block_start + BLOCK_MSG_DELAY && !msg_written) { if (max_threads_reached) sql_print_error(MAX_THREADS_REACHED_MSG); else sql_print_error(CREATE_THREAD_ERROR_MSG, my_errno); - + sql_print_information("Threadpool has been blocked for %u seconds\n", (uint)((now- pool_block_start)/1000000)); /* avoid reperated messages for the same blocking situation */ @@ -1690,6 +1729,4 @@ static void print_pool_blocked_message(bool max_threads_reached) } } - - #endif /* HAVE_POOL_OF_THREADS */ diff --git a/sql/threadpool_generic.h b/sql/threadpool_generic.h index e54cc8bb272..b7a35b7cbf0 100644 --- a/sql/threadpool_generic.h +++ b/sql/threadpool_generic.h @@ -25,7 +25,7 @@ #include #include "threadpool_winsockets.h" /* AIX may define this, too ?*/ -#define HAVE_IOCP +#define HAVE_IOCP #endif @@ -90,7 +90,7 @@ struct TP_connection_generic :public TP_connection TP_file_handle fd; bool bound_to_poll_descriptor; int waiting; - + bool fix_group; #ifdef _WIN32 win_aiosocket win_sock{}; void init_vio(st_vio *vio) override @@ -128,7 +128,7 @@ struct thread_group_counters_t ulonglong polls[2]; }; -struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) thread_group_t +struct thread_group_t { mysql_mutex_t mutex; connection_queue_t queues[NQUEUES]; @@ -147,6 +147,7 @@ struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) thread_group_t bool shutdown; bool stalled; thread_group_counters_t counters; + char pad[CPU_LEVEL1_DCACHE_LINESIZE]; }; #define TP_INCREMENT_GROUP_COUNTER(group,var) do {group->counters.var++;}while(0) diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index 63ec66522c1..515bf0e02bc 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -59,10 +59,10 @@ PTP_CALLBACK_ENVIRON get_threadpool_win_callback_environ() */ -static void CALLBACK timer_callback(PTP_CALLBACK_INSTANCE instance, +static void CALLBACK timer_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_TIMER timer); -static void CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, +static void CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PVOID overlapped, ULONG io_result, ULONG_PTR nbytes, PTP_IO io); @@ -251,7 +251,7 @@ static void pre_callback(PVOID context, PTP_CALLBACK_INSTANCE instance) /* - Decrement number of threads when a thread exits . + Decrement number of threads when a thread exits. On Windows, FlsAlloc() provides the thread destruction callbacks. */ static VOID WINAPI thread_destructor(void *data) @@ -275,7 +275,7 @@ static inline void tp_callback(PTP_CALLBACK_INSTANCE instance, PVOID context) /* Handle read completion/notification. */ -static VOID CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, +static VOID CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PVOID overlapped, ULONG io_result, ULONG_PTR nbytes, PTP_IO io) { TP_connection_win *c= (TP_connection_win *)context; diff --git a/sql/transaction.cc b/sql/transaction.cc index c9fd211c1f8..421aa1cfc51 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -60,7 +60,14 @@ void trans_reset_one_shot_chistics(THD *thd) thd->tx_read_only= thd->variables.tx_read_only; } -/* Conditions under which the transaction state must not change. */ + +/* + Conditions under which the transaction state must not change + + @result TRUE Transaction can not commit + @result FALSE Transaction can commit +*/ + static bool trans_check(THD *thd) { DBUG_ENTER("trans_check"); @@ -69,15 +76,17 @@ static bool trans_check(THD *thd) Always commit statement transaction before manipulating with the normal one. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty()); + DBUG_ASSERT(thd->transaction->stmt.is_empty()); if (unlikely(thd->in_sub_stmt)) + { my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - if (thd->transaction.xid_state.is_explicit_XA()) - thd->transaction.xid_state.er_xaer_rmfail(); - else + DBUG_RETURN(TRUE); + } + if (likely(!thd->transaction->xid_state.is_explicit_XA())) DBUG_RETURN(FALSE); + thd->transaction->xid_state.er_xaer_rmfail(); DBUG_RETURN(TRUE); } @@ -130,10 +139,10 @@ bool trans_begin(THD *thd, uint flags) The following set should not be needed as transaction state should already be reset. We should at some point change this to an assert. */ - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->has_waiter= false; thd->waiting_on_group_commit= false; - thd->transaction.start_time.reset(thd); + thd->transaction->start_time.reset(thd); if (res) DBUG_RETURN(TRUE); @@ -261,10 +270,10 @@ bool trans_commit(THD *thd) mysql_mutex_assert_not_owner(&LOCK_after_binlog_sync); mysql_mutex_assert_not_owner(&LOCK_commit_ordered); - /* - if res is non-zero, then ha_commit_trans has rolled back the - transaction, so the hooks for rollback will be called. - */ + /* + if res is non-zero, then ha_commit_trans has rolled back the + transaction, so the hooks for rollback will be called. + */ #ifdef HAVE_REPLICATION if (res) repl_semisync_master.wait_after_rollback(thd, FALSE); @@ -272,7 +281,7 @@ bool trans_commit(THD *thd) repl_semisync_master.wait_after_commit(thd, FALSE); #endif thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->lex->start_transaction_opt= 0; /* The transaction should be marked as complete in P_S. */ @@ -321,7 +330,7 @@ bool trans_commit_implicit(THD *thd) } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); + thd->transaction->all.reset(); /* The transaction should be marked as complete in P_S. */ DBUG_ASSERT(thd->m_transaction_psi == NULL); @@ -367,7 +376,7 @@ bool trans_rollback(THD *thd) /* Reset the binlog transaction marker */ thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG | OPTION_GTID_BEGIN); - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->lex->start_transaction_opt= 0; /* The transaction should be marked as complete in P_S. */ @@ -405,7 +414,7 @@ bool trans_rollback_implicit(THD *thd) Don't perform rollback in the middle of sub-statement, wait till its end. */ - DBUG_ASSERT(thd->transaction.stmt.is_empty() && !thd->in_sub_stmt); + DBUG_ASSERT(thd->transaction->stmt.is_empty() && !thd->in_sub_stmt); thd->server_status&= ~SERVER_STATUS_IN_TRANS; DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -416,7 +425,7 @@ bool trans_rollback_implicit(THD *thd) preserve backward compatibility. */ thd->variables.option_bits&= ~(OPTION_KEEP_LOG); - thd->transaction.all.reset(); + thd->transaction->all.reset(); /* Rollback should clear transaction_rollback_request flag. */ DBUG_ASSERT(!thd->transaction_rollback_request); @@ -458,7 +467,7 @@ bool trans_commit_stmt(THD *thd) thd->merge_unsafe_rollback_flags(); - if (thd->transaction.stmt.ha_list) + if (thd->transaction->stmt.ha_list) { res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) @@ -493,7 +502,7 @@ bool trans_commit_stmt(THD *thd) DBUG_ASSERT(thd->in_active_multi_stmt_transaction() || thd->m_transaction_psi == NULL); - thd->transaction.stmt.reset(); + thd->transaction->stmt.reset(); DBUG_RETURN(MY_TEST(res)); } @@ -521,7 +530,7 @@ bool trans_rollback_stmt(THD *thd) thd->merge_unsafe_rollback_flags(); - if (thd->transaction.stmt.ha_list) + if (thd->transaction->stmt.ha_list) { ha_rollback_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) @@ -536,7 +545,7 @@ bool trans_rollback_stmt(THD *thd) DBUG_ASSERT(thd->in_active_multi_stmt_transaction() || thd->m_transaction_psi == NULL); - thd->transaction.stmt.reset(); + thd->transaction->stmt.reset(); DBUG_RETURN(FALSE); } @@ -545,7 +554,7 @@ bool trans_rollback_stmt(THD *thd) static SAVEPOINT ** find_savepoint(THD *thd, LEX_CSTRING name) { - SAVEPOINT **sv= &thd->transaction.savepoints; + SAVEPOINT **sv= &thd->transaction->savepoints; while (*sv) { @@ -579,7 +588,7 @@ bool trans_savepoint(THD *thd, LEX_CSTRING name) !opt_using_transactions) DBUG_RETURN(FALSE); - if (thd->transaction.xid_state.check_has_uncommitted_xa()) + if (thd->transaction->xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); sv= find_savepoint(thd, name); @@ -590,14 +599,14 @@ bool trans_savepoint(THD *thd, LEX_CSTRING name) ha_release_savepoint(thd, *sv); *sv= (*sv)->prev; } - else if ((newsv= (SAVEPOINT *) alloc_root(&thd->transaction.mem_root, + else if ((newsv= (SAVEPOINT *) alloc_root(&thd->transaction->mem_root, savepoint_alloc_size)) == NULL) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); DBUG_RETURN(TRUE); } - newsv->name= strmake_root(&thd->transaction.mem_root, name.str, name.length); + newsv->name= strmake_root(&thd->transaction->mem_root, name.str, name.length); newsv->length= (uint)name.length; /* @@ -608,8 +617,8 @@ bool trans_savepoint(THD *thd, LEX_CSTRING name) if (unlikely(ha_savepoint(thd, newsv))) DBUG_RETURN(TRUE); - newsv->prev= thd->transaction.savepoints; - thd->transaction.savepoints= newsv; + newsv->prev= thd->transaction->savepoints; + thd->transaction->savepoints= newsv; /* Remember locks acquired before the savepoint was set. @@ -655,7 +664,7 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) DBUG_RETURN(TRUE); } - if (thd->transaction.xid_state.check_has_uncommitted_xa()) + if (thd->transaction->xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); /** @@ -688,13 +697,13 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) if (ha_rollback_to_savepoint(thd, sv)) res= TRUE; else if (((thd->variables.option_bits & OPTION_KEEP_LOG) || - thd->transaction.all.modified_non_trans_table) && + thd->transaction->all.modified_non_trans_table) && !thd->slave_thread) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, ER_THD(thd, ER_WARNING_NOT_COMPLETE_ROLLBACK)); - thd->transaction.savepoints= sv; + thd->transaction->savepoints= sv; if (!res && mdl_can_safely_rollback_to_savepoint) thd->mdl_context.rollback_to_savepoint(sv->mdl_savepoint); @@ -732,7 +741,7 @@ bool trans_release_savepoint(THD *thd, LEX_CSTRING name) if (ha_release_savepoint(thd, sv)) res= TRUE; - thd->transaction.savepoints= sv->prev; + thd->transaction->savepoints= sv->prev; DBUG_RETURN(MY_TEST(res)); } diff --git a/sql/tztime.cc b/sql/tztime.cc index 72db37fde9c..b1c0c79d5d7 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1699,7 +1699,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) { tl->table->use_all_columns(); /* Force close at the end of the function to free memory. */ - tl->table->m_needs_reopen= TRUE; + tl->table->mark_table_for_reopen(); } /* @@ -1900,7 +1900,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) Most probably user has mistyped time zone name, so no need to bark here unless we need it for debugging. */ - sql_print_error("Can't find description of time zone '%.*s'", + sql_print_error("Can't find description of time zone '%.*b'", tz_name->length(), tz_name->ptr()); #endif goto end; @@ -2330,16 +2330,21 @@ my_tz_find(THD *thd, const String *name) else if (time_zone_tables_exist) { TABLE_LIST tz_tables[MY_TZ_TABLES_COUNT]; - Open_tables_backup open_tables_state_backup; + /* + Allocate start_new_trans with malloc as it's > 4000 bytes and this + function can be called deep inside a stored procedure + */ + start_new_trans *new_trans= new start_new_trans(thd); tz_init_table_list(tz_tables); init_mdl_requests(tz_tables); - if (!open_system_tables_for_read(thd, tz_tables, - &open_tables_state_backup)) + if (!open_system_tables_for_read(thd, tz_tables)) { result_tz= tz_load_from_open_tables(name, tz_tables); - close_system_tables(thd, &open_tables_state_backup); + thd->commit_whole_transaction_and_close_tables(); } + new_trans->restore_old_transaction(); + delete new_trans; } } diff --git a/sql/uniques.cc b/sql/uniques.cc index 60918ea534e..a0cebe3e4dd 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -317,6 +317,9 @@ double Unique::get_use_cost(uint *buffer, size_t nkeys, uint key_size, max_elements_in_tree= ((size_t) max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size)); + if (max_elements_in_tree == 0) + max_elements_in_tree= 1; + n_full_trees= nkeys / max_elements_in_tree; last_tree_elems= nkeys % max_elements_in_tree; @@ -735,6 +738,13 @@ bool Unique::merge(TABLE *table, uchar *buff, size_t buff_size, sort_param.cmp_context.key_compare= tree.compare; sort_param.cmp_context.key_compare_arg= tree.custom_arg; + /* + We need to remove the size allocated for the unique buffer. + The sort_buffer_size is: + MY_MAX(MERGEBUFF2+1, max_in_memory_size/full_size+1) * full_size; + */ + buff_size-= full_size; + /* Merge the buffers to one file, removing duplicates */ if (merge_many_buff(&sort_param, Bounds_checked_array(buff, buff_size), @@ -802,7 +812,13 @@ bool Unique::get(TABLE *table) /* Not enough memory; Save the result to file && free memory used by tree */ if (flush()) DBUG_RETURN(1); - size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + /* + merge_buffer must fit at least MERGEBUFF2 + 1 keys, because + merge_index() can merge that many BUFFPEKs at once. The extra space for + one key for Sort_param::unique_buff + */ + size_t buff_sz= MY_MAX(MERGEBUFF2+1, max_in_memory_size/full_size+1) * full_size; + if (!(sort_buffer= (uchar*) my_malloc(key_memory_Unique_sort_buffer, buff_sz, MYF(MY_THREAD_SPECIFIC|MY_WME)))) DBUG_RETURN(1); diff --git a/sql/uniques.h b/sql/uniques.h index a78e626907f..7e12a391fbd 100644 --- a/sql/uniques.h +++ b/sql/uniques.h @@ -86,6 +86,9 @@ public: { size_t max_elems_in_tree= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); + + if (max_elems_in_tree == 0) + max_elems_in_tree= 1; return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); } diff --git a/sql/unireg.cc b/sql/unireg.cc index 6860d2c6347..fa193a7712d 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB Corporation + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -787,6 +787,18 @@ static bool pack_vcols(String *buf, List &create_fields, } +static uint typelib_values_packed_length(const TYPELIB *t) +{ + uint length= 0; + for (uint i= 0; t->type_names[i]; i++) + { + length+= t->type_lengths[i]; + length++; /* Separator */ + } + return length; +} + + /* Make formheader */ static bool pack_header(THD *thd, uchar *forminfo, @@ -881,9 +893,8 @@ static bool pack_header(THD *thd, uchar *forminfo, field->interval_id=get_interval_id(&int_count,create_fields,field); if (old_int_count != int_count) { - for (const char **pos=field->interval->type_names ; *pos ; pos++) - int_length+=(uint) strlen(*pos)+1; // field + suffix prefix - int_parts+=field->interval->count+1; + int_length+= typelib_values_packed_length(field->interval); + int_parts+= field->interval->count + 1; } } if (f_maybe_null(field->pack_flag)) @@ -972,11 +983,7 @@ static size_t packed_fields_length(List &create_fields) { int_count= field->interval_id; length++; - for (int i=0; field->interval->type_names[i]; i++) - { - length+= field->interval->type_lengths[i]; - length++; - } + length+= typelib_values_packed_length(field->interval); length++; } @@ -1100,9 +1107,10 @@ static bool pack_fields(uchar **buff_arg, List &create_fields, static bool make_empty_rec_store_default(THD *thd, Field *regfield, - Virtual_column_info *default_value) + Create_field *field) { - if (default_value && !default_value->flags) + Virtual_column_info *default_value= field->default_value; + if (!field->vers_sys_field() && default_value && !default_value->flags) { Item *expr= default_value->expr; // may be already fixed if ALTER TABLE @@ -1184,7 +1192,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, !f_bit_as_char(field->pack_flag)) null_count+= field->length & 7; - error= make_empty_rec_store_default(thd, regfield, field->default_value); + error= make_empty_rec_store_default(thd, regfield, field); delete regfield; // Avoid memory leaks if (error) goto err; diff --git a/sql/upgrade_conf_file.cc b/sql/upgrade_conf_file.cc index 7951fac1a4f..a08fd087172 100644 --- a/sql/upgrade_conf_file.cc +++ b/sql/upgrade_conf_file.cc @@ -54,6 +54,7 @@ static const char *removed_variables[] = "innodb_buffer_pool_shm_checksum", "innodb_buffer_pool_shm_key", "innodb_checkpoint_age_target", +"innodb_checksums", "innodb_cleaner_eviction_factor", "innodb_cleaner_flush_chunk_size", "innodb_cleaner_free_list_lwm", @@ -81,11 +82,13 @@ static const char *removed_variables[] = "innodb_large_prefix", "innodb_lazy_drop_table", "innodb_locking_fake_changes", +"innodb_locks_unsafe_for_binlog", "innodb_log_arch_dir", "innodb_log_arch_expire_sec", "innodb_log_archive", "innodb_log_block_size", "innodb_log_checksum_algorithm", +"innodb_rollback_segments", "innodb_max_bitmap_file_size", "innodb_max_changed_pages", "innodb_merge_sort_block_size", @@ -101,6 +104,7 @@ static const char *removed_variables[] = "innodb_show_locks_held", "innodb_show_verbose_locks", "innodb_stats_auto_update", +"innodb_stats_sample_pages", "innodb_stats_update_need_lock", "innodb_support_xa", "innodb_thread_concurrency_timer_based", diff --git a/sql/winservice.c b/sql/winservice.c index 78ab736d37f..44e9302e3d3 100644 --- a/sql/winservice.c +++ b/sql/winservice.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, Monty Program Ab + Copyright (c) 2011, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -148,13 +148,10 @@ int get_mysql_service_properties(const wchar_t *bin_path, { /* There are rare cases where service config does not have - --defaults-file in the binary parth . There services were + --defaults-file in the binary path . There services were registered with plain mysqld --install, the data directory is - next to "bin" in this case. Service name (second parameter) - must be MySQL. + next to "bin" in this case. */ - if (wcscmp(args[1], L"MySQL") != 0) - goto end; have_inifile= FALSE; } else if(numargs == 3) @@ -213,7 +210,7 @@ int get_mysql_service_properties(const wchar_t *bin_path, } } - if(!have_inifile) + if(!have_inifile || props->datadir[0] == 0) { /* Hard, although a rare case, we're guessing datadir and defaults-file. @@ -237,22 +234,25 @@ int get_mysql_service_properties(const wchar_t *bin_path, *p= 0; } - /* Look for my.ini, my.cnf in the install root */ - sprintf_s(props->inifile, MAX_PATH, "%s\\my.ini", install_root); - if (GetFileAttributes(props->inifile) == INVALID_FILE_ATTRIBUTES) + if (!have_inifile) { - sprintf_s(props->inifile, MAX_PATH, "%s\\my.cnf", install_root); - } - if (GetFileAttributes(props->inifile) != INVALID_FILE_ATTRIBUTES) - { - /* Ini file found, get datadir from there */ - GetPrivateProfileString("mysqld", "datadir", NULL, props->datadir, - MAX_PATH, props->inifile); - } - else - { - /* No ini file */ - props->inifile[0]= 0; + /* Look for my.ini, my.cnf in the install root */ + sprintf_s(props->inifile, MAX_PATH, "%s\\my.ini", install_root); + if (GetFileAttributes(props->inifile) == INVALID_FILE_ATTRIBUTES) + { + sprintf_s(props->inifile, MAX_PATH, "%s\\my.cnf", install_root); + } + if (GetFileAttributes(props->inifile) != INVALID_FILE_ATTRIBUTES) + { + /* Ini file found, get datadir from there */ + GetPrivateProfileString("mysqld", "datadir", NULL, props->datadir, + MAX_PATH, props->inifile); + } + else + { + /* No ini file */ + props->inifile[0]= 0; + } } /* Try datadir in install directory.*/ diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 25a4e22aeb4..4005de22e72 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -191,7 +191,7 @@ int wsrep_apply_events(THD* thd, /* Use the original server id for logging. */ thd->set_server_id(ev->server_id); thd->set_time(); // time the query - thd->transaction.start_time.reset(thd); + thd->transaction->start_time.reset(thd); thd->lex->current_select= 0; if (!ev->when) { diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index 992883aa797..de0aab4b81a 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -507,10 +507,12 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_executing); thd_proc_info(thd, "applying write set"); + /* moved dbug sync point here, after possible THD switch for SR transactions has ben done */ /* Allow tests to block the applier thread using the DBUG facilities */ +#ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("sync.wsrep_apply_cb", { const char act[]= @@ -520,6 +522,7 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif /* ENABLED_DEBUG_SYNC */ wsrep_setup_uk_and_fk_checks(thd); int ret= apply_events(thd, m_rli, data, err); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 327b7161633..0c31631d19b 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1,4 +1,5 @@ /* Copyright 2008-2015 Codership Oy + Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -99,6 +100,7 @@ my_bool wsrep_desync; // De(re)synchronize the node fr my_bool wsrep_strict_ddl; // Reject DDL to // effected tables not // supporting Galera replication +bool wsrep_service_started; // If Galera was initialized long wsrep_slave_threads; // No. of slave appliers threads ulong wsrep_retry_autocommit; // Retry aborted autocommit trx ulong wsrep_max_ws_size; // Max allowed ws (RBR buffer) size @@ -831,10 +833,6 @@ int wsrep_init() return err; } - global_system_variables.wsrep_on= 1; - - WSREP_ON_= wsrep_provider && strcmp(wsrep_provider, WSREP_NONE); - if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates) { WSREP_ERROR("Option --log-slave-updates is required if " @@ -866,6 +864,11 @@ int wsrep_init() return 1; } + /* Now WSREP is fully initialized */ + global_system_variables.wsrep_on= 1; + WSREP_ON_= wsrep_provider && strcmp(wsrep_provider, WSREP_NONE); + wsrep_service_started= 1; + wsrep_init_provider_status_variables(); wsrep_capabilities_export(Wsrep_server_state::instance().provider().capabilities(), &wsrep_provider_capabilities); @@ -1162,18 +1165,21 @@ bool wsrep_start_replication() bool wsrep_must_sync_wait (THD* thd, uint mask) { - bool ret; - mysql_mutex_lock(&thd->LOCK_thd_data); - ret= (thd->variables.wsrep_sync_wait & mask) && - thd->wsrep_client_thread && - thd->variables.wsrep_on && - !(thd->variables.wsrep_dirty_reads && - !is_update_query(thd->lex->sql_command)) && - !thd->in_active_multi_stmt_transaction() && - thd->wsrep_trx().state() != - wsrep::transaction::s_replaying && - thd->wsrep_cs().sync_wait_gtid().is_undefined(); - mysql_mutex_unlock(&thd->LOCK_thd_data); + bool ret= 0; + if (thd->variables.wsrep_on) + { + mysql_mutex_lock(&thd->LOCK_thd_data); + ret= (thd->variables.wsrep_sync_wait & mask) && + thd->wsrep_client_thread && + thd->variables.wsrep_on && + !(thd->variables.wsrep_dirty_reads && + !is_update_query(thd->lex->sql_command)) && + !thd->in_active_multi_stmt_transaction() && + thd->wsrep_trx().state() != + wsrep::transaction::s_replaying && + thd->wsrep_cs().sync_wait_gtid().is_undefined(); + mysql_mutex_unlock(&thd->LOCK_thd_data); + } return ret; } @@ -2363,7 +2369,7 @@ void wsrep_to_isolation_end(THD *thd) */ void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, - MDL_ticket *ticket, + const MDL_ticket *ticket, const MDL_key *key) { /* Fallback to the non-wsrep behaviour */ @@ -3070,6 +3076,7 @@ void wsrep_commit_empty(THD* thd, bool all) if (wsrep_is_real(thd, all) && wsrep_thd_is_local(thd) && thd->wsrep_trx().active() && + !thd->internal_transaction() && thd->wsrep_trx().state() != wsrep::transaction::s_committed) { /* @todo CTAS with STATEMENT binlog format and empty result set diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index cf2404e329e..3347a94cdd6 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -1,4 +1,5 @@ /* Copyright 2008-2017 Codership Oy + Copyright (c) 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -186,6 +187,7 @@ void wsrep_recover_sr_from_storage(THD *); // Other wsrep global variables extern my_bool wsrep_inited; // whether wsrep is initialized ? +extern bool wsrep_service_started; extern "C" void wsrep_fire_rollbacker(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); @@ -526,7 +528,7 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr); extern void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, - MDL_ticket *ticket, + const MDL_ticket *ticket, const MDL_key *key); enum wsrep_thread_type { diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index 50aea494255..7ba744b4d3c 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -303,9 +303,21 @@ wsrep::gtid Wsrep_server_service::get_position(wsrep::client_service&) return wsrep_get_SE_checkpoint(); } -void Wsrep_server_service::set_position(wsrep::client_service&, +void Wsrep_server_service::set_position(wsrep::client_service& c WSREP_UNUSED, const wsrep::gtid& gtid) { + Wsrep_client_service& cs WSREP_UNUSED (static_cast(c)); + DBUG_ASSERT(cs.m_client_state.transaction().state() + == wsrep::transaction::s_aborted); + // Wait until all prior committers have finished. + wsrep::gtid wait_for(gtid.id(), + wsrep::seqno(gtid.seqno().get() - 1)); + if (auto err = Wsrep_server_state::instance().provider() + .wait_for_gtid(wait_for, std::numeric_limits::max())) + { + WSREP_WARN("Wait for gtid returned error %d while waiting for " + "prior transactions to commit before setting position", err); + } wsrep_set_SE_checkpoint(gtid, wsrep_gtid_server.gtid()); } diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index 55bb7462d99..35f670b9af6 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -34,7 +34,8 @@ void wsrep_commit_empty(THD* thd, bool all); static inline bool wsrep_is_active(THD* thd) { return (thd->wsrep_cs().state() != wsrep::client_state::s_none && - thd->wsrep_cs().transaction().active()); + thd->wsrep_cs().transaction().active() && + !thd->internal_transaction()); } /* @@ -82,7 +83,7 @@ static inline bool wsrep_not_committed(THD* thd) */ static inline bool wsrep_is_real(THD* thd, bool all) { - return (all || thd->transaction.all.ha_list == 0); + return (all || thd->transaction->all.ha_list == 0); } /* @@ -158,7 +159,7 @@ static inline int wsrep_start_trx_if_not_started(THD* thd) Return zero on succes, non-zero on failure. */ -static inline int wsrep_after_row(THD* thd, bool) +static inline int wsrep_after_row_internal(THD* thd) { if (thd->wsrep_cs().state() != wsrep::client_state::s_none && wsrep_thd_is_local(thd)) @@ -340,6 +341,8 @@ static inline int wsrep_after_commit(THD* thd, bool all) (long long)wsrep_thd_trx_seqno(thd), wsrep_has_changes(thd)); DBUG_ASSERT(wsrep_run_commit_hook(thd, all)); + if (thd->internal_transaction()) + DBUG_RETURN(0); int ret= 0; if (thd->wsrep_trx().state() == wsrep::transaction::s_committing) { @@ -409,7 +412,8 @@ static inline int wsrep_after_rollback(THD* thd, bool all) static inline int wsrep_before_statement(THD* thd) { - return (thd->wsrep_cs().state() != wsrep::client_state::s_none ? + return (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction() ? thd->wsrep_cs().before_statement() : 0); } @@ -417,7 +421,8 @@ static inline int wsrep_after_statement(THD* thd) { DBUG_ENTER("wsrep_after_statement"); - DBUG_RETURN(thd->wsrep_cs().state() != wsrep::client_state::s_none ? + DBUG_RETURN(thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction() ? thd->wsrep_cs().after_statement() : 0); } @@ -425,7 +430,8 @@ static inline void wsrep_after_apply(THD* thd) { DBUG_ASSERT(wsrep_thd_is_applying(thd)); WSREP_DEBUG("wsrep_after_apply %lld", thd->thread_id); - thd->wsrep_cs().after_applying(); + if (!thd->internal_transaction()) + thd->wsrep_cs().after_applying(); } static inline void wsrep_open(THD* thd) @@ -448,7 +454,8 @@ static inline void wsrep_open(THD* thd) static inline void wsrep_close(THD* thd) { DBUG_ENTER("wsrep_close"); - if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + if (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction()) { thd->wsrep_cs().close(); } @@ -459,7 +466,8 @@ static inline void wsrep_wait_rollback_complete_and_acquire_ownership(THD *thd) { DBUG_ENTER("wsrep_wait_rollback_complete_and_acquire_ownership"); - if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + if (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction()) { thd->wsrep_cs().wait_rollback_complete_and_acquire_ownership(); } @@ -468,8 +476,9 @@ wsrep_wait_rollback_complete_and_acquire_ownership(THD *thd) static inline int wsrep_before_command(THD* thd) { - return (thd->wsrep_cs().state() != wsrep::client_state::s_none ? - thd->wsrep_cs().before_command() : 0); + return (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction() ? + thd->wsrep_cs().before_command() : 0); } /* Called after each command. @@ -478,7 +487,8 @@ static inline int wsrep_before_command(THD* thd) */ static inline void wsrep_after_command_before_result(THD* thd) { - if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + if (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction()) { thd->wsrep_cs().after_command_before_result(); } @@ -486,7 +496,8 @@ static inline void wsrep_after_command_before_result(THD* thd) static inline void wsrep_after_command_after_result(THD* thd) { - if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + if (thd->wsrep_cs().state() != wsrep::client_state::s_none && + !thd->internal_transaction()) { thd->wsrep_cs().after_command_after_result(); } diff --git a/sql/xa.cc b/sql/xa.cc index 69e9fd70af6..68e6e67fa0b 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -397,11 +397,11 @@ bool xa_trans_force_rollback(THD *thd) } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG | OPTION_GTID_BEGIN); - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); - xid_cache_delete(thd, &thd->transaction.xid_state); + xid_cache_delete(thd, &thd->transaction->xid_state); trans_track_end_trx(thd); @@ -422,17 +422,17 @@ bool trans_xa_start(THD *thd) { DBUG_ENTER("trans_xa_start"); - if (thd->transaction.xid_state.is_explicit_XA() && - thd->transaction.xid_state.xid_cache_element->xa_state == XA_IDLE && + if (thd->transaction->xid_state.is_explicit_XA() && + thd->transaction->xid_state.xid_cache_element->xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME) { bool not_equal= - !thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid); + !thd->transaction->xid_state.xid_cache_element->xid.eq(thd->lex->xid); if (not_equal) my_error(ER_XAER_NOTA, MYF(0)); else { - thd->transaction.xid_state.xid_cache_element->xa_state= XA_ACTIVE; + thd->transaction->xid_state.xid_cache_element->xa_state= XA_ACTIVE; MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_ACTIVE); } DBUG_RETURN(not_equal); @@ -443,14 +443,14 @@ bool trans_xa_start(THD *thd) my_error(ER_XAER_INVAL, MYF(0)); else if (!thd->lex->xid->gtrid_length) my_error(ER_XAER_INVAL, MYF(0)); - else if (thd->transaction.xid_state.is_explicit_XA()) - thd->transaction.xid_state.er_xaer_rmfail(); + else if (thd->transaction->xid_state.is_explicit_XA()) + thd->transaction->xid_state.er_xaer_rmfail(); else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) my_error(ER_XAER_OUTSIDE, MYF(0)); else if (!trans_begin(thd)) { MYSQL_SET_TRANSACTION_XID(thd->m_transaction_psi, thd->lex->xid, XA_ACTIVE); - if (xid_cache_insert(thd, &thd->transaction.xid_state, thd->lex->xid)) + if (xid_cache_insert(thd, &thd->transaction->xid_state, thd->lex->xid)) { trans_rollback(thd); DBUG_RETURN(true); @@ -478,19 +478,19 @@ bool trans_xa_end(THD *thd) /* TODO: SUSPEND and FOR MIGRATE are not supported yet. */ if (thd->lex->xa_opt != XA_NONE) my_error(ER_XAER_INVAL, MYF(0)); - else if (!thd->transaction.xid_state.is_explicit_XA() || - thd->transaction.xid_state.xid_cache_element->xa_state != XA_ACTIVE) - thd->transaction.xid_state.er_xaer_rmfail(); - else if (!thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid)) + else if (!thd->transaction->xid_state.is_explicit_XA() || + thd->transaction->xid_state.xid_cache_element->xa_state != XA_ACTIVE) + thd->transaction->xid_state.er_xaer_rmfail(); + else if (!thd->transaction->xid_state.xid_cache_element->xid.eq(thd->lex->xid)) my_error(ER_XAER_NOTA, MYF(0)); - else if (!xa_trans_rolled_back(thd->transaction.xid_state.xid_cache_element)) + else if (!xa_trans_rolled_back(thd->transaction->xid_state.xid_cache_element)) { - thd->transaction.xid_state.xid_cache_element->xa_state= XA_IDLE; + thd->transaction->xid_state.xid_cache_element->xa_state= XA_IDLE; MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_IDLE); } DBUG_RETURN(thd->is_error() || - thd->transaction.xid_state.xid_cache_element->xa_state != XA_IDLE); + thd->transaction->xid_state.xid_cache_element->xa_state != XA_IDLE); } @@ -509,10 +509,10 @@ bool trans_xa_prepare(THD *thd) DBUG_ENTER("trans_xa_prepare"); - if (!thd->transaction.xid_state.is_explicit_XA() || - thd->transaction.xid_state.xid_cache_element->xa_state != XA_IDLE) - thd->transaction.xid_state.er_xaer_rmfail(); - else if (!thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid)) + if (!thd->transaction->xid_state.is_explicit_XA() || + thd->transaction->xid_state.xid_cache_element->xa_state != XA_IDLE) + thd->transaction->xid_state.er_xaer_rmfail(); + else if (!thd->transaction->xid_state.xid_cache_element->xid.eq(thd->lex->xid)) my_error(ER_XAER_NOTA, MYF(0)); else { @@ -533,15 +533,15 @@ bool trans_xa_prepare(THD *thd) if (!mdl_request.ticket) ha_rollback_trans(thd, TRUE); thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); - xid_cache_delete(thd, &thd->transaction.xid_state); + xid_cache_delete(thd, &thd->transaction->xid_state); my_error(ER_XA_RBROLLBACK, MYF(0)); } else { - thd->transaction.xid_state.xid_cache_element->xa_state= XA_PREPARED; + thd->transaction->xid_state.xid_cache_element->xa_state= XA_PREPARED; MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_PREPARED); res= thd->variables.pseudo_slave_mode || thd->slave_thread ? slave_applier_reset_xa_trans(thd) : 0; @@ -564,7 +564,7 @@ bool trans_xa_prepare(THD *thd) bool trans_xa_commit(THD *thd) { bool res= true; - XID_STATE &xid_state= thd->transaction.xid_state; + XID_STATE &xid_state= thd->transaction->xid_state; DBUG_ENTER("trans_xa_commit"); @@ -655,7 +655,7 @@ bool trans_xa_commit(THD *thd) if ((res= MY_TEST(r))) my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); } - else if (thd->transaction.xid_state.xid_cache_element->xa_state == XA_PREPARED) + else if (thd->transaction->xid_state.xid_cache_element->xa_state == XA_PREPARED) { MDL_request mdl_request; if (thd->lex->xa_opt != XA_NONE) @@ -710,7 +710,7 @@ bool trans_xa_commit(THD *thd) } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.reset(); + thd->transaction->all.reset(); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -734,7 +734,7 @@ bool trans_xa_commit(THD *thd) bool trans_xa_rollback(THD *thd) { - XID_STATE &xid_state= thd->transaction.xid_state; + XID_STATE &xid_state= thd->transaction->xid_state; DBUG_ENTER("trans_xa_rollback"); @@ -817,22 +817,22 @@ bool trans_xa_rollback(THD *thd) bool trans_xa_detach(THD *thd) { - DBUG_ASSERT(thd->transaction.xid_state.is_explicit_XA()); + DBUG_ASSERT(thd->transaction->xid_state.is_explicit_XA()); - if (thd->transaction.xid_state.xid_cache_element->xa_state != XA_PREPARED) + if (thd->transaction->xid_state.xid_cache_element->xa_state != XA_PREPARED) return xa_trans_force_rollback(thd); - else if (!thd->transaction.all.is_trx_read_write()) + else if (!thd->transaction->all.is_trx_read_write()) { - thd->transaction.xid_state.set_error(ER_XA_RBROLLBACK); + thd->transaction->xid_state.set_error(ER_XA_RBROLLBACK); ha_rollback_trans(thd, true); } - thd->transaction.xid_state.xid_cache_element->acquired_to_recovered(); - thd->transaction.xid_state.xid_cache_element= 0; - thd->transaction.cleanup(); + thd->transaction->xid_state.xid_cache_element->acquired_to_recovered(); + thd->transaction->xid_state.xid_cache_element= 0; + thd->transaction->cleanup(); Ha_trx_info *ha_info, *ha_info_next; - for (ha_info= thd->transaction.all.ha_list; + for (ha_info= thd->transaction->all.ha_list; ha_info; ha_info= ha_info_next) { @@ -840,8 +840,8 @@ bool trans_xa_detach(THD *thd) ha_info->reset(); /* keep it conveniently zero-filled */ } - thd->transaction.all.ha_list= 0; - thd->transaction.all.no_2pc= 0; + thd->transaction->all.ha_list= 0; + thd->transaction->all.no_2pc= 0; return false; } @@ -1055,23 +1055,23 @@ static bool slave_applier_reset_xa_trans(THD *thd) ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); - thd->transaction.xid_state.xid_cache_element->acquired_to_recovered(); - thd->transaction.xid_state.xid_cache_element= 0; + thd->transaction->xid_state.xid_cache_element->acquired_to_recovered(); + thd->transaction->xid_state.xid_cache_element= 0; - for (Ha_trx_info *ha_info= thd->transaction.all.ha_list, *ha_info_next; + for (Ha_trx_info *ha_info= thd->transaction->all.ha_list, *ha_info_next; ha_info; ha_info= ha_info_next) { ha_info_next= ha_info->next(); ha_info->reset(); } - thd->transaction.all.ha_list= 0; + thd->transaction->all.ha_list= 0; ha_close_connection(thd); - thd->transaction.cleanup(); - thd->transaction.all.reset(); + thd->transaction->cleanup(); + thd->transaction->all.reset(); - DBUG_ASSERT(!thd->transaction.all.ha_list); - DBUG_ASSERT(!thd->transaction.all.no_2pc); + DBUG_ASSERT(!thd->transaction->all.ha_list); + DBUG_ASSERT(!thd->transaction->all.no_2pc); thd->has_waiter= false; MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi); // TODO/Fixme: commit? diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 15548350b20..98589f1d043 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -399,7 +399,7 @@ static int blackhole_init(void *p) blackhole_hton= (handlerton *)p; blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB; blackhole_hton->create= blackhole_create_handler; - blackhole_hton->flags= HTON_CAN_RECREATE; + blackhole_hton->flags= HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE; mysql_mutex_init(bh_key_mutex_blackhole, &blackhole_mutex, MY_MUTEX_INIT_FAST); diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h index 6ee30877b64..646fba6da9f 100644 --- a/storage/blackhole/ha_blackhole.h +++ b/storage/blackhole/ha_blackhole.h @@ -95,6 +95,10 @@ public: THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); + int delete_table(const char *name) + { + return 0; + } private: virtual int write_row(const uchar *buf); virtual int update_row(const uchar *old_data, const uchar *new_data); diff --git a/storage/cassandra/CMakeLists.txt b/storage/cassandra/CMakeLists.txt index 7f94c94f69d..ecf54826ba5 100644 --- a/storage/cassandra/CMakeLists.txt +++ b/storage/cassandra/CMakeLists.txt @@ -50,5 +50,5 @@ LINK_DIRECTORIES(${LINK_DIR}) IF(CASSANDRASE_OK) MYSQL_ADD_PLUGIN(cassandra ${cassandra_sources} STORAGE_ENGINE - MODULE_ONLY LINK_LIBRARIES thrift COMPONENT cassandra-engine) + MODULE_ONLY LINK_LIBRARIES thrift COMPONENT cassandra-engine DISABLED) ENDIF(CASSANDRASE_OK) diff --git a/storage/columnstore/CMakeLists.txt b/storage/columnstore/CMakeLists.txt new file mode 100644 index 00000000000..34a4255b2c5 --- /dev/null +++ b/storage/columnstore/CMakeLists.txt @@ -0,0 +1,35 @@ +#set(PLUGIN_COLUMNSTORE "NO" CACHE STRING "Enable ColumnStore engine") + +if("NO" STREQUAL "${PLUGIN_COLUMNSTORE}") + return() +endif() + +# this does everything, gets the var from the correct scope, appends new +# values, sets in the correct scope +macro(APPEND_FOR_CPACK V) + get_directory_property(var DIRECTORY columnstore DEFINITION ${V}) + set(${V} "${var}${ARGN}" PARENT_SCOPE) +endmacro() + +IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR +CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR +CMAKE_SYSTEM_PROCESSOR STREQUAL "i386" OR +CMAKE_SYSTEM_PROCESSOR STREQUAL "i686") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCOLUMNSTORE_MATURITY=MariaDB_PLUGIN_MATURITY_BETA") + add_subdirectory(columnstore) + + IF(TARGET columnstore) + # Needed to bump the component changes up to the main scope + APPEND_FOR_CPACK(CPACK_COMPONENTS_ALL) + IF (RPM) + APPEND_FOR_CPACK(CPACK_RPM_columnstore-engine_PACKAGE_REQUIRES " binutils net-tools python3") + APPEND_FOR_CPACK(CPACK_RPM_columnstore-engine_USER_FILELIST ";%ignore /var/lib;%ignore /var") + APPEND_FOR_CPACK(CPACK_RPM_columnstore-engine_PACKAGE_CONFLICTS " thrift MariaDB-columnstore-platform MariaDB-columnstore-libs") + # these three don't have the list semantics, so no append here + SET(CPACK_RPM_columnstore-engine_PRE_INSTALL_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/columnstore/build/preInstall_storage_engine.sh PARENT_SCOPE) + SET(CPACK_RPM_columnstore-engine_POST_INSTALL_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/columnstore/build/postInstall_storage_engine.sh PARENT_SCOPE) + SET(CPACK_RPM_columnstore-engine_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/columnstore/build/preUn_storage_engine.sh PARENT_SCOPE) + ENDIF() + INSTALL_MYSQL_TEST("${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/" "plugin/columnstore") + ENDIF() +ENDIF() diff --git a/storage/columnstore/columnstore b/storage/columnstore/columnstore new file mode 160000 index 00000000000..d9a8f5fd3ca --- /dev/null +++ b/storage/columnstore/columnstore @@ -0,0 +1 @@ +Subproject commit d9a8f5fd3cad63d736ca9c900ce3e9d76c4c0947 diff --git a/storage/columnstore/mysql-test/columnstore/include/cleanup_columnstore.inc b/storage/columnstore/mysql-test/columnstore/include/cleanup_columnstore.inc new file mode 100644 index 00000000000..c1286a5ea64 --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/include/cleanup_columnstore.inc @@ -0,0 +1,4 @@ +--disable_query_log +DROP FUNCTION IF EXISTS mcssystemready; +--enable_query_log + diff --git a/storage/columnstore/mysql-test/columnstore/include/have_columnstore.inc b/storage/columnstore/mysql-test/columnstore/include/have_columnstore.inc new file mode 100644 index 00000000000..f6b97fed471 --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/include/have_columnstore.inc @@ -0,0 +1,13 @@ +if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'columnstore' AND support IN ('YES', 'DEFAULT', 'ENABLED')`) +{ + --skip Test requires engine ColumnStore. +} + +--disable_query_log +CREATE FUNCTION mcssystemready RETURNS INTEGER SONAME 'ha_columnstore.so'; +--enable_query_log + +if (`SELECT mcssystemready() = 0`) +{ + --skip Test requires ColumnStore to be running +} diff --git a/storage/columnstore/mysql-test/columnstore/r/basic.result b/storage/columnstore/mysql-test/columnstore/r/basic.result new file mode 100644 index 00000000000..3be76759732 --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/r/basic.result @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT, b VARCHAR(255)) ENGINE=columnstore; +INSERT INTO t1 (a, b) VALUES (1, 'columnstore'), (2, 'test'); +SELECT * FROM t1; +a b +1 columnstore +2 test +UPDATE t1 SET a=a+100; +SELECT * FROM t1; +a b +101 columnstore +102 test +DELETE FROM t1 WHERE a=101; +SELECT * FROM t1; +a b +102 test +DROP TABLE t1; diff --git a/storage/columnstore/mysql-test/columnstore/suite.opt b/storage/columnstore/mysql-test/columnstore/suite.opt new file mode 100644 index 00000000000..fbd322fdd72 --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/suite.opt @@ -0,0 +1 @@ +--plugin-load-add=$HA_COLUMNSTORE_SO diff --git a/storage/columnstore/mysql-test/columnstore/suite.pm b/storage/columnstore/mysql-test/columnstore/suite.pm new file mode 100644 index 00000000000..5579df4048e --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/suite.pm @@ -0,0 +1,7 @@ +package My::Suite::ColumnStore; + +use My::SysInfo; + +@ISA = qw(My::Suite); + +bless { }; diff --git a/storage/columnstore/mysql-test/columnstore/t/basic.test b/storage/columnstore/mysql-test/columnstore/t/basic.test new file mode 100644 index 00000000000..34ab07d7f64 --- /dev/null +++ b/storage/columnstore/mysql-test/columnstore/t/basic.test @@ -0,0 +1,20 @@ +--source include/have_columnstore.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT, b VARCHAR(255)) ENGINE=columnstore; + +INSERT INTO t1 (a, b) VALUES (1, 'columnstore'), (2, 'test'); +SELECT * FROM t1; + +UPDATE t1 SET a=a+100; +SELECT * FROM t1; + +DELETE FROM t1 WHERE a=101; +SELECT * FROM t1; + +DROP TABLE t1; + +--source include/cleanup_columnstore.inc diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 4ce5b9c6429..e2a919d4684 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -314,7 +314,7 @@ ENDIF(CONNECT_WITH_MONGO) OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON) IF(CONNECT_WITH_REST) - MESSAGE(STATUS "=====> REST support is ON") + MESSAGE_ONCE(CONNECT_WITH_REST "REST support is ON") SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp tabrest.h) add_definitions(-DREST_SUPPORT) FIND_PACKAGE(cpprestsdk QUIET) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 8fa39cc2651..b1b44085e53 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2203,7 +2203,7 @@ int ha_connect::MakeRecord(char *buf) case TYPE_DECIM: p= value->GetCharString(val); charset= tdbp->data_charset(); - rc= fp->store(p, strlen(p), charset, CHECK_FIELD_WARN); + rc= fp->store_text(p, strlen(p), charset, CHECK_FIELD_WARN); break; case TYPE_BIN: p= value->GetCharValue(); @@ -5192,7 +5192,8 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) } // endif pos } // endif open_table_def - + else + rc= ENOENT; free_table_share(share); } else // Temporary file ok= true; diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result index f0ad8553d8b..34f58a845dc 100644 --- a/storage/connect/mysql-test/connect/r/drop-open-error.result +++ b/storage/connect/mysql-test/connect/r/drop-open-error.result @@ -2,6 +2,8 @@ create table t1 (c varchar(8)); create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")'; ERROR HY000: Too long value for 'SRCDEF' drop table mdev9949; +Warnings: +Warning 1017 Can't find file: './test/mdev9949.dos' (errno: 2 "No such file or directory") drop table t1; select @@secure_file_priv 'must be NULL'; must be NULL diff --git a/storage/connect/mysql-test/connect/r/type_inet6.result b/storage/connect/mysql-test/connect/r/type_inet6.result new file mode 100644 index 00000000000..495a7a515b7 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/type_inet6.result @@ -0,0 +1,15 @@ +# +# MDEV-21764 CONNECT table with INET6 field produces warnings upon SELECT +# +CREATE TABLE t1 (a INET6) ENGINE=CONNECT TABLE_TYPE=DOS; +Warnings: +Warning 1105 No file name. Table will use t1.dos +INSERT INTO t1 VALUES ('::'); +INSERT INTO t1 VALUES ('::ffff'); +INSERT INTO t1 VALUES ('ffff::ffff'); +SELECT * FROM t1; +a +:: +::ffff +ffff::ffff +DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/t/type_inet6.test b/storage/connect/mysql-test/connect/t/type_inet6.test new file mode 100644 index 00000000000..19f5c13e270 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/type_inet6.test @@ -0,0 +1,10 @@ +--echo # +--echo # MDEV-21764 CONNECT table with INET6 field produces warnings upon SELECT +--echo # + +CREATE TABLE t1 (a INET6) ENGINE=CONNECT TABLE_TYPE=DOS; +INSERT INTO t1 VALUES ('::'); +INSERT INTO t1 VALUES ('::ffff'); +INSERT INTO t1 VALUES ('ffff::ffff'); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index 6fa3f2e6433..1a266f0e263 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -52,7 +52,6 @@ /* DB static variables. */ /***********************************************************************/ extern int num_read, num_there, num_eq[2]; // Statistics -static const longlong M2G = 0x80000000; char BINCOL::Endian = 'H'; /***********************************************************************/ diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index d9473a8b045..4983236d840 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -883,10 +883,11 @@ err: for CSV engine. For more details see mysys/thr_lock.c */ -void tina_get_status(void* param, my_bool concurrent_insert) +my_bool tina_get_status(void* param, my_bool concurrent_insert) { ha_tina *tina= (ha_tina*) param; tina->get_status(); + return 0; } void tina_update_status(void* param) diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 00168791d35..b62b74d12bb 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -484,7 +484,8 @@ int federated_db_init(void *p) federated_hton->commit= federated_commit; federated_hton->rollback= federated_rollback; federated_hton->create= federated_create_handler; - federated_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION; + federated_hton->flags= (HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION | + HTON_AUTOMATIC_DELETE_TABLE); /* Support for transactions disabled until WL#2952 fixes it. diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index 080d0ebd5f0..2e785f87858 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -244,7 +244,10 @@ public: void update_auto_increment(void); int repair(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt); - + int delete_table(const char *name) + { + return 0; + } int delete_all_rows(void); int truncate(); int create(const char *name, TABLE *form, diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index fef349bbaaf..2370473236e 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -438,7 +438,8 @@ int federatedx_db_init(void *p) federatedx_hton->rollback= ha_federatedx::rollback; federatedx_hton->discover_table_structure= ha_federatedx::discover_assisted; federatedx_hton->create= federatedx_create_handler; - federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED; + federatedx_hton->flags= (HTON_ALTER_NOT_SUPPORTED | + HTON_AUTOMATIC_DELETE_TABLE); federatedx_hton->create_derived= create_federatedx_derived_handler; federatedx_hton->create_select= create_federatedx_select_handler; @@ -3625,6 +3626,9 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, char buf[1024]; String query(buf, sizeof(buf), cs); static LEX_CSTRING cut_clause={STRING_WITH_LEN(" WITH SYSTEM VERSIONING")}; + static LEX_CSTRING cut_start={STRING_WITH_LEN("GENERATED ALWAYS AS ROW START")}; + static LEX_CSTRING cut_end={STRING_WITH_LEN("GENERATED ALWAYS AS ROW END")}; + static LEX_CSTRING set_ts={STRING_WITH_LEN("DEFAULT TIMESTAMP'1971-01-01 00:00:00'")}; int cut_offset; MYSQL_RES *res; MYSQL_ROW rdata; @@ -3663,7 +3667,21 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, cut_offset= (int)query.length() - (int)cut_clause.length; if (cut_offset > 0 && !memcmp(query.ptr() + cut_offset, cut_clause.str, cut_clause.length)) + { query.length(cut_offset); + const char *ptr= strstr(query.ptr(), cut_start.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_start.length, + set_ts.str, (uint32) set_ts.length); + } + ptr= strstr(query.ptr(), cut_end.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_end.length, + set_ts.str, (uint32) set_ts.length); + } + } query.append(STRING_WITH_LEN(" CONNECTION='"), cs); query.append_for_single_quote(table_s->connect_string.str, table_s->connect_string.length); diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index a62456e1c33..67fe5f8cc22 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -431,7 +431,10 @@ public: void update_auto_increment(void); int repair(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt); - + int delete_table(const char *name) + { + return 0; + } int delete_all_rows(void); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); //required diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 3a6b1a25a96..b6ea78115e9 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -56,9 +56,7 @@ SET(INNOBASE_SOURCES fsp/fsp0space.cc fsp/fsp0sysspace.cc fut/fut0lst.cc - ha/ha0ha.cc ha/ha0storage.cc - ha/hash0hash.cc fts/fts0fts.cc fts/fts0ast.cc fts/fts0blex.cc @@ -76,6 +74,218 @@ SET(INNOBASE_SOURCES handler/handler0alter.cc handler/i_s.cc ibuf/ibuf0ibuf.cc + include/btr0btr.h + include/btr0btr.ic + include/btr0bulk.h + include/btr0cur.h + include/btr0cur.ic + include/btr0defragment.h + include/btr0pcur.h + include/btr0pcur.ic + include/btr0sea.h + include/btr0sea.ic + include/btr0types.h + include/buf0buddy.h + include/buf0buf.h + include/buf0buf.ic + include/buf0checksum.h + include/buf0dblwr.h + include/buf0dump.h + include/buf0flu.h + include/buf0flu.ic + include/buf0lru.h + include/buf0rea.h + include/buf0types.h + include/data0data.h + include/data0data.ic + include/data0type.h + include/data0type.ic + include/data0types.h + include/db0err.h + include/dict0boot.h + include/dict0boot.ic + include/dict0crea.h + include/dict0crea.ic + include/dict0defrag_bg.h + include/dict0dict.h + include/dict0dict.ic + include/dict0load.h + include/dict0mem.h + include/dict0mem.ic + include/dict0pagecompress.h + include/dict0pagecompress.ic + include/dict0priv.h + include/dict0priv.ic + include/dict0stats.h + include/dict0stats.ic + include/dict0stats_bg.h + include/dict0types.h + include/dyn0buf.h + include/dyn0types.h + include/eval0eval.h + include/eval0eval.ic + include/eval0proc.h + include/eval0proc.ic + include/fil0crypt.h + include/fil0crypt.ic + include/fil0fil.h + include/fil0fil.ic + include/fil0pagecompress.h + include/fsp0file.h + include/fsp0fsp.h + include/fsp0space.h + include/fsp0sysspace.h + include/fsp0types.h + include/fts0ast.h + include/fts0blex.h + include/fts0fts.h + include/fts0opt.h + include/fts0pars.h + include/fts0plugin.h + include/fts0priv.h + include/fts0priv.ic + include/fts0tlex.h + include/fts0tokenize.h + include/fts0types.h + include/fts0types.ic + include/fts0vlc.ic + include/fut0fut.h + include/fut0lst.h + include/gis0geo.h + include/gis0rtree.h + include/gis0rtree.ic + include/gis0type.h + include/ha_prototypes.h + include/ha0ha.h + include/ha0ha.ic + include/ha0storage.h + include/ha0storage.ic + include/handler0alter.h + include/hash0hash.h + include/ib0mutex.h + include/ibuf0ibuf.h + include/ibuf0ibuf.ic + include/ibuf0types.h + include/lock0iter.h + include/lock0lock.h + include/lock0lock.ic + include/lock0prdt.h + include/lock0priv.h + include/lock0priv.ic + include/lock0types.h + include/log0crypt.h + include/log0log.h + include/log0log.ic + include/log0recv.h + include/log0types.h + include/mach0data.h + include/mach0data.ic + include/mem0mem.h + include/mem0mem.ic + include/mtr0log.h + include/mtr0mtr.h + include/mtr0mtr.ic + include/mtr0types.h + include/os0api.h + include/os0event.h + include/os0file.h + include/os0file.ic + include/os0proc.h + include/os0thread.h + include/page0cur.h + include/page0cur.ic + include/page0page.h + include/page0page.ic + include/page0types.h + include/page0zip.h + include/page0zip.ic + include/pars0grm.h + include/pars0opt.h + include/pars0pars.h + include/pars0sym.h + include/pars0types.h + include/que0que.h + include/que0que.ic + include/que0types.h + include/read0types.h + include/rem0cmp.h + include/rem0cmp.ic + include/rem0rec.h + include/rem0rec.ic + include/rem0types.h + include/row0ext.h + include/row0ext.ic + include/row0ftsort.h + include/row0import.h + include/row0ins.h + include/row0log.h + include/row0log.ic + include/row0merge.h + include/row0mysql.h + include/row0purge.h + include/row0quiesce.h + include/row0row.h + include/row0row.ic + include/row0sel.h + include/row0sel.ic + include/row0types.h + include/row0uins.h + include/row0umod.h + include/row0undo.h + include/row0upd.h + include/row0upd.ic + include/row0vers.h + include/srv0conc.h + include/srv0mon.h + include/srv0mon.ic + include/srv0srv.h + include/srv0start.h + include/sync0arr.h + include/sync0arr.ic + include/sync0debug.h + include/sync0policy.h + include/sync0rw.h + include/sync0rw.ic + include/sync0sync.h + include/sync0types.h + include/trx0i_s.h + include/trx0purge.h + include/trx0rec.h + include/trx0rec.ic + include/trx0roll.h + include/trx0rseg.h + include/trx0rseg.ic + include/trx0sys.h + include/trx0trx.h + include/trx0trx.ic + include/trx0types.h + include/trx0undo.h + include/trx0undo.ic + include/trx0xa.h + include/univ.i + include/ut0byte.h + include/ut0byte.ic + include/ut0counter.h + include/ut0crc32.h + include/ut0dbg.h + include/ut0list.h + include/ut0list.ic + include/ut0lst.h + include/ut0mem.h + include/ut0mem.ic + include/ut0mutex.h + include/ut0new.h + include/ut0pool.h + include/ut0rbt.h + include/ut0rnd.h + include/ut0rnd.ic + include/ut0sort.h + include/ut0stage.h + include/ut0ut.h + include/ut0ut.ic + include/ut0vec.h + include/ut0vec.ic + include/ut0wqueue.h lock/lock0iter.cc lock/lock0prdt.cc lock/lock0lock.cc @@ -150,7 +360,6 @@ MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE DEFAULT RECOMPILE_FOR_EMBEDDED LINK_LIBRARIES ${ZLIB_LIBRARY} - ${CRC32_LIBRARY} ${NUMA_LIBRARY} ${LIBSYSTEMD} ${LINKER_SCRIPT} @@ -192,6 +401,6 @@ IF(MSVC) ENDIF() IF(NOT (PLUGIN_INNOBASE STREQUAL DYNAMIC)) - TARGET_LINK_LIBRARIES(innobase tpool) + TARGET_LINK_LIBRARIES(innobase tpool mysys) ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/extra/mariabackup ${CMAKE_BINARY_DIR}/extra/mariabackup) ENDIF() diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 0a4fb9e1c2b..43a3b44903f 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -65,7 +65,7 @@ btr_can_merge_with_page( void btr_corruption_report(const buf_block_t* block, const dict_index_t* index) { ib::fatal() - << "Flag mismatch in page " << block->page.id + << "Flag mismatch in page " << block->page.id() << " index " << index->name << " of table " << index->table->name; } @@ -287,10 +287,9 @@ btr_height_get( buf_block_t* root_block; ut_ad(srv_read_only_mode - || mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_S_LOCK - | MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); + || mtr->memo_contains_flagged(&index->lock, MTR_MEMO_S_LOCK + | MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); /* S latches the page */ root_block = btr_root_block_get(index, RW_S_LATCH, mtr); @@ -438,7 +437,7 @@ btr_page_create( ulint level, /*!< in: the B-tree level of the page */ mtr_t* mtr) /*!< in: mtr */ { - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); byte *index_id= my_assume_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID + block->frame); @@ -538,22 +537,6 @@ btr_page_alloc_low( seg_header, hint_page_no, file_direction, true, mtr, init_mtr); -#ifdef UNIV_DEBUG_SCRUBBING - if (block != NULL) { - fprintf(stderr, - "alloc %lu:%lu to index: %lu root: %lu\n", - buf_block_get_page_no(block), - buf_block_get_space(block), - index->id, - dict_index_get_page(index)); - } else { - fprintf(stderr, - "failed alloc index: %lu root: %lu\n", - index->id, - dict_index_get_page(index)); - } -#endif /* UNIV_DEBUG_SCRUBBING */ - return block; } @@ -607,8 +590,7 @@ btr_get_size( ulint n=0; ut_ad(srv_read_only_mode - || mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_S_LOCK)); + || mtr->memo_contains(index->lock, MTR_MEMO_S_LOCK)); ut_ad(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE); if (index->page == FIL_NULL @@ -654,9 +636,7 @@ btr_get_size_and_reserved( { ulint dummy; - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_S_LOCK)); - + ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_S_LOCK)); ut_a(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE); if (index->page == FIL_NULL @@ -697,7 +677,7 @@ btr_page_free_for_ibuf( buf_block_t* block, /*!< in: block to be freed, x-latched */ mtr_t* mtr) /*!< in: mtr */ { - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr); @@ -715,14 +695,17 @@ btr_page_free_for_ibuf( void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, bool blob) { - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); #ifdef BTR_CUR_HASH_ADAPT - ut_ad(!block->index || !blob); - ut_ad(!block->index || page_is_leaf(block->frame)); + if (block->index && !block->index->freed()) { + ut_ad(!blob); + ut_ad(page_is_leaf(block->frame)); + } #endif - ut_ad(index->table->space_id == block->page.id.space()); + const page_id_t id(block->page.id()); + ut_ad(index->table->space_id == id.space()); /* The root page is freed by btr_free_root(). */ - ut_ad(block->page.id.page_no() != index->page); + ut_ad(id.page_no() != index->page); ut_ad(mtr->is_named_space(index->table->space)); /* The page gets invalid for optimistic searches: increment the frame @@ -743,18 +726,13 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, ? PAGE_HEADER + PAGE_BTR_SEG_LEAF : PAGE_HEADER + PAGE_BTR_SEG_TOP]; fseg_free_page(seg_header, - index->table->space, block->page.id.page_no(), - block->index != NULL, mtr); + index->table->space, id.page_no(), mtr); + buf_page_free(id, mtr, __FILE__, __LINE__); /* The page was marked free in the allocation bitmap, but it should remain exclusively latched until mtr_t::commit() or until it is explicitly freed from the mini-transaction. */ - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - - /* MDEV-15528 FIXME: Zero out the page after the redo log for - this mini-transaction has been durably written. - This must be done unconditionally if - srv_immediate_scrub_data_uncompressed is set. */ + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); } /** Set the child page number in a node pointer record. @@ -833,14 +811,13 @@ btr_page_get_father_node_ptr_func( ut_ad(latch_mode == BTR_CONT_MODIFY_TREE || latch_mode == BTR_CONT_SEARCH_TREE); - page_no = btr_cur_get_block(cursor)->page.id.page_no(); + page_no = btr_cur_get_block(cursor)->page.id().page_no(); index = btr_cur_get_index(cursor); ut_ad(!dict_index_is_spatial(index)); ut_ad(srv_read_only_mode - || mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); + || mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); ut_ad(dict_index_get_page(index) != page_no); @@ -961,34 +938,22 @@ have been called. In a persistent tablespace, the caller must invoke fsp_init_file_page() before mtr.commit(). @param[in,out] block index root page -@param[in,out] mtr mini-transaction -@param[in] invalidate whether to invalidate PAGE_INDEX_ID */ -static void btr_free_root(buf_block_t *block, mtr_t *mtr, bool invalidate) +@param[in,out] mtr mini-transaction */ +static void btr_free_root(buf_block_t *block, mtr_t *mtr) { - ut_ad(mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr->is_named_space(block->page.id.space())); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->is_named_space(block->page.id().space())); btr_search_drop_page_hash_index(block); #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame, - block->page.id.space())); + block->page.id().space())); #endif /* UNIV_BTR_DEBUG */ - if (invalidate) - { - constexpr uint16_t field= PAGE_HEADER + PAGE_INDEX_ID; - - byte *page_index_id= my_assume_aligned<2>(field + block->frame); - if (mtr->write<8,mtr_t::MAYBE_NOP>(*block, page_index_id, - BTR_FREED_INDEX_ID) && - UNIV_LIKELY_NULL(block->page.zip.data)) - memcpy_aligned<2>(&block->page.zip.data[field], page_index_id, 8); - } /* Free the entire segment in small steps. */ - while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame, - true, mtr)); + while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP + block->frame, mtr)); } /** Prepare to free a B-tree. @@ -1068,7 +1033,7 @@ btr_create( buf_block_dbg_add_level( ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW); - ut_ad(ibuf_hdr_block->page.id.page_no() + ut_ad(ibuf_hdr_block->page.id().page_no() == IBUF_HEADER_PAGE_NO); /* Allocate then the next page to the segment: it will be the tree root page */ @@ -1083,7 +1048,7 @@ btr_create( return(FIL_NULL); } - ut_ad(block->page.id.page_no() == IBUF_TREE_ROOT_PAGE_NO); + ut_ad(block->page.id().page_no() == IBUF_TREE_ROOT_PAGE_NO); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); @@ -1098,12 +1063,11 @@ btr_create( buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); - if (!fseg_create(space, block->page.id.page_no(), + if (!fseg_create(space, block->page.id().page_no(), PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { /* Not enough space for new segment, free root segment before return. */ - btr_free_root(block, mtr, - !index || !index->table->is_temporary()); + btr_free_root(block, mtr); return(FIL_NULL); } @@ -1164,7 +1128,7 @@ btr_create( ut_ad(page_get_max_insert_size(block->frame, 2) > 2 * BTR_PAGE_MAX_REC_SIZE); - return(block->page.id.page_no()); + return(block->page.id().page_no()); } /** Free a B-tree except the root page. The root page MUST be freed after @@ -1184,7 +1148,7 @@ btr_free_but_not_root( leaf_loop: mtr_start(&mtr); mtr_set_log_mode(&mtr, log_mode); - mtr.set_named_space_id(block->page.id.space()); + mtr.set_named_space_id(block->page.id().space()); page_t* root = block->frame; @@ -1195,16 +1159,16 @@ leaf_loop: #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF - + root, block->page.id.space())); + + root, block->page.id().space())); ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP - + root, block->page.id.space())); + + root, block->page.id().space())); #endif /* UNIV_BTR_DEBUG */ /* NOTE: page hash indexes are dropped when a page is freed inside fsp0fsp. */ bool finished = fseg_free_step(root + PAGE_HEADER + PAGE_BTR_SEG_LEAF, - true, &mtr); + &mtr); mtr_commit(&mtr); if (!finished) { @@ -1214,17 +1178,17 @@ leaf_loop: top_loop: mtr_start(&mtr); mtr_set_log_mode(&mtr, log_mode); - mtr.set_named_space_id(block->page.id.space()); + mtr.set_named_space_id(block->page.id().space()); root = block->frame; #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP - + root, block->page.id.space())); + + root, block->page.id().space())); #endif /* UNIV_BTR_DEBUG */ finished = fseg_free_step_not_header( - root + PAGE_HEADER + PAGE_BTR_SEG_TOP, true, &mtr); + root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr); mtr_commit(&mtr); if (!finished) { @@ -1253,7 +1217,7 @@ btr_free_if_exists( btr_free_but_not_root(root, mtr->get_log_mode()); mtr->set_named_space_id(page_id.space()); - btr_free_root(root, mtr, true); + btr_free_root(root, mtr); } /** Free an index tree in a temporary tablespace. @@ -1268,7 +1232,7 @@ void btr_free(const page_id_t page_id) if (block) { btr_free_but_not_root(block, MTR_LOG_NO_REDO); - btr_free_root(block, &mtr, false); + btr_free_root(block, &mtr); } mtr.commit(); } @@ -1382,12 +1346,13 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index, buf_block_t *const block= cursor->block; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!is_buf_block_get_page_zip(block)); btr_assert_not_corrupted(block, index); ut_ad(fil_page_index_page_check(block->frame)); - ut_ad(index->is_dummy || block->page.id.space() == index->table->space->id); - ut_ad(index->is_dummy || block->page.id.page_no() != index->page || + ut_ad(index->is_dummy || + block->page.id().space() == index->table->space->id); + ut_ad(index->is_dummy || block->page.id().page_no() != index->page || !page_has_siblings(block->frame)); buf_block_t *old= buf_block_alloc(); @@ -1422,7 +1387,7 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index, clustered index root pages. */ ut_ad(dict_index_is_sec_or_ibuf(index) ? page_is_leaf(block->frame) - : block->page.id.page_no() == index->page); + : block->page.id().page_no() == index->page); else /* PAGE_MAX_TRX_ID is unused in clustered index pages (other than the root where it is repurposed as PAGE_ROOT_AUTO_INC), non-leaf @@ -1450,7 +1415,7 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index, else ut_ad(cursor->rec == page_get_infimum_rec(block->frame)); - if (block->page.id.page_no() == index->page && + if (block->page.id().page_no() == index->page && fil_page_get_type(old->frame) == FIL_PAGE_TYPE_INSTANT) { /* Preserve the PAGE_INSTANT information. */ @@ -1690,10 +1655,10 @@ btr_page_empty( ulint level, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_zip == buf_block_get_page_zip(block)); ut_ad(!index->is_dummy); - ut_ad(index->table->space->id == block->page.id.space()); + ut_ad(index->table->space->id == block->page.id().space()); #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index)); #endif /* UNIV_ZIP_DEBUG */ @@ -1707,7 +1672,7 @@ btr_page_empty( root page. */ const ib_uint64_t autoinc = dict_index_is_clust(index) - && index->page == block->page.id.page_no() + && index->page == block->page.id().page_no() ? page_get_autoinc(block->frame) : 0; @@ -1748,7 +1713,7 @@ void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr) ut_ad(fil_page_get_type(root->frame) == FIL_PAGE_TYPE_INSTANT || fil_page_get_type(root->frame) == FIL_PAGE_INDEX); ut_ad(!page_has_siblings(root->frame)); - ut_ad(root->page.id.page_no() == index.page); + ut_ad(root->page.id().page_no() == index.page); rec_t* infimum = page_get_infimum_rec(root->frame); rec_t* supremum = page_get_supremum_rec(root->frame); @@ -1890,12 +1855,11 @@ btr_root_raise_and_insert( + root->frame, space)); } - ut_a(dict_index_get_page(index) == root->page.id.page_no()); + ut_a(dict_index_get_page(index) == root->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, root, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(root, MTR_MEMO_PAGE_X_FIX)); /* Allocate a new page to the tree. Root splitting is done by first moving the root records to the new page, emptying the root, putting @@ -2003,7 +1967,7 @@ btr_root_raise_and_insert( } rec = page_rec_get_next(page_get_infimum_rec(new_block->frame)); - new_page_no = new_block->page.id.page_no(); + new_page_no = new_block->page.id().page_no(); /* Build the node pointer (= node key and page address) for the child */ @@ -2487,8 +2451,8 @@ btr_attach_half_pages( buf_block_t* lower_block; buf_block_t* upper_block; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains(mtr, new_block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(new_block, MTR_MEMO_PAGE_X_FIX)); /* Create a memory heap where the data tuple is stored */ heap = mem_heap_create(1024); @@ -2512,7 +2476,7 @@ btr_attach_half_pages( btr_node_ptr_set_child_page_no( btr_cur_get_block(&cursor), btr_cur_get_rec(&cursor), - offsets, lower_block->page.id.page_no(), mtr); + offsets, lower_block->page.id().page_no(), mtr); mem_heap_empty(heap); } else { lower_block = block; @@ -2541,7 +2505,8 @@ btr_attach_half_pages( half */ node_ptr_upper = dict_index_build_node_ptr( - index, split_rec, upper_block->page.id.page_no(), heap, level); + index, split_rec, upper_block->page.id().page_no(), + heap, level); /* Insert it next to the pointer to the lower half. Note that this may generate recursion leading to a split on the higher level. */ @@ -2559,9 +2524,9 @@ btr_attach_half_pages( ut_a(page_is_comp(prev_block->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_next(prev_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ - btr_page_set_next(prev_block, lower_block->page.id.page_no(), + btr_page_set_next(prev_block, lower_block->page.id().page_no(), mtr); } @@ -2570,9 +2535,9 @@ btr_attach_half_pages( ut_a(page_is_comp(next_block->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_prev(next_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ - btr_page_set_prev(next_block, upper_block->page.id.page_no(), + btr_page_set_prev(next_block, upper_block->page.id().page_no(), mtr); } @@ -2586,8 +2551,8 @@ btr_attach_half_pages( btr_page_set_next(upper_block, next_page_no, mtr); } - btr_page_set_prev(upper_block, lower_block->page.id.page_no(), mtr); - btr_page_set_next(lower_block, upper_block->page.id.page_no(), mtr); + btr_page_set_prev(upper_block, lower_block->page.id().page_no(), mtr); + btr_page_set_next(lower_block, upper_block->page.id().page_no(), mtr); } /*************************************************************//** @@ -2649,10 +2614,9 @@ btr_insert_into_right_sibling( page_t* page = buf_block_get_frame(block); const uint32_t next_page_no = btr_page_get_next(page); - ut_ad(mtr_memo_contains_flagged( - mtr, dict_index_get_lock(cursor->index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, + MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(heap); if (next_page_no == FIL_NULL || !page_rec_is_supremum( @@ -2731,7 +2695,7 @@ btr_insert_into_right_sibling( } dtuple_t* node_ptr = dict_index_build_node_ptr( - cursor->index, rec, next_block->page.id.page_no(), + cursor->index, rec, next_block->page.id().page_no(), heap, level); btr_insert_on_non_leaf_level( @@ -2811,9 +2775,8 @@ func_start: mem_heap_empty(*heap); *offsets = NULL; - ut_ad(mtr_memo_contains_flagged(mtr, - dict_index_get_lock(cursor->index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); ut_ad(!dict_index_is_online_ddl(cursor->index) || (flags & BTR_CREATE_FLAG) || dict_index_is_clust(cursor->index)); @@ -2824,7 +2787,7 @@ func_start: page = buf_block_get_frame(block); page_zip = buf_block_get_page_zip(block); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!page_is_empty(page)); /* try to insert to the next page if possible before split */ @@ -2837,7 +2800,7 @@ func_start: tuple to be inserted should be the first record on the upper half-page */ bool insert_left = false; - ulint hint_page_no = block->page.id.page_no() + 1; + ulint hint_page_no = block->page.id().page_no() + 1; byte direction = FSP_UP; if (tuple && n_iterations > 0) { @@ -3173,9 +3136,9 @@ func_exit: void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, &block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_X_FIX)); ut_ad(block.zip_size() == index.table->space->zip_size()); - ut_ad(index.table->space->id == block.page.id.space()); + ut_ad(index.table->space->id == block.page.id().space()); /* Get the previous and next page numbers of page */ const page_t* page = block.frame; @@ -3242,7 +3205,7 @@ btr_lift_page_up( buf_block_t* block_orig = block; ut_ad(!page_has_siblings(page)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); page_level = btr_page_get_level(page); root_page_no = dict_index_get_page(index); @@ -3276,7 +3239,7 @@ btr_lift_page_up( the first level, the tree is in an inconsistent state and can not be searched. */ for (b = father_block; - b->page.id.page_no() != root_page_no; ) { + b->page.id().page_no() != root_page_no; ) { ut_a(n_blocks < BTR_MAX_LEVELS); if (dict_index_is_spatial(index)) { @@ -3309,8 +3272,8 @@ btr_lift_page_up( page_level = btr_page_get_level(page); ut_ad(!page_has_siblings(page)); - ut_ad(mtr_memo_contains( - mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, + MTR_MEMO_PAGE_X_FIX)); father_block = blocks[0]; father_page_zip = buf_block_get_page_zip(father_block); @@ -3327,7 +3290,7 @@ btr_lift_page_up( ut_ad(!page_get_instant(father_block->frame)); if (index->is_instant() - && father_block->page.id.page_no() == root_page_no) { + && father_block->page.id().page_no() == root_page_no) { ut_ad(!father_page_zip); btr_set_instant(father_block, *index, mtr); } @@ -3370,7 +3333,7 @@ btr_lift_page_up( if (dict_index_is_spatial(index)) { lock_mutex_enter(); lock_prdt_page_free_from_discard( - block, lock_sys.prdt_page_hash); + block, &lock_sys.prdt_page_hash); lock_mutex_exit(); } lock_update_copy_and_discard(father_block, block); @@ -3446,18 +3409,9 @@ btr_compress( btr_assert_not_corrupted(block, index); -#ifdef UNIV_DEBUG - if (dict_index_is_spatial(index)) { - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK)); - } else { - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - } -#endif /* UNIV_DEBUG */ - - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); MONITOR_INC(MONITOR_INDEX_MERGE_ATTEMPTS); @@ -3477,16 +3431,15 @@ btr_compress( if (dict_index_is_spatial(index)) { offsets = rtr_page_get_father_block( NULL, heap, index, block, mtr, cursor, &father_cursor); - ut_ad(cursor->page_cur.block->page.id.page_no() - == block->page.id.page_no()); + ut_ad(cursor->page_cur.block->page.id() == block->page.id()); rec_t* my_rec = father_cursor.page_cur.rec; ulint page_no = btr_node_ptr_get_child_page_no(my_rec, offsets); - if (page_no != block->page.id.page_no()) { + if (page_no != block->page.id().page_no()) { ib::info() << "father positioned on page " << page_no << "instead of " - << block->page.id.page_no(); + << block->page.id().page_no(); offsets = btr_page_get_father_block( NULL, heap, index, block, mtr, &father_cursor); } @@ -3537,25 +3490,13 @@ retry: #ifdef UNIV_BTR_DEBUG if (is_left) { ut_a(btr_page_get_next(merge_page) - == block->page.id.page_no()); + == block->page.id().page_no()); } else { ut_a(btr_page_get_prev(merge_page) - == block->page.id.page_no()); + == block->page.id().page_no()); } #endif /* UNIV_BTR_DEBUG */ -#ifdef UNIV_GIS_DEBUG - if (dict_index_is_spatial(index)) { - if (is_left) { - fprintf(stderr, "GIS_DIAG: merge left %ld to %ld \n", - (long) block->page.id.page_no(), left_page_no); - } else { - fprintf(stderr, "GIS_DIAG: merge right %ld to %ld\n", - (long) block->page.id.page_no(), right_page_no); - } - } -#endif /* UNIV_GIS_DEBUG */ - ut_ad(page_validate(merge_page, index)); merge_page_zip = buf_block_get_page_zip(merge_block); @@ -3622,13 +3563,10 @@ retry: ulint page_no = btr_node_ptr_get_child_page_no( my_rec, offsets); - if (page_no != block->page.id.page_no()) { - + if (page_no != block->page.id().page_no()) { ib::fatal() << "father positioned on " << page_no << " instead of " - << block->page.id.page_no(); - - ut_ad(0); + << block->page.id().page_no(); } if (mbr_changed) { @@ -3650,7 +3588,7 @@ retry: /* No GAP lock needs to be worrying about */ lock_mutex_enter(); lock_prdt_page_free_from_discard( - block, lock_sys.prdt_page_hash); + block, &lock_sys.prdt_page_hash); lock_rec_free_all_from_discard_page(block); lock_mutex_exit(); } else { @@ -3747,8 +3685,8 @@ retry: btr_level_list_remove(*block, *index, mtr); ut_ad(btr_node_ptr_get_child_page_no( - btr_cur_get_rec(&father_cursor), offsets) - == block->page.id.page_no()); + btr_cur_get_rec(&father_cursor), offsets) + == block->page.id().page_no()); /* Replace the address of the old child node (= page) with the address of the merge page to the right */ @@ -3803,7 +3741,7 @@ retry: } lock_mutex_enter(); lock_prdt_page_free_from_discard( - block, lock_sys.prdt_page_hash); + block, &lock_sys.prdt_page_hash); lock_rec_free_all_from_discard_page(block); lock_mutex_exit(); } else { @@ -3877,13 +3815,6 @@ retry: #endif /* UNIV_ZIP_DEBUG */ if (dict_index_is_spatial(index)) { -#ifdef UNIV_GIS_DEBUG - fprintf(stderr, "GIS_DIAG: compressed away %ld\n", - (long) block->page.id.page_no()); - fprintf(stderr, "GIS_DIAG: merged to %ld\n", - (long) merge_block->page.id.page_no()); -#endif - rtr_check_discard_page(index, NULL, block); } @@ -3945,7 +3876,7 @@ btr_discard_only_page_on_level( /* Save the PAGE_MAX_TRX_ID from the leaf page. */ max_trx_id = page_get_max_trx_id(buf_block_get_frame(block)); - while (block->page.id.page_no() != dict_index_get_page(index)) { + while (block->page.id().page_no() != dict_index_get_page(index)) { btr_cur_t cursor; buf_block_t* father; const page_t* page = buf_block_get_frame(block); @@ -3954,8 +3885,8 @@ btr_discard_only_page_on_level( ut_a(page_level == btr_page_get_level(page)); ut_a(!page_has_siblings(page)); ut_ad(fil_page_index_page_check(page)); - ut_ad(block->page.id.space() == index->table->space->id); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(block->page.id().space() == index->table->space->id); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); btr_search_drop_page_hash_index(block); if (dict_index_is_spatial(index)) { @@ -3997,11 +3928,14 @@ btr_discard_only_page_on_level( mem_heap_t* heap = NULL; const rec_t* rec = NULL; rec_offs* offsets = NULL; - if (index->table->instant) { + + if (index->table->instant || index->must_avoid_clear_instant_add()) { const rec_t* r = page_rec_get_next(page_get_infimum_rec( block->frame)); ut_ad(rec_is_metadata(r, *index) == index->is_instant()); - if (rec_is_alter_metadata(r, *index)) { + if (!rec_is_metadata(r, *index)) { + } else if (!index->table->instant + || rec_is_alter_metadata(r, *index)) { heap = mem_heap_create(srv_page_size); offsets = rec_get_offsets(r, index, NULL, true, ULINT_UNDEFINED, &heap); @@ -4063,12 +3997,11 @@ btr_discard_page( block = btr_cur_get_block(cursor); index = btr_cur_get_index(cursor); - ut_ad(dict_index_get_page(index) != block->page.id.page_no()); + ut_ad(dict_index_get_page(index) != block->page.id().page_no()); - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); - - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); MONITOR_INC(MONITOR_INDEX_DISCARD); @@ -4089,7 +4022,7 @@ btr_discard_page( true, mtr); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_next(merge_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ ut_d(parent_is_different = (page_rec_get_next( @@ -4102,7 +4035,7 @@ btr_discard_page( true, mtr); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_prev(merge_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ ut_d(parent_is_different = page_rec_is_supremum( page_rec_get_next(btr_cur_get_rec(&parent_cursor)))); @@ -4169,7 +4102,8 @@ btr_discard_page( ut_ad(parent_is_different || btr_check_node_ptr(index, merge_block, mtr)); - if (btr_cur_get_block(&parent_cursor)->page.id.page_no() == index->page + if (btr_cur_get_block(&parent_cursor)->page.id().page_no() + == index->page && !page_has_siblings(btr_cur_get_page(&parent_cursor)) && page_get_n_recs(btr_cur_get_page(&parent_cursor)) == 1) { btr_lift_page_up(index, merge_block, mtr); @@ -4235,7 +4169,7 @@ btr_print_recursive( ulint i = 0; mtr_t mtr2; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_SX_FIX)); ib::info() << "NODE ON LEVEL " << btr_page_get_level(page) << " page " << block->page.id; @@ -4329,9 +4263,9 @@ btr_check_node_ptr( btr_cur_t cursor; page_t* page = buf_block_get_frame(block); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); - if (dict_index_get_page(index) == block->page.id.page_no()) { + if (dict_index_get_page(index) == block->page.id().page_no()) { return(TRUE); } @@ -4614,7 +4548,7 @@ btr_validate_report1( const buf_block_t* block) /*!< in: index page */ { ib::error error; - error << "In page " << block->page.id.page_no() + error << "In page " << block->page.id().page_no() << " of index " << index->name << " of table " << index->table->name; @@ -4634,14 +4568,13 @@ btr_validate_report2( const buf_block_t* block1, /*!< in: first index page */ const buf_block_t* block2) /*!< in: second index page */ { - ib::error error; - error << "In pages " << block1->page.id - << " and " << block2->page.id << " of index " << index->name - << " of table " << index->table->name; + ib::error error; + error << "In pages " << block1->page.id() + << " and " << block2->page.id() << " of index " << index->name + << " of table " << index->table->name; - if (level > 0) { - error << ", index tree level " << level; - } + if (level) + error << ", index tree level " << level; } /************************************************************//** @@ -4700,7 +4633,7 @@ btr_validate_level( while (level != btr_page_get_level(page)) { const rec_t* node_ptr; - if (fseg_page_is_free(space, block->page.id.page_no())) { + if (fseg_page_is_free(space, block->page.id().page_no())) { btr_validate_report1(index, level, block); @@ -4709,8 +4642,8 @@ btr_validate_level( ret = false; } - ut_a(index->table->space_id == block->page.id.space()); - ut_a(block->page.id.space() == page_get_space_id(page)); + ut_a(index->table->space_id == block->page.id().space()); + ut_a(block->page.id().space() == page_get_space_id(page)); #ifdef UNIV_ZIP_DEBUG page_zip = buf_block_get_page_zip(block); ut_a(!page_zip || page_zip_validate(page_zip, page, index)); @@ -4773,9 +4706,9 @@ loop: ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - ut_a(block->page.id.space() == index->table->space_id); + ut_a(block->page.id().space() == index->table->space_id); - if (fseg_page_is_free(space, block->page.id.page_no())) { + if (fseg_page_is_free(space, block->page.id().page_no())) { btr_validate_report1(index, level, block); @@ -4885,7 +4818,7 @@ loop: 2) Search parent from root is very costly for R-tree. We will add special validation mechanism for R-tree later (WL #7520) */ if (!dict_index_is_spatial(index) - && block->page.id.page_no() != dict_index_get_page(index)) { + && block->page.id().page_no() != dict_index_get_page(index)) { /* Check father node pointers */ rec_t* node_ptr; @@ -4914,7 +4847,7 @@ loop: if (node_ptr != btr_cur_get_rec(&node_cur) || btr_node_ptr_get_child_page_no(node_ptr, offsets) - != block->page.id.page_no()) { + != block->page.id().page_no()) { btr_validate_report1(index, level, block); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 00e1599229a..a282826b8de 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -227,10 +227,10 @@ btr_cur_latch_leaves( compile_time_assert(int(MTR_MEMO_PAGE_S_FIX) == int(RW_S_LATCH)); compile_time_assert(int(MTR_MEMO_PAGE_X_FIX) == int(RW_X_LATCH)); compile_time_assert(int(MTR_MEMO_PAGE_SX_FIX) == int(RW_SX_LATCH)); - ut_ad(block->page.id.space() == cursor->index->table->space->id); + ut_ad(block->page.id().space() == cursor->index->table->space->id); spatial = dict_index_is_spatial(cursor->index) && cursor->rtr_info; - ut_ad(buf_page_in_file(&block->page)); + ut_ad(block->page.in_file()); switch (latch_mode) { case BTR_SEARCH_LEAF: @@ -244,7 +244,7 @@ btr_cur_latch_leaves( mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH; latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); get_block = btr_block_get(*cursor->index, - block->page.id.page_no(), mode, + block->page.id().page_no(), mode, true, mtr); latch_leaves.blocks[1] = get_block; #ifdef UNIV_BTR_DEBUG @@ -260,10 +260,9 @@ btr_cur_latch_leaves( case BTR_MODIFY_TREE: /* It is exclusive for other operations which calls btr_page_set_prev() */ - ut_ad(mtr_memo_contains_flagged( - mtr, - dict_index_get_lock(cursor->index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); /* x-latch also siblings from left to right */ left_page_no = btr_page_get_prev(block->frame); @@ -293,7 +292,7 @@ btr_cur_latch_leaves( latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); get_block = btr_block_get( - *cursor->index, block->page.id.page_no(), + *cursor->index, block->page.id().page_no(), RW_X_LATCH, true, mtr); latch_leaves.blocks[1] = get_block; @@ -303,7 +302,7 @@ btr_cur_latch_leaves( ut_a(page_is_comp(latch_leaves.blocks[0]->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_next(latch_leaves.blocks[0]->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); } ut_a(page_is_comp(get_block->frame) == page_is_comp(block->frame)); @@ -331,7 +330,7 @@ btr_cur_latch_leaves( ut_a(page_is_comp(get_block->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_prev(get_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ if (spatial) { cursor->rtr_info->tree_blocks[ @@ -360,13 +359,13 @@ btr_cur_latch_leaves( ut_a(page_is_comp(get_block->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_next(get_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ } latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); get_block = btr_block_get(*cursor->index, - block->page.id.page_no(), mode, + block->page.id().page_no(), mode, true, mtr); latch_leaves.blocks[1] = get_block; #ifdef UNIV_BTR_DEBUG @@ -784,14 +783,11 @@ btr_cur_optimistic_latch_leaves( mode = *latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH; - buf_page_mutex_enter(block); - if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { - buf_page_mutex_exit(block); + if (block->page.state() != BUF_BLOCK_FILE_PAGE) { return(false); } /* pin the block not to be relocated */ buf_block_buf_fix_inc(block, file, line); - buf_page_mutex_exit(block); rw_lock_s_lock(&block->lock); if (block->modify_clock != modify_clock) { @@ -916,8 +912,8 @@ btr_cur_will_modify_tree( mtr_t* mtr) { ut_ad(!page_is_leaf(page)); - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); /* Pessimistic delete of the first record causes delete & insert of node_ptr at upper level. And a subsequent page shrink is @@ -1303,10 +1299,12 @@ btr_cur_search_to_nth_level_func( ut_ad(!(index->type & DICT_FTS)); ut_ad(index->page != FIL_NULL); - UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match); - UNIV_MEM_INVALID(&cursor->up_bytes, sizeof cursor->up_bytes); - UNIV_MEM_INVALID(&cursor->low_match, sizeof cursor->low_match); - UNIV_MEM_INVALID(&cursor->low_bytes, sizeof cursor->low_bytes); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&cursor->up_match, sizeof cursor->up_match); + MEM_UNDEFINED(&cursor->up_bytes, sizeof cursor->up_bytes); + MEM_UNDEFINED(&cursor->low_match, sizeof cursor->low_match); + MEM_UNDEFINED(&cursor->low_bytes, sizeof cursor->low_bytes); +#endif /* HAVE_valgrind_or_MSAN */ #ifdef UNIV_DEBUG cursor->up_match = ULINT_UNDEFINED; cursor->low_match = ULINT_UNDEFINED; @@ -1318,10 +1316,8 @@ btr_cur_search_to_nth_level_func( ut_ad(!s_latch_by_caller || srv_read_only_mode - || mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_S_LOCK - | MTR_MEMO_SX_LOCK)); + || mtr->memo_contains_flagged(&index->lock, MTR_MEMO_S_LOCK + | MTR_MEMO_SX_LOCK)); /* These flags are mutually exclusive, they are lumped together with the latch mode for historical reasons. It's possible for @@ -1479,10 +1475,9 @@ x_latch_index: case BTR_CONT_SEARCH_TREE: /* Do nothing */ ut_ad(srv_read_only_mode - || mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); + || mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); if (dict_index_is_spatial(index) && latch_mode == BTR_CONT_MODIFY_TREE) { /* If we are about to locating parent page for split @@ -1678,11 +1673,11 @@ retry_page_get: cursor->flag = BTR_CUR_DELETE_IBUF; } else { /* The purge could not be buffered. */ - buf_pool_watch_unset(page_id); + buf_pool.watch_unset(page_id); break; } - buf_pool_watch_unset(page_id); + buf_pool.watch_unset(page_id); goto func_exit; default: @@ -1877,10 +1872,10 @@ retry_page_get: if (n_releases == 0 && (modify_external || autoinc)) { /* keep the root page latch */ - ut_ad(mtr_memo_contains_flagged( - mtr, tree_blocks[n_releases], - MTR_MEMO_PAGE_SX_FIX - | MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged( + tree_blocks[n_releases], + MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_PAGE_X_FIX)); continue; } @@ -2090,9 +2085,8 @@ need_opposite_intention: if (latch_mode == BTR_MODIFY_TREE && rw_latch == RW_NO_LATCH) { - ut_ad(mtr_memo_contains_flagged( - mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK + ut_ad(mtr->memo_contains_flagged( + &index->lock, MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); rw_lock_s_lock(&block->lock); add_latch = true; @@ -2248,9 +2242,9 @@ need_opposite_intention: && !retrying_for_search_prev) { /* block should be latched for consistent btr_page_get_prev() */ - ut_ad(mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged( + block, MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX)); if (page_has_prev(page) && page_rec_is_first(node_ptr, page)) { @@ -2280,7 +2274,7 @@ need_opposite_intention: - (leftmost_from_level - 1); page_id.set_page_no( - tree_blocks[idx]->page.id.page_no()); + tree_blocks[idx]->page.id().page_no()); for (ulint i = n_blocks - (leftmost_from_level - 1); @@ -2402,18 +2396,16 @@ need_opposite_intention: ? RW_X_LATCH : RW_SX_LATCH, false, mtr); btr_assert_not_corrupted(child_block, index); } else { - ut_ad(mtr_memo_contains(mtr, block, - static_cast - (upper_rw_latch))); + ut_ad(mtr->memo_contains_flagged(block, + upper_rw_latch)); btr_assert_not_corrupted(block, index); if (s_latch_by_caller) { ut_ad(latch_mode == BTR_SEARCH_TREE); /* to exclude modifying tree operations should sx-latch the index. */ - ut_ad(mtr_memo_contains( - mtr, dict_index_get_lock(index), - MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains(index->lock, + MTR_MEMO_SX_LOCK)); /* because has sx-latch of index, can release upper blocks. */ for (; n_releases < n_blocks; n_releases++) { @@ -2592,10 +2584,9 @@ btr_cur_open_at_index_side_func( break; default: ut_ad(!s_latch_by_caller - || mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_SX_LOCK - | MTR_MEMO_S_LOCK)); + || mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_SX_LOCK + | MTR_MEMO_S_LOCK)); if (!srv_read_only_mode) { if (!s_latch_by_caller) { /* BTR_SEARCH_TREE is intended to be used with @@ -2729,14 +2720,14 @@ btr_cur_open_at_index_side_func( ut_ad(latch_mode == BTR_SEARCH_TREE); ut_ad(s_latch_by_caller); ut_ad(upper_rw_latch == RW_S_LATCH); - ut_ad(mtr_memo_contains(mtr, block, - MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_flagged(block, + MTR_MEMO_PAGE_S_FIX)); if (s_latch_by_caller) { /* to exclude modifying tree operations should sx-latch the index. */ - ut_ad(mtr_memo_contains(mtr, &index->lock, - MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains(index->lock, + MTR_MEMO_SX_LOCK)); /* because has sx-latch of index, can release upper blocks. */ for (; n_releases < n_blocks; n_releases++) { @@ -3188,8 +3179,8 @@ btr_cur_insert_if_possible( ut_ad(dtuple_check_typed(tuple)); - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); page_cursor = btr_cur_get_page_cur(cursor); /* Now, try the insert */ @@ -3306,16 +3297,14 @@ static void btr_cur_prefetch_siblings(const buf_block_t* block) const page_t *page= block->frame; ut_ad(page_is_leaf(page)); - uint32_t left_page_no= mach_read_from_4(my_assume_aligned<4> - (page + FIL_PAGE_PREV)); - uint32_t right_page_no= mach_read_from_4(my_assume_aligned<4> - (page + FIL_PAGE_NEXT)); + uint32_t prev= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV)); + uint32_t next= mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_NEXT)); - if (left_page_no != FIL_NULL) - buf_read_page_background(page_id_t(block->page.id.space(), left_page_no), + if (prev != FIL_NULL) + buf_read_page_background(page_id_t(block->page.id().space(), prev), block->zip_size(), false); - if (right_page_no != FIL_NULL) - buf_read_page_background(page_id_t(block->page.id.space(), right_page_no), + if (next != FIL_NULL) + buf_read_page_background(page_id_t(block->page.id().space(), next), block->zip_size(), false); } @@ -3360,7 +3349,7 @@ btr_cur_optimistic_insert( page_t* page; rec_t* dummy; bool leaf; - bool reorg; + bool reorg __attribute__((unused)); bool inherit = true; ulint rec_size; dberr_t err; @@ -3372,19 +3361,18 @@ btr_cur_optimistic_insert( page = buf_block_get_frame(block); index = cursor->index; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_online_ddl(index) || dict_index_is_clust(index) || (flags & BTR_CREATE_FLAG)); ut_ad(dtuple_check_typed(entry)); -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind_or_MSAN if (block->page.zip.data) { - UNIV_MEM_ASSERT_RW(page, srv_page_size); - UNIV_MEM_ASSERT_RW(block->page.zip.data, - block->zip_size()); + MEM_CHECK_DEFINED(page, srv_page_size); + MEM_CHECK_DEFINED(block->page.zip.data, block->zip_size()); } -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ leaf = page_is_leaf(page); @@ -3574,7 +3562,7 @@ fail_err: ut_ad(index->is_instant()); ut_ad(flags == BTR_NO_LOCKING_FLAG); } else { - rw_lock_t* ahi_latch = btr_get_search_latch(index); + rw_lock_t* ahi_latch = btr_search_sys.get_latch(*index); if (!reorg && cursor->flag == BTR_CUR_HASH) { btr_search_update_hash_node_on_insert( cursor, ahi_latch); @@ -3666,11 +3654,10 @@ btr_cur_pessimistic_insert( *big_rec = NULL; - ut_ad(mtr_memo_contains_flagged( - mtr, dict_index_get_lock(btr_cur_get_index(cursor)), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_online_ddl(index) || dict_index_is_clust(index) || (flags & BTR_CREATE_FLAG)); @@ -3731,7 +3718,7 @@ btr_cur_pessimistic_insert( } if (dict_index_get_page(index) - == btr_cur_get_block(cursor)->page.id.page_no()) { + == btr_cur_get_block(cursor)->page.id().page_no()) { /* The page is the root page */ *rec = btr_root_raise_and_insert( @@ -3786,7 +3773,7 @@ btr_cur_pessimistic_insert( ut_ad(!(flags & BTR_CREATE_FLAG)); } else { btr_search_update_hash_on_insert( - cursor, btr_get_search_latch(index)); + cursor, btr_search_sys.get_latch(*index)); } #endif /* BTR_CUR_HASH_ADAPT */ if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) { @@ -4288,7 +4275,7 @@ btr_cur_update_in_place( #ifdef BTR_CUR_HASH_ADAPT { rw_lock_t* ahi_latch = block->index - ? btr_get_search_latch(index) : NULL; + ? btr_search_sys.get_latch(*index) : NULL; if (ahi_latch) { /* TO DO: Can we skip this if none of the fields index->search_info->curr_n_fields @@ -4526,7 +4513,7 @@ btr_cur_optimistic_update( index = cursor->index; ut_ad(trx_id > 0 || (flags & BTR_KEEP_SYS_FLAG)); ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); /* This is intended only for leaf page updates */ ut_ad(page_is_leaf(page)); /* The insert buffer tree should never be updated in place. */ @@ -4544,7 +4531,7 @@ btr_cur_optimistic_update( ULINT_UNDEFINED, heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(rec, *offsets) - || trx_is_recv(thr_get_trx(thr))); + || thr_get_trx(thr) == trx_roll_crash_recv_trx); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ if (UNIV_LIKELY(!update->is_metadata()) @@ -4795,17 +4782,18 @@ btr_cur_pess_upd_restore_supremum( const uint32_t prev_page_no = btr_page_get_prev(page); - const page_id_t page_id(block->page.id.space(), prev_page_no); + const page_id_t page_id(block->page.id().space(), prev_page_no); ut_ad(prev_page_no != FIL_NULL); prev_block = buf_page_get_with_no_latch(page_id, block->zip_size(), mtr); #ifdef UNIV_BTR_DEBUG - ut_a(btr_page_get_next(prev_block->frame) == block->page.id.page_no()); + ut_a(btr_page_get_next(prev_block->frame) + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ /* We must already have an x-latch on prev_block! */ - ut_ad(mtr_memo_contains(mtr, prev_block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(prev_block, MTR_MEMO_PAGE_X_FIX)); lock_rec_reset_and_inherit_gap_locks(prev_block, block, PAGE_HEAP_NO_SUPREMUM, @@ -4867,10 +4855,9 @@ btr_cur_pessimistic_update( page_zip = buf_block_get_page_zip(block); index = cursor->index; - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | - MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK | + MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index)); #endif /* UNIV_ZIP_DEBUG */ @@ -5172,11 +5159,8 @@ btr_cur_pessimistic_update( big_rec, so that row_upd_clust_rec() can store the big_rec in the same mini-transaction. */ - ut_ad(mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_X_LOCK | - MTR_MEMO_SX_LOCK)); - + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); mtr_sx_lock_index(index, mtr); } @@ -5396,11 +5380,10 @@ btr_cur_compress_if_useful( cursor position even if compression occurs */ mtr_t* mtr) /*!< in/out: mini-transaction */ { - ut_ad(mtr_memo_contains_flagged( - mtr, dict_index_get_lock(btr_cur_get_index(cursor)), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, + MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); if (cursor->index->is_spatial()) { const trx_t* trx = cursor->rtr_info->thr @@ -5409,8 +5392,8 @@ btr_cur_compress_if_useful( const buf_block_t* block = btr_cur_get_block(cursor); /* Check whether page lock prevents the compression */ - if (!lock_test_prdt_page_lock(trx, block->page.id.space(), - block->page.id.page_no())) { + if (!lock_test_prdt_page_lock(trx, block->page.id().space(), + block->page.id().page_no())) { return(false); } } @@ -5448,8 +5431,8 @@ btr_cur_optimistic_delete_func( rec_offs_init(offsets_); ut_ad(flags == 0 || flags == BTR_CREATE_FLAG); - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->is_named_space(cursor->index->table->space)); ut_ad(!cursor->index->is_dummy); @@ -5457,7 +5440,7 @@ btr_cur_optimistic_delete_func( block = btr_cur_get_block(cursor); - ut_ad(block->page.id.space() == cursor->index->table->space->id); + ut_ad(block->page.id().space() == cursor->index->table->space->id); ut_ad(page_is_leaf(buf_block_get_frame(block))); ut_ad(!dict_index_is_online_ddl(cursor->index) || dict_index_is_clust(cursor->index) @@ -5465,10 +5448,11 @@ btr_cur_optimistic_delete_func( rec = btr_cur_get_rec(cursor); - if (UNIV_UNLIKELY(block->page.id.page_no() == cursor->index->page + if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index->page && page_get_n_recs(block->frame) == 1 + (cursor->index->is_instant() - && !rec_is_metadata(rec, *cursor->index)))) { + && !rec_is_metadata(rec, *cursor->index)) + && !cursor->index->must_avoid_clear_instant_add())) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the only user record, also delete the metadata record @@ -5638,13 +5622,12 @@ btr_cur_pessimistic_delete( ut_ad(!dict_index_is_online_ddl(index) || dict_index_is_clust(index) || (flags & BTR_CREATE_FLAG)); - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->is_named_space(index->table->space)); ut_ad(!index->is_dummy); - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id().space() == index->table->space->id); if (!has_reserved_extents) { /* First reserve enough free space for the file segments @@ -5701,12 +5684,13 @@ btr_cur_pessimistic_delete( lock_update_delete(block, rec); } - if (block->page.id.page_no() != index->page) { + if (block->page.id().page_no() != index->page) { if (page_get_n_recs(page) < 2) { goto discard_page; } } else if (page_get_n_recs(page) == 1 - + (index->is_instant() && !is_metadata)) { + + (index->is_instant() && !is_metadata) + && !index->must_avoid_clear_instant_add()) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the only user record, also delete the metadata record @@ -5815,7 +5799,7 @@ discard_page: const ulint level = btr_page_get_level(page); // FIXME: reuse the node_ptr from above dtuple_t* node_ptr = dict_index_build_node_ptr( - index, next_rec, block->page.id.page_no(), + index, next_rec, block->page.id().page_no(), heap, level); btr_insert_on_non_leaf_level( @@ -5856,7 +5840,7 @@ discard_page: cursor, FALSE, mtr); } else { ib::warn() << "Not merging page " - << block->page.id + << block->page.id() << " in index " << index->name << " of " << index->table->name; ut_ad("MDEV-14637" == 0); @@ -5889,8 +5873,8 @@ return_after_reservations: @param[in,out] mtr mini-transaction */ void btr_cur_node_ptr_delete(btr_cur_t* parent, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(parent), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(parent), + MTR_MEMO_PAGE_X_FIX)); dberr_t err; ibool compressed = btr_cur_pessimistic_delete(&err, TRUE, parent, BTR_CREATE_FLAG, false, @@ -5938,7 +5922,7 @@ btr_cur_add_path_info( slot->nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor)); slot->n_recs = page_get_n_recs(block->frame); - slot->page_no = block->page.id.page_no(); + slot->page_no = block->page.id().page_no(); slot->page_level = btr_page_get_level(block->frame); } @@ -6216,7 +6200,7 @@ btr_estimate_n_rows_in_range_low( should_count_the_left_border = false; } - tuple1->page_id= cursor.page_cur.block->page.id; + tuple1->page_id= cursor.page_cur.block->page.id(); mtr_commit(&mtr); @@ -6289,7 +6273,7 @@ btr_estimate_n_rows_in_range_low( should_count_the_right_border = false; } - tuple2->page_id= cursor.page_cur.block->page.id; + tuple2->page_id= cursor.page_cur.block->page.id(); mtr_commit(&mtr); @@ -7038,17 +7022,19 @@ btr_blob_get_next_page_no( @param mtr mini-transaction to commit */ static void btr_blob_free(buf_block_t *block, bool all, mtr_t *mtr) { - const page_id_t page_id= block->page.id; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + const page_id_t page_id(block->page.id()); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); mtr->commit(); + const ulint fold= page_id.fold(); + mutex_enter(&buf_pool.mutex); - /* Free the block if it is still allocated to the same file page. */ - if (block->page.state == BUF_BLOCK_FILE_PAGE && block->page.id == page_id && - !buf_LRU_free_page(&block->page, all) && all && block->page.zip.data) - /* Attempt to deallocate the redundant copy of the uncompressed page - if the whole ROW_FORMAT=COMPRESSED block cannot be deallocted. */ - buf_LRU_free_page(&block->page, false); + + if (buf_page_t *bpage= buf_pool.page_hash_get_low(page_id, fold)) + if(!buf_LRU_free_page(bpage, all) && all && bpage->zip.data) + /* Attempt to deallocate the redundant copy of the uncompressed page + if the whole ROW_FORMAT=COMPRESSED block cannot be deallocted. */ + buf_LRU_free_page(bpage, false); mutex_exit(&buf_pool.mutex); } @@ -7106,7 +7092,7 @@ struct btr_blob_log_check_t { if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) { offs = page_offset(*m_rec); - page_no = (*m_block)->page.id.page_no(); + page_no = (*m_block)->page.id().page_no(); buf_block_buf_fix_inc(*m_block, __FILE__, __LINE__); } else { btr_pcur_store_position(m_pcur, m_mtr); @@ -7152,9 +7138,9 @@ struct btr_blob_log_check_t { MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); ut_ad((m_op == BTR_STORE_INSERT_BULK) - == !mtr_memo_contains_flagged(m_mtr, &index->lock, - MTR_MEMO_SX_LOCK - | MTR_MEMO_X_LOCK)); + == !m_mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_SX_LOCK + | MTR_MEMO_X_LOCK)); } }; @@ -7208,18 +7194,17 @@ btr_store_big_rec_extern_fields( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_any_extern(offsets)); ut_ad(op == BTR_STORE_INSERT_BULK - || mtr_memo_contains_flagged(btr_mtr, &index->lock, - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); + || btr_mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(btr_mtr->memo_contains_flagged(rec_block, MTR_MEMO_PAGE_X_FIX)); ut_ad(buf_block_get_frame(rec_block) == page_align(rec)); ut_a(dict_index_is_clust(index)); btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block, &rec, op); page_zip = buf_block_get_page_zip(rec_block); - space_id = rec_block->page.id.space(); - rec_page_no = rec_block->page.id.page_no(); + space_id = rec_block->page.id().space(); + rec_page_no = rec_block->page.id().page_no(); ut_a(fil_page_index_page_check(page_align(rec)) || op == BTR_STORE_INSERT_BULK); @@ -7279,9 +7264,7 @@ btr_store_big_rec_extern_fields( BTR_EXTERN_FIELD_REF_SIZE)); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ extern_len = big_rec_vec->fields[i].len; - UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data, - extern_len); - + MEM_CHECK_DEFINED(big_rec_vec->fields[i].data, extern_len); ut_a(extern_len > 0); prev_page_no = FIL_NULL; @@ -7310,14 +7293,14 @@ btr_store_big_rec_extern_fields( rec, offsets, field_no); page_zip = buf_block_get_page_zip(rec_block); - rec_page_no = rec_block->page.id.page_no(); + rec_page_no = rec_block->page.id().page_no(); } mtr.start(); index->set_modified(mtr); mtr.set_log_mode(btr_mtr->get_log_mode()); - buf_page_get(rec_block->page.id, + buf_page_get(rec_block->page.id(), rec_block->zip_size(), RW_X_LATCH, &mtr); if (prev_page_no == FIL_NULL) { @@ -7341,7 +7324,7 @@ btr_store_big_rec_extern_fields( ut_a(block != NULL); - page_no = block->page.id.page_no(); + page_no = block->page.id().page_no(); if (prev_page_no != FIL_NULL) { buf_block_t* prev_block; @@ -7573,7 +7556,7 @@ static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read) if (UNIV_LIKELY(type == FIL_PAGE_TYPE_BLOB)) return; /* FIXME: take the tablespace as a parameter */ - if (fil_space_t *space= fil_space_acquire_silent(block.page.id.space())) + if (fil_space_t *space= fil_space_acquire_silent(block.page.id().space())) { /* Old versions of InnoDB did not initialize FIL_PAGE_TYPE on BLOB pages. Do not print anything about the type mismatch when reading @@ -7583,7 +7566,7 @@ static void btr_check_blob_fil_page_type(const buf_block_t& block, bool read) ib::fatal() << "FIL_PAGE_TYPE=" << type << (read ? " on BLOB read file " : " on BLOB purge file ") << space->chain.start->name - << " page " << block.page.id.page_no(); + << " page " << block.page.id().page_no(); } space->release(); } @@ -7628,10 +7611,10 @@ btr_free_externally_stored_field( mtr_t mtr; ut_ad(index->is_primary()); - ut_ad(mtr_memo_contains_flagged(local_mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); - ut_ad(mtr_memo_contains_page(local_mtr, field_ref, - MTR_MEMO_PAGE_X_FIX)); + ut_ad(local_mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ut_ad(local_mtr->memo_contains_page_flagged(field_ref, + MTR_MEMO_PAGE_X_FIX)); ut_ad(!rec || rec_offs_validate(rec, index, offsets)); ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i)); ut_ad(local_mtr->is_named_space( @@ -7728,7 +7711,7 @@ btr_free_externally_stored_field( if (UNIV_LIKELY_NULL(block->page.zip.data)) { mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO, next_page_no); - memset(field_ref + BTR_EXTERN_LEN, 0, 4); + memset(field_ref + BTR_EXTERN_LEN + 4, 0, 4); page_zip_write_blob_ptr(block, rec, index, offsets, i, &mtr); } else { @@ -7786,7 +7769,7 @@ btr_rec_free_externally_stored_fields( ulint i; ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX)); ut_ad(index->is_primary()); ut_ad(page_rec_is_leaf(rec)); /* Free possible externally stored fields in the record */ @@ -7824,7 +7807,7 @@ btr_rec_free_updated_extern_fields( ulint i; ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX)); /* Free possible externally stored fields in the record */ @@ -7894,7 +7877,7 @@ btr_copy_blob_prefix( mtr_commit(&mtr); if (page_no == FIL_NULL || copy_len != part_len) { - UNIV_MEM_ASSERT_RW(buf, copied_len); + MEM_CHECK_DEFINED(buf, copied_len); return(copied_len); } @@ -8050,7 +8033,7 @@ end_of_blob: func_exit: inflateEnd(&d_stream); mem_heap_free(heap); - UNIV_MEM_ASSERT_RW(buf, d_stream.total_out); + MEM_CHECK_DEFINED(buf, d_stream.total_out); return(d_stream.total_out); } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index d2a51736793..cc8c11c42e1 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -112,18 +112,16 @@ btr_pcur_store_position( rec = page_cur_get_rec(page_cursor); offs = rec - block->frame; - ut_ad(block->page.id.page_no() == page_get_page_no(block->frame)); - ut_ad(block->page.buf_fix_count); + ut_ad(block->page.id().page_no() == page_get_page_no(block->frame)); + ut_ad(block->page.buf_fix_count()); /* For spatial index, when we do positioning on parent buffer if necessary, it might not hold latches, but the tree must be locked to prevent change on the page */ - ut_ad(mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX) - || (dict_index_is_spatial(index) - && mtr_memo_contains_flagged( - mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK))); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX) + || (index->is_spatial() + && mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK))); cursor->old_stored = true; @@ -134,7 +132,7 @@ btr_pcur_store_position( ut_a(!page_has_siblings(block->frame)); ut_ad(page_is_leaf(block->frame)); - ut_ad(block->page.id.page_no() == index->page); + ut_ad(block->page.id().page_no() == index->page); if (page_rec_is_supremum_low(offs)) { cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; @@ -151,10 +149,16 @@ before_first: ut_ad(!page_rec_is_infimum(rec)); if (UNIV_UNLIKELY(rec_is_metadata(rec, *index))) { +#if 0 /* MDEV-22867 had to relax this */ + /* If the table is emptied during an ALGORITHM=NOCOPY + DROP COLUMN ... that is not ALGORITHM=INSTANT, + then we must preserve any instant ADD metadata. */ ut_ad(index->table->instant); +#endif + ut_ad(index->is_instant()); ut_ad(page_get_n_recs(block->frame) == 1); ut_ad(page_is_leaf(block->frame)); - ut_ad(page_get_page_no(block->frame) == index->page); + ut_ad(!page_has_prev(block->frame)); cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; return; } @@ -483,7 +487,7 @@ btr_pcur_move_to_next_page( #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_page) == page_is_comp(page)); ut_a(btr_page_get_prev(next_page) - == btr_pcur_get_block(cursor)->page.id.page_no()); + == btr_pcur_get_block(cursor)->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr); diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 3891d3963b8..92cb38d0a85 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -41,7 +41,6 @@ Created 2/17/1996 Heikki Tuuri #include "btr0btr.h" #include "ha0ha.h" #include "srv0mon.h" -#include "sync0sync.h" /** Is search system enabled. Search system is protected by array of latches. */ @@ -57,25 +56,8 @@ ulint btr_search_n_succ = 0; ulint btr_search_n_hash_fail = 0; #endif /* UNIV_SEARCH_PERF_STAT */ -/** padding to prevent other memory update -hotspots from residing on the same memory -cache line as btr_search_latches */ -UNIV_INTERN byte btr_sea_pad1[CACHE_LINE_SIZE]; - -/** The latches protecting the adaptive search system: this latches protects the -(1) positions of records on those pages where a hash index has been built. -NOTE: It does not protect values of non-ordering fields within a record from -being updated in-place! We can use fact (1) to perform unique searches to -indexes. We will allocate the latches from dynamic memory to get it to the -same DRAM page as other hotspot semaphores */ -rw_lock_t** btr_search_latches; - -/** padding to prevent other memory update hotspots from residing on -the same memory cache line */ -UNIV_INTERN byte btr_sea_pad2[CACHE_LINE_SIZE]; - /** The adaptive hash index */ -btr_search_sys_t* btr_search_sys; +btr_search_sys_t btr_search_sys; /** If the number of records on the page divided by this parameter would have been successfully accessed using a hash index, the index @@ -187,188 +169,63 @@ probable that, when have reserved the btr search system latch and we need to allocate a new node to the hash table, it will succeed. However, the check will not guarantee success. @param[in] index index handler */ -static -void -btr_search_check_free_space_in_heap(const dict_index_t* index) +static void btr_search_check_free_space_in_heap(const dict_index_t *index) { - hash_table_t* table; - mem_heap_t* heap; + /* Note that we peek the value of heap->free_block without reserving + the latch: this is ok, because we will not guarantee that there will + be enough free space in the hash table. */ - ut_ad(!btr_search_own_any(RW_LOCK_S)); - ut_ad(!btr_search_own_any(RW_LOCK_X)); + buf_block_t *block= buf_block_alloc(); + auto part= btr_search_sys.get_part(*index); - table = btr_get_search_table(index); + rw_lock_x_lock(&part->latch); - heap = table->heap; + if (!btr_search_enabled || part->heap->free_block) + buf_block_free(block); + else + part->heap->free_block= block; - /* Note that we peek the value of heap->free_block without reserving - the latch: this is ok, because we will not guarantee that there will - be enough free space in the hash table. */ - - if (heap->free_block == NULL) { - buf_block_t* block = buf_block_alloc(); - rw_lock_t* ahi_latch = btr_get_search_latch(index); - - rw_lock_x_lock(ahi_latch); - - if (btr_search_enabled - && heap->free_block == NULL) { - heap->free_block = block; - } else { - buf_block_free(block); - } - - rw_lock_x_unlock(ahi_latch); - } -} - -/** Creates and initializes the adaptive search system at a database start. -@param[in] hash_size hash table size. */ -void btr_search_sys_create(ulint hash_size) -{ - /* Search System is divided into n parts. - Each part controls access to distinct set of hash buckets from - hash table through its own latch. */ - - /* Step-1: Allocate latches (1 per part). */ - btr_search_latches = reinterpret_cast( - ut_malloc(sizeof(rw_lock_t*) * btr_ahi_parts, mem_key_ahi)); - - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - btr_search_latches[i] = reinterpret_cast( - ut_malloc(sizeof(rw_lock_t), mem_key_ahi)); - - rw_lock_create(btr_search_latch_key, - btr_search_latches[i], SYNC_SEARCH_SYS); - } - - /* Step-2: Allocate hash tablees. */ - btr_search_sys = reinterpret_cast( - ut_malloc(sizeof(btr_search_sys_t), mem_key_ahi)); - - btr_search_sys->hash_tables = reinterpret_cast( - ut_malloc(sizeof(hash_table_t*) * btr_ahi_parts, mem_key_ahi)); - - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - btr_search_sys->hash_tables[i] = - ib_create((hash_size / btr_ahi_parts), - LATCH_ID_HASH_TABLE_MUTEX, - 0, MEM_HEAP_FOR_BTR_SEARCH); - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - btr_search_sys->hash_tables[i]->adaptive = TRUE; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - } -} - -/** Resize hash index hash table. -@param[in] hash_size hash index hash table size */ -void btr_search_sys_resize(ulint hash_size) -{ - /* Step-1: Lock all search latches in exclusive mode. */ - btr_search_x_lock_all(); - - if (btr_search_enabled) { - - btr_search_x_unlock_all(); - - ib::error() << "btr_search_sys_resize failed because" - " hash index hash table is not empty."; - ut_ad(0); - return; - } - - /* Step-2: Recreate hash tables with new size. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - mem_heap_free(btr_search_sys->hash_tables[i]->heap); - hash_table_free(btr_search_sys->hash_tables[i]); - - btr_search_sys->hash_tables[i] = - ib_create((hash_size / btr_ahi_parts), - LATCH_ID_HASH_TABLE_MUTEX, - 0, MEM_HEAP_FOR_BTR_SEARCH); - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - btr_search_sys->hash_tables[i]->adaptive = TRUE; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - } - - /* Step-3: Unlock all search latches from exclusive mode. */ - btr_search_x_unlock_all(); -} - -/** Frees the adaptive search system at a database shutdown. */ -void btr_search_sys_free() -{ - if (!btr_search_sys) { - ut_ad(!btr_search_latches); - return; - } - - ut_ad(btr_search_latches); - - /* Step-1: Release the hash tables. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - mem_heap_free(btr_search_sys->hash_tables[i]->heap); - hash_table_free(btr_search_sys->hash_tables[i]); - - } - - ut_free(btr_search_sys->hash_tables); - ut_free(btr_search_sys); - btr_search_sys = NULL; - - /* Step-2: Release all allocates latches. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - rw_lock_free(btr_search_latches[i]); - ut_free(btr_search_latches[i]); - } - - ut_free(btr_search_latches); - btr_search_latches = NULL; + rw_lock_x_unlock(&part->latch); } /** Set index->ref_count = 0 on all indexes of a table. @param[in,out] table table handler */ -static -void -btr_search_disable_ref_count( - dict_table_t* table) +static void btr_search_disable_ref_count(dict_table_t *table) { - dict_index_t* index; - - ut_ad(mutex_own(&dict_sys.mutex)); - - for (index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - index->search_info->ref_count = 0; - } + for (dict_index_t *index= dict_table_get_first_index(table); index; + index= dict_table_get_next_index(index)) + index->search_info->ref_count= 0; } -/** Disable the adaptive hash search system and empty the index. -@param[in] need_mutex need to acquire dict_sys.mutex */ -void btr_search_disable(bool need_mutex) +/** Lazily free detached metadata when removing the last reference. */ +ATTRIBUTE_COLD static void btr_search_lazy_free(dict_index_t *index) +{ + ut_ad(index->freed()); + dict_table_t *table= index->table; + /* Perform the skipped steps of dict_index_remove_from_cache_low(). */ + UT_LIST_REMOVE(table->freed_indexes, index); + rw_lock_free(&index->lock); + dict_mem_index_free(index); + + if (!UT_LIST_GET_LEN(table->freed_indexes) && + !UT_LIST_GET_LEN(table->indexes)) + { + ut_ad(table->id == 0); + dict_mem_table_free(table); + } +} + +/** Disable the adaptive hash search system and empty the index. */ +void btr_search_disable() { dict_table_t* table; - if (need_mutex) { - mutex_enter(&dict_sys.mutex); - } + mutex_enter(&dict_sys.mutex); - ut_ad(mutex_own(&dict_sys.mutex)); btr_search_x_lock_all(); if (!btr_search_enabled) { - if (need_mutex) { - mutex_exit(&dict_sys.mutex); - } - + mutex_exit(&dict_sys.mutex); btr_search_x_unlock_all(); return; } @@ -389,60 +246,43 @@ void btr_search_disable(bool need_mutex) btr_search_disable_ref_count(table); } - if (need_mutex) { - mutex_exit(&dict_sys.mutex); - } + mutex_exit(&dict_sys.mutex); /* Set all block->index = NULL. */ buf_pool.clear_hash_index(); /* Clear the adaptive hash index. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - hash_table_clear(btr_search_sys->hash_tables[i]); - mem_heap_empty(btr_search_sys->hash_tables[i]->heap); - } + btr_search_sys.clear(); btr_search_x_unlock_all(); } -/** Enable the adaptive hash search system. */ -void btr_search_enable() +/** Enable the adaptive hash search system. +@param resize whether buf_pool_t::resize() is the caller */ +void btr_search_enable(bool resize) { - mutex_enter(&buf_pool.mutex); - if (srv_buf_pool_old_size != srv_buf_pool_size) { + if (!resize) { + mutex_enter(&buf_pool.mutex); + bool changed = srv_buf_pool_old_size != srv_buf_pool_size; mutex_exit(&buf_pool.mutex); - return; + if (changed) { + return; + } } - mutex_exit(&buf_pool.mutex); btr_search_x_lock_all(); - btr_search_enabled = true; - btr_search_x_unlock_all(); -} + ulint hash_size = buf_pool_get_curr_size() / sizeof(void *) / 64; -/** Returns the value of ref_count. The value is protected by latch. -@param[in] info search info -@param[in] index index identifier -@return ref_count value. */ -ulint -btr_search_info_get_ref_count( - btr_search_t* info, - dict_index_t* index) -{ - ulint ret = 0; - - if (!btr_search_enabled) { - return(ret); + if (btr_search_sys.parts[0].heap) { + ut_ad(btr_search_enabled); + btr_search_x_unlock_all(); + return; } - ut_ad(info); + btr_search_sys.alloc(hash_size); - rw_lock_t* ahi_latch = btr_get_search_latch(index); - rw_lock_s_lock(ahi_latch); - ret = info->ref_count; - rw_lock_s_unlock(ahi_latch); - - return(ret); + btr_search_enabled = true; + btr_search_x_unlock_all(); } /** Updates the search info of an index about hash successes. NOTE that info @@ -571,8 +411,11 @@ btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block) RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); info->last_hash_succ = FALSE; - - ut_a(buf_block_state_valid(block)); + ut_d(auto state= block->page.state()); + ut_ad(state == BUF_BLOCK_NOT_USED + || state == BUF_BLOCK_FILE_PAGE + || state == BUF_BLOCK_MEMORY + || state == BUF_BLOCK_REMOVE_HASH); ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N); if ((block->n_hash_helps > 0) @@ -620,6 +463,220 @@ btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block) return(false); } +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +/** Maximum number of records in a page */ +constexpr ulint MAX_N_POINTERS = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES; +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + +__attribute__((nonnull)) +/** +Insert an entry into the hash table. If an entry with the same fold number +is found, its node is updated to point to the new data, and no new node +is inserted. +@param table hash table +@param heap memory heap +@param fold folded value of the record +@param block buffer block containing the record +@param data the record +@retval true on success +@retval false if no more memory could be allocated */ +static bool ha_insert_for_fold(hash_table_t *table, mem_heap_t* heap, + ulint fold, +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + buf_block_t *block, /*!< buffer block of data */ +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + const rec_t *data) +{ +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(block->frame == page_align(data)); +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + ut_ad(btr_search_enabled); + + hash_cell_t *cell= &table->array[table->calc_hash(fold)]; + + for (ha_node_t *prev= static_cast(cell->node); prev; + prev= prev->next) + { + if (prev->fold == fold) + { +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + buf_block_t *prev_block= prev->block; + ut_a(prev_block->frame == page_align(prev->data)); + ut_a(prev_block->n_pointers-- < MAX_N_POINTERS); + ut_a(block->n_pointers++ < MAX_N_POINTERS); + + prev->block= block; +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + prev->data= data; + return true; + } + } + + /* We have to allocate a new chain node */ + ha_node_t *node= static_cast(mem_heap_alloc(heap, sizeof *node)); + + if (!node) + return false; + + ha_node_set_data(node, block, data); + +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(block->n_pointers++ < MAX_N_POINTERS); +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + + node->fold= fold; + node->next= nullptr; + + ha_node_t *prev= static_cast(cell->node); + if (!prev) + cell->node= node; + else + { + while (prev->next) + prev= prev->next; + prev->next= node; + } + return true; +} + +__attribute__((nonnull)) +/** Delete a record. +@param table hash table +@param heap memory heap +@param del_node record to be deleted */ +static void ha_delete_hash_node(hash_table_t *table, mem_heap_t *heap, + ha_node_t *del_node) +{ + ut_ad(btr_search_enabled); +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(del_node->block->frame == page_align(del_node->data)); + ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS); +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + + const ulint fold= del_node->fold; + + HASH_DELETE(ha_node_t, next, table, fold, del_node); + + ha_node_t *top= static_cast(mem_heap_get_top(heap, sizeof *top)); + + if (del_node != top) + { + /* Compact the heap of nodes by moving the top in the place of del_node. */ + *del_node= *top; + hash_cell_t *cell= &table->array[table->calc_hash(top->fold)]; + + /* Look for the pointer to the top node, to update it */ + if (cell->node == top) + /* The top node is the first in the chain */ + cell->node= del_node; + else + { + /* We have to look for the predecessor */ + ha_node_t *node= static_cast(cell->node); + + while (top != HASH_GET_NEXT(next, node)) + node= static_cast(HASH_GET_NEXT(next, node)); + + /* Now we have the predecessor node */ + node->next= del_node; + } + } + + /* Free the occupied space */ + mem_heap_free_top(heap, sizeof *top); +} + +__attribute__((nonnull)) +/** Delete all pointers to a page. +@param table hash table +@param heap memory heap +@param page record to be deleted */ +static void ha_remove_all_nodes_to_page(hash_table_t *table, mem_heap_t *heap, + ulint fold, const page_t *page) +{ + for (ha_node_t *node= ha_chain_get_first(table, fold); node; ) + { + if (page_align(ha_node_get_data(node)) == page) + { + ha_delete_hash_node(table, heap, node); + /* The deletion may compact the heap of nodes and move other nodes! */ + node= ha_chain_get_first(table, fold); + } + else + node= ha_chain_get_next(node); + } +#ifdef UNIV_DEBUG + /* Check that all nodes really got deleted */ + for (ha_node_t *node= ha_chain_get_first(table, fold); node; + node= ha_chain_get_next(node)) + ut_ad(page_align(ha_node_get_data(node)) != page); +#endif /* UNIV_DEBUG */ +} + +/** Delete a record if found. +@param table hash table +@param heap memory heap for the hash bucket chain +@param fold folded value of the searched data +@param data pointer to the record +@return whether the record was found */ +static bool ha_search_and_delete_if_found(hash_table_t *table, + mem_heap_t *heap, + ulint fold, const rec_t *data) +{ + if (ha_node_t *node= ha_search_with_data(table, fold, data)) + { + ha_delete_hash_node(table, heap, node); + return true; + } + + return false; +} + +__attribute__((nonnull)) +/** Looks for an element when we know the pointer to the data and +updates the pointer to data if found. +@param table hash table +@param fold folded value of the searched data +@param data pointer to the data +@param new_data new pointer to the data +@return whether the element was found */ +static bool ha_search_and_update_if_found(hash_table_t *table, ulint fold, + const rec_t *data, +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + /** block containing new_data */ + buf_block_t *new_block, +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + const rec_t *new_data) +{ +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(new_block->frame == page_align(new_data)); +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + + if (!btr_search_enabled) + return false; + + if (ha_node_t *node= ha_search_with_data(table, fold, data)) + { +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(node->block->n_pointers-- < MAX_N_POINTERS); + ut_a(new_block->n_pointers++ < MAX_N_POINTERS); + node->block= new_block; +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + node->data= new_data; + + return true; + } + + return false; +} + +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#else +# define ha_insert_for_fold(t,h,f,b,d) ha_insert_for_fold(t,h,f,d) +# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ + ha_search_and_update_if_found(table,fold,data,new_data) +#endif + /** Updates a hash node reference when it has been unsuccessfully used in a search which could have succeeded with the used hash parameters. This can happen because when building a hash index for a page, we do not check @@ -637,58 +694,59 @@ btr_search_update_hash_ref( buf_block_t* block, const btr_cur_t* cursor) { - dict_index_t* index; - ulint fold; - rec_t* rec; - ut_ad(cursor->flag == BTR_CUR_HASH_FAIL); - ut_ad(rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X)); + ut_ad(rw_lock_own_flagged(&block->lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame); ut_ad(page_is_leaf(block->frame)); assert_block_ahi_valid(block); - index = block->index; - - if (!index) { + dict_index_t* index = block->index; + if (!index || !info->n_hash_potential) { return; } - ut_ad(block->page.id.space() == index->table->space_id); + ut_ad(block->page.id().space() == index->table->space_id); ut_ad(index == cursor->index); ut_ad(!dict_index_is_ibuf(index)); + auto part = btr_search_sys.get_part(*index); + rw_lock_x_lock(&part->latch); + ut_ad(!block->index || block->index == index); - if ((info->n_hash_potential > 0) + if (block->index && (block->curr_n_fields == info->n_fields) && (block->curr_n_bytes == info->n_bytes) - && (block->curr_left_side == info->left_side)) { + && (block->curr_left_side == info->left_side) + && btr_search_enabled) { mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); - rec = btr_cur_get_rec(cursor); + const rec_t* rec = btr_cur_get_rec(cursor); if (!page_rec_is_user_rec(rec)) { - - return; + goto func_exit; } - fold = rec_fold(rec, - rec_get_offsets(rec, index, offsets_, true, - ULINT_UNDEFINED, &heap), - block->curr_n_fields, - block->curr_n_bytes, index->id); + ulint fold = rec_fold( + rec, + rec_get_offsets(rec, index, offsets_, true, + ULINT_UNDEFINED, &heap), + block->curr_n_fields, + block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - ha_insert_for_fold(btr_get_search_table(index), fold, - block, rec); + ha_insert_for_fold(&part->table, part->heap, fold, block, rec); MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); } + +func_exit: + rw_lock_x_unlock(&part->latch); } /** Checks if a guessed position for a tree cursor is right. Note that if @@ -847,6 +905,8 @@ inline void buf_pool_t::clear_hash_index() ut_ad(!resizing); ut_ad(!btr_search_enabled); + std::set garbage; + for (chunk_t *chunk= chunks + n_chunks; chunk-- != chunks; ) { for (buf_block_t *block= chunk->blocks, * const end= block + chunk->size; @@ -855,8 +915,9 @@ inline void buf_pool_t::clear_hash_index() dict_index_t *index= block->index; assert_block_ahi_valid(block); - /* We can clear block->index block->n_pointers when + /* We can clear block->index and block->n_pointers when btr_search_own_all(RW_LOCK_X); see the comments in buf0buf.h */ + if (!index) { # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG @@ -865,7 +926,7 @@ inline void buf_pool_t::clear_hash_index() continue; } - ut_d(buf_page_state state= buf_block_get_state(block)); + ut_d(buf_page_state state= block->page.state()); /* Another thread may have set the state to BUF_BLOCK_REMOVE_HASH in buf_LRU_block_remove_hashed(). @@ -877,9 +938,14 @@ inline void buf_pool_t::clear_hash_index() # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG block->n_pointers= 0; # endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + if (index->freed()) + garbage.insert(index); block->index= nullptr; } } + + for (dict_index_t *index : garbage) + btr_search_lazy_free(index); } /** Get a buffer block from an adaptive hash index pointer. @@ -906,10 +972,10 @@ inline buf_block_t* buf_pool_t::block_from_ahi(const byte *ptr) const /* buf_pool_t::chunk_t::init() invokes buf_block_init() so that block[n].frame == block->frame + n * srv_page_size. Check it. */ ut_ad(block->frame == page_align(ptr)); - /* Read the state of the block without holding a mutex. + /* Read the state of the block without holding hash_lock. A state transition from BUF_BLOCK_FILE_PAGE to BUF_BLOCK_REMOVE_HASH is possible during this execution. */ - ut_d(const buf_page_state state = buf_block_get_state(block)); + ut_d(const buf_page_state state = block->page.state()); ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_REMOVE_HASH); return block; } @@ -943,7 +1009,6 @@ btr_search_guess_on_hash( rw_lock_t* ahi_latch, mtr_t* mtr) { - const rec_t* rec; ulint fold; index_id_t index_id; @@ -952,11 +1017,12 @@ btr_search_guess_on_hash( ahi_latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); if (!btr_search_enabled) { - return(FALSE); + return false; } ut_ad(!index->is_ibuf()); - ut_ad(!ahi_latch || ahi_latch == btr_get_search_latch(index)); + ut_ad(!ahi_latch + || ahi_latch == &btr_search_sys.get_part(*index)->latch); ut_ad((latch_mode == BTR_SEARCH_LEAF) || (latch_mode == BTR_MODIFY_LEAF)); compile_time_assert(ulint{BTR_SEARCH_LEAF} == ulint{RW_S_LATCH}); @@ -969,16 +1035,14 @@ btr_search_guess_on_hash( any latch here! */ if (info->n_hash_potential == 0) { - - return(FALSE); + return false; } cursor->n_fields = info->n_fields; cursor->n_bytes = info->n_bytes; if (dtuple_get_n_fields(tuple) < btr_search_get_n_fields(cursor)) { - - return(FALSE); + return false; } index_id = index->id; @@ -991,10 +1055,11 @@ btr_search_guess_on_hash( cursor->fold = fold; cursor->flag = BTR_CUR_HASH; - rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index); + auto part = btr_search_sys.get_part(*index); + const rec_t* rec; - if (use_latch) { - rw_lock_s_lock(use_latch); + if (!ahi_latch) { + rw_lock_s_lock(&part->latch); if (!btr_search_enabled) { goto fail; @@ -1004,39 +1069,43 @@ btr_search_guess_on_hash( ut_ad(rw_lock_own(ahi_latch, RW_LOCK_S)); } - rec = (rec_t*) ha_search_and_get_data( - btr_get_search_table(index), fold); + rec = static_cast( + ha_search_and_get_data(&part->table, fold)); - if (rec == NULL) { - if (use_latch) { + if (!rec) { + if (!ahi_latch) { fail: - rw_lock_s_unlock(use_latch); + rw_lock_s_unlock(&part->latch); } btr_search_failure(info, cursor); - - return(FALSE); + return false; } buf_block_t* block = buf_pool.block_from_ahi(rec); - if (use_latch) { - mutex_enter(&block->mutex); + if (!ahi_latch) { + page_hash_latch* hash_lock = buf_pool.hash_lock_get( + block->page.id()); + hash_lock->read_lock(); - if (buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH) { + if (block->page.state() == BUF_BLOCK_REMOVE_HASH) { /* Another thread is just freeing the block from the LRU list of the buffer pool: do not try to access this page. */ - mutex_exit(&block->mutex); + hash_lock->read_unlock(); goto fail; } - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - DBUG_ASSERT(block->page.status != buf_page_t::FREED); + const bool fail = index != block->index + && index_id == block->index->id; + ut_a(!fail || block->index->freed()); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); + DBUG_ASSERT(fail || block->page.status != buf_page_t::FREED); - buf_page_set_accessed(&block->page); buf_block_buf_fix_inc(block, __FILE__, __LINE__); - mutex_exit(&block->mutex); + hash_lock->read_unlock(); + block->page.set_accessed(); buf_page_make_young_if_needed(&block->page); mtr_memo_type_t fix_type; @@ -1059,23 +1128,29 @@ got_no_latch: buf_pool.stat.n_page_gets++; - rw_lock_s_unlock(use_latch); + rw_lock_s_unlock(&part->latch); buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); + if (UNIV_UNLIKELY(fail)) { + goto fail_and_release_page; + } + } else if (UNIV_UNLIKELY(index != block->index + && index_id == block->index->id)) { + ut_a(block->index->freed()); + goto fail_and_release_page; } - if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { + if (block->page.state() != BUF_BLOCK_FILE_PAGE) { - ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH); + ut_ad(block->page.state() == BUF_BLOCK_REMOVE_HASH); +fail_and_release_page: if (!ahi_latch) { - btr_leaf_page_release(block, latch_mode, mtr); } btr_search_failure(info, cursor); - - return(FALSE); + return false; } ut_ad(page_rec_is_user_rec(rec)); @@ -1091,14 +1166,7 @@ got_no_latch: right. */ if (index_id != btr_page_get_index_id(block->frame) || !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) { - - if (!ahi_latch) { - btr_leaf_page_release(block, latch_mode, mtr); - } - - btr_search_failure(info, cursor); - - return(FALSE); + goto fail_and_release_page; } if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) { @@ -1176,66 +1244,53 @@ void btr_search_drop_page_hash_index(buf_block_t* block) ulint* folds; ulint i; mem_heap_t* heap; - const dict_index_t* index; rec_offs* offsets; - rw_lock_t* latch; - btr_search_t* info; retry: - /* Do a dirty check on block->index, return if the block is - not in the adaptive hash index. */ - index = block->index; /* This debug check uses a dirty read that could theoretically cause false positives while buf_pool.clear_hash_index() is executing. */ assert_block_ahi_valid(block); ut_ad(!btr_search_own_any(RW_LOCK_S)); ut_ad(!btr_search_own_any(RW_LOCK_X)); - if (index == NULL) { + if (!block->index) { return; } - ut_ad(block->page.buf_fix_count == 0 - || buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH + ut_ad(!block->page.buf_fix_count() + || block->page.state() == BUF_BLOCK_REMOVE_HASH || rw_lock_own_flagged(&block->lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); + RW_LOCK_FLAG_X | RW_LOCK_FLAG_S + | RW_LOCK_FLAG_SX)); ut_ad(page_is_leaf(block->frame)); - /* We must not dereference index here, because it could be freed + /* We must not dereference block->index here, because it could be freed if (index->table->n_ref_count == 0 && !mutex_own(&dict_sys.mutex)). Determine the ahi_slot based on the block contents. */ const index_id_t index_id = btr_page_get_index_id(block->frame); - const ulint ahi_slot - = ut_fold_ulint_pair(static_cast(index_id), - static_cast(block->page.id.space())) - % btr_ahi_parts; - latch = btr_search_latches[ahi_slot]; - rw_lock_s_lock(latch); + auto part = btr_search_sys.get_part(index_id, + block->page.id().space()); + + rw_lock_s_lock(&part->latch); assert_block_ahi_valid(block); - if (block->index == NULL) { - rw_lock_s_unlock(latch); + if (!block->index || !btr_search_enabled) { + rw_lock_s_unlock(&part->latch); return; } - /* The index associated with a block must remain the - same, because we are holding block->lock or the block is - not accessible by other threads (BUF_BLOCK_REMOVE_HASH), - or the index is not accessible to other threads - (buf_fix_count == 0 when DROP TABLE or similar is executing - buf_LRU_drop_page_hash_for_tablespace()). */ - ut_a(index == block->index); + dict_index_t* index = block->index; #ifdef MYSQL_INDEX_DISABLE_AHI ut_ad(!index->disable_ahi); #endif ut_ad(btr_search_enabled); - ut_ad(block->page.id.space() == index->table->space_id); + ut_ad(block->page.id().space() == index->table->space_id); ut_a(index_id == index->id); - ut_a(!dict_index_is_ibuf(index)); + ut_ad(!dict_index_is_ibuf(index)); #ifdef UNIV_DEBUG switch (dict_index_get_online_status(index)) { case ONLINE_INDEX_CREATION: @@ -1263,7 +1318,7 @@ retry: /* NOTE: The AHI fields of block must not be accessed after releasing search latch, as the index page might only be s-latched! */ - rw_lock_s_unlock(latch); + rw_lock_s_unlock(&part->latch); ut_a(n_fields > 0 || n_bytes > 0); @@ -1314,7 +1369,7 @@ next_rec: mem_heap_free(heap); } - rw_lock_x_lock(latch); + rw_lock_x_lock(&part->latch); if (UNIV_UNLIKELY(!block->index)) { /* Someone else has meanwhile dropped the hash index */ @@ -1330,22 +1385,25 @@ next_rec: /* Someone else has meanwhile built a new hash index on the page, with different parameters */ - rw_lock_x_unlock(latch); + rw_lock_x_unlock(&part->latch); ut_free(folds); goto retry; } for (i = 0; i < n_cached; i++) { - - ha_remove_all_nodes_to_page( - btr_search_sys->hash_tables[ahi_slot], - folds[i], page); + ha_remove_all_nodes_to_page(&part->table, part->heap, + folds[i], page); } - info = btr_search_get_info(block->index); - ut_a(info->ref_count > 0); - info->ref_count--; + switch (index->search_info->ref_count--) { + case 0: + ut_error; + case 1: + if (index->freed()) { + btr_search_lazy_free(index); + } + } block->index = NULL; @@ -1354,7 +1412,7 @@ next_rec: cleanup: assert_block_ahi_valid(block); - rw_lock_x_unlock(latch); + rw_lock_x_unlock(&part->latch); ut_free(folds); } @@ -1430,7 +1488,6 @@ btr_search_build_page_hash_index( ulint n_recs; ulint* folds; const rec_t** recs; - ulint i; mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; @@ -1443,24 +1500,30 @@ btr_search_build_page_hash_index( } rec_offs_init(offsets_); - ut_ad(ahi_latch == btr_get_search_latch(index)); + ut_ad(ahi_latch == &btr_search_sys.get_part(*index)->latch); ut_ad(index); - ut_ad(block->page.id.space() == index->table->space_id); - ut_a(!dict_index_is_ibuf(index)); + ut_ad(block->page.id().space() == index->table->space_id); + ut_ad(!dict_index_is_ibuf(index)); ut_ad(page_is_leaf(block->frame)); ut_ad(rw_lock_own_flagged(&block->lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); + ut_ad(block->page.id().page_no() >= 3); rw_lock_s_lock(ahi_latch); - const bool rebuild = block->index + const bool enabled = btr_search_enabled; + const bool rebuild = enabled && block->index && (block->curr_n_fields != n_fields || block->curr_n_bytes != n_bytes || block->curr_left_side != left_side); rw_lock_s_unlock(ahi_latch); + if (!enabled) { + return; + } + if (rebuild) { btr_search_drop_page_hash_index(block); } @@ -1561,19 +1624,12 @@ btr_search_build_page_hash_index( btr_search_check_free_space_in_heap(index); - hash_table_t* table = btr_get_search_table(index); rw_lock_x_lock(ahi_latch); if (!btr_search_enabled) { goto exit_func; } - if (block->index && ((block->curr_n_fields != n_fields) - || (block->curr_n_bytes != n_bytes) - || (block->curr_left_side != left_side))) { - goto exit_func; - } - /* This counter is decremented every time we drop page hash index entries and is incremented here. Since we can rebuild hash index for a page that is already hashed, we @@ -1582,6 +1638,10 @@ btr_search_build_page_hash_index( if (!block->index) { assert_block_ahi_empty(block); index->search_info->ref_count++; + } else if (block->curr_n_fields != n_fields + || block->curr_n_bytes != n_bytes + || block->curr_left_side != left_side) { + goto exit_func; } block->n_hash_helps = 0; @@ -1591,9 +1651,12 @@ btr_search_build_page_hash_index( block->curr_left_side = left_side; block->index = index; - for (i = 0; i < n_cached; i++) { - - ha_insert_for_fold(table, folds[i], block, recs[i]); + { + auto part = btr_search_sys.get_part(*index); + for (ulint i = 0; i < n_cached; i++) { + ha_insert_for_fold(&part->table, part->heap, + folds[i], block, recs[i]); + } } MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED); @@ -1615,8 +1678,8 @@ exit_func: void btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor) { - rw_lock_t* ahi_latch = btr_get_search_latch(cursor->index); - + rw_lock_t* ahi_latch = &btr_search_sys.get_part(*cursor->index) + ->latch; ut_ad(!rw_lock_own_flagged(ahi_latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); @@ -1643,11 +1706,7 @@ btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor) btr_search_n_hash_fail++; #endif /* UNIV_SEARCH_PERF_STAT */ - rw_lock_x_lock(ahi_latch); - btr_search_update_hash_ref(info, block, cursor); - - rw_lock_x_unlock(ahi_latch); } if (build_index) { @@ -1689,7 +1748,9 @@ btr_search_move_or_delete_hash_entries( assert_block_ahi_valid(block); assert_block_ahi_valid(new_block); - rw_lock_t* ahi_latch = index ? btr_get_search_latch(index) : NULL; + rw_lock_t* ahi_latch = index + ? &btr_search_sys.get_part(*index)->latch + : nullptr; if (new_block->index) { btr_search_drop_page_hash_index(block); @@ -1732,7 +1793,6 @@ btr_search_move_or_delete_hash_entries( using btr_cur_search_, the record is not yet deleted.*/ void btr_search_update_hash_on_delete(btr_cur_t* cursor) { - hash_table_t* table; buf_block_t* block; const rec_t* rec; ulint fold; @@ -1762,12 +1822,10 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) return; } - ut_ad(block->page.id.space() == index->table->space_id); + ut_ad(block->page.id().space() == index->table->space_id); ut_a(index == cursor->index); ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0); - ut_a(!dict_index_is_ibuf(index)); - - table = btr_get_search_table(index); + ut_ad(!dict_index_is_ibuf(index)); rec = btr_cur_get_rec(cursor); @@ -1778,25 +1836,25 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) mem_heap_free(heap); } - rw_lock_t* ahi_latch = btr_get_search_latch(index); + auto part = btr_search_sys.get_part(*index); - rw_lock_x_lock(ahi_latch); + rw_lock_x_lock(&part->latch); assert_block_ahi_valid(block); - if (block->index) { + if (block->index && btr_search_enabled) { ut_a(block->index == index); - if (ha_search_and_delete_if_found(table, fold, rec)) { + if (ha_search_and_delete_if_found(&part->table, part->heap, + fold, rec)) { MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVED); } else { - MONITOR_INC( - MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND); + MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND); } assert_block_ahi_valid(block); } - rw_lock_x_unlock(ahi_latch); + rw_lock_x_unlock(&part->latch); } /** Updates the page hash index when a single record is inserted on a page. @@ -1807,12 +1865,11 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) void btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) { - hash_table_t* table; buf_block_t* block; dict_index_t* index; rec_t* rec; - ut_ad(ahi_latch == btr_get_search_latch(cursor->index)); + ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch); ut_ad(!btr_search_own_any(RW_LOCK_S)); ut_ad(!btr_search_own_any(RW_LOCK_X)); #ifdef MYSQL_INDEX_DISABLE_AHI @@ -1836,10 +1893,10 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) } ut_a(cursor->index == index); - ut_a(!dict_index_is_ibuf(index)); + ut_ad(!dict_index_is_ibuf(index)); rw_lock_x_lock(ahi_latch); - if (!block->index) { + if (!block->index || !btr_search_enabled) { goto func_exit; } @@ -1851,10 +1908,9 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) && (cursor->n_bytes == block->curr_n_bytes) && !block->curr_left_side) { - table = btr_get_search_table(index); - if (ha_search_and_update_if_found( - table, cursor->fold, rec, block, + &btr_search_sys.get_part(*cursor->index)->table, + cursor->fold, rec, block, page_rec_get_next(rec))) { MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED); } @@ -1878,7 +1934,7 @@ func_exit: void btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) { - hash_table_t* table; + btr_search_sys_t::partition* part; buf_block_t* block; dict_index_t* index; const rec_t* rec; @@ -1889,14 +1945,12 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) ulint next_fold = 0; /* remove warning (??? bug ???) */ ulint n_fields; ulint n_bytes; - ibool left_side; - bool locked = false; mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; rec_offs_init(offsets_); - ut_ad(ahi_latch == btr_get_search_latch(cursor->index)); + ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch); ut_ad(page_is_leaf(btr_cur_get_page(cursor))); ut_ad(!btr_search_own_any(RW_LOCK_S)); ut_ad(!btr_search_own_any(RW_LOCK_X)); @@ -1919,22 +1973,20 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) return; } - ut_ad(block->page.id.space() == index->table->space_id); + ut_ad(block->page.id().space() == index->table->space_id); btr_search_check_free_space_in_heap(index); - table = btr_get_search_table(index); - rec = btr_cur_get_rec(cursor); #ifdef MYSQL_INDEX_DISABLE_AHI ut_a(!index->disable_ahi); #endif ut_a(index == cursor->index); - ut_a(!dict_index_is_ibuf(index)); + ut_ad(!dict_index_is_ibuf(index)); n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; - left_side = block->curr_left_side; + const bool left_side = block->curr_left_side; ins_rec = page_rec_get_next_const(rec); next_rec = page_rec_get_next_const(ins_rec); @@ -1951,6 +2003,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) n_bytes, index->id); } + bool locked = false; + if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, *index)) { offsets = rec_get_offsets( rec, index, offsets, true, @@ -1961,11 +2015,14 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) locked = true; rw_lock_x_lock(ahi_latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } - ha_insert_for_fold(table, ins_fold, block, ins_rec); + part = btr_search_sys.get_part(*index); + ha_insert_for_fold(&part->table, part->heap, + ins_fold, block, ins_rec); + MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); } goto check_next_rec; @@ -1977,16 +2034,20 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) locked = true; rw_lock_x_lock(ahi_latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + part = btr_search_sys.get_part(*index); } if (!left_side) { - ha_insert_for_fold(table, fold, block, rec); + ha_insert_for_fold(&part->table, part->heap, + fold, block, rec); } else { - ha_insert_for_fold(table, ins_fold, block, ins_rec); + ha_insert_for_fold(&part->table, part->heap, + ins_fold, block, ins_rec); } + MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); } check_next_rec: @@ -1997,33 +2058,39 @@ check_next_rec: locked = true; rw_lock_x_lock(ahi_latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + part = btr_search_sys.get_part(*index); } - ha_insert_for_fold(table, ins_fold, block, ins_rec); + ha_insert_for_fold(&part->table, part->heap, + ins_fold, block, ins_rec); + MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); } goto function_exit; } if (ins_fold != next_fold) { - if (!locked) { locked = true; rw_lock_x_lock(ahi_latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + part = btr_search_sys.get_part(*index); } if (!left_side) { - ha_insert_for_fold(table, ins_fold, block, ins_rec); + ha_insert_for_fold(&part->table, part->heap, + ins_fold, block, ins_rec); } else { - ha_insert_for_fold(table, next_fold, block, next_rec); + ha_insert_for_fold(&part->table, part->heap, + next_fold, block, next_rec); } + MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); } function_exit: @@ -2037,6 +2104,31 @@ function_exit: } #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +__attribute__((nonnull)) +/** @return whether a range of the cells is valid */ +static bool ha_validate(const hash_table_t *table, + ulint start_index, ulint end_index) +{ + ut_a(start_index <= end_index); + ut_a(end_index < table->n_cells); + + bool ok= true; + + for (ulint i= start_index; i <= end_index; i++) + { + for (auto node= static_cast(table->array[i].node); node; + node= node->next) + { + if (table->calc_hash(node->fold) != i) { + ib::error() << "Hash table node fold value " << node->fold + << " does not match the cell number " << i; + ok= false; + } + } + } + + return ok; +} /** Validates the search system for given hash table. @param[in] hash_table_id hash table to validate @@ -2053,7 +2145,9 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; + btr_search_x_lock_all(); if (!btr_search_enabled) { + btr_search_x_unlock_all(); return(TRUE); } @@ -2063,11 +2157,11 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs_init(offsets_); - btr_search_x_lock_all(); mutex_enter(&buf_pool.mutex); - cell_count = hash_get_n_cells( - btr_search_sys->hash_tables[hash_table_id]); + auto &part = btr_search_sys.parts[hash_table_id]; + + cell_count = part.table.n_cells; for (i = 0; i < cell_count; i++) { /* We release search latches every once in a while to @@ -2080,10 +2174,15 @@ btr_search_hash_table_validate(ulint hash_table_id) os_thread_yield(); btr_search_x_lock_all(); + + if (!btr_search_enabled) { + ok = true; + goto func_exit; + } + mutex_enter(&buf_pool.mutex); - ulint curr_cell_count = hash_get_n_cells( - btr_search_sys->hash_tables[hash_table_id]); + ulint curr_cell_count = part.table.n_cells; if (cell_count != curr_cell_count) { @@ -2095,16 +2194,14 @@ btr_search_hash_table_validate(ulint hash_table_id) } } - node = (ha_node_t*) hash_get_nth_cell( - btr_search_sys->hash_tables[hash_table_id], i)->node; + node = static_cast(part.table.array[i].node); for (; node != NULL; node = node->next) { const buf_block_t* block = buf_pool.block_from_ahi((byte*) node->data); - const buf_block_t* hash_block; index_id_t page_index_id; - if (UNIV_LIKELY(buf_block_get_state(block) + if (UNIV_LIKELY(block->page.state() == BUF_BLOCK_FILE_PAGE)) { /* The space and offset are only valid @@ -2112,31 +2209,24 @@ btr_search_hash_table_validate(ulint hash_table_id) the block is being freed (BUF_BLOCK_REMOVE_HASH, see the assertion and the comment below) */ - hash_block = buf_block_hash_get( - block->page.id); - } else { - hash_block = NULL; + const page_id_t id(block->page.id()); + if (const buf_page_t* hash_page + = buf_pool.page_hash_get_low( + id, id.fold())) { + ut_ad(hash_page == &block->page); + goto state_ok; + } } - if (hash_block) { - ut_a(hash_block == block); - } else { - /* When a block is being freed, - buf_LRU_search_and_free_block() first - removes the block from - buf_pool.page_hash by calling - buf_LRU_block_remove_hashed_page(). - After that, it invokes - btr_search_drop_page_hash_index() to - remove the block from - btr_search_sys->hash_tables[i]. */ - - ut_a(buf_block_get_state(block) - == BUF_BLOCK_REMOVE_HASH); - } - - ut_a(!dict_index_is_ibuf(block->index)); - ut_ad(block->page.id.space() + /* When a block is being freed, + buf_LRU_search_and_free_block() first removes + the block from buf_pool.page_hash by calling + buf_LRU_block_remove_hashed_page(). Then it + invokes btr_search_drop_page_hash_index(). */ + ut_a(block->page.state() == BUF_BLOCK_REMOVE_HASH); +state_ok: + ut_ad(!dict_index_is_ibuf(block->index)); + ut_ad(block->page.id().space() == block->index->table->space_id); page_index_id = btr_page_get_index_id(block->frame); @@ -2160,7 +2250,7 @@ btr_search_hash_table_validate(ulint hash_table_id) ib::error() << "Error in an adaptive hash" << " index pointer to page " - << block->page.id + << block->page.id() << ", ptr mem address " << reinterpret_cast( node->data) @@ -2192,10 +2282,15 @@ btr_search_hash_table_validate(ulint hash_table_id) os_thread_yield(); btr_search_x_lock_all(); + + if (!btr_search_enabled) { + ok = true; + goto func_exit; + } + mutex_enter(&buf_pool.mutex); - ulint curr_cell_count = hash_get_n_cells( - btr_search_sys->hash_tables[hash_table_id]); + ulint curr_cell_count = part.table.n_cells; if (cell_count != curr_cell_count) { @@ -2209,13 +2304,13 @@ btr_search_hash_table_validate(ulint hash_table_id) ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1); - if (!ha_validate(btr_search_sys->hash_tables[hash_table_id], - i, end_index)) { + if (!ha_validate(&part.table, i, end_index)) { ok = FALSE; } } mutex_exit(&buf_pool.mutex); +func_exit: btr_search_x_unlock_all(); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index a78974992b0..bedf00441ec 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -81,7 +81,6 @@ enum buf_buddy_state_t { are in use */ }; -#ifdef UNIV_DEBUG_VALGRIND /**********************************************************************//** Invalidate memory area that we won't access while page is free */ UNIV_INLINE @@ -91,15 +90,11 @@ buf_buddy_mem_invalid( buf_buddy_free_t* buf, /*!< in: block to check */ ulint i) /*!< in: index of zip_free[] */ { - const size_t size = BUF_BUDDY_LOW << i; - ut_ad(i <= BUF_BUDDY_SIZES); + ut_ad(i <= BUF_BUDDY_SIZES); - UNIV_MEM_ASSERT_W(buf, size); - UNIV_MEM_INVALID(buf, size); + MEM_CHECK_ADDRESSABLE(buf, BUF_BUDDY_LOW << i); + MEM_UNDEFINED(buf, BUF_BUDDY_LOW << i); } -#else /* UNIV_DEBUG_VALGRIND */ -# define buf_buddy_mem_invalid(buf, i) ut_ad((i) <= BUF_BUDDY_SIZES) -#endif /* UNIV_DEBUG_VALGRIND */ /**********************************************************************//** Check if a buddy is stamped free. @@ -333,11 +328,10 @@ static buf_buddy_free_t* buf_buddy_alloc_zip(ulint i) if (buf) { /* Trash the page other than the BUF_BUDDY_STAMP_NONFREE. */ - UNIV_MEM_TRASH((void*) buf, (int) ~i, BUF_BUDDY_STAMP_OFFSET); - UNIV_MEM_TRASH(BUF_BUDDY_STAMP_OFFSET + 4 - + buf->stamp.bytes, (int) ~i, - (BUF_BUDDY_LOW << i) - - (BUF_BUDDY_STAMP_OFFSET + 4)); + MEM_UNDEFINED(buf, BUF_BUDDY_STAMP_OFFSET); + MEM_UNDEFINED(BUF_BUDDY_STAMP_OFFSET + 4 + buf->stamp.bytes, + (BUF_BUDDY_LOW << i) + - (BUF_BUDDY_STAMP_OFFSET + 4)); ut_ad(mach_read_from_4(buf->stamp.bytes + BUF_BUDDY_STAMP_OFFSET) == BUF_BUDDY_STAMP_NONFREE); @@ -357,27 +351,25 @@ buf_buddy_block_free(void* buf) buf_block_t* block; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); ut_a(!ut_align_offset(buf, srv_page_size)); - HASH_SEARCH(hash, buf_pool.zip_hash, fold, buf_page_t*, bpage, - ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY - && bpage->in_zip_hash && !bpage->in_page_hash), + HASH_SEARCH(hash, &buf_pool.zip_hash, fold, buf_page_t*, bpage, + ut_ad(bpage->state() == BUF_BLOCK_MEMORY + && bpage->in_zip_hash), ((buf_block_t*) bpage)->frame == buf); ut_a(bpage); - ut_a(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY); - ut_ad(!bpage->in_page_hash); + ut_a(bpage->state() == BUF_BLOCK_MEMORY); ut_ad(bpage->in_zip_hash); - ut_d(bpage->in_zip_hash = FALSE); - HASH_DELETE(buf_page_t, hash, buf_pool.zip_hash, fold, bpage); + ut_d(bpage->in_zip_hash = false); + HASH_DELETE(buf_page_t, hash, &buf_pool.zip_hash, fold, bpage); ut_d(memset(buf, 0, srv_page_size)); - UNIV_MEM_INVALID(buf, srv_page_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(buf, srv_page_size); +#endif /* HAVE_valgrind_or_MSAN */ block = (buf_block_t*) bpage; - buf_page_mutex_enter(block); buf_LRU_block_free_non_file_page(block); - buf_page_mutex_exit(block); ut_ad(buf_pool.buddy_n_frames > 0); ut_d(buf_pool.buddy_n_frames--); @@ -392,19 +384,14 @@ buf_buddy_block_register( buf_block_t* block) /*!< in: buffer frame to allocate */ { const ulint fold = BUF_POOL_ZIP_FOLD(block); - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE); - - buf_block_set_state(block, BUF_BLOCK_MEMORY); + ut_ad(block->page.state() == BUF_BLOCK_MEMORY); ut_a(block->frame); ut_a(!ut_align_offset(block->frame, srv_page_size)); - ut_ad(!block->page.in_page_hash); ut_ad(!block->page.in_zip_hash); - ut_d(block->page.in_zip_hash = TRUE); - HASH_INSERT(buf_page_t, hash, buf_pool.zip_hash, fold, &block->page); + ut_d(block->page.in_zip_hash = true); + HASH_INSERT(buf_page_t, hash, &buf_pool.zip_hash, fold, &block->page); ut_d(buf_pool.buddy_n_frames++); } @@ -440,16 +427,15 @@ buf_buddy_alloc_from(void* buf, ulint i, ulint j) return(buf); } -/** Allocate a block. -@param[in] i index of buf_pool.zip_free[] or BUF_BUDDY_SIZES -@param[out] lru whether buf_pool.mutex was temporarily released +/** Allocate a ROW_FORMAT=COMPRESSED block. +@param i index of buf_pool.zip_free[] or BUF_BUDDY_SIZES +@param lru assigned to true if buf_pool.mutex was temporarily released @return allocated block, never NULL */ byte *buf_buddy_alloc_low(ulint i, bool *lru) { buf_block_t* block; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); if (i < BUF_BUDDY_SIZES) { @@ -469,9 +455,7 @@ byte *buf_buddy_alloc_low(ulint i, bool *lru) } /* Try replacing an uncompressed page in the buffer pool. */ - mutex_exit(&buf_pool.mutex); - block = buf_LRU_get_free_block(); - mutex_enter(&buf_pool.mutex); + block = buf_LRU_get_free_block(true); if (lru) { *lru = true; } @@ -502,31 +486,26 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) ulint offset; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); ut_ad(!ut_align_offset(src, size)); ut_ad(!ut_align_offset(dst, size)); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); - UNIV_MEM_ASSERT_W(dst, size); + MEM_CHECK_ADDRESSABLE(dst, size); space = mach_read_from_4((const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); offset = mach_read_from_4((const byte*) src + FIL_PAGE_OFFSET); - /* Suppress Valgrind warnings about conditional jump - on uninitialized value. */ - UNIV_MEM_VALID(&space, sizeof space); - UNIV_MEM_VALID(&offset, sizeof offset); + /* Suppress Valgrind or MSAN warnings. */ + MEM_MAKE_DEFINED(&space, sizeof space); + MEM_MAKE_DEFINED(&offset, sizeof offset); ut_ad(space != BUF_BUDDY_STAMP_FREE); const page_id_t page_id(space, offset); + const ulint fold= page_id.fold(); - rw_lock_t* hash_lock = buf_page_hash_lock_get(page_id); - - rw_lock_x_lock(hash_lock); - - bpage = buf_page_hash_get_low(page_id); + bpage = buf_pool.page_hash_get_low(page_id, fold); if (!bpage || bpage->zip.data != src) { /* The block has probably been freshly @@ -534,8 +513,6 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) added to buf_pool.page_hash yet. Obviously, it cannot be relocated. */ - rw_lock_x_unlock(hash_lock); - if (!force || space != 0 || offset != 0) { return(false); } @@ -546,8 +523,7 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) bpage = UT_LIST_GET_FIRST(buf_pool.LRU); while (bpage != NULL) { if (bpage->zip.data == src) { - hash_lock = buf_page_hash_lock_get(bpage->id); - rw_lock_x_lock(hash_lock); + ut_ad(bpage->id() == page_id); break; } bpage = UT_LIST_GET_NEXT(LRU, bpage); @@ -563,21 +539,21 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) have to relocate all blocks covered by src. For the sake of simplicity, give up. */ ut_ad(page_zip_get_size(&bpage->zip) < size); - - rw_lock_x_unlock(hash_lock); - return(false); } /* The block must have been allocated, but it may contain uninitialized data. */ - UNIV_MEM_ASSERT_W(src, size); + MEM_CHECK_ADDRESSABLE(src, size); - BPageMutex* block_mutex = buf_page_get_mutex(bpage); + if (!bpage->can_relocate()) { + return false; + } - mutex_enter(block_mutex); + page_hash_latch *hash_lock = buf_pool.page_hash.lock_get(fold); + hash_lock->write_lock(); - if (buf_page_can_relocate(bpage)) { + if (bpage->can_relocate()) { /* Relocate the compressed page. */ const ulonglong ns = my_interval_timer(); @@ -586,9 +562,7 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) memcpy(dst, src, size); bpage->zip.data = reinterpret_cast(dst); - rw_lock_x_unlock(hash_lock); - - mutex_exit(block_mutex); + hash_lock->write_unlock(); buf_buddy_mem_invalid( reinterpret_cast(src), i); @@ -599,9 +573,8 @@ static bool buf_buddy_relocate(void* src, void* dst, ulint i, bool force) return(true); } - rw_lock_x_unlock(hash_lock); + hash_lock->write_unlock(); - mutex_exit(block_mutex); return(false); } @@ -614,14 +587,13 @@ void buf_buddy_free_low(void* buf, ulint i) buf_buddy_free_t* buddy; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); ut_ad(i <= BUF_BUDDY_SIZES); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); ut_ad(buf_pool.buddy_stat[i].used > 0); buf_pool.buddy_stat[i].used--; recombine: - UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); + MEM_UNDEFINED(buf, BUF_BUDDY_LOW << i); if (i == BUF_BUDDY_SIZES) { buf_buddy_block_free(buf); @@ -701,7 +673,6 @@ buf_buddy_realloc(void* buf, ulint size) ulint i = buf_buddy_get_slot(size); ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.zip_mutex)); ut_ad(i <= BUF_BUDDY_SIZES); ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN)); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 4d38ded88fe..1e2abc2e04d 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -40,6 +40,7 @@ Created 11/5/1995 Heikki Tuuri #include #ifndef UNIV_INNOCHECKSUM +#include "my_cpu.h" #include "mem0mem.h" #include "btr0btr.h" #include "fil0fil.h" @@ -200,7 +201,7 @@ in the main memory, undisturbed. The unzip_LRU list contains a subset of the common LRU list. The blocks on the unzip_LRU list hold a compressed file page and the corresponding uncompressed page frame. A block is in unzip_LRU if and -only if the predicate buf_page_belongs_to_unzip_LRU(&block->page) +only if the predicate block->page.belongs_to_unzip_LRU() holds. The blocks in unzip_LRU will be in same order as they are in the common LRU list. That is, each manipulation of the common LRU list will result in the same manipulation of the unzip_LRU list. @@ -278,16 +279,55 @@ the read requests for the whole area. */ #ifndef UNIV_INNOCHECKSUM +void page_hash_latch::read_lock_wait() +{ + auto l= read_lock_yield(); + /* First, try busy spinning for a while. */ + for (auto spin= srv_n_spin_wait_rounds; spin--; ) + { + if (l & WRITER_PENDING) + ut_delay(srv_spin_wait_delay); + if (read_trylock()) + return; + l= read_lock_yield(); + } + /* Fall back to yielding to other threads. */ + for (;;) + { + if (l & WRITER_PENDING) + os_thread_yield(); + if (read_trylock()) + return; + l= read_lock_yield(); + } +} + +void page_hash_latch::write_lock_wait() +{ + write_lock_wait_start(); + + /* First, try busy spinning for a while. */ + for (auto spin= srv_n_spin_wait_rounds; spin--; ) + { + if (write_lock_poll()) + return; + ut_delay(srv_spin_wait_delay); + } + + /* Fall back to yielding to other threads. */ + do + os_thread_yield(); + while (!write_lock_poll()); +} + /** Value in microseconds */ -static const int WAIT_FOR_READ = 100; -static const int WAIT_FOR_WRITE = 100; +constexpr int WAIT_FOR_READ= 100; +constexpr int WAIT_FOR_WRITE= 100; /** Number of attempts made to read in a page in the buffer pool */ -static const ulint BUF_PAGE_READ_MAX_RETRIES = 100; -/** Number of pages to read ahead */ -static const ulint BUF_READ_AHEAD_PAGES = 64; +constexpr ulint BUF_PAGE_READ_MAX_RETRIES= 100; /** The maximum portion of the buffer pool that can be used for the read-ahead buffer. (Divide buf_pool size by this amount) */ -static const ulint BUF_READ_AHEAD_PORTION = 32; +constexpr uint32_t BUF_READ_AHEAD_PORTION= 32; /** The InnoDB buffer pool */ buf_pool_t buf_pool; @@ -297,20 +337,16 @@ buf_pool_t::chunk_t::map *buf_pool_t::chunk_t::map_ref; #ifdef UNIV_DEBUG /** Disable resizing buffer pool to make assertion code not expensive. */ my_bool buf_disable_resize_buffer_pool_debug = TRUE; -#endif /* UNIV_DEBUG */ -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** This is used to insert validation operations in execution in the debug version */ -static ulint buf_dbg_counter = 0; -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +static ulint buf_dbg_counter; +#endif /* UNIV_DEBUG */ #if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK # ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK -/* Buffer block mutexes and rwlocks can be registered -in one group rather than individually. If PFS_GROUP_BUFFER_SYNC -is defined, register buffer block mutex and rwlock +/* If defined, register buf_block_t::lock in one group after their initialization. */ # define PFS_GROUP_BUFFER_SYNC @@ -374,24 +410,27 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame) /** Decrypt a page. @param[in,out] bpage Page control block -@param[in,out] space tablespace +@param[in] node data file @return whether the operation was successful */ -static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space) +static bool buf_page_decrypt_after_read(buf_page_t *bpage, + const fil_node_t &node) { - ut_ad(space->pending_io()); - ut_ad(space->id == bpage->id.space()); + ut_ad(node.space->pending_io()); + ut_ad(node.space->id == bpage->id().space()); + const auto flags = node.space->flags; byte* dst_frame = bpage->zip.data ? bpage->zip.data : ((buf_block_t*) bpage)->frame; - bool page_compressed = space->is_compressed() - && buf_page_is_compressed(dst_frame, space->flags); + bool page_compressed = node.space->is_compressed() + && buf_page_is_compressed(dst_frame, flags); + const page_id_t id(bpage->id()); - if (bpage->id.page_no() == 0) { + if (id.page_no() == 0) { /* File header pages are not encrypted/compressed */ return (true); } - if (space->purpose == FIL_TYPE_TEMPORARY + if (node.space->purpose == FIL_TYPE_TEMPORARY && innodb_encrypt_temporary_tables) { buf_tmp_buffer_t* slot = buf_pool.io_buf_reserve(); ut_a(slot); @@ -399,8 +438,8 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space) if (!buf_tmp_page_decrypt(slot->crypt_buf, dst_frame)) { slot->release(); - ib::error() << "Encrypted page " << bpage->id - << " in file " << space->chain.start->name; + ib::error() << "Encrypted page " << id + << " in file " << node.name; return false; } @@ -413,14 +452,14 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space) also for pages first compressed and then encrypted. */ buf_tmp_buffer_t* slot; - uint key_version = buf_page_get_key_version(dst_frame, space->flags); + uint key_version = buf_page_get_key_version(dst_frame, flags); if (page_compressed && !key_version) { /* the page we read is unencrypted */ /* Find free slot from temporary memory array */ decompress: - if (space->full_crc32() - && buf_page_is_corrupted(true, dst_frame, space->flags)) { + if (fil_space_t::full_crc32(flags) + && buf_page_is_corrupted(true, dst_frame, flags)) { return false; } @@ -429,24 +468,24 @@ decompress: slot->allocate(); decompress_with_slot: - ut_d(fil_page_type_validate(space, dst_frame)); + ut_d(fil_page_type_validate(node.space, dst_frame)); ulint write_size = fil_page_decompress( - slot->crypt_buf, dst_frame, space->flags); + slot->crypt_buf, dst_frame, flags); slot->release(); - - ut_ad(!write_size || fil_page_type_validate(space, dst_frame)); - ut_ad(space->pending_io()); + ut_ad(!write_size + || fil_page_type_validate(node.space, dst_frame)); + ut_ad(node.space->pending_io()); return write_size != 0; } - if (key_version && space->crypt_data) { + if (key_version && node.space->crypt_data) { /* Verify encryption checksum before we even try to decrypt. */ - if (!buf_page_verify_crypt_checksum(dst_frame, space->flags)) { + if (!buf_page_verify_crypt_checksum(dst_frame, flags)) { decrypt_failed: - ib::error() << "Encrypted page " << bpage->id - << " in file " << space->chain.start->name + ib::error() << "Encrypted page " << id + << " in file " << node.name << " looks corrupted; key_version=" << key_version; return false; @@ -455,17 +494,17 @@ decrypt_failed: slot = buf_pool.io_buf_reserve(); ut_a(slot); slot->allocate(); - ut_d(fil_page_type_validate(space, dst_frame)); + ut_d(fil_page_type_validate(node.space, dst_frame)); /* decrypt using crypt_buf to dst_frame */ - if (!fil_space_decrypt(space, slot->crypt_buf, dst_frame)) { + if (!fil_space_decrypt(node.space, slot->crypt_buf, dst_frame)) { slot->release(); goto decrypt_failed; } - ut_d(fil_page_type_validate(space, dst_frame)); + ut_d(fil_page_type_validate(node.space, dst_frame)); - if ((space->full_crc32() && page_compressed) + if ((fil_space_t::full_crc32(flags) && page_compressed) || fil_page_get_type(dst_frame) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { goto decompress_with_slot; @@ -477,47 +516,33 @@ decrypt_failed: goto decompress; } - ut_ad(space->pending_io()); + ut_ad(node.space->pending_io()); return true; } /** @return the smallest oldest_modification lsn for any page. -@retval 0 if all modified persistent pages have been flushed */ -lsn_t -buf_pool_get_oldest_modification() +@retval 0 if all modified persistent pages have been flushed */ +lsn_t buf_pool_t::get_oldest_modification() { - mutex_enter(&buf_pool.flush_list_mutex); + mutex_enter(&flush_list_mutex); - buf_page_t* bpage; + /* FIXME: Keep temporary tablespace pages in a separate flush + list. We would only need to write out temporary pages if the + page is about to be evicted from the buffer pool, and the page + contents is still needed (the page has not been freed). */ + const buf_page_t *bpage; + for (bpage= UT_LIST_GET_LAST(flush_list); + bpage && fsp_is_system_temporary(bpage->id().space()); + bpage= UT_LIST_GET_PREV(list, bpage)) + ut_ad(bpage->oldest_modification()); - /* FIXME: Keep temporary tablespace pages in a separate flush - list. We would only need to write out temporary pages if the - page is about to be evicted from the buffer pool, and the page - contents is still needed (the page has not been freed). */ - for (bpage = UT_LIST_GET_LAST(buf_pool.flush_list); - bpage != NULL && fsp_is_system_temporary(bpage->id.space()); - bpage = UT_LIST_GET_PREV(list, bpage)) { - ut_ad(bpage->in_flush_list); - } + lsn_t oldest_lsn= bpage ? bpage->oldest_modification() : 0; + mutex_exit(&flush_list_mutex); - lsn_t oldest_lsn = bpage ? bpage->oldest_modification : 0; - mutex_exit(&buf_pool.flush_list_mutex); - - /* The returned answer may be out of date: the flush_list can - change after the mutex has been released. */ - - return(oldest_lsn); -} - -/** Allocate a buffer block. -@return own: the allocated block, in state BUF_BLOCK_MEMORY */ -buf_block_t* -buf_block_alloc() -{ - buf_block_t* block = buf_LRU_get_free_block(); - buf_block_set_state(block, BUF_BLOCK_MEMORY); - return(block); + /* The result may become stale as soon as we released the mutex. + On log checkpoint, also log_sys.flush_order_mutex will be needed. */ + return oldest_lsn; } #endif /* !UNIV_INNOCHECKSUM */ @@ -1218,8 +1243,6 @@ void buf_page_print(const byte* read_buf, ulint zip_size) } # ifdef PFS_GROUP_BUFFER_SYNC -extern mysql_pfs_key_t buffer_block_mutex_key; - /********************************************************************//** This function registers mutexes and rwlocks in buffer blocks with performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is @@ -1241,13 +1264,6 @@ pfs_register_buffer_block( chunk->size, PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER); for (ulint i = 0; i < num_to_register; i++) { -# ifdef UNIV_PFS_MUTEX - BPageMutex* mutex; - - mutex = &block->mutex; - mutex->pfs_add(buffer_block_mutex_key); -# endif /* UNIV_PFS_MUTEX */ - rw_lock_t* rwlock; # ifdef UNIV_PFS_RWLOCK @@ -1279,39 +1295,24 @@ static void buf_block_init(buf_block_t* block, byte* frame) { - UNIV_MEM_DESC(frame, srv_page_size); - /* This function should only be executed at database startup or by buf_pool.resize(). Either way, adaptive hash index must not exist. */ assert_block_ahi_empty_on_init(block); block->frame = frame; - block->page.flush_type = BUF_FLUSH_LRU; - block->page.state = BUF_BLOCK_NOT_USED; - block->page.buf_fix_count = 0; - block->page.io_fix = BUF_IO_NONE; - block->page.real_size = 0; block->modify_clock = 0; - block->page.slot = NULL; - block->page.status = buf_page_t::NORMAL; - + block->page.init(BUF_BLOCK_NOT_USED, page_id_t(~0ULL)); #ifdef BTR_CUR_HASH_ADAPT block->index = NULL; #endif /* BTR_CUR_HASH_ADAPT */ block->skip_flush_check = false; - ut_d(block->page.in_page_hash = FALSE); - ut_d(block->page.in_zip_hash = FALSE); - ut_d(block->page.in_flush_list = FALSE); - ut_d(block->page.in_free_list = FALSE); - ut_d(block->page.in_LRU_list = FALSE); - ut_d(block->in_unzip_LRU_list = FALSE); - ut_d(block->in_withdraw_list = FALSE); + ut_d(block->in_unzip_LRU_list = false); + ut_d(block->in_withdraw_list = false); page_zip_des_init(&block->page.zip); - mutex_create(LATCH_ID_BUF_BLOCK_MUTEX, &block->mutex); ut_d(block->debug_latch = (rw_lock_t *) ut_malloc_nokey(sizeof(rw_lock_t))); #if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC @@ -1409,7 +1410,7 @@ inline bool buf_pool_t::chunk_t::create(size_t bytes) for (auto i= size; i--; ) { buf_block_init(block, frame); - UNIV_MEM_INVALID(block->frame, srv_page_size); + MEM_UNDEFINED(block->frame, srv_page_size); /* Add the block to the free list */ UT_LIST_ADD_LAST(buf_pool.free, &block->page); @@ -1435,16 +1436,13 @@ inline const buf_block_t *buf_pool_t::chunk_t::not_freed() const buf_block_t *block= blocks; for (auto i= size; i--; block++) { - switch (buf_block_get_state(block)) { - case BUF_BLOCK_POOL_WATCH: + switch (block->page.state()) { case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: /* The uncompressed buffer pool should never contain ROW_FORMAT=COMPRESSED block descriptors. */ ut_error; break; case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: /* Skip blocks that are not being used for file pages. */ @@ -1454,19 +1452,16 @@ inline const buf_block_t *buf_pool_t::chunk_t::not_freed() const { /* The page cleaner is disabled in read-only mode. No pages can be dirtied, so all of them must be clean. */ - ut_ad(block->page.oldest_modification == 0 || - block->page.oldest_modification == recv_sys.recovered_lsn || + ut_d(lsn_t oldest_modification= block->page.oldest_modification()); + ut_ad(oldest_modification == 0 || + oldest_modification == recv_sys.recovered_lsn || srv_force_recovery == SRV_FORCE_NO_LOG_REDO); - ut_ad(block->page.buf_fix_count == 0); - ut_ad(block->page.io_fix == BUF_IO_NONE); + ut_ad(!block->page.buf_fix_count()); + ut_ad(block->page.io_fix() == BUF_IO_NONE); break; } - buf_page_mutex_enter(block); - auto ready= buf_flush_ready_for_replace(&block->page); - buf_page_mutex_exit(block); - - if (!ready) + if (!block->page.ready_for_replace()) return block; break; @@ -1481,12 +1476,20 @@ inline const buf_block_t *buf_pool_t::chunk_t::not_freed() const @param[in,out] block buffer pool block descriptor */ static void buf_block_free_mutexes(buf_block_t* block) { - mutex_free(&block->mutex); rw_lock_free(&block->lock); ut_d(rw_lock_free(block->debug_latch)); ut_d(ut_free(block->debug_latch)); } +/** Create the hash table. +@param n the lower bound of n_cells */ +void buf_pool_t::page_hash_table::create(ulint n) +{ + n_cells= ut_find_prime(n); + array= static_cast + (ut_zalloc_nokey(pad(n_cells) * sizeof *array)); +} + /** Create the buffer pool. @return whether the creation failed */ bool buf_pool_t::create() @@ -1523,17 +1526,17 @@ bool buf_pool_t::create() { buf_block_t* block= chunk->blocks; - for (auto i= chunk->size; i--; block++) + for (auto i= chunk->size; i--; block++) buf_block_free_mutexes(block); - allocator.deallocate_large_dodump(chunk->mem, &chunk->mem_pfx); - } - ut_free(chunks); - chunks= nullptr; - UT_DELETE(chunk_t::map_reg); - chunk_t::map_reg= nullptr; - ut_ad(!is_initialised()); - return true; + allocator.deallocate_large_dodump(chunk->mem, &chunk->mem_pfx); + } + ut_free(chunks); + chunks= nullptr; + UT_DELETE(chunk_t::map_reg); + chunk_t::map_reg= nullptr; + ut_ad(!is_initialised()); + return true; } curr_size+= chunk->size; @@ -1542,7 +1545,6 @@ bool buf_pool_t::create() ut_ad(is_initialised()); mutex_create(LATCH_ID_BUF_POOL, &mutex); - mutex_create(LATCH_ID_BUF_POOL_ZIP, &zip_mutex); UT_LIST_INIT(LRU, &buf_page_t::LRU); UT_LIST_INIT(withdraw, &buf_page_t::list); @@ -1550,42 +1552,29 @@ bool buf_pool_t::create() UT_LIST_INIT(flush_list, &buf_page_t::list); UT_LIST_INIT(unzip_LRU, &buf_block_t::unzip_LRU); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - UT_LIST_INIT(zip_clean, &buf_page_t::list); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ + ut_d(UT_LIST_INIT(zip_clean, &buf_page_t::list)); for (size_t i= 0; i < UT_ARR_SIZE(zip_free); ++i) UT_LIST_INIT(zip_free[i], &buf_buddy_free_t::list); - - read_ahead_area= ut_min(BUF_READ_AHEAD_PAGES, - ut_2_power_up(curr_size / BUF_READ_AHEAD_PORTION)); + ulint s= curr_size; + old_size= s; + s/= BUF_READ_AHEAD_PORTION; + read_ahead_area= s >= READ_AHEAD_PAGES + ? READ_AHEAD_PAGES + : my_round_up_to_next_power(static_cast(s)); curr_pool_size= srv_buf_pool_size; - old_size= curr_size; n_chunks_new= n_chunks; - /* Number of locks protecting page_hash must be a power of two */ - srv_n_page_hash_locks= static_cast - (ut_2_power_up(srv_n_page_hash_locks)); - ut_a(srv_n_page_hash_locks != 0); - ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS); - - page_hash= ib_create(2 * curr_size, - LATCH_ID_HASH_TABLE_RW_LOCK, - srv_n_page_hash_locks, MEM_HEAP_FOR_PAGE_HASH); - - ut_ad(!page_hash_old); - zip_hash= hash_create(2 * curr_size); + page_hash.create(2 * curr_size); + zip_hash.create(2 * curr_size); last_printout_time= time(NULL); mutex_create(LATCH_ID_FLUSH_LIST, &flush_list_mutex); - for (int i= BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) + for (int i= 0; i < 3; i++) no_flush[i]= os_event_create(0); - watch= static_cast - (ut_zalloc_nokey(sizeof *watch * BUF_POOL_WATCH_SIZE)); - try_LRU_scan= true; ut_d(flush_hp.m_mutex= &flush_list_mutex;); @@ -1603,7 +1592,7 @@ bool buf_pool_t::create() chunk_t::map_ref= chunk_t::map_reg; buf_LRU_old_ratio_update(100 * 3 / 8, false); - btr_search_sys_create(srv_buf_pool_curr_size / sizeof(void*) / 64); + btr_search_sys_create(); ut_ad(is_initialised()); return false; } @@ -1616,7 +1605,6 @@ void buf_pool_t::close() return; mutex_free(&mutex); - mutex_free(&zip_mutex); mutex_free(&flush_list_mutex); if (flush_rbt) @@ -1629,22 +1617,18 @@ void buf_pool_t::close() bpage= prev_bpage) { prev_bpage= UT_LIST_GET_PREV(LRU, bpage); - buf_page_state state= buf_page_get_state(bpage); - - ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); ut_ad(bpage->in_LRU_list); + /* The buffer pool must be clean during normal shutdown. + Only on aborted startup (with recovery) or with innodb_fast_shutdown=2 + we may discard changes. */ + ut_ad(!bpage->oldest_modification() || srv_is_being_started || + srv_fast_shutdown == 2); - if (state != BUF_BLOCK_FILE_PAGE) - { - /* We must not have any dirty block except during a fast shutdown. */ - ut_ad(state == BUF_BLOCK_ZIP_PAGE || srv_fast_shutdown == 2); + if (bpage->state() != BUF_BLOCK_FILE_PAGE) buf_page_free_descriptor(bpage); - } } - ut_free(watch); - watch= nullptr; - for (auto chunk= chunks + n_chunks; --chunk >= chunks; ) { buf_block_t *block= chunk->blocks; @@ -1655,14 +1639,20 @@ void buf_pool_t::close() allocator.deallocate_large_dodump(chunk->mem, &chunk->mem_pfx); } - for (ulint i= BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; ++i) + for (int i= 0; i < 3; ++i) os_event_destroy(no_flush[i]); ut_free(chunks); chunks= nullptr; - ha_clear(page_hash); - hash_table_free(page_hash); - hash_table_free(zip_hash); + page_hash.free(); + while (page_hash_table *old_page_hash= freed_page_hash) + { + freed_page_hash= static_cast + (old_page_hash->array[1].node); + old_page_hash->free(); + UT_DELETE(old_page_hash); + } + zip_hash.free(); io_buf.close(); UT_DELETE(chunk_t::map_reg); @@ -1678,7 +1668,7 @@ inline bool buf_pool_t::realloc(buf_block_t *block) ut_ad(withdrawing); ut_ad(mutex_own(&mutex)); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); new_block = buf_LRU_get_free_only(); @@ -1686,28 +1676,17 @@ inline bool buf_pool_t::realloc(buf_block_t *block) return(false); /* free list was not enough */ } - rw_lock_t* hash_lock = buf_page_hash_lock_get(block->page.id); - rw_lock_x_lock(hash_lock); - mutex_enter(&block->mutex); - - if (buf_page_can_relocate(&block->page)) { - mutex_enter(&new_block->mutex); + const page_id_t id(block->page.id()); + page_hash_latch* hash_lock = hash_lock_get(id); + hash_lock->write_lock(); + if (block->page.can_relocate()) { memcpy_aligned( new_block->frame, block->frame, srv_page_size); new (&new_block->page) buf_page_t(block->page); /* relocate LRU list */ - ut_ad(block->page.in_LRU_list); - ut_ad(!block->page.in_zip_hash); - ut_d(block->page.in_LRU_list = FALSE); - - buf_LRU_adjust_hp(&block->page); - - buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, &block->page); - UT_LIST_REMOVE(LRU, &block->page); - - if (prev_b != NULL) { + if (buf_page_t* prev_b = buf_pool.LRU_remove(&block->page)) { UT_LIST_INSERT_AFTER(LRU, prev_b, &new_block->page); } else { UT_LIST_ADD_FIRST(LRU, &new_block->page); @@ -1722,14 +1701,12 @@ inline bool buf_pool_t::realloc(buf_block_t *block) /* relocate unzip_LRU list */ if (block->page.zip.data != NULL) { ut_ad(block->in_unzip_LRU_list); - ut_d(new_block->in_unzip_LRU_list = TRUE); - UNIV_MEM_DESC(&new_block->page.zip.data, - page_zip_get_size(&new_block->page.zip)); + ut_d(new_block->in_unzip_LRU_list = true); buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); UT_LIST_REMOVE(unzip_LRU, block); - ut_d(block->in_unzip_LRU_list = FALSE); + ut_d(block->in_unzip_LRU_list = false); block->page.zip.data = NULL; page_zip_set_size(&block->page.zip, 0); @@ -1740,19 +1717,17 @@ inline bool buf_pool_t::realloc(buf_block_t *block) } } else { ut_ad(!block->in_unzip_LRU_list); - ut_d(new_block->in_unzip_LRU_list = FALSE); + ut_d(new_block->in_unzip_LRU_list = false); } /* relocate page_hash */ ut_ad(block->page.in_page_hash); - ut_ad(&block->page == buf_page_hash_get_low(block->page.id)); - ut_d(block->page.in_page_hash = FALSE); - ulint fold = block->page.id.fold(); - ut_ad(fold == new_block->page.id.fold()); - HASH_REPLACE(buf_page_t, hash, page_hash, fold, - &block->page, &new_block->page); - ut_ad(new_block->page.in_page_hash); + const ulint fold = id.fold(); + ut_ad(&block->page == page_hash_get_low(id, fold)); + ut_d(block->page.in_page_hash = false); + HASH_REPLACE(buf_page_t, hash, &page_hash, fold, + &block->page, &new_block->page); buf_block_modify_clock_inc(block); static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); @@ -1761,17 +1736,19 @@ inline bool buf_pool_t::realloc(buf_block_t *block) "not perfect alignment"); memset_aligned<2>(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4); - UNIV_MEM_INVALID(block->frame, srv_page_size); - buf_block_set_state(block, BUF_BLOCK_REMOVE_HASH); - block->page.id - = page_id_t(ULINT32_UNDEFINED, ULINT32_UNDEFINED); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(block->frame, srv_page_size); +#endif /* HAVE_valgrind_or_MSAN */ + block->page.set_state(BUF_BLOCK_REMOVE_HASH); /* Relocate flush_list. */ - if (block->page.oldest_modification) { + if (block->page.oldest_modification()) { buf_flush_relocate_on_flush_list( &block->page, &new_block->page); } + block->page.set_corrupt_id(); + /* set other flags of buf_block_t */ #ifdef BTR_CUR_HASH_ADAPT @@ -1788,25 +1765,16 @@ inline bool buf_pool_t::realloc(buf_block_t *block) new_block->lock_hash_val = block->lock_hash_val; ut_ad(new_block->lock_hash_val == lock_rec_hash( - new_block->page.id.space(), - new_block->page.id.page_no())); + id.space(), id.page_no())); - rw_lock_x_unlock(hash_lock); - mutex_exit(&new_block->mutex); + hash_lock->write_unlock(); /* free block */ - buf_block_set_state(block, BUF_BLOCK_MEMORY); + ut_d(block->page.set_state(BUF_BLOCK_MEMORY)); buf_LRU_block_free_non_file_page(block); - - mutex_exit(&block->mutex); } else { - rw_lock_x_unlock(hash_lock); - mutex_exit(&block->mutex); - - /* free new_block */ - mutex_enter(&new_block->mutex); + hash_lock->write_unlock(); buf_LRU_block_free_non_file_page(new_block); - mutex_exit(&new_block->mutex); } return(true); /* free_list was enough */ @@ -1863,9 +1831,9 @@ inline bool buf_pool_t::withdraw_blocks() while (block != NULL && UT_LIST_GET_LEN(withdraw) < withdraw_target) { ut_ad(block->page.in_free_list); - ut_ad(!block->page.in_flush_list); + ut_ad(!block->page.oldest_modification()); ut_ad(!block->page.in_LRU_list); - ut_a(!buf_page_in_file(&block->page)); + ut_a(!block->page.in_file()); buf_block_t* next_block; next_block = reinterpret_cast( @@ -1876,7 +1844,7 @@ inline bool buf_pool_t::withdraw_blocks() /* This should be withdrawn */ UT_LIST_REMOVE(free, &block->page); UT_LIST_ADD_LAST(withdraw, &block->page); - ut_d(block->in_withdraw_list = TRUE); + ut_d(block->in_withdraw_list = true); count1++; } @@ -1900,8 +1868,8 @@ inline bool buf_pool_t::withdraw_blocks() static_cast(srv_LRU_scan_depth)), scan_depth); - buf_flush_do_batch(BUF_FLUSH_LRU, scan_depth, 0, &n); - buf_flush_wait_batch_end(BUF_FLUSH_LRU); + buf_flush_do_batch(true, scan_depth, 0, &n); + buf_flush_wait_batch_end(true); if (n.flushed) { MONITOR_INC_VALUE_CUMULATIVE( @@ -1919,18 +1887,10 @@ inline bool buf_pool_t::withdraw_blocks() buf_page_t* bpage; bpage = UT_LIST_GET_FIRST(LRU); while (bpage != NULL) { - BPageMutex* block_mutex; - buf_page_t* next_bpage; - - block_mutex = buf_page_get_mutex(bpage); - mutex_enter(block_mutex); - - next_bpage = UT_LIST_GET_NEXT(LRU, bpage); - + buf_page_t* next_bpage = UT_LIST_GET_NEXT(LRU, bpage); if (bpage->zip.data != NULL && will_be_withdrawn(bpage->zip.data) - && buf_page_can_relocate(bpage)) { - mutex_exit(block_mutex); + && bpage->can_relocate()) { buf_pool_mutex_exit_forbid(); if (!buf_buddy_realloc( bpage->zip.data, @@ -1940,15 +1900,12 @@ inline bool buf_pool_t::withdraw_blocks() break; } buf_pool_mutex_exit_allow(); - mutex_enter(block_mutex); count2++; } - if (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE + if (bpage->state() == BUF_BLOCK_FILE_PAGE && buf_pool.will_be_withdrawn(*bpage)) { - if (buf_page_can_relocate(bpage)) { - mutex_exit(block_mutex); + if (bpage->can_relocate()) { buf_pool_mutex_exit_forbid(); if (!realloc( reinterpret_cast( @@ -1959,13 +1916,9 @@ inline bool buf_pool_t::withdraw_blocks() } buf_pool_mutex_exit_allow(); count2++; - } else { - mutex_exit(block_mutex); } /* NOTE: if the page is in use, not relocated yet */ - } else { - mutex_exit(block_mutex); } bpage = next_bpage; @@ -1999,7 +1952,7 @@ inline bool buf_pool_t::withdraw_blocks() * const echunk = chunks + n_chunks; chunk != echunk; chunk++) { block = chunk->blocks; for (ulint j = chunk->size; j--; block++) { - ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED); + ut_a(block->page.state() == BUF_BLOCK_NOT_USED); ut_ad(block->in_withdraw_list); } } @@ -2014,81 +1967,135 @@ inline bool buf_pool_t::withdraw_blocks() } /** resize page_hash and zip_hash */ -static void buf_pool_resize_hash() +inline void buf_pool_t::resize_hash() { - hash_table_t* new_hash_table; + page_hash_table *new_page_hash= UT_NEW_NOKEY(page_hash_table()); + new_page_hash->create(2 * buf_pool.curr_size); + new_page_hash->write_lock_all(); - ut_ad(buf_pool.page_hash_old == NULL); + for (auto i= page_hash.pad(page_hash.n_cells); i--; ) + { + static_assert(!((page_hash_table::ELEMENTS_PER_LATCH + 1) & + page_hash_table::ELEMENTS_PER_LATCH), + "must be one less than a power of 2"); + if (!(i & page_hash_table::ELEMENTS_PER_LATCH)) + { + ut_ad(reinterpret_cast + (&page_hash.array[i])->is_write_locked()); + continue; + } + while (buf_page_t *bpage= static_cast + (page_hash.array[i].node)) + { + ut_ad(bpage->in_page_hash); + const ulint fold= bpage->id().fold(); + HASH_DELETE(buf_page_t, hash, &buf_pool.page_hash, fold, bpage); + HASH_INSERT(buf_page_t, hash, new_page_hash, fold, bpage); + } + } - /* recreate page_hash */ - new_hash_table = ib_recreate( - buf_pool.page_hash, 2 * buf_pool.curr_size); + buf_pool.page_hash.array[1].node= freed_page_hash; + std::swap(buf_pool.page_hash, *new_page_hash); + freed_page_hash= new_page_hash; - for (ulint i = 0; i < hash_get_n_cells(buf_pool.page_hash); i++) { - buf_page_t* bpage; + /* recreate zip_hash */ + hash_table_t new_hash; + new_hash.create(2 * buf_pool.curr_size); - bpage = static_cast( - HASH_GET_FIRST( - buf_pool.page_hash, i)); + for (ulint i= 0; i < buf_pool.zip_hash.n_cells; i++) + { + while (buf_page_t *bpage= static_cast + (HASH_GET_FIRST(&buf_pool.zip_hash, i))) + { + const ulint fold= BUF_POOL_ZIP_FOLD_BPAGE(bpage); + HASH_DELETE(buf_page_t, hash, &buf_pool.zip_hash, fold, bpage); + HASH_INSERT(buf_page_t, hash, &new_hash, fold, bpage); + } + } - while (bpage) { - buf_page_t* prev_bpage = bpage; - ulint fold; - - bpage = static_cast( - HASH_GET_NEXT( - hash, prev_bpage)); - - fold = prev_bpage->id.fold(); - - HASH_DELETE(buf_page_t, hash, - buf_pool.page_hash, fold, - prev_bpage); - - HASH_INSERT(buf_page_t, hash, - new_hash_table, fold, - prev_bpage); - } - } - - buf_pool.page_hash_old = buf_pool.page_hash; - buf_pool.page_hash = new_hash_table; - - /* recreate zip_hash */ - new_hash_table = hash_create(2 * buf_pool.curr_size); - - for (ulint i = 0; i < hash_get_n_cells(buf_pool.zip_hash); i++) { - buf_page_t* bpage; - - bpage = static_cast( - HASH_GET_FIRST(buf_pool.zip_hash, i)); - - while (bpage) { - buf_page_t* prev_bpage = bpage; - ulint fold; - - bpage = static_cast( - HASH_GET_NEXT( - hash, prev_bpage)); - - fold = BUF_POOL_ZIP_FOLD( - reinterpret_cast( - prev_bpage)); - - HASH_DELETE(buf_page_t, hash, - buf_pool.zip_hash, fold, - prev_bpage); - - HASH_INSERT(buf_page_t, hash, - new_hash_table, fold, - prev_bpage); - } - } - - hash_table_free(buf_pool.zip_hash); - buf_pool.zip_hash = new_hash_table; + std::swap(buf_pool.zip_hash.array, new_hash.array); + buf_pool.zip_hash.n_cells= new_hash.n_cells; + new_hash.free(); } + +inline void buf_pool_t::page_hash_table::write_lock_all() +{ + for (auto n= pad(n_cells) & ~ELEMENTS_PER_LATCH;; n-= ELEMENTS_PER_LATCH + 1) + { + reinterpret_cast(array[n]).write_lock(); + if (!n) + break; + } +} + + +inline void buf_pool_t::page_hash_table::write_unlock_all() +{ + for (auto n= pad(n_cells) & ~ELEMENTS_PER_LATCH;; n-= ELEMENTS_PER_LATCH + 1) + { + reinterpret_cast(array[n]).write_unlock(); + if (!n) + break; + } +} + + +inline void buf_pool_t::write_lock_all_page_hash() +{ + ut_ad(mutex_own(&mutex)); + page_hash.write_lock_all(); + for (page_hash_table *old_page_hash= freed_page_hash; old_page_hash; + old_page_hash= static_cast + (old_page_hash->array[1].node)) + old_page_hash->write_lock_all(); +} + + +inline void buf_pool_t::write_unlock_all_page_hash() +{ + page_hash.write_unlock_all(); + for (page_hash_table *old_page_hash= freed_page_hash; old_page_hash; + old_page_hash= static_cast + (old_page_hash->array[1].node)) + old_page_hash->write_unlock_all(); +} + +namespace +{ + +struct find_interesting_trx +{ + void operator()(const trx_t &trx) + { + if (trx.state == TRX_STATE_NOT_STARTED) + return; + if (trx.mysql_thd == nullptr) + return; + if (withdraw_started <= trx.start_time) + return; + + if (!found) + { + ib::warn() << "The following trx might hold " + "the blocks in buffer pool to " + "be withdrawn. Buffer pool " + "resizing can complete only " + "after all the transactions " + "below release the blocks."; + found= true; + } + + lock_trx_print_wait_and_mvcc_state(stderr, &trx, current_time); + } + + bool &found; + time_t withdraw_started; + time_t current_time; +}; + +} // namespace + /** Resize from srv_buf_pool_old_size to srv_buf_pool_size. */ inline void buf_pool_t::resize() { @@ -2132,7 +2139,7 @@ inline void buf_pool_t::resize() btr_search_s_unlock_all(); } - btr_search_disable(true); + btr_search_disable(); if (btr_search_disabled) { ib::info() << "disabled adaptive hash index."; @@ -2185,30 +2192,9 @@ withdraw_retry: } lock_mutex_enter(); - mutex_enter(&trx_sys.mutex); bool found = false; - for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys.trx_list); - trx != NULL; - trx = UT_LIST_GET_NEXT(trx_list, trx)) { - if (trx->state != TRX_STATE_NOT_STARTED - && trx->mysql_thd != NULL - && withdraw_started > trx->start_time) { - if (!found) { - ib::warn() << - "The following trx might hold" - " the blocks in buffer pool to" - " be withdrawn. Buffer pool" - " resizing can complete only" - " after all the transactions" - " below release the blocks."; - found = true; - } - - lock_trx_print_wait_and_mvcc_state( - stderr, trx, current_time); - } - } - mutex_exit(&trx_sys.mutex); + trx_sys.trx_list.for_each(find_interesting_trx{ + found, withdraw_started, current_time}); lock_mutex_exit(); withdraw_started = current_time; @@ -2252,8 +2238,9 @@ withdraw_retry: /* Indicate critical path */ resizing.store(true, std::memory_order_relaxed); - mutex_enter(&mutex); - hash_lock_x_all(page_hash); + mutex_enter(&mutex); + write_lock_all_page_hash(); + chunk_t::map_reg = UT_NEW_NOKEY(chunk_t::map()); /* add/delete chunks */ @@ -2380,13 +2367,15 @@ calc_buf_pool_size: /* set size */ ut_ad(UT_LIST_GET_LEN(withdraw) == 0); - read_ahead_area = ut_min( - BUF_READ_AHEAD_PAGES, - ut_2_power_up(curr_size / BUF_READ_AHEAD_PORTION)); - curr_pool_size = n_chunks * srv_buf_pool_chunk_unit; - srv_buf_pool_curr_size = curr_pool_size;/* FIXME: remove*/ - old_size = curr_size; - innodb_set_buf_pool_size(buf_pool_size_align(srv_buf_pool_curr_size)); + ulint s= curr_size; + old_size= s; + s/= BUF_READ_AHEAD_PORTION; + read_ahead_area= s >= READ_AHEAD_PAGES + ? READ_AHEAD_PAGES + : my_round_up_to_next_power(static_cast(s)); + curr_pool_size= n_chunks * srv_buf_pool_chunk_unit; + srv_buf_pool_curr_size= curr_pool_size;/* FIXME: remove*/ + innodb_set_buf_pool_size(buf_pool_size_align(srv_buf_pool_curr_size)); const bool new_size_too_diff = srv_buf_pool_base_size > srv_buf_pool_size * 2 @@ -2396,17 +2385,12 @@ calc_buf_pool_size: if the new size is too different */ if (!warning && new_size_too_diff) { buf_resize_status("Resizing hash table"); - buf_pool_resize_hash(); + resize_hash(); ib::info() << "hash tables were resized"; } - hash_unlock_x_all(page_hash); - mutex_exit(&mutex); - - if (page_hash_old != NULL) { - hash_table_free(page_hash_old); - page_hash_old = NULL; - } + mutex_exit(&mutex); + write_unlock_all_page_hash(); UT_DELETE(chunk_map_old); @@ -2418,15 +2402,9 @@ calc_buf_pool_size: buf_resize_status("Resizing also other hash tables."); - /* normalize lock_sys */ srv_lock_table_size = 5 * (srv_buf_pool_size >> srv_page_size_shift); lock_sys.resize(srv_lock_table_size); - - /* normalize btr_search_sys */ - btr_search_sys_resize( - buf_pool_get_curr_size() / sizeof(void*) / 64); - dict_sys.resize(); ib::info() << "Resized hash tables at lock_sys," @@ -2450,7 +2428,7 @@ calc_buf_pool_size: #ifdef BTR_CUR_HASH_ADAPT /* enable AHI if needed */ if (btr_search_disabled) { - btr_search_enable(); + btr_search_enable(true); ib::info() << "Re-enabled adaptive hash index."; } #endif /* BTR_CUR_HASH_ADAPT */ @@ -2466,9 +2444,7 @@ calc_buf_pool_size: " finished resizing at %s.", now); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ + ut_d(validate()); return; } @@ -2513,314 +2489,134 @@ void buf_resize_shutdown() /** Relocate a ROW_FORMAT=COMPRESSED block in the LRU list and buf_pool.page_hash. The caller must relocate bpage->list. -@param bpage control block in BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE +@param bpage BUF_BLOCK_ZIP_PAGE block @param dpage destination control block */ static void buf_relocate(buf_page_t *bpage, buf_page_t *dpage) { - buf_page_t* b; - - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_hash_lock_held_x(bpage)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE); - ut_a(bpage->buf_fix_count == 0); - ut_ad(bpage->in_LRU_list); - ut_ad(!bpage->in_zip_hash); - ut_ad(bpage->in_page_hash); - ut_ad(bpage == buf_page_hash_get_low(bpage->id)); - ut_ad(!buf_pool_watch_is_sentinel(bpage)); -#ifdef UNIV_DEBUG - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_FILE_PAGE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - ut_error; - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_ZIP_PAGE: - break; - } -#endif /* UNIV_DEBUG */ - - new (dpage) buf_page_t(*bpage); - - /* Important that we adjust the hazard pointer before - removing bpage from LRU list. */ - buf_LRU_adjust_hp(bpage); - - ut_d(bpage->in_LRU_list = FALSE); - ut_d(bpage->in_page_hash = FALSE); - - /* relocate buf_pool.LRU */ - b = UT_LIST_GET_PREV(LRU, bpage); - UT_LIST_REMOVE(buf_pool.LRU, bpage); - - if (b != NULL) { - UT_LIST_INSERT_AFTER(buf_pool.LRU, b, dpage); - } else { - UT_LIST_ADD_FIRST(buf_pool.LRU, dpage); - } - - if (UNIV_UNLIKELY(buf_pool.LRU_old == bpage)) { - buf_pool.LRU_old = dpage; -#ifdef UNIV_LRU_DEBUG - /* buf_pool.LRU_old must be the first item in the LRU list - whose "old" flag is set. */ - ut_a(buf_pool.LRU_old->old); - ut_a(!UT_LIST_GET_PREV(LRU, buf_pool.LRU_old) - || !UT_LIST_GET_PREV(LRU, buf_pool.LRU_old)->old); - ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool.LRU_old) - || UT_LIST_GET_NEXT(LRU, buf_pool.LRU_old)->old); - } else { - /* Check that the "old" flag is consistent in - the block and its neighbours. */ - buf_page_set_old(dpage, buf_page_is_old(dpage)); -#endif /* UNIV_LRU_DEBUG */ - } - - ut_d(CheckInLRUList::validate()); - - /* relocate buf_pool.page_hash */ - ulint fold = bpage->id.fold(); - ut_ad(fold == dpage->id.fold()); - HASH_REPLACE(buf_page_t, hash, buf_pool.page_hash, fold, bpage, - dpage); -} - -/** Determine if a block is a sentinel for a buffer pool watch. -@param[in] bpage block -@return whether bpage a sentinel for a buffer pool watch */ -bool buf_pool_watch_is_sentinel(const buf_page_t* bpage) -{ - /* We must own the appropriate hash lock. */ - ut_ad(buf_page_hash_lock_held_s_or_x(bpage)); - ut_ad(buf_page_in_file(bpage)); - - if (bpage < &buf_pool.watch[0] - || bpage >= &buf_pool.watch[BUF_POOL_WATCH_SIZE]) { - - ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE - || bpage->zip.data != NULL); - - return false; - } - - ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE); - ut_ad(!bpage->in_zip_hash); - ut_ad(bpage->in_page_hash); - ut_ad(bpage->zip.data == NULL); - return true; -} - -/** Add watch for the given page to be read in. Caller must have -appropriate hash_lock for the bpage. This function may release the -hash_lock and reacquire it. -@param[in] page_id page id -@param[in,out] hash_lock hash_lock currently latched -@return NULL if watch set, block if the page is in the buffer pool */ -static -buf_page_t* -buf_pool_watch_set( - const page_id_t page_id, - rw_lock_t** hash_lock) -{ - buf_page_t* bpage; - ulint i; - - ut_ad(*hash_lock == buf_page_hash_lock_get(page_id)); - - ut_ad(rw_lock_own(*hash_lock, RW_LOCK_X)); - - bpage = buf_page_hash_get_low(page_id); - - if (bpage != NULL) { -page_found: - if (!buf_pool_watch_is_sentinel(bpage)) { - /* The page was loaded meanwhile. */ - return(bpage); - } - - /* Add to an existing watch. */ - bpage->fix(); - return(NULL); - } - - /* From this point this function becomes fairly heavy in terms - of latching. We acquire the buf_pool mutex as well as all the - hash_locks. buf_pool mutex is needed because any changes to - the page_hash must be covered by it and hash_locks are needed - because we don't want to read any stale information in - buf_pool.watch[]. However, it is not in the critical code path - as this function will be called only by the purge thread. */ - - /* To obey latching order first release the hash_lock. */ - rw_lock_x_unlock(*hash_lock); - - mutex_enter(&buf_pool.mutex); - hash_lock_x_all(buf_pool.page_hash); - - /* We have to recheck that the page - was not loaded or a watch set by some other - purge thread. This is because of the small - time window between when we release the - hash_lock to acquire buf_pool.mutex above. */ - - *hash_lock = buf_page_hash_lock_get(page_id); - - bpage = buf_page_hash_get_low(page_id); - if (UNIV_LIKELY_NULL(bpage)) { - mutex_exit(&buf_pool.mutex); - hash_unlock_x_all_but(buf_pool.page_hash, *hash_lock); - goto page_found; - } - - /* The maximum number of purge threads should never exceed - BUF_POOL_WATCH_SIZE. So there is no way for a purge task - to hold a watch when setting another watch. */ - for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) { - bpage = &buf_pool.watch[i]; - - ut_ad(bpage->access_time == 0); - ut_ad(bpage->oldest_modification == 0); - ut_ad(bpage->zip.data == NULL); - ut_ad(!bpage->in_zip_hash); - - switch (bpage->state) { - case BUF_BLOCK_POOL_WATCH: - ut_ad(!bpage->in_page_hash); - ut_ad(bpage->buf_fix_count == 0); - - /* bpage is pointing to buf_pool.watch[], - which is protected by buf_pool.mutex. - Normally, buf_page_t objects are protected by - buf_block_t::mutex or buf_pool.zip_mutex or both. */ - - bpage->state = BUF_BLOCK_ZIP_PAGE; - bpage->id = page_id; - bpage->buf_fix_count = 1; - - ut_d(bpage->in_page_hash = TRUE); - HASH_INSERT(buf_page_t, hash, buf_pool.page_hash, - page_id.fold(), bpage); - - mutex_exit(&buf_pool.mutex); - /* Once the sentinel is in the page_hash we can - safely release all locks except just the - relevant hash_lock */ - hash_unlock_x_all_but(buf_pool.page_hash, - *hash_lock); - - return(NULL); - case BUF_BLOCK_ZIP_PAGE: - ut_ad(bpage->in_page_hash); - ut_ad(bpage->buf_fix_count > 0); - break; - default: - ut_error; - } - } - - /* Allocation failed. Either the maximum number of purge - threads should never exceed BUF_POOL_WATCH_SIZE, or this code - should be modified to return a special non-NULL value and the - caller should purge the record directly. */ - ut_error; - - /* Fix compiler warning */ - return(NULL); -} - -/** Remove the sentinel block for the watch before replacing it with a -real block. buf_pool_watch_unset() or buf_pool_watch_occurred() will notice -that the block has been replaced with the real block. -@param[in,out] watch sentinel for watch -@return reference count, to be added to the replacement block */ -static void buf_pool_watch_remove(buf_page_t *watch) -{ - ut_ad(rw_lock_own(buf_page_hash_lock_get(watch->id), RW_LOCK_X)); + const ulint fold= bpage->id().fold(); + ut_ad(bpage->state() == BUF_BLOCK_ZIP_PAGE); ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(buf_pool.hash_lock_get(bpage->id())->is_write_locked()); + ut_a(bpage->io_fix() == BUF_IO_NONE); + ut_a(!bpage->buf_fix_count()); + ut_ad(bpage == buf_pool.page_hash_get_low(bpage->id(), fold)); + ut_ad(!buf_pool.watch_is_sentinel(*bpage)); + ut_ad(bpage->state() == BUF_BLOCK_ZIP_PAGE); - ut_ad(watch->in_page_hash); - ut_d(watch->in_page_hash= FALSE); - HASH_DELETE(buf_page_t, hash, buf_pool.page_hash, watch->id.fold(), watch); - watch->buf_fix_count= 0; - watch->state= BUF_BLOCK_POOL_WATCH; -} + new (dpage) buf_page_t(*bpage); -/** Stop watching if the page has been read in. -buf_pool_watch_set(same_page_id) must have returned NULL before. -@param[in] page_id page id */ -void buf_pool_watch_unset(const page_id_t page_id) -{ - /* FIXME: We only need buf_pool.mutex during the HASH_DELETE - because it protects watch->in_page_hash. */ - mutex_enter(&buf_pool.mutex); + /* Important that we adjust the hazard pointer before + removing bpage from LRU list. */ + if (buf_page_t *b= buf_pool.LRU_remove(bpage)) + UT_LIST_INSERT_AFTER(buf_pool.LRU, b, dpage); + else + UT_LIST_ADD_FIRST(buf_pool.LRU, dpage); - rw_lock_t *hash_lock= buf_page_hash_lock_get(page_id); - rw_lock_x_lock(hash_lock); - - /* The page must exist because buf_pool_watch_set() increments - buf_fix_count. */ - buf_page_t *watch= buf_page_hash_get_low(page_id); - - if (watch->unfix() == 0 && buf_pool_watch_is_sentinel(watch)) + if (UNIV_UNLIKELY(buf_pool.LRU_old == bpage)) { - /* The following is based on buf_pool_watch_remove(). */ - ut_d(watch->in_page_hash= FALSE); - HASH_DELETE(buf_page_t, hash, buf_pool.page_hash, page_id.fold(), watch); - rw_lock_x_unlock(hash_lock); - /* Now that the watch is no longer reachable via buf_pool.page_hash, - release it to buf_pool.watch[] for reuse. */ - watch->buf_fix_count= 0; - watch->state= BUF_BLOCK_POOL_WATCH; + buf_pool.LRU_old= dpage; +#ifdef UNIV_LRU_DEBUG + /* buf_pool.LRU_old must be the first item in the LRU list + whose "old" flag is set. */ + ut_a(buf_pool.LRU_old->old); + ut_a(!UT_LIST_GET_PREV(LRU, buf_pool.LRU_old) || + !UT_LIST_GET_PREV(LRU, buf_pool.LRU_old)->old); + ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool.LRU_old) || + UT_LIST_GET_NEXT(LRU, buf_pool.LRU_old)->old); } else - rw_lock_x_unlock(hash_lock); - mutex_exit(&buf_pool.mutex); + { + /* Check that the "old" flag is consistent in + the block and its neighbours. */ + dpage->set_old(dpage->is_old()); +#endif /* UNIV_LRU_DEBUG */ + } + + ut_d(CheckInLRUList::validate()); + + /* relocate buf_pool.page_hash */ + ut_ad(bpage->in_page_hash); + ut_ad(dpage->in_page_hash); + ut_d(bpage->in_page_hash= false); + HASH_REPLACE(buf_page_t, hash, &buf_pool.page_hash, fold, bpage, dpage); } -/** Check if the page has been read in. -This may only be called after buf_pool_watch_set(same_page_id) -has returned NULL and before invoking buf_pool_watch_unset(same_page_id). -@param[in] page_id page id -@return false if the given page was not read in, true if it was */ -bool buf_pool_watch_occurred(const page_id_t page_id) +/** Register a watch for a page identifier. The caller must hold an +exclusive page hash latch. The *hash_lock may be released, +relocated, and reacquired. +@param id page identifier +@param hash_lock exclusively held page_hash latch +@return a buffer pool block corresponding to id +@retval nullptr if the block was not present, and a watch was installed */ +inline buf_page_t *buf_pool_t::watch_set(const page_id_t id, + page_hash_latch **hash_lock) { - bool ret; - buf_page_t* bpage; - rw_lock_t* hash_lock = buf_page_hash_lock_get(page_id); + const ulint fold= id.fold(); + ut_ad(*hash_lock == page_hash.lock_get(fold)); + ut_ad((*hash_lock)->is_write_locked()); - rw_lock_s_lock(hash_lock); +retry: + if (buf_page_t *bpage= page_hash_get_low(id, fold)) + { + if (!watch_is_sentinel(*bpage)) + /* The page was loaded meanwhile. */ + return bpage; + /* Add to an existing watch. */ + bpage->fix(); + return nullptr; + } - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = buf_page_hash_lock_s_confirm(hash_lock, page_id); + (*hash_lock)->write_unlock(); + /* Allocate a watch[] and then try to insert it into the page_hash. */ + mutex_enter(&mutex); - /* The page must exist because buf_pool_watch_set() - increments buf_fix_count. */ - bpage = buf_page_hash_get_low(page_id); + /* The maximum number of purge tasks should never exceed + the UT_ARR_SIZE(watch) - 1, and there is no way for a purge task to hold a + watch when setting another watch. */ + for (buf_page_t *w= &watch[UT_ARR_SIZE(watch)]; w-- >= watch; ) + { + ut_ad(w->access_time == 0); + ut_ad(!w->oldest_modification()); + ut_ad(!w->zip.data); + ut_ad(!w->in_zip_hash); + if (w->state() == BUF_BLOCK_ZIP_PAGE) + /* This watch may be in use for some other page. */ + continue; + ut_ad(w->state() == BUF_BLOCK_NOT_USED); + ut_ad(!w->buf_fix_count()); + /* w is pointing to watch[], which is protected by mutex. + Normally, buf_page_t::id for objects that are reachable by + page_hash_get_low(id, fold) are protected by hash_lock. */ + w->set_state(BUF_BLOCK_ZIP_PAGE); + w->id_= id; - ret = !buf_pool_watch_is_sentinel(bpage); - rw_lock_s_unlock(hash_lock); + *hash_lock= page_hash.lock_get(fold); + (*hash_lock)->write_lock(); + mutex_exit(&mutex); - return(ret); -} + buf_page_t *bpage= page_hash_get_low(id, fold); + if (UNIV_LIKELY_NULL(bpage)) + { + (*hash_lock)->write_unlock(); + mutex_enter(&mutex); + w->set_state(BUF_BLOCK_NOT_USED); + *hash_lock= page_hash.lock_get(fold); + (*hash_lock)->write_lock(); + mutex_exit(&mutex); + goto retry; + } -/********************************************************************//** -Moves a page to the start of the buffer pool LRU list. This high-level -function can be used to prevent an important page from slipping out of -the buffer pool. -@param[in,out] bpage buffer block of a file page */ -void buf_page_make_young(buf_page_t* bpage) -{ - mutex_enter(&buf_pool.mutex); + ut_ad(!w->buf_fix_count_); + w->buf_fix_count_= 1; + ut_ad(!w->in_page_hash); + ut_d(w->in_page_hash= true); /* Not holding buf_pool.mutex here! */ + HASH_INSERT(buf_page_t, hash, &page_hash, fold, w); + return nullptr; + } - ut_a(buf_page_in_file(bpage)); - - buf_LRU_make_block_young(bpage); - - mutex_exit(&buf_pool.mutex); + ut_error; + mutex_exit(&mutex); + return nullptr; } /** Mark the page status as FREED for the given tablespace id and @@ -2841,37 +2637,33 @@ void buf_page_free(const page_id_t page_id, ut_ad(mtr); ut_ad(mtr->is_active()); buf_pool.stat.n_page_gets++; - rw_lock_t *hash_lock= buf_page_hash_lock_get(page_id); - rw_lock_s_lock(hash_lock); - /* page_hash can be changed. */ - hash_lock= buf_page_hash_lock_s_confirm(hash_lock, page_id); + const ulint fold= page_id.fold(); + page_hash_latch *hash_lock= buf_pool.page_hash.lock(fold); buf_block_t *block= reinterpret_cast - (buf_page_hash_get_low(page_id)); + (buf_pool.page_hash_get_low(page_id, fold)); - if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) +#if 0 /* FIXME: MDEV-22970 Potential corruption */ + /* TODO: Find out how and when a freed page can be marked + allocated in the same mini-transaction. At least it seems to + happen during a pessimistic insert operation. */ + /* TODO: try to all this part of mtr_t::free() */ + if (srv_immediate_scrub_data_uncompressed || mtr->is_page_compressed()) + mtr->add_freed_offset(page_id); +#endif + + if (!block || block->page.state() != BUF_BLOCK_FILE_PAGE) { /* FIXME: if block!=NULL, convert to BUF_BLOCK_FILE_PAGE, but avoid buf_zip_decompress() */ - /* FIXME: If block==NULL, introduce a separate data structure - to cover freed page ranges to augment buf_flush_freed_page() */ - rw_lock_s_unlock(hash_lock); + hash_lock->read_unlock(); return; } block->fix(); - mutex_enter(&block->mutex); - /* Now safe to release page_hash mutex */ - rw_lock_s_unlock(hash_lock); - ut_ad(block->page.buf_fix_count > 0); - -#ifdef UNIV_DEBUG - if (!fsp_is_system_temporary(page_id.space())) - { - ibool ret= rw_lock_s_lock_nowait(block->debug_latch, file, line); - ut_a(ret); - } -#endif /* UNIV_DEBUG */ + ut_ad(block->page.buf_fix_count()); + ut_ad(fsp_is_system_temporary(page_id.space()) || + rw_lock_s_lock_nowait(block->debug_latch, file, line)); mtr_memo_type_t fix_type= MTR_MEMO_PAGE_X_FIX; rw_lock_x_lock_inline(&block->lock, 0, file, line); @@ -2879,31 +2671,7 @@ void buf_page_free(const page_id_t page_id, block->page.status= buf_page_t::FREED; buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - mutex_exit(&block->mutex); -} - -/** Attempts to discard the uncompressed frame of a compressed page. -The caller should not be holding any mutexes when this function is called. -@param[in] page_id page id */ -static void buf_block_try_discard_uncompressed(const page_id_t page_id) -{ - buf_page_t* bpage; - - /* Since we need to acquire buf_pool mutex to discard - the uncompressed frame and because page_hash mutex resides - below buf_pool mutex in sync ordering therefore we must - first release the page_hash mutex. This means that the - block in question can move out of page_hash. Therefore - we need to check again if the block is still in page_hash. */ - mutex_enter(&buf_pool.mutex); - - bpage = buf_page_hash_get(page_id); - - if (bpage) { - buf_LRU_free_page(bpage, false); - } - - mutex_exit(&buf_pool.mutex); + hash_lock->read_unlock(); } /** Get read access to a compressed page (usually of type @@ -2918,123 +2686,96 @@ the same set of mutexes or latches. @return pointer to the block */ buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size) { - buf_page_t* bpage; - BPageMutex* block_mutex; - rw_lock_t* hash_lock; - ibool discard_attempted = FALSE; - ibool must_read; + ut_ad(zip_size); + ut_ad(ut_is_2pow(zip_size)); + buf_pool.stat.n_page_gets++; - ut_ad(zip_size); - ut_ad(ut_is_2pow(zip_size)); - buf_pool.stat.n_page_gets++; + bool discard_attempted= false; + const ulint fold= page_id.fold(); + buf_page_t *bpage; + page_hash_latch *hash_lock; - for (;;) { + for (;;) + { lookup: + bpage= buf_pool.page_hash_get_locked(page_id, fold, &hash_lock); + if (bpage) + break; - /* The following call will also grab the page_hash - mutex if the page is found. */ - bpage = buf_page_hash_get_s_locked(page_id, &hash_lock); - if (bpage) { - ut_ad(!buf_pool_watch_is_sentinel(bpage)); - break; - } + dberr_t err= buf_read_page(page_id, zip_size); - /* Page not in buf_pool: needs to be read from file */ + if (UNIV_UNLIKELY(err != DB_SUCCESS)) + { + ib::error() << "Reading compressed page " << page_id + << " failed with error: " << err; + goto err_exit; + } - ut_ad(!hash_lock); - dberr_t err = buf_read_page(page_id, zip_size); +#ifdef UNIV_DEBUG + if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); +#endif /* UNIV_DEBUG */ + } - if (err != DB_SUCCESS) { - ib::error() << "Reading compressed page " << page_id - << " failed with error: " << ut_strerr(err); + ut_ad(hash_lock->is_read_locked()); - goto err_exit; - } - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - } - - ut_ad(buf_page_hash_lock_held_s(bpage)); - - if (!bpage->zip.data) { - /* There is no compressed page. */ + if (!bpage->zip.data) + { + /* There is no compressed page. */ err_exit: - rw_lock_s_unlock(hash_lock); - return(NULL); - } + hash_lock->read_unlock(); + return nullptr; + } - ut_ad(!buf_pool_watch_is_sentinel(bpage)); + ut_ad(!buf_pool.watch_is_sentinel(*bpage)); - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - bpage->fix(); - block_mutex = &buf_pool.zip_mutex; - goto got_block; - case BUF_BLOCK_FILE_PAGE: - /* Discard the uncompressed page frame if possible. */ - if (!discard_attempted) { - rw_lock_s_unlock(hash_lock); - buf_block_try_discard_uncompressed(page_id); - discard_attempted = TRUE; - goto lookup; - } + switch (bpage->state()) { + case BUF_BLOCK_ZIP_PAGE: + bpage->fix(); + goto got_block; + case BUF_BLOCK_FILE_PAGE: + /* Discard the uncompressed page frame if possible. */ + if (!discard_attempted) + { + discard_attempted= true; + hash_lock->read_unlock(); + mutex_enter(&buf_pool.mutex); + if (buf_page_t *bpage= buf_pool.page_hash_get_low(page_id, fold)) + buf_LRU_free_page(bpage, false); + mutex_exit(&buf_pool.mutex); + goto lookup; + } - buf_block_buf_fix_inc((buf_block_t*) bpage, - __FILE__, __LINE__); + buf_block_buf_fix_inc(reinterpret_cast(bpage), + __FILE__, __LINE__); + goto got_block; + default: + break; + } - block_mutex = &((buf_block_t*) bpage)->mutex; - goto got_block; - default: - break; - } - - ut_error; - goto err_exit; + ut_error; + goto err_exit; got_block: - mutex_enter(block_mutex); - must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ; + bool must_read= bpage->io_fix() == BUF_IO_READ; + hash_lock->read_unlock(); - rw_lock_s_unlock(hash_lock); + DBUG_ASSERT(bpage->status != buf_page_t::FREED); - DBUG_ASSERT(bpage->status != buf_page_t::FREED); + bpage->set_accessed(); + buf_page_make_young_if_needed(bpage); - buf_page_set_accessed(bpage); +#ifdef UNIV_DEBUG + if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); +#endif /* UNIV_DEBUG */ + ut_ad(bpage->buf_fix_count()); + ut_ad(bpage->in_file()); - mutex_exit(block_mutex); + if (must_read) + /* Let us wait until the read operation completes */ + while (bpage->io_fix() == BUF_IO_READ) + os_thread_sleep(WAIT_FOR_READ); - buf_page_make_young_if_needed(bpage); - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); - ut_a(bpage->buf_fix_count > 0); - ut_a(buf_page_in_file(bpage)); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - if (must_read) { - /* Let us wait until the read operation - completes */ - - for (;;) { - enum buf_io_fix io_fix; - - mutex_enter(block_mutex); - io_fix = buf_page_get_io_fix(bpage); - mutex_exit(block_mutex); - - if (io_fix == BUF_IO_READ) { - - os_thread_sleep(WAIT_FOR_READ); - } else { - break; - } - } - } - - return(bpage); + return bpage; } /********************************************************************//** @@ -3072,7 +2813,7 @@ buf_zip_decompress( ulint size = page_zip_get_size(&block->page.zip); /* The tablespace will not be found if this function is called during IMPORT. */ - fil_space_t* space = fil_space_acquire_for_io(block->page.id.space()); + fil_space_t* space= fil_space_acquire_for_io(block->page.id().space()); const unsigned key_version = mach_read_from_4( frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); fil_space_crypt_t* crypt_data = space ? space->crypt_data : NULL; @@ -3082,13 +2823,13 @@ buf_zip_decompress( || srv_encrypt_tables); ut_ad(block->zip_size()); - ut_a(block->page.id.space() != 0); + ut_a(block->page.id().space() != 0); if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) { ib::error() << "Compressed page checksum mismatch for " << (space ? space->chain.start->name : "") - << block->page.id << ": stored: " + << block->page.id() << ": stored: " << mach_read_from_4(frame + FIL_PAGE_SPACE_OR_CHKSUM) << ", crc32: " << page_zip_calc_checksum( @@ -3116,7 +2857,7 @@ buf_zip_decompress( ib::error() << "Unable to decompress " << (space ? space->chain.start->name : "") - << block->page.id; + << block->page.id(); goto err_exit; case FIL_PAGE_TYPE_ALLOCATED: case FIL_PAGE_INODE: @@ -3137,7 +2878,7 @@ buf_zip_decompress( ib::error() << "Unknown compressed page type " << fil_page_get_type(frame) << " in " << (space ? space->chain.start->name : "") - << block->page.id; + << block->page.id(); err_exit: if (encrypted) { @@ -3158,20 +2899,6 @@ err_exit: return(FALSE); } -#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG -/********************************************************************//** -Return true if probe is enabled. -@return true if probe enabled. */ -static -bool -buf_debug_execute_is_force_flush() -/*==============================*/ -{ - DBUG_EXECUTE_IF("ib_buf_force_flush", return(true); ); - return(false); -} -#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ - /** Wait for the block to be read in. @param[in] block The block to check */ static @@ -3181,38 +2908,58 @@ buf_wait_for_read( { /* Note: - We are using the block->lock to check for IO state (and a dirty read). - We set the IO_READ state under the protection of the hash_lock - (and block->mutex). This is safe because another thread can only + We are using the block->lock to check for IO state. + We set the IO_READ state under the protection of the hash_lock. + This is safe because another thread can only access the block (and check for IO state) after the block has been added to the page hashtable. */ - if (buf_block_get_io_fix(block) == BUF_IO_READ) { - - /* Wait until the read operation completes */ - - BPageMutex* mutex = buf_page_get_mutex(&block->page); - - for (;;) { - buf_io_fix io_fix; - - mutex_enter(mutex); - - io_fix = buf_block_get_io_fix(block); - - mutex_exit(mutex); - - if (io_fix == BUF_IO_READ) { - /* Wait by temporaly s-latch */ - rw_lock_s_lock(&block->lock); - rw_lock_s_unlock(&block->lock); - } else { - break; - } - } + while (block->page.io_fix() == BUF_IO_READ) { + rw_lock_s_lock(&block->lock); + rw_lock_s_unlock(&block->lock); } } +#ifdef BTR_CUR_HASH_ADAPT +/** If a stale adaptive hash index exists on the block, drop it. +Multiple executions of btr_search_drop_page_hash_index() on the +same block must be prevented by exclusive page latch. */ +ATTRIBUTE_COLD +static void buf_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type) +{ + switch (fix_type) { + case MTR_MEMO_BUF_FIX: + /* We do not drop the adaptive hash index, because safely doing + so would require acquiring block->lock, and that is not safe + to acquire in some RW_NO_LATCH access paths. Those code paths + should have no business accessing the adaptive hash index anyway. */ + break; + case MTR_MEMO_PAGE_S_FIX: + /* Temporarily release our S-latch. */ + rw_lock_s_unlock(&block->lock); + rw_lock_x_lock(&block->lock); + if (dict_index_t *index= block->index) + if (index->freed()) + btr_search_drop_page_hash_index(block); + rw_lock_x_unlock(&block->lock); + rw_lock_s_lock(&block->lock); + break; + case MTR_MEMO_PAGE_SX_FIX: + rw_lock_sx_unlock(&block->lock); + rw_lock_x_lock(&block->lock); + if (dict_index_t *index= block->index) + if (index->freed()) + btr_search_drop_page_hash_index(block); + rw_lock_x_unlock(&block->lock); + rw_lock_sx_lock(&block->lock); + break; + default: + ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX); + btr_search_drop_page_hash_index(block); + } +} +#endif /* BTR_CUR_HASH_ADAPT */ + /** Lock the page with the given latch type. @param[in,out] block block to be locked @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH @@ -3231,7 +2978,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block, { case RW_NO_LATCH: fix_type= MTR_MEMO_BUF_FIX; - break; + goto done; case RW_S_LATCH: rw_lock_s_lock_inline(&block->lock, 0, file, line); fix_type= MTR_MEMO_PAGE_S_FIX; @@ -3247,6 +2994,15 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block, break; } +#ifdef BTR_CUR_HASH_ADAPT + { + dict_index_t *index= block->index; + if (index && index->freed()) + buf_defer_drop_ahi(block, fix_type); + } +#endif /* BTR_CUR_HASH_ADAPT */ + +done: mtr_memo_push(mtr, block, fix_type); return block; } @@ -3282,9 +3038,8 @@ buf_page_get_low( { buf_block_t* block; unsigned access_time; - rw_lock_t* hash_lock; - buf_block_t* fix_block; ulint retries = 0; + const ulint fold = page_id.fold(); ut_ad((mtr == NULL) == (mode == BUF_EVICT_IF_IN_POOL)); ut_ad(!mtr || mtr->is_active()); @@ -3334,87 +3089,57 @@ buf_page_get_low( || ibuf_page_low(page_id, zip_size, FALSE, file, line, NULL)); buf_pool.stat.n_page_gets++; - hash_lock = buf_page_hash_lock_get(page_id); loop: + buf_block_t* fix_block; block = guess; - rw_lock_s_lock(hash_lock); + page_hash_latch* hash_lock = buf_pool.page_hash.lock(fold); - /* page_hash can be changed. */ - hash_lock = buf_page_hash_lock_s_confirm(hash_lock, page_id); - - if (block != NULL) { + if (block) { /* If the guess is a compressed page descriptor that has been allocated by buf_page_alloc_descriptor(), it may have been freed by buf_relocate(). */ if (!buf_pool.is_uncompressed(block) - || page_id != block->page.id - || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { + || page_id != block->page.id() + || block->page.state() != BUF_BLOCK_FILE_PAGE) { /* Our guess was bogus or things have changed since. */ - block = guess = NULL; + guess = nullptr; + goto lookup; } else { ut_ad(!block->page.in_zip_hash); } + } else { +lookup: + block = reinterpret_cast( + buf_pool.page_hash_get_low(page_id, fold)); } - if (block == NULL) { - block = (buf_block_t*) buf_page_hash_get_low(page_id); + if (!block || buf_pool.watch_is_sentinel(block->page)) { + hash_lock->read_unlock(); + block = nullptr; } - if (!block || buf_pool_watch_is_sentinel(&block->page)) { - rw_lock_s_unlock(hash_lock); - block = NULL; - } - - if (block == NULL) { - + if (UNIV_UNLIKELY(!block)) { /* Page not in buf_pool: needs to be read from file */ - if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { - rw_lock_x_lock(hash_lock); + hash_lock = buf_pool.page_hash.lock(fold); - /* If not own buf_pool_mutex, - page_hash can be changed. */ - hash_lock = buf_page_hash_lock_x_confirm( - hash_lock, page_id); - - block = (buf_block_t*) buf_pool_watch_set( - page_id, &hash_lock); - - if (block) { + if (buf_page_t *bpage= buf_pool.watch_set( + page_id, &hash_lock)) { /* We can release hash_lock after we increment the fix count to make sure that no state change takes place. */ + bpage->fix(); + hash_lock->write_unlock(); + block = reinterpret_cast(bpage); fix_block = block; - - if (fsp_is_system_temporary(page_id.space())) { - /* For temporary tablespace, - the mutex is being used for - synchronization between user - thread and flush thread, - instead of block->lock. See - buf_flush_page() for the flush - thread counterpart. */ - - BPageMutex* fix_mutex - = buf_page_get_mutex( - &fix_block->page); - mutex_enter(fix_mutex); - fix_block->fix(); - mutex_exit(fix_mutex); - } else { - fix_block->fix(); - } - - /* Now safe to release page_hash mutex */ - rw_lock_x_unlock(hash_lock); goto got_block; } - rw_lock_x_unlock(hash_lock); + hash_lock->write_unlock(); } switch (mode) { @@ -3422,15 +3147,12 @@ loop: case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_PEEK_IF_IN_POOL: case BUF_EVICT_IF_IN_POOL: - ut_ad(!rw_lock_own_flagged( - hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); return(NULL); } /* The call path is buf_read_page() -> buf_read_page_low() (fil_io()) -> - buf_page_io_complete() -> + buf_page_read_complete() -> buf_decrypt_after_read(). Here fil_space_t* is used and we decrypt -> buf_page_check_corrupt() where page checksums are compared. Decryption, decompression as @@ -3502,30 +3224,16 @@ loop: " See https://mariadb.com/kb/en/library/innodb-recovery-modes/"; } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ goto loop; } else { fix_block = block; } - if (fsp_is_system_temporary(page_id.space())) { - /* For temporary tablespace, the mutex is being used - for synchorization between user thread and flush thread, - instead of block->lock. See buf_flush_page() for the flush - thread counterpart. */ - BPageMutex* fix_mutex = buf_page_get_mutex( - &fix_block->page); - mutex_enter(fix_mutex); - fix_block->fix(); - mutex_exit(fix_mutex); - } else { - fix_block->fix(); - } - - /* Now safe to release page_hash mutex */ - rw_lock_s_unlock(hash_lock); + fix_block->fix(); + hash_lock->read_unlock(); got_block: switch (mode) { @@ -3535,28 +3243,19 @@ got_block: case BUF_GET_IF_IN_POOL: case BUF_PEEK_IF_IN_POOL: case BUF_EVICT_IF_IN_POOL: - buf_page_t* fix_page = &fix_block->page; - BPageMutex* fix_mutex = buf_page_get_mutex(fix_page); - mutex_enter(fix_mutex); - const bool must_read - = (buf_page_get_io_fix(fix_page) == BUF_IO_READ); - mutex_exit(fix_mutex); - - if (must_read) { + if (fix_block->page.io_fix() == BUF_IO_READ) { /* The page is being read to buffer pool, but we cannot wait around for the read to complete. */ fix_block->unfix(); - return(NULL); } } - switch (UNIV_EXPECT(buf_block_get_state(fix_block), - BUF_BLOCK_FILE_PAGE)) { + switch (UNIV_EXPECT(fix_block->page.state(), BUF_BLOCK_FILE_PAGE)) { case BUF_BLOCK_FILE_PAGE: if (fsp_is_system_temporary(page_id.space()) - && buf_block_get_io_fix(block) != BUF_IO_NONE) { + && block->page.io_fix() != BUF_IO_NONE) { /* This suggests that the page is being flushed. Avoid returning reference to this page. Instead wait for the flush action to complete. */ @@ -3567,7 +3266,7 @@ got_block: if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) { evict_from_pool: - ut_ad(!fix_block->page.oldest_modification); + ut_ad(!fix_block->page.oldest_modification()); mutex_enter(&buf_pool.mutex); fix_block->unfix(); @@ -3578,13 +3277,13 @@ evict_from_pool: mutex_exit(&buf_pool.mutex); return(NULL); } + break; default: ut_error; break; case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) { goto evict_from_pool; } @@ -3602,8 +3301,8 @@ evict_from_pool: buf_page_t* bpage = &block->page; /* Note: We have already buffer fixed this block. */ - if (bpage->buf_fix_count > 1 - || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + if (bpage->buf_fix_count() > 1 + || bpage->io_fix() != BUF_IO_NONE) { /* This condition often occurs when the buffer is not buffer-fixed, but I/O-fixed by @@ -3621,43 +3320,36 @@ evict_from_pool: or relocated while we are attempting to allocate an uncompressed page. */ - block = buf_LRU_get_free_block(); + block = buf_LRU_get_free_block(false); + buf_block_init_low(block); mutex_enter(&buf_pool.mutex); + hash_lock = buf_pool.page_hash.lock_get(fold); - hash_lock = buf_page_hash_lock_get(page_id); - - rw_lock_x_lock(hash_lock); + hash_lock->write_lock(); /* Buffer-fixing prevents the page_hash from changing. */ - ut_ad(bpage == buf_page_hash_get_low(page_id)); + ut_ad(bpage == buf_pool.page_hash_get_low(page_id, fold)); - fix_block->unfix(); + fix_block->unfix(); /* hash_lock protects us after this */ - buf_page_mutex_enter(block); - mutex_enter(&buf_pool.zip_mutex); - - fix_block = block; - - if (bpage->buf_fix_count > 0 - || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { - - mutex_exit(&buf_pool.zip_mutex); + if (bpage->buf_fix_count() || bpage->io_fix() != BUF_IO_NONE) { /* The block was buffer-fixed or I/O-fixed while buf_pool.mutex was not held by this thread. Free the block that was allocated and retry. This should be extremely unlikely, for example, if buf_page_get_zip() was invoked. */ + hash_lock->write_unlock(); buf_LRU_block_free_non_file_page(block); mutex_exit(&buf_pool.mutex); - rw_lock_x_unlock(hash_lock); - buf_page_mutex_exit(block); /* Try again */ goto loop; } + fix_block = block; + /* Move the compressed page from bpage to block, and uncompress it. */ @@ -3666,22 +3358,14 @@ evict_from_pool: any list or hash table */ buf_relocate(bpage, &block->page); - buf_block_init_low(block); - /* Set after buf_relocate(). */ - block->page.buf_fix_count = 1; + block->page.set_buf_fix_count(1); block->lock_hash_val = lock_rec_hash(page_id.space(), page_id.page_no()); - UNIV_MEM_DESC(&block->page.zip.data, - page_zip_get_size(&block->page.zip)); - - if (buf_page_get_state(&block->page) == BUF_BLOCK_ZIP_PAGE) { -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - UT_LIST_REMOVE(buf_pool.zip_clean, &block->page); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - ut_ad(!block->page.in_flush_list); + if (!block->page.oldest_modification()) { + ut_d(UT_LIST_REMOVE(buf_pool.zip_clean, &block->page)); } else { /* Relocate buf_pool.flush_list. */ buf_flush_relocate_on_flush_list(bpage, &block->page); @@ -3690,45 +3374,39 @@ evict_from_pool: /* Buffer-fix, I/O-fix, and X-latch the block for the duration of the decompression. Also add the block to the unzip_LRU list. */ - block->page.state = BUF_BLOCK_FILE_PAGE; + block->page.set_state(BUF_BLOCK_FILE_PAGE); /* Insert at the front of unzip_LRU list */ buf_unzip_LRU_add_block(block, FALSE); - buf_block_set_io_fix(block, BUF_IO_READ); + block->page.set_io_fix(BUF_IO_READ); rw_lock_x_lock_inline(&block->lock, 0, file, line); - UNIV_MEM_INVALID(bpage, sizeof *bpage); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(bpage, sizeof *bpage); +#endif /* HAVE_valgrind_or_MSAN */ - rw_lock_x_unlock(hash_lock); - buf_pool.n_pend_unzip++; - mutex_exit(&buf_pool.zip_mutex); mutex_exit(&buf_pool.mutex); + hash_lock->write_unlock(); + buf_pool.n_pend_unzip++; - access_time = buf_page_is_accessed(&block->page); - - buf_page_mutex_exit(block); + access_time = block->page.is_accessed(); if (!access_time && !recv_no_ibuf_operations - && ibuf_page_exists(block->page.id, zip_size)) { + && ibuf_page_exists(block->page.id(), zip_size)) { block->page.ibuf_exist = true; } buf_page_free_descriptor(bpage); /* Decompress the page while not holding - buf_pool.mutex or block->mutex. */ + buf_pool.mutex. */ - if (!buf_zip_decompress(block, TRUE)) { - mutex_enter(&buf_pool.mutex); - buf_page_mutex_enter(fix_block); - buf_block_set_io_fix(fix_block, BUF_IO_NONE); - buf_page_mutex_exit(fix_block); - - --buf_pool.n_pend_unzip; - mutex_exit(&buf_pool.mutex); - fix_block->unfix(); + if (!buf_zip_decompress(block, false)) { rw_lock_x_unlock(&fix_block->lock); + fix_block->page.io_unfix(); + fix_block->unfix(); + --buf_pool.n_pend_unzip; if (err) { *err = DB_PAGE_CORRUPTED; @@ -3736,36 +3414,24 @@ evict_from_pool: return NULL; } - mutex_enter(&buf_pool.mutex); - - buf_page_mutex_enter(fix_block); - - buf_block_set_io_fix(fix_block, BUF_IO_NONE); - - buf_page_mutex_exit(fix_block); - - --buf_pool.n_pend_unzip; - - mutex_exit(&buf_pool.mutex); - rw_lock_x_unlock(&block->lock); - + fix_block->page.io_unfix(); + --buf_pool.n_pend_unzip; break; } ut_ad(block == fix_block); - ut_ad(fix_block->page.buf_fix_count > 0); + ut_ad(fix_block->page.buf_fix_count()); - ut_ad(!rw_lock_own_flagged(hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - - ut_ad(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE); + ut_ad(fix_block->page.state() == BUF_BLOCK_FILE_PAGE); #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG - if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH) - && (ibuf_debug || buf_debug_execute_is_force_flush())) { - + if (mode != BUF_GET_IF_IN_POOL + && mode != BUF_GET_IF_IN_POOL_OR_WATCH) { + } else if (!ibuf_debug) { + } else if (fil_space_t* space = + fil_space_acquire_for_io(page_id.space())) { /* Try to evict the block from the buffer pool, to use the insert buffer (change buffer) as much as possible. */ @@ -3773,36 +3439,22 @@ evict_from_pool: fix_block->unfix(); - /* Now we are only holding the buf_pool.mutex, - not block->mutex or hash_lock. Blocks cannot be - relocated or enter or exit the buf_pool while we - are holding the buf_pool.mutex. */ + /* Blocks cannot be relocated or enter or exit the + buf_pool while we are holding the buf_pool.mutex. */ if (buf_LRU_free_page(&fix_block->page, true)) { - + space->release_for_io(); + hash_lock = buf_pool.page_hash.lock_get(fold); + hash_lock->write_lock(); mutex_exit(&buf_pool.mutex); - - /* page_hash can be changed. */ - hash_lock = buf_page_hash_lock_get(page_id); - rw_lock_x_lock(hash_lock); - - /* If not own buf_pool_mutex, - page_hash can be changed. */ - hash_lock = buf_page_hash_lock_x_confirm( - hash_lock, page_id); - - if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { - /* Set the watch, as it would have - been set if the page were not in the - buffer pool in the first place. */ - block = (buf_block_t*) buf_pool_watch_set( - page_id, &hash_lock); - } else { - block = (buf_block_t*) buf_page_hash_get_low( - page_id); - } - - rw_lock_x_unlock(hash_lock); + /* We may set the watch, as it would have + been set if the page were not in the + buffer pool in the first place. */ + block= reinterpret_cast( + mode == BUF_GET_IF_IN_POOL_OR_WATCH + ? buf_pool.watch_set(page_id, &hash_lock) + : buf_pool.page_hash_get_low(page_id, fold)); + hash_lock->write_unlock(); if (block != NULL) { /* Either the page has been read in or @@ -3818,16 +3470,15 @@ evict_from_pool: return(NULL); } - buf_page_mutex_enter(fix_block); - - if (buf_flush_page_try(fix_block)) { + bool flushed = fix_block->page.ready_for_flush() + && buf_flush_page(&fix_block->page, + IORequest::SINGLE_PAGE, space, true); + space->release_for_io(); + if (flushed) { guess = fix_block; - goto loop; } - buf_page_mutex_exit(fix_block); - fix_block->fix(); /* Failed to evict the page; change it directly */ @@ -3836,7 +3487,7 @@ evict_from_pool: } #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ - ut_ad(fix_block->page.buf_fix_count > 0); + ut_ad(fix_block->page.buf_fix_count()); #ifdef UNIV_DEBUG /* We have already buffer fixed the page, and we are committed to @@ -3862,33 +3513,22 @@ evict_from_pool: || mode == BUF_PEEK_IF_IN_POOL || fix_block->page.status != buf_page_t::FREED); - /* Check if this is the first access to the page */ - access_time = buf_page_is_accessed(&fix_block->page); - - /* This is a heuristic and we don't care about ordering issues. */ - if (access_time == 0) { - buf_page_mutex_enter(fix_block); - - buf_page_set_accessed(&fix_block->page); - - buf_page_mutex_exit(fix_block); - } + const bool not_first_access = fix_block->page.set_accessed(); if (mode != BUF_PEEK_IF_IN_POOL) { buf_page_make_young_if_needed(&fix_block->page); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); - ut_a(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ + ut_ad(fix_block->page.state() == BUF_BLOCK_FILE_PAGE); /* We have to wait here because the IO_READ state was set - under the protection of the hash_lock and not the block->mutex - and block->lock. */ + under the protection of the hash_lock and not block->lock. */ buf_wait_for_read(fix_block); - if (fix_block->page.id != page_id) { + if (fix_block->page.id() != page_id) { fix_block->unfix(); #ifdef UNIV_DEBUG @@ -3928,16 +3568,13 @@ get_latch: file, line); } - if (mode != BUF_PEEK_IF_IN_POOL && !access_time) { + if (!not_first_access && mode != BUF_PEEK_IF_IN_POOL) { /* In the case of a first access, try to apply linear read-ahead */ buf_read_ahead_linear(page_id, zip_size, ibuf_inside(mtr)); } - ut_ad(!rw_lock_own_flagged(hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - return(fix_block); } @@ -4014,52 +3651,46 @@ buf_page_optimistic_get( unsigned line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mini-transaction */ { - unsigned access_time; ibool success; ut_ad(block); ut_ad(mtr); ut_ad(mtr->is_active()); - ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); + ut_ad(rw_latch == RW_S_LATCH || rw_latch == RW_X_LATCH); - buf_page_mutex_enter(block); + if (UNIV_UNLIKELY(block->page.state() != BUF_BLOCK_FILE_PAGE + || block->page.io_fix() != BUF_IO_NONE)) { + return FALSE; + } - if (UNIV_UNLIKELY(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE)) { - - buf_page_mutex_exit(block); + page_hash_latch *hash_lock = buf_pool.hash_lock_get(block->page.id()); + hash_lock->read_lock(); + if (UNIV_UNLIKELY(block->page.state() != BUF_BLOCK_FILE_PAGE + || block->page.io_fix() != BUF_IO_NONE)) { + hash_lock->read_unlock(); return(FALSE); } buf_block_buf_fix_inc(block, file, line); + hash_lock->read_unlock(); - access_time = buf_page_is_accessed(&block->page); - - buf_page_set_accessed(&block->page); - - buf_page_mutex_exit(block); + block->page.set_accessed(); buf_page_make_young_if_needed(&block->page); ut_ad(!ibuf_inside(mtr) - || ibuf_page(block->page.id, block->zip_size(), NULL)); + || ibuf_page(block->page.id(), block->zip_size(), NULL)); mtr_memo_type_t fix_type; - switch (rw_latch) { - case RW_S_LATCH: - success = rw_lock_s_lock_nowait(&block->lock, file, line); - + if (rw_latch == RW_S_LATCH) { fix_type = MTR_MEMO_PAGE_S_FIX; - break; - case RW_X_LATCH: + success = rw_lock_s_lock_nowait(&block->lock, file, line); + } else { + fix_type = MTR_MEMO_PAGE_X_FIX; success = rw_lock_x_lock_func_nowait_inline( &block->lock, file, line); - - fix_type = MTR_MEMO_PAGE_X_FIX; - break; - default: - ut_error; /* RW_SX_LATCH is not implemented yet */ } if (!success) { @@ -4083,18 +3714,11 @@ buf_page_optimistic_get( mtr_memo_push(mtr, block, fix_type); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); - ut_a(block->page.buf_fix_count > 0); - ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - if (!access_time) { - /* In the case of a first access, try to apply linear - read-ahead */ - buf_read_ahead_linear(block->page.id, block->zip_size(), - ibuf_inside(mtr)); - } +#endif /* UNIV_DEBUG */ + ut_ad(block->page.buf_fix_count()); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); buf_pool.stat.n_page_gets++; @@ -4116,551 +3740,208 @@ buf_page_try_get_func( unsigned line, mtr_t* mtr) { - buf_block_t* block; - ibool success; - rw_lock_t* hash_lock; + ut_ad(mtr); + ut_ad(mtr->is_active()); - ut_ad(mtr); - ut_ad(mtr->is_active()); + page_hash_latch *hash_lock; + buf_page_t *bpage= buf_pool.page_hash_get_locked(page_id, + page_id.fold(), + &hash_lock); + if (!bpage) + return nullptr; + if (bpage->state() != BUF_BLOCK_FILE_PAGE) + { + hash_lock->read_unlock(); + return nullptr; + } - block = buf_block_hash_get_s_locked(page_id, &hash_lock); + buf_block_t *block= reinterpret_cast(bpage); + buf_block_buf_fix_inc(block, file, line); + hash_lock->read_unlock(); - if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { - if (block) { - rw_lock_s_unlock(hash_lock); - } - return(NULL); - } + mtr_memo_type_t fix_type= MTR_MEMO_PAGE_S_FIX; + if (!rw_lock_s_lock_nowait(&block->lock, file, line)) + { + /* Let us try to get an X-latch. If the current thread + is holding an X-latch on the page, we cannot get an S-latch. */ + fix_type= MTR_MEMO_PAGE_X_FIX; + if (!rw_lock_x_lock_func_nowait_inline(&block->lock, file, line)) + { + buf_block_buf_fix_dec(block); + return nullptr; + } + } - ut_ad(!buf_pool_watch_is_sentinel(&block->page)); + mtr_memo_push(mtr, block, fix_type); - buf_page_mutex_enter(block); - rw_lock_s_unlock(hash_lock); +#ifdef UNIV_DEBUG + if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); +#endif /* UNIV_DEBUG */ + ut_ad(bpage->buf_fix_count()); + ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); + ut_ad(bpage->id() == page_id); + buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_a(page_id == block->page.id); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - buf_block_buf_fix_inc(block, file, line); - buf_page_mutex_exit(block); - - mtr_memo_type_t fix_type = MTR_MEMO_PAGE_S_FIX; - success = rw_lock_s_lock_nowait(&block->lock, file, line); - - if (!success) { - /* Let us try to get an X-latch. If the current thread - is holding an X-latch on the page, we cannot get an - S-latch. */ - - fix_type = MTR_MEMO_PAGE_X_FIX; - success = rw_lock_x_lock_func_nowait_inline(&block->lock, - file, line); - } - - if (!success) { - buf_block_buf_fix_dec(block); - return(NULL); - } - - mtr_memo_push(mtr, block, fix_type); - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); - ut_a(block->page.buf_fix_count > 0); - ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - - buf_pool.stat.n_page_gets++; - - return(block); + buf_pool.stat.n_page_gets++; + return block; } -/********************************************************************//** -Initialize some fields of a control block. */ -UNIV_INLINE -void -buf_page_init_low( -/*==============*/ - buf_page_t* bpage) /*!< in: block to init */ +/** Initialize the block. +@param page_id page identifier +@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param fix initial buf_fix_count() */ +void buf_block_t::initialise(const page_id_t page_id, ulint zip_size, + uint32_t fix) { - bpage->flush_type = BUF_FLUSH_LRU; - bpage->io_fix = BUF_IO_NONE; - bpage->buf_fix_count = 0; - bpage->old = 0; - bpage->freed_page_clock = 0; - bpage->access_time = 0; - bpage->oldest_modification = 0; - bpage->real_size = 0; - bpage->slot = NULL; - bpage->ibuf_exist = false; - bpage->status = buf_page_t::NORMAL; - HASH_INVALIDATE(bpage, hash); -} - -/** Inits a page to the buffer buf_pool. -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in,out] block block to init */ -static void buf_page_init(const page_id_t page_id, ulint zip_size, - buf_block_t *block) -{ - buf_page_t* hash_page; - - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_mutex_own(block)); - ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); - ut_ad(rw_lock_own(buf_page_hash_lock_get(page_id), RW_LOCK_X)); - - /* Set the state of the block */ - buf_block_set_file_page(block, page_id); - -#ifdef UNIV_DEBUG_VALGRIND - if (is_system_tablespace(page_id.space())) { - /* Silence valid Valgrind warnings about uninitialized - data being written to data files. There are some unused - bytes on some pages that InnoDB does not initialize. */ - UNIV_MEM_VALID(block->frame, srv_page_size); - } -#endif /* UNIV_DEBUG_VALGRIND */ - - buf_block_init_low(block); - - block->lock_hash_val = lock_rec_hash(page_id.space(), - page_id.page_no()); - - buf_page_init_low(&block->page); - - /* Insert into the hash table of file pages */ - - hash_page = buf_page_hash_get_low(page_id); - - if (hash_page == NULL) { - /* Block not found in hash table */ - } else if (buf_pool_watch_is_sentinel(hash_page)) { - /* Preserve the reference count. */ - ib_uint32_t buf_fix_count = hash_page->buf_fix_count; - - ut_a(buf_fix_count > 0); - - block->page.buf_fix_count += buf_fix_count; - - buf_pool_watch_remove(hash_page); - } else { - ib::fatal() << "Page " << page_id - << " already found in the hash table: " - << hash_page << ", " << block; - } - - ut_ad(!block->page.in_zip_hash); - ut_ad(!block->page.in_page_hash); - ut_d(block->page.in_page_hash = TRUE); - - block->page.id = page_id; - - HASH_INSERT(buf_page_t, hash, buf_pool.page_hash, - page_id.fold(), &block->page); - - page_zip_set_size(&block->page.zip, zip_size); -} - -/** Initialize a page for read to the buffer buf_pool. If the page is -(1) already in buf_pool, or -(2) if we specify to read only ibuf pages and the page is not an ibuf page, or -(3) if the space is deleted or being deleted, -then this function does nothing. -Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock -on the buffer frame. The io-handler must take care that the flag is cleared -and the lock released later. -@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED -@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] unzip whether the uncompressed page is - requested (for ROW_FORMAT=COMPRESSED) -@return pointer to the block -@retval NULL in case of an error */ -buf_page_t* -buf_page_init_for_read( - dberr_t* err, - ulint mode, - const page_id_t page_id, - ulint zip_size, - bool unzip) -{ - buf_block_t* block; - buf_page_t* bpage = NULL; - buf_page_t* watch_page; - rw_lock_t* hash_lock; - mtr_t mtr; - bool lru = false; - void* data; - - *err = DB_SUCCESS; - - if (mode == BUF_READ_IBUF_PAGES_ONLY) { - /* It is a read-ahead within an ibuf routine */ - - ut_ad(!ibuf_bitmap_page(page_id, zip_size)); - - ibuf_mtr_start(&mtr); - - if (!recv_no_ibuf_operations - && !ibuf_page(page_id, zip_size, &mtr)) { - - ibuf_mtr_commit(&mtr); - - return(NULL); - } - } else { - ut_ad(mode == BUF_READ_ANY_PAGE); - } - - if (zip_size && !unzip && !recv_recovery_is_on()) { - block = NULL; - } else { - block = buf_LRU_get_free_block(); - ut_ad(block); - } - - mutex_enter(&buf_pool.mutex); - - hash_lock = buf_page_hash_lock_get(page_id); - rw_lock_x_lock(hash_lock); - - watch_page = buf_page_hash_get_low(page_id); - if (watch_page && !buf_pool_watch_is_sentinel(watch_page)) { - /* The page is already in the buffer pool. */ - watch_page = NULL; - rw_lock_x_unlock(hash_lock); - if (block) { - buf_page_mutex_enter(block); - buf_LRU_block_free_non_file_page(block); - buf_page_mutex_exit(block); - } - - bpage = NULL; - goto func_exit; - } - - if (block) { - bpage = &block->page; - - buf_page_mutex_enter(block); - - buf_page_init(page_id, zip_size, block); - - /* Note: We are using the hash_lock for protection. This is - safe because no other thread can lookup the block from the - page hashtable yet. */ - - buf_page_set_io_fix(bpage, BUF_IO_READ); - - rw_lock_x_unlock(hash_lock); - - /* The block must be put to the LRU list, to the old blocks */ - buf_LRU_add_block(bpage, TRUE/* to old blocks */); - - /* We set a pass-type x-lock on the frame because then - the same thread which called for the read operation - (and is running now at this point of code) can wait - for the read to complete by waiting for the x-lock on - the frame; if the x-lock were recursive, the same - thread would illegally get the x-lock before the page - read is completed. The x-lock is cleared by the - io-handler thread. */ - - rw_lock_x_lock_gen(&block->lock, BUF_IO_READ); - - if (zip_size) { - /* buf_pool.mutex may be released and - reacquired by buf_buddy_alloc(). Thus, we - must release block->mutex in order not to - break the latching order in the reacquisition - of buf_pool.mutex. We also must defer this - operation until after the block descriptor has - been added to buf_pool.LRU and - buf_pool.page_hash. */ - buf_page_mutex_exit(block); - data = buf_buddy_alloc(zip_size, &lru); - buf_page_mutex_enter(block); - block->page.zip.data = (page_zip_t*) data; - - /* To maintain the invariant - block->in_unzip_LRU_list - == buf_page_belongs_to_unzip_LRU(&block->page) - we have to add this block to unzip_LRU - after block->page.zip.data is set. */ - ut_ad(buf_page_belongs_to_unzip_LRU(&block->page)); - buf_unzip_LRU_add_block(block, TRUE); - } - - buf_page_mutex_exit(block); - } else { - rw_lock_x_unlock(hash_lock); - - /* The compressed page must be allocated before the - control block (bpage), in order to avoid the - invocation of buf_buddy_relocate_block() on - uninitialized data. */ - data = buf_buddy_alloc(zip_size, &lru); - - rw_lock_x_lock(hash_lock); - - /* If buf_buddy_alloc() allocated storage from the LRU list, - it released and reacquired buf_pool.mutex. Thus, we must - check the page_hash again, as it may have been modified. */ - if (UNIV_UNLIKELY(lru)) { - watch_page = buf_page_hash_get_low(page_id); - - if (UNIV_UNLIKELY(watch_page - && !buf_pool_watch_is_sentinel(watch_page))) { - - /* The block was added by some other thread. */ - rw_lock_x_unlock(hash_lock); - watch_page = NULL; - buf_buddy_free(data, zip_size); - - bpage = NULL; - goto func_exit; - } - } - - bpage = buf_page_alloc_descriptor(); - - page_zip_des_init(&bpage->zip); - page_zip_set_size(&bpage->zip, zip_size); - bpage->zip.data = (page_zip_t*) data; - - mutex_enter(&buf_pool.zip_mutex); - UNIV_MEM_DESC(bpage->zip.data, zip_size); - - buf_page_init_low(bpage); - - bpage->state = BUF_BLOCK_ZIP_PAGE; - bpage->id = page_id; - bpage->status = buf_page_t::NORMAL; - - ut_d(bpage->in_page_hash = FALSE); - ut_d(bpage->in_zip_hash = FALSE); - ut_d(bpage->in_flush_list = FALSE); - ut_d(bpage->in_free_list = FALSE); - ut_d(bpage->in_LRU_list = FALSE); - - ut_d(bpage->in_page_hash = TRUE); - - if (watch_page != NULL) { - - /* Preserve the reference count. */ - ib_uint32_t buf_fix_count; - - buf_fix_count = watch_page->buf_fix_count; - - ut_a(buf_fix_count > 0); - - bpage->buf_fix_count += buf_fix_count; - - ut_ad(buf_pool_watch_is_sentinel(watch_page)); - buf_pool_watch_remove(watch_page); - } - - HASH_INSERT(buf_page_t, hash, buf_pool.page_hash, - bpage->id.fold(), bpage); - - rw_lock_x_unlock(hash_lock); - - /* The block must be put to the LRU list, to the old blocks. - The zip size is already set into the page zip */ - buf_LRU_add_block(bpage, TRUE/* to old blocks */); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - buf_LRU_insert_zip_clean(bpage); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - - buf_page_set_io_fix(bpage, BUF_IO_READ); - - mutex_exit(&buf_pool.zip_mutex); - } - - buf_pool.n_pend_reads++; -func_exit: - mutex_exit(&buf_pool.mutex); - - if (mode == BUF_READ_IBUF_PAGES_ONLY) { - - ibuf_mtr_commit(&mtr); - } - - ut_ad(!rw_lock_own_flagged(hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - ut_ad(!bpage || buf_page_in_file(bpage)); - - return(bpage); + ut_ad(page.state() != BUF_BLOCK_FILE_PAGE); + buf_block_init_low(this); + lock_hash_val= lock_rec_hash(page_id.space(), page_id.page_no()); + page.init(page_id, fix); + page_zip_set_size(&page.zip, zip_size); } /** Initialize a page in the buffer pool. The page is usually not read from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => FILE_PAGE (the other is buf_page_get_gen). -@param[in] page_id page id +@param[in,out] space space object +@param[in] offset offset of the tablespace @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction @return pointer to the block, page bufferfixed */ buf_block_t* -buf_page_create( - const page_id_t page_id, - ulint zip_size, - mtr_t* mtr) +buf_page_create(fil_space_t *space, uint32_t offset, + ulint zip_size, mtr_t *mtr) { - buf_frame_t* frame; - buf_block_t* block; - buf_block_t* free_block = NULL; - rw_lock_t* hash_lock; + page_id_t page_id(space->id, offset); + ut_ad(mtr->is_active()); + ut_ad(page_id.space() != 0 || !zip_size); - ut_ad(mtr->is_active()); - ut_ad(page_id.space() != 0 || !zip_size); + space->free_page(offset, false); + buf_block_t *free_block= buf_LRU_get_free_block(false); + free_block->initialise(page_id, zip_size, 1); - free_block = buf_LRU_get_free_block(); + const ulint fold= page_id.fold(); - mutex_enter(&buf_pool.mutex); + mutex_enter(&buf_pool.mutex); - hash_lock = buf_page_hash_lock_get(page_id); - rw_lock_x_lock(hash_lock); + buf_block_t *block= reinterpret_cast + (buf_pool.page_hash_get_low(page_id, fold)); - block = (buf_block_t*) buf_page_hash_get_low(page_id); + if (block && block->page.in_file() && + !buf_pool.watch_is_sentinel(block->page)) + { + /* Page can be found in buf_pool */ + buf_LRU_block_free_non_file_page(free_block); + mutex_exit(&buf_pool.mutex); - if (block - && buf_page_in_file(&block->page) - && !buf_pool_watch_is_sentinel(&block->page)) { - /* Page can be found in buf_pool */ - mutex_exit(&buf_pool.mutex); - rw_lock_x_unlock(hash_lock); +#ifdef BTR_CUR_HASH_ADAPT + if (block->page.state() == BUF_BLOCK_FILE_PAGE && + UNIV_LIKELY_NULL(block->index)) + btr_search_drop_page_hash_index(block); +#endif /* BTR_CUR_HASH_ADAPT */ + if (!recv_recovery_is_on()) + /* FIXME: Remove the redundant lookup and avoid + the unnecessary invocation of buf_zip_decompress(). + We may have to convert buf_page_t to buf_block_t, + but we are going to initialize the page. */ + return buf_page_get_gen(page_id, zip_size, RW_NO_LATCH, + block, BUF_GET_POSSIBLY_FREED, + __FILE__, __LINE__, mtr); + mutex_exit(&recv_sys.mutex); + block= buf_page_get_with_no_latch(page_id, zip_size, mtr); + mutex_enter(&recv_sys.mutex); + return block; + } - buf_block_free(free_block); + /* If we get here, the page was not in buf_pool: init it there */ - if (!recv_recovery_is_on()) { - /* FIXME: Remove the redundant lookup and avoid - the unnecessary invocation of buf_zip_decompress(). - We may have to convert buf_page_t to buf_block_t, - but we are going to initialize the page. */ - return buf_page_get_gen(page_id, zip_size, RW_NO_LATCH, - block, BUF_GET_POSSIBLY_FREED, - __FILE__, __LINE__, mtr); - } + DBUG_PRINT("ib_buf", ("create page %u:%u", + page_id.space(), page_id.page_no())); - mutex_exit(&recv_sys.mutex); - block = buf_page_get_with_no_latch(page_id, zip_size, mtr); - mutex_enter(&recv_sys.mutex); - return block; - } + block= free_block; - /* If we get here, the page was not in buf_pool: init it there */ + /* Duplicate buf_block_buf_fix_inc_func() */ + ut_ad(block->page.buf_fix_count() == 1); + ut_ad(fsp_is_system_temporary(page_id.space()) || + rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__)); - DBUG_PRINT("ib_buf", ("create page %u:%u", - page_id.space(), page_id.page_no())); + /* The block must be put to the LRU list */ + buf_LRU_add_block(&block->page, false); + page_hash_latch *hash_lock= buf_pool.page_hash.lock_get(fold); + hash_lock->write_lock(); + block->page.set_state(BUF_BLOCK_FILE_PAGE); + ut_d(block->page.in_page_hash= true); + HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, &block->page); - block = free_block; + if (UNIV_UNLIKELY(zip_size)) + { + /* Prevent race conditions during buf_buddy_alloc(), which may + release and reacquire buf_pool.mutex, by IO-fixing and X-latching + the block. */ + block->page.set_io_fix(BUF_IO_READ); + rw_lock_x_lock(&block->lock); + hash_lock->write_unlock(); - buf_page_mutex_enter(block); + /* buf_pool.mutex may be released and reacquired by + buf_buddy_alloc(). We must defer this operation until + after the block descriptor has been added to + buf_pool.LRU and buf_pool.page_hash. */ + block->page.zip.data= buf_buddy_alloc(zip_size); - buf_page_init(page_id, zip_size, block); + /* To maintain the invariant block->in_unzip_LRU_list == + block->page.belongs_to_unzip_LRU() we have to add this + block to unzip_LRU after block->page.zip.data is set. */ + ut_ad(block->page.belongs_to_unzip_LRU()); + buf_unzip_LRU_add_block(block, FALSE); - rw_lock_x_unlock(hash_lock); + block->page.set_io_fix(BUF_IO_NONE); + rw_lock_x_unlock(&block->lock); + } + else + hash_lock->write_unlock(); - /* The block must be put to the LRU list */ - buf_LRU_add_block(&block->page, FALSE); + mutex_exit(&buf_pool.mutex); - buf_block_buf_fix_inc(block, __FILE__, __LINE__); - buf_pool.stat.n_pages_created++; + mtr->memo_push(block, MTR_MEMO_BUF_FIX); + block->page.set_accessed(); + buf_pool.stat.n_pages_created++; - if (zip_size) { - /* Prevent race conditions during buf_buddy_alloc(), - which may release and reacquire buf_pool.mutex, - by IO-fixing and X-latching the block. */ + /* Delete possible entries for the page from the insert buffer: + such can exist if the page belonged to an index which was dropped */ + if (!recv_recovery_is_on()) + ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size, true); - buf_page_set_io_fix(&block->page, BUF_IO_READ); - rw_lock_x_lock(&block->lock); + static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent"); + memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8); + mach_write_to_2(block->frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); - buf_page_mutex_exit(block); - /* buf_pool.mutex may be released and reacquired by - buf_buddy_alloc(). Thus, we must release block->mutex - in order not to break the latching order in - the reacquisition of buf_pool.mutex. We also must - defer this operation until after the block descriptor - has been added to buf_pool.LRU and buf_pool.page_hash. */ - block->page.zip.data = buf_buddy_alloc(zip_size); - buf_page_mutex_enter(block); + /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the + following pages: + (1) The first page of the InnoDB system tablespace (page 0:0) + (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages + (3) key_version on encrypted pages (not page 0:0) */ - /* To maintain the invariant - block->in_unzip_LRU_list - == buf_page_belongs_to_unzip_LRU(&block->page) - we have to add this block to unzip_LRU after - block->page.zip.data is set. */ - ut_ad(buf_page_belongs_to_unzip_LRU(&block->page)); - buf_unzip_LRU_add_block(block, FALSE); + memset(block->frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8); + memset_aligned<8>(block->frame + FIL_PAGE_LSN, 0, 8); - buf_page_set_io_fix(&block->page, BUF_IO_NONE); - rw_lock_x_unlock(&block->lock); - } - - mutex_exit(&buf_pool.mutex); - - mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); - - buf_page_set_accessed(&block->page); - - buf_page_mutex_exit(block); - - /* Delete possible entries for the page from the insert buffer: - such can exist if the page belonged to an index which was dropped */ - if (!recv_recovery_is_on()) { - ibuf_merge_or_delete_for_page(NULL, page_id, zip_size, true); - } - - frame = block->frame; - - static_assert(FIL_PAGE_PREV % 8 == 0, "alignment"); - static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent"); - memset_aligned<8>(frame + FIL_PAGE_PREV, 0xff, 8); - mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED); - - /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the - following pages: - (1) The first page of the InnoDB system tablespace (page 0:0) - (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages - (3) key_version on encrypted pages (not page 0:0) */ - - memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8); - static_assert(FIL_PAGE_LSN % 8 == 0, "alignment"); - memset_aligned<8>(frame + FIL_PAGE_LSN, 0, 8); - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - return(block); +#ifdef UNIV_DEBUG + if (!(++buf_dbg_counter % 5771)) buf_pool.validate(); +#endif /* UNIV_DEBUG */ + return block; } -/********************************************************************//** -Monitor the buffer page read/write activity, and increment corresponding -counter value if MONITOR_MODULE_BUF_PAGE (module_buf_page) module is -enabled. */ -static -void -buf_page_monitor( -/*=============*/ - const buf_page_t* bpage, /*!< in: pointer to the block */ - enum buf_io_fix io_type)/*!< in: io_fix types */ +/** Monitor the buffer page read/write activity, and increment corresponding +counter value in MONITOR_MODULE_BUF_PAGE. +@param bpage buffer page whose read or write was completed +@param io_type BUF_IO_READ or BUF_IO_WRITE */ +ATTRIBUTE_COLD __attribute__((nonnull)) +void buf_page_monitor(const buf_page_t *bpage, buf_io_fix io_type) { const byte* frame; monitor_id_t counter; - /* If the counter module is not turned on, just return */ - if (!MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)) { - return; - } - - ut_a(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE); + ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE); frame = bpage->zip.data ? bpage->zip.data @@ -4766,50 +4047,45 @@ static void buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t& space) } } +/** Release and evict a corrupted page. +@param bpage page that was being read */ +void buf_pool_t::corrupted_evict(buf_page_t *bpage) +{ + const page_id_t id(bpage->id()); + page_hash_latch *hash_lock= hash_lock_get(id); + + mutex_enter(&mutex); + hash_lock->write_lock(); + + ut_ad(bpage->io_fix() == BUF_IO_READ); + ut_ad(!bpage->oldest_modification()); + bpage->set_corrupt_id(); + + if (bpage->state() == BUF_BLOCK_FILE_PAGE) + rw_lock_x_unlock_gen(&reinterpret_cast(bpage)->lock, + BUF_IO_READ); + + bpage->io_unfix(); + + /* remove from LRU and page_hash */ + buf_LRU_free_one_page(bpage, id, hash_lock); + mutex_exit(&mutex); + + ut_d(auto n=) n_pend_reads--; + ut_ad(n > 0); +} + /** Mark a table corrupted. @param[in] bpage Corrupted page -@param[in] space Corrupted page belongs to tablespace +@param[in] node data file Also remove the bpage from LRU list. */ -static -void -buf_corrupt_page_release(buf_page_t* bpage, const fil_space_t* space) +static void buf_corrupt_page_release(buf_page_t *bpage, const fil_node_t &node) { - const ibool uncompressed = (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE); - page_id_t old_page_id = bpage->id; + ut_ad(bpage->id().space() == node.space->id); + buf_pool.corrupted_evict(bpage); - /* First unfix and release lock on the bpage */ - mutex_enter(&buf_pool.mutex); - mutex_enter(buf_page_get_mutex(bpage)); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); - ut_ad(bpage->id.space() == space->id); - - /* buf_fix_count can be greater than zero. Because other thread - can wait in buf_page_wait_read() for the page to be read. */ - - bpage->id.set_corrupt_id(); - /* Set BUF_IO_NONE before we remove the block from LRU list */ - buf_page_set_io_fix(bpage, BUF_IO_NONE); - - if (uncompressed) { - rw_lock_x_unlock_gen( - &((buf_block_t*) bpage)->lock, - BUF_IO_READ); - } - - mutex_exit(buf_page_get_mutex(bpage)); - - if (!srv_force_recovery) { - buf_mark_space_corrupt(bpage, *space); - } - - /* After this point bpage can't be referenced. */ - buf_LRU_free_one_page(bpage, old_page_id); - - ut_ad(buf_pool.n_pend_reads > 0); - buf_pool.n_pend_reads--; - - mutex_exit(&buf_pool.mutex); + if (!srv_force_recovery) + buf_mark_space_corrupt(bpage, *node.space); } /** Check if the encrypted page is corrupted for the full crc32 format. @@ -4835,21 +4111,23 @@ static bool buf_page_full_crc32_is_corrupted(ulint space_id, const byte* d, corrupted page. Note that we can't be 100% sure if page is corrupted or decrypt/decompress just failed. @param[in,out] bpage page -@param[in,out] space tablespace from fil_space_acquire_for_io() +@param[in] node data file @return whether the operation succeeded @retval DB_SUCCESS if page has been read and is not corrupted @retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted @retval DB_DECRYPTION_FAILED if page post encryption checksum matches but after decryption normal page checksum does not match. @retval DB_TABLESPACE_DELETED if accessed tablespace is not found */ -static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) +static dberr_t buf_page_check_corrupt(buf_page_t *bpage, + const fil_node_t &node) { - ut_ad(space->pending_io()); + ut_ad(node.space->pending_io()); byte* dst_frame = (bpage->zip.data) ? bpage->zip.data : ((buf_block_t*) bpage)->frame; dberr_t err = DB_SUCCESS; - uint key_version = buf_page_get_key_version(dst_frame, space->flags); + uint key_version = buf_page_get_key_version(dst_frame, + node.space->flags); /* In buf_decrypt_after_read we have either decrypted the page if page post encryption checksum matches and used key_id is found @@ -4857,33 +4135,35 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) not decrypted and it could be either encrypted and corrupted or corrupted or good page. If we decrypted, there page could still be corrupted if used key does not match. */ - const bool seems_encrypted = !space->full_crc32() && key_version - && space->crypt_data - && space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED; - ut_ad(space->purpose != FIL_TYPE_TEMPORARY || space->full_crc32()); + const bool seems_encrypted = !node.space->full_crc32() && key_version + && node.space->crypt_data + && node.space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED; + ut_ad(node.space->purpose != FIL_TYPE_TEMPORARY || + node.space->full_crc32()); /* If traditional checksums match, we assume that page is not anymore encrypted. */ - if (space->full_crc32() + if (node.space->full_crc32() && !buf_is_zeroes(span(dst_frame, - space->physical_size())) - && (key_version || space->is_compressed() - || space->purpose == FIL_TYPE_TEMPORARY)) { + node.space->physical_size())) + && (key_version || node.space->is_compressed() + || node.space->purpose == FIL_TYPE_TEMPORARY)) { if (buf_page_full_crc32_is_corrupted( - space->id, dst_frame, space->is_compressed())) { + bpage->id().space(), dst_frame, + node.space->is_compressed())) { err = DB_PAGE_CORRUPTED; } - } else if (buf_page_is_corrupted(true, dst_frame, space->flags)) { + } else if (buf_page_is_corrupted(true, dst_frame, node.space->flags)) { err = DB_PAGE_CORRUPTED; } if (seems_encrypted && err == DB_PAGE_CORRUPTED - && bpage->id.page_no() != 0) { + && bpage->id().page_no() != 0) { err = DB_DECRYPTION_FAILED; ib::error() - << "The page " << bpage->id << " in file '" - << space->chain.start->name + << "The page " << bpage->id() + << " in file '" << node.name << "' cannot be decrypted."; ib::info() @@ -4892,7 +4172,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) << " is not found or" " used encryption algorithm or method does not match."; - if (bpage->id.space() != TRX_SYS_SPACE) { + if (bpage->id().space() != TRX_SYS_SPACE) { ib::info() << "Marking tablespace as missing." " You may drop this table or" @@ -4904,280 +4184,164 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) return (err); } -/** Complete a read or write request of a file page to or from the buffer pool. -@param[in,out] bpage page to complete -@param[in] dblwr whether the doublewrite buffer was used (on write) -@param[in] evict whether or not to evict the page from LRU list +/** Complete a read request of a file page to buf_pool. +@param bpage recently read page +@param node data file @return whether the operation succeeded -@retval DB_SUCCESS always when writing, or if a read page was OK -@retval DB_TABLESPACE_DELETED if the tablespace does not exist -@retval DB_PAGE_CORRUPTED if the checksum fails on a page read -@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but - after decryption normal page checksum does - not match */ -UNIV_INTERN -dberr_t -buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict) +@retval DB_SUCCESS always when writing, or if a read page was OK +@retval DB_PAGE_CORRUPTED if the checksum fails on a page read +@retval DB_DECRYPTION_FAILED if the page cannot be decrypted */ +dberr_t buf_page_read_complete(buf_page_t *bpage, const fil_node_t &node) { - enum buf_io_fix io_type; - const bool uncompressed = (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE); - ut_a(buf_page_in_file(bpage)); + const page_id_t id(bpage->id()); + ut_ad(bpage->in_file()); + ut_ad(id.space() || !buf_dblwr_page_inside(id.page_no())); + ut_ad(id.space() == node.space->id); + ut_ad(bpage->zip_size() == node.space->zip_size()); - /* We do not need protect io_fix here by mutex to read - it because this is the only function where we can change the value - from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code - ensures that this is the only thread that handles the i/o for this - block. */ + /* We do not need protect io_fix here by mutex to read it because + this and buf_page_write_complete() are the only functions where we can + change the value from BUF_IO_READ or BUF_IO_WRITE to some other + value, and our code ensures that this is the only thread that handles + the i/o for this block. */ - io_type = buf_page_get_io_fix(bpage); - ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE); - ut_ad(!!bpage->zip.ssize == (bpage->zip.data != NULL)); - ut_ad(uncompressed || bpage->zip.data); + ut_ad(bpage->io_fix() == BUF_IO_READ); + ut_ad(!!bpage->zip.ssize == !!bpage->zip.data); + ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE || bpage->zip.data); - if (io_type == BUF_IO_READ) { - ulint read_page_no = 0; - ulint read_space_id = 0; - byte* frame = bpage->zip.data - ? bpage->zip.data - : reinterpret_cast(bpage)->frame; - ut_ad(frame); - fil_space_t* space = fil_space_acquire_for_io( - bpage->id.space()); - if (!space) { - return DB_TABLESPACE_DELETED; - } + const byte *frame= bpage->zip.data + ? bpage->zip.data + : reinterpret_cast(bpage)->frame; + ut_ad(frame); - dberr_t err; + dberr_t err; + if (!buf_page_decrypt_after_read(bpage, node)) + { + err= DB_DECRYPTION_FAILED; + goto database_corrupted; + } - if (!buf_page_decrypt_after_read(bpage, space)) { - err = DB_DECRYPTION_FAILED; - goto database_corrupted; - } + if (bpage->zip.data && bpage->state() == BUF_BLOCK_FILE_PAGE) + { + buf_pool.n_pend_unzip++; + auto ok= buf_zip_decompress(reinterpret_cast(bpage), FALSE); + buf_pool.n_pend_unzip--; - if (bpage->zip.data && uncompressed) { - buf_pool.n_pend_unzip++; - ibool ok = buf_zip_decompress((buf_block_t*) bpage, - FALSE); - buf_pool.n_pend_unzip--; + if (!ok) + { + ib::info() << "Page " << id << " zip_decompress failure."; + err= DB_PAGE_CORRUPTED; + goto database_corrupted; + } + } - if (!ok) { - ib::info() << "Page " - << bpage->id - << " zip_decompress failure."; + { + const page_id_t read_id(mach_read_from_4(frame + FIL_PAGE_SPACE_ID), + mach_read_from_4(frame + FIL_PAGE_OFFSET)); - err = DB_PAGE_CORRUPTED; - goto database_corrupted; - } - } - - /* If this page is not uninitialized and not in the - doublewrite buffer, then the page number and space id - should be the same as in block. */ - read_page_no = mach_read_from_4(frame + FIL_PAGE_OFFSET); - read_space_id = mach_read_from_4( - frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - - if (bpage->id.space() == TRX_SYS_SPACE - && buf_dblwr_page_inside(bpage->id.page_no())) { - - ib::error() << "Reading page " << bpage->id - << ", which is in the doublewrite buffer!"; - - } else if (read_space_id == 0 && read_page_no == 0) { - /* This is likely an uninitialized page. */ - } else if (((!space->full_crc32() - || bpage->id.space() != TRX_SYS_SPACE) - && bpage->id.space() != read_space_id) - || bpage->id.page_no() != read_page_no) { - /* We do not compare space_id to read_space_id - in the system tablespace unless space->full_crc32(), - because the field was written as garbage before - MySQL 4.1.1, which introduced support for - innodb_file_per_table. */ - - if (space->full_crc32() - && *reinterpret_cast - (&frame[FIL_PAGE_FCRC32_KEY_VERSION]) - && space->crypt_data - && space->crypt_data->type - != CRYPT_SCHEME_UNENCRYPTED) { - ib::error() << "Cannot decrypt " << bpage->id; - err = DB_DECRYPTION_FAILED; - goto release_page; - } - - ib::error() << "Space id and page no stored in " - "the page, read in are " - << page_id_t(read_space_id, read_page_no) - << ", should be " << bpage->id; - } - - err = buf_page_check_corrupt(bpage, space); + if (read_id == id); + else if (read_id == page_id_t(0, 0)) + /* This is likely an uninitialized page. */; + else if (!node.space->full_crc32() && + page_id_t(0, read_id.page_no()) == id) + /* FIL_PAGE_SPACE_ID was written as garbage in the system tablespace + before MySQL 4.1.1, which introduced innodb_file_per_table. */; + else if (node.space->full_crc32() && + *reinterpret_cast + (&frame[FIL_PAGE_FCRC32_KEY_VERSION]) && + node.space->crypt_data && + node.space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED) + { + ib::error() << "Cannot decrypt " << id; + err= DB_DECRYPTION_FAILED; + goto release_page; + } + else + ib::error() << "Space id and page no stored in the page, read in are " + << read_id << ", should be " << id; + } + err= buf_page_check_corrupt(bpage, node); + if (err != DB_SUCCESS) + { database_corrupted: + /* Not a real corruption if it was triggered by error injection */ + DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", + if (!is_predefined_tablespace(id.space())) + { + buf_corrupt_page_release(bpage, node); + ib::info() << "Simulated IMPORT corruption"; + return err; + } + err= DB_SUCCESS; + goto page_not_corrupt;); - if (err != DB_SUCCESS) { - /* Not a real corruption if it was triggered by - error injection */ - DBUG_EXECUTE_IF( - "buf_page_import_corrupt_failure", - if (!is_predefined_tablespace( - bpage->id.space())) { - buf_corrupt_page_release(bpage, space); - ib::info() << "Simulated IMPORT " - "corruption"; - space->release_for_io(); - return(err); - } - err = DB_SUCCESS; - goto page_not_corrupt; - ); + if (bpage->zip.data && bpage->state() == BUF_BLOCK_FILE_PAGE) + memset(reinterpret_cast(bpage)->frame, 0, srv_page_size); - if (err == DB_PAGE_CORRUPTED) { - ib::error() - << "Database page corruption on disk" - " or a failed file read of tablespace " - << space->name << " page " << bpage->id - << ". You may have to recover from " - << "a backup."; + if (err == DB_PAGE_CORRUPTED) + { + ib::error() << "Database page corruption on disk" + " or a failed read of file '" + << node.name << "' page " << id + << ". You may have to recover from a backup."; - buf_page_print(frame, bpage->zip_size()); + buf_page_print(frame, bpage->zip_size()); - ib::info() - << "It is also possible that your" - " operating system has corrupted" - " its own file cache and rebooting" - " your computer removes the error." - " If the corrupt page is an index page." - " You can also try to fix the" - " corruption by dumping, dropping," - " and reimporting the corrupt table." - " You can use CHECK TABLE to scan" - " your table for corruption. " - << FORCE_RECOVERY_MSG; - } + ib::info() << " You can use CHECK TABLE to scan" + " your table for corruption. " + << FORCE_RECOVERY_MSG; + } - if (!srv_force_recovery) { + if (!srv_force_recovery) + { + /* If the corruption is in the system tablespace, we will + intentionally crash the server. */ + if (id.space() == TRX_SYS_SPACE) + ib::fatal() << "Aborting because of a corrupt database page."; + buf_corrupt_page_release(bpage, node); + return err; + } + } - /* If page space id is larger than TRX_SYS_SPACE - (0), we will attempt to mark the corresponding - table as corrupted instead of crashing server */ - if (bpage->id.space() == TRX_SYS_SPACE) { - ib::fatal() << "Aborting because of" - " a corrupt database page."; - } + DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", + page_not_corrupt: bpage= bpage; ); - buf_corrupt_page_release(bpage, space); - space->release_for_io(); - return(err); - } - } - - DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", - page_not_corrupt: bpage = bpage; ); - - if (err == DB_PAGE_CORRUPTED - || err == DB_DECRYPTION_FAILED) { + if (err == DB_PAGE_CORRUPTED || err == DB_DECRYPTION_FAILED) + { release_page: - const page_id_t corrupt_page_id = bpage->id; + buf_corrupt_page_release(bpage, node); + if (recv_recovery_is_on()) + recv_sys.free_corrupted_page(id); + return err; + } - buf_corrupt_page_release(bpage, space); + if (recv_recovery_is_on()) + recv_recover_page(node.space, bpage); - if (recv_recovery_is_on()) { - recv_sys.free_corrupted_page(corrupt_page_id); - } + if (bpage->state() == BUF_BLOCK_FILE_PAGE && !recv_no_ibuf_operations && + (!id.space() || !is_predefined_tablespace(id.space())) && + fil_page_get_type(frame) == FIL_PAGE_INDEX && + page_is_leaf(frame) && ibuf_page_exists(id, bpage->zip_size())) + bpage->ibuf_exist= true; - space->release_for_io(); - return err; - } + if (UNIV_UNLIKELY(MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE))) + buf_page_monitor(bpage, BUF_IO_READ); + DBUG_PRINT("ib_buf", ("read page %u:%u", + id.space(), id.page_no())); - if (recv_recovery_is_on()) { - recv_recover_page(space, bpage); - } + /* Because this thread which does the unlocking might not be the same that + did the locking, we use a pass value != 0 in unlock, which simply + removes the newest lock debug record, without checking the thread id. */ + if (bpage->state() == BUF_BLOCK_FILE_PAGE) + rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock, BUF_IO_READ); + bpage->io_unfix(); - if (uncompressed - && !recv_no_ibuf_operations - && (bpage->id.space() == 0 - || !is_predefined_tablespace(bpage->id.space())) - && fil_page_get_type(frame) == FIL_PAGE_INDEX - && page_is_leaf(frame) - && ibuf_page_exists(bpage->id, bpage->zip_size())) { - bpage->ibuf_exist = true; - } + ut_d(auto n=) buf_pool.n_pend_reads--; + ut_ad(n > 0); + buf_pool.stat.n_pages_read++; - space->release_for_io(); - } else { - /* io_type == BUF_IO_WRITE */ - if (bpage->slot) { - /* Mark slot free */ - bpage->slot->release(); - bpage->slot = NULL; - } - } - - BPageMutex* block_mutex = buf_page_get_mutex(bpage); - mutex_enter(&buf_pool.mutex); - mutex_enter(block_mutex); - - /* Because this thread which does the unlocking is not the same that - did the locking, we use a pass value != 0 in unlock, which simply - removes the newest lock debug record, without checking the thread - id. */ - - buf_page_set_io_fix(bpage, BUF_IO_NONE); - buf_page_monitor(bpage, io_type); - - if (io_type == BUF_IO_READ) { - /* NOTE that the call to ibuf may have moved the ownership of - the x-latch to this OS thread: do not let this confuse you in - debugging! */ - - ut_ad(buf_pool.n_pend_reads > 0); - buf_pool.n_pend_reads--; - buf_pool.stat.n_pages_read++; - - if (uncompressed) { - rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock, - BUF_IO_READ); - } - - mutex_exit(block_mutex); - } else { - /* Write means a flush operation: call the completion - routine in the flush system */ - - buf_flush_write_complete(bpage, dblwr); - - if (uncompressed) { - rw_lock_sx_unlock_gen(&((buf_block_t*) bpage)->lock, - BUF_IO_WRITE); - } - - buf_pool.stat.n_pages_written++; - - /* We decide whether or not to evict the page from the - LRU list based on the flush_type. - * BUF_FLUSH_LIST: don't evict - * BUF_FLUSH_LRU: always evict - * BUF_FLUSH_SINGLE_PAGE: eviction preference is passed - by the caller explicitly. */ - if (buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU) { - evict = true; - } - - mutex_exit(block_mutex); - - if (evict) { - buf_LRU_free_page(bpage, true); - } - } - - DBUG_PRINT("ib_buf", ("%s page %u:%u", - io_type == BUF_IO_READ ? "read" : "wrote", - bpage->id.space(), bpage->id.page_no())); - mutex_exit(&buf_pool.mutex); - return DB_SUCCESS; + return DB_SUCCESS; } #ifdef UNIV_DEBUG @@ -5190,7 +4354,7 @@ void buf_pool_t::assert_all_freed() const chunk_t *chunk= chunks; for (auto i= n_chunks; i--; chunk++) if (const buf_block_t* block= chunk->not_freed()) - ib::fatal() << "Page " << block->page.id << " still fixed or dirty"; + ib::fatal() << "Page " << block->page.id() << " still fixed or dirty"; mutex_exit(&mutex); } #endif /* UNIV_DEBUG */ @@ -5207,29 +4371,27 @@ All pages must be in a replaceable state (not modified or latched). */ void buf_pool_invalidate() { mutex_enter(&buf_pool.mutex); + ut_ad(!buf_pool.init_flush[IORequest::LRU]); + ut_ad(!buf_pool.init_flush[IORequest::FLUSH_LIST]); + ut_ad(!buf_pool.init_flush[IORequest::SINGLE_PAGE]); + ut_ad(!buf_pool.n_flush[IORequest::SINGLE_PAGE]); - for (unsigned i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) { - - /* As this function is called during startup and - during redo application phase during recovery, InnoDB - is single threaded (apart from IO helper threads) at - this stage. No new write batch can be in intialization - stage at this point. */ - ut_ad(!buf_pool.init_flush[i]); - - /* However, it is possible that a write batch that has - been posted earlier is still not complete. For buffer - pool invalidation to proceed we must ensure there is NO - write activity happening. */ - if (buf_pool.n_flush[i] > 0) { - buf_flush_t type = buf_flush_t(i); - - mutex_exit(&buf_pool.mutex); - buf_flush_wait_batch_end(type); - mutex_enter(&buf_pool.mutex); - } + if (buf_pool.n_flush[IORequest::LRU]) { + mutex_exit(&buf_pool.mutex); + buf_flush_wait_batch_end(true); + mutex_enter(&buf_pool.mutex); } + if (buf_pool.n_flush[IORequest::FLUSH_LIST]) { + mutex_exit(&buf_pool.mutex); + buf_flush_wait_batch_end(false); + mutex_enter(&buf_pool.mutex); + } + + /* It is possible that a write batch that has been posted + earlier is still not complete. For buffer pool invalidation to + proceed we must ensure there is NO write activity happening. */ + ut_d(mutex_exit(&buf_pool.mutex)); ut_d(buf_pool.assert_all_freed()); ut_d(mutex_enter(&buf_pool.mutex)); @@ -5248,111 +4410,61 @@ void buf_pool_invalidate() mutex_exit(&buf_pool.mutex); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Validate the buffer pool. */ void buf_pool_t::validate() { - buf_page_t* b; - chunk_t* chunk; - ulint i; - ulint n_lru_flush = 0; - ulint n_page_flush = 0; - ulint n_list_flush = 0; ulint n_lru = 0; - ulint n_flush = 0; + ulint n_flushing = 0; ulint n_free = 0; ulint n_zip = 0; - mutex_enter(&buf_pool.mutex); - hash_lock_x_all(buf_pool.page_hash); + mutex_enter(&mutex); - chunk = buf_pool.chunks; + chunk_t* chunk = chunks; /* Check the uncompressed blocks. */ - for (i = buf_pool.n_chunks; i--; chunk++) { + for (auto i = n_chunks; i--; chunk++) { ulint j; buf_block_t* block = chunk->blocks; for (j = chunk->size; j--; block++) { - - buf_page_mutex_enter(block); - - switch (buf_block_get_state(block)) { - case BUF_BLOCK_POOL_WATCH: + switch (block->page.state()) { case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: /* These should only occur on zip_clean, zip_free[], or flush_list. */ ut_error; break; - case BUF_BLOCK_FILE_PAGE: - ut_ad(buf_page_hash_get_low(block->page.id) - == &block->page); - - switch (buf_page_get_io_fix(&block->page)) { - case BUF_IO_NONE: - break; - - case BUF_IO_WRITE: - switch (buf_page_get_flush_type( - &block->page)) { - case BUF_FLUSH_LRU: - n_lru_flush++; - goto assert_s_latched; - case BUF_FLUSH_SINGLE_PAGE: - n_page_flush++; -assert_s_latched: - ut_a(rw_lock_is_locked( - &block->lock, - RW_LOCK_S) - || rw_lock_is_locked( - &block->lock, - RW_LOCK_SX)); - break; - case BUF_FLUSH_LIST: - n_list_flush++; - break; - default: - ut_error; - } - break; - case BUF_IO_READ: - ut_ad(rw_lock_is_locked(&block->lock, - RW_LOCK_X)); - break; - case BUF_IO_PIN: - break; - } - - n_lru++; - break; - case BUF_BLOCK_NOT_USED: n_free++; break; - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: /* do nothing */ break; - } - buf_page_mutex_exit(block); + case BUF_BLOCK_FILE_PAGE: + const page_id_t id = block->page.id(); + ut_ad(page_hash_get_low(id, id.fold()) + == &block->page); + n_lru++; + break; + + } } } - mutex_enter(&buf_pool.zip_mutex); - /* Check clean compressed-only blocks. */ - for (b = UT_LIST_GET_FIRST(buf_pool.zip_clean); b; + for (buf_page_t* b = UT_LIST_GET_FIRST(zip_clean); b; b = UT_LIST_GET_NEXT(list, b)) { - ut_ad(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); - switch (buf_page_get_io_fix(b)) { + ut_ad(b->state() == BUF_BLOCK_ZIP_PAGE); + ut_ad(!b->oldest_modification()); + switch (b->io_fix()) { case BUF_IO_NONE: case BUF_IO_PIN: /* All clean blocks should be I/O-unfixed. */ @@ -5368,102 +4480,68 @@ assert_s_latched: break; } - /* It is OK to read oldest_modification here because - we have acquired buf_pool.zip_mutex above which acts - as the 'block->mutex' for these bpages. */ - ut_ad(!b->oldest_modification); - ut_ad(buf_page_hash_get_low(b->id) == b); + const page_id_t id = b->id(); + ut_ad(page_hash_get_low(id, id.fold()) == b); n_lru++; n_zip++; } /* Check dirty blocks. */ - mutex_enter(&buf_pool.flush_list_mutex); - for (b = UT_LIST_GET_FIRST(buf_pool.flush_list); b; + mutex_enter(&flush_list_mutex); + for (buf_page_t* b = UT_LIST_GET_FIRST(flush_list); b; b = UT_LIST_GET_NEXT(list, b)) { - ut_ad(b->in_flush_list); - ut_ad(b->oldest_modification); - n_flush++; + ut_ad(b->oldest_modification()); + n_flushing++; - switch (buf_page_get_state(b)) { - case BUF_BLOCK_ZIP_DIRTY: + switch (b->state()) { + case BUF_BLOCK_ZIP_PAGE: n_lru++; n_zip++; - switch (buf_page_get_io_fix(b)) { - case BUF_IO_NONE: - case BUF_IO_READ: - case BUF_IO_PIN: - break; - case BUF_IO_WRITE: - switch (buf_page_get_flush_type(b)) { - case BUF_FLUSH_LRU: - n_lru_flush++; - break; - case BUF_FLUSH_SINGLE_PAGE: - n_page_flush++; - break; - case BUF_FLUSH_LIST: - n_list_flush++; - break; - default: - ut_error; - } - break; - } break; case BUF_BLOCK_FILE_PAGE: /* uncompressed page */ break; - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: ut_error; break; } - ut_ad(buf_page_hash_get_low(b->id) == b); + const page_id_t id = b->id(); + ut_ad(page_hash_get_low(id, id.fold()) == b); } - ut_ad(UT_LIST_GET_LEN(buf_pool.flush_list) == n_flush); + ut_ad(UT_LIST_GET_LEN(flush_list) == n_flushing); - hash_unlock_x_all(buf_pool.page_hash); - mutex_exit(&buf_pool.flush_list_mutex); + mutex_exit(&flush_list_mutex); - mutex_exit(&buf_pool.zip_mutex); - - if (buf_pool.curr_size == buf_pool.old_size - && n_lru + n_free > buf_pool.curr_size + n_zip) { + if (curr_size == old_size + && n_lru + n_free > curr_size + n_zip) { ib::fatal() << "n_LRU " << n_lru << ", n_free " << n_free - << ", pool " << buf_pool.curr_size + << ", pool " << curr_size << " zip " << n_zip << ". Aborting..."; } - ut_ad(UT_LIST_GET_LEN(buf_pool.LRU) == n_lru); + ut_ad(UT_LIST_GET_LEN(LRU) == n_lru); - if (buf_pool.curr_size == buf_pool.old_size - && UT_LIST_GET_LEN(buf_pool.free) != n_free) { + if (curr_size == old_size + && UT_LIST_GET_LEN(free) != n_free) { ib::fatal() << "Free list len " - << UT_LIST_GET_LEN(buf_pool.free) + << UT_LIST_GET_LEN(free) << ", free blocks " << n_free << ". Aborting..."; } - ut_ad(buf_pool.n_flush[BUF_FLUSH_LIST] == n_list_flush); - ut_ad(buf_pool.n_flush[BUF_FLUSH_LRU] == n_lru_flush); - ut_ad(buf_pool.n_flush[BUF_FLUSH_SINGLE_PAGE] == n_page_flush); - - mutex_exit(&buf_pool.mutex); + mutex_exit(&mutex); ut_d(buf_LRU_validate()); ut_d(buf_flush_validate()); } -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ -#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG /** Write information of the buf_pool to the error log. */ void buf_pool_t::print() { @@ -5495,9 +4573,9 @@ void buf_pool_t::print() << UT_LIST_GET_LEN(flush_list) << ", n pending decompressions=" << n_pend_unzip << ", n pending reads=" << n_pend_reads - << ", n pending flush LRU=" << n_flush[BUF_FLUSH_LRU] - << " list=" << n_flush[BUF_FLUSH_LIST] - << " single page=" << n_flush[BUF_FLUSH_SINGLE_PAGE] + << ", n pending flush LRU=" << n_flush[IORequest::LRU] + << " list=" << n_flush[IORequest::FLUSH_LIST] + << " single page=" << n_flush[IORequest::SINGLE_PAGE] << ", pages made young=" << stat.n_pages_made_young << ", not young=" << stat.n_pages_not_made_young << ", pages read=" << stat.n_pages_read @@ -5567,7 +4645,7 @@ void buf_pool_t::print() validate(); } -#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG */ #ifdef UNIV_DEBUG /** @return the number of latched pages in the buffer pool */ @@ -5582,41 +4660,27 @@ ulint buf_get_latched_pages_number() auto chunk = buf_pool.chunks; for (i = buf_pool.n_chunks; i--; chunk++) { - buf_block_t* block; - ulint j; + buf_block_t* block= chunk->blocks; - block = chunk->blocks; + for (auto j= chunk->size; j--; block++) { + if (block->page.state() == BUF_BLOCK_FILE_PAGE + && (block->page.buf_fix_count() + || block->page.io_fix() != BUF_IO_NONE)) { - for (j = chunk->size; j--; block++) { - if (buf_block_get_state(block) - != BUF_BLOCK_FILE_PAGE) { - - continue; - } - - buf_page_mutex_enter(block); - - if (block->page.buf_fix_count != 0 - || buf_page_get_io_fix(&block->page) - != BUF_IO_NONE) { fixed_pages_number++; } - - buf_page_mutex_exit(block); } } - mutex_enter(&buf_pool.zip_mutex); - /* Traverse the lists of clean and dirty compressed-only blocks. */ for (b = UT_LIST_GET_FIRST(buf_pool.zip_clean); b; b = UT_LIST_GET_NEXT(list, b)) { - ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); - ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE); + ut_a(b->state() == BUF_BLOCK_ZIP_PAGE); + ut_a(!b->oldest_modification()); + ut_a(b->io_fix() != BUF_IO_WRITE); - if (b->buf_fix_count != 0 - || buf_page_get_io_fix(b) != BUF_IO_NONE) { + if (b->buf_fix_count() || b->io_fix() != BUF_IO_NONE) { fixed_pages_number++; } } @@ -5624,31 +4688,26 @@ ulint buf_get_latched_pages_number() mutex_enter(&buf_pool.flush_list_mutex); for (b = UT_LIST_GET_FIRST(buf_pool.flush_list); b; b = UT_LIST_GET_NEXT(list, b)) { - ut_ad(b->in_flush_list); + ut_ad(b->oldest_modification()); - switch (buf_page_get_state(b)) { - case BUF_BLOCK_ZIP_DIRTY: - if (b->buf_fix_count != 0 - || buf_page_get_io_fix(b) != BUF_IO_NONE) { + switch (b->state()) { + case BUF_BLOCK_ZIP_PAGE: + if (b->buf_fix_count() || b->io_fix() != BUF_IO_NONE) { fixed_pages_number++; } - break; + continue; case BUF_BLOCK_FILE_PAGE: /* uncompressed page */ - break; - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: + continue; case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: - ut_error; break; } + ut_error; } mutex_exit(&buf_pool.flush_list_mutex); - mutex_exit(&buf_pool.zip_mutex); mutex_exit(&buf_pool.mutex); return(fixed_pages_number); @@ -5680,16 +4739,16 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info) pool_info->n_pend_reads = buf_pool.n_pend_reads; pool_info->n_pending_flush_lru = - (buf_pool.n_flush[BUF_FLUSH_LRU] - + buf_pool.init_flush[BUF_FLUSH_LRU]); + (buf_pool.n_flush[IORequest::LRU] + + buf_pool.init_flush[IORequest::LRU]); pool_info->n_pending_flush_list = - (buf_pool.n_flush[BUF_FLUSH_LIST] - + buf_pool.init_flush[BUF_FLUSH_LIST]); + (buf_pool.n_flush[IORequest::FLUSH_LIST] + + buf_pool.init_flush[IORequest::FLUSH_LIST]); pool_info->n_pending_flush_single_page = - (buf_pool.n_flush[BUF_FLUSH_SINGLE_PAGE] - + buf_pool.init_flush[BUF_FLUSH_SINGLE_PAGE]); + (buf_pool.n_flush[IORequest::SINGLE_PAGE] + + buf_pool.init_flush[IORequest::SINGLE_PAGE]); mutex_exit(&buf_pool.flush_list_mutex); @@ -5911,22 +4970,6 @@ bool buf_page_verify_crypt_checksum(const byte* page, ulint fsp_flags) return !buf_page_is_corrupted(true, page, fsp_flags); } -/** Checks that there currently are no I/O operations pending. -@return number of pending i/o */ -ulint buf_pool_check_no_pending_io() -{ - /* FIXME: use atomics, no mutex */ - ulint pending_io = buf_pool.n_pend_reads; - mutex_enter(&buf_pool.mutex); - pending_io += - + buf_pool.n_flush[BUF_FLUSH_LRU] - + buf_pool.n_flush[BUF_FLUSH_SINGLE_PAGE] - + buf_pool.n_flush[BUF_FLUSH_LIST]; - mutex_exit(&buf_pool.mutex); - - return(pending_io); -} - /** Print the given page_id_t object. @param[in,out] out the output stream @param[in] page_id the page_id_t object to be printed @@ -5938,17 +4981,6 @@ std::ostream& operator<<(std::ostream &out, const page_id_t page_id) return out; } -/** -Should we punch hole to deallocate unused portion of the page. -@param[in] bpage Page control block -@return true if punch hole should be used, false if not */ -bool -buf_page_should_punch_hole( - const buf_page_t* bpage) -{ - return bpage->real_size != bpage->physical_size(); -} - /** Calculate the length of trim (punch_hole) operation. @param[in] bpage Page control block diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 38160a9e4a7..3f8fc7b75a8 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -82,18 +82,6 @@ inline buf_block_t *buf_dblwr_trx_sys_get(mtr_t *mtr) return block; } -/********************************************************************//** -Flush a batch of writes to the datafiles that have already been -written to the dblwr buffer on disk. */ -void -buf_dblwr_sync_datafiles() -/*======================*/ -{ - /* Wait that all async writes to tablespaces have been posted to - the OS */ - os_aio_wait_until_no_pending_writes(); -} - /****************************************************************//** Creates or initialializes the doublewrite buffer at a database start. */ static void buf_dblwr_init(const byte *doublewrite) @@ -125,15 +113,12 @@ static void buf_dblwr_init(const byte *doublewrite) buf_dblwr->block2 = mach_read_from_4( doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK2); - buf_dblwr->in_use = static_cast( - ut_zalloc_nokey(buf_size * sizeof(bool))); - buf_dblwr->write_buf = static_cast( aligned_malloc(buf_size << srv_page_size_shift, srv_page_size)); - buf_dblwr->buf_block_arr = static_cast( - ut_zalloc_nokey(buf_size * sizeof(void*))); + buf_dblwr->buf_block_arr = static_cast( + ut_zalloc_nokey(buf_size * sizeof(buf_dblwr_t::element))); } /** Create the doublewrite buffer if the doublewrite buffer header @@ -242,7 +227,7 @@ too_small: has not been written to in doublewrite. */ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1); - page_no = new_block->page.id.page_no(); + page_no = new_block->page.id().page_no(); /* We only do this in the debug build, to ensure that the check in buf_flush_init_for_writing() will see a valid page type. The flushes of new_block are actually @@ -554,16 +539,20 @@ buf_dblwr_process() request.dblwr_recover(); /* Read in the actual page from the file */ - dberr_t err = fil_io( + fil_io_t fio = fil_io( request, true, page_id, zip_size, 0, physical_size, read_buf, NULL); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) { ib::warn() << "Double write buffer recovery: " << page_id << " read failed with " - << "error: " << ut_strerr(err); + << "error: " << fio.err; + } + + if (fio.node) { + fio.node->space->release_for_io(); } const bool is_all_zero = buf_is_zeroes( @@ -649,15 +638,17 @@ bad: /* Write the good page from the doublewrite buffer to the intended position. */ + fio = fil_io(IORequestWrite, true, page_id, zip_size, + 0, physical_size, const_cast(page), + nullptr); - IORequest write_request(IORequest::WRITE); - - fil_io(write_request, true, page_id, zip_size, - 0, physical_size, - const_cast(page), NULL); - - ib::info() << "Recovered page " << page_id - << " from the doublewrite buffer."; + if (fio.node) { + ut_ad(fio.err == DB_SUCCESS); + ib::info() << "Recovered page " << page_id + << " to '" << fio.node->name + << "' from the doublewrite buffer."; + fio.node->space->release_for_io(); + } } recv_dblwr.pages.clear(); @@ -680,75 +671,59 @@ buf_dblwr_free() os_event_destroy(buf_dblwr->s_event); aligned_free(buf_dblwr->write_buf); ut_free(buf_dblwr->buf_block_arr); - ut_free(buf_dblwr->in_use); mutex_free(&buf_dblwr->mutex); ut_free(buf_dblwr); buf_dblwr = NULL; } -/********************************************************************//** -Updates the doublewrite buffer when an IO request is completed. */ -void -buf_dblwr_update( -/*=============*/ - const buf_page_t* bpage, /*!< in: buffer block descriptor */ - buf_flush_t flush_type)/*!< in: flush type */ +/** Update the doublewrite buffer on write completion. */ +void buf_dblwr_update(const buf_page_t &bpage, bool single_page) { - ut_ad(srv_use_doublewrite_buf); - ut_ad(buf_dblwr); - ut_ad(!fsp_is_system_temporary(bpage->id.space())); - ut_ad(!srv_read_only_mode); + ut_ad(srv_use_doublewrite_buf); + ut_ad(buf_dblwr); + ut_ad(!fsp_is_system_temporary(bpage.id().space())); + ut_ad(!srv_read_only_mode); - switch (flush_type) { - case BUF_FLUSH_LIST: - case BUF_FLUSH_LRU: - mutex_enter(&buf_dblwr->mutex); + if (!single_page) + { + mutex_enter(&buf_dblwr->mutex); - ut_ad(buf_dblwr->batch_running); - ut_ad(buf_dblwr->b_reserved > 0); - ut_ad(buf_dblwr->b_reserved <= buf_dblwr->first_free); + ut_ad(buf_dblwr->batch_running); + ut_ad(buf_dblwr->b_reserved > 0); + ut_ad(buf_dblwr->b_reserved <= buf_dblwr->first_free); - buf_dblwr->b_reserved--; + if (!--buf_dblwr->b_reserved) + { + mutex_exit(&buf_dblwr->mutex); + /* This will finish the batch. Sync data files to the disk. */ + fil_flush_file_spaces(); + mutex_enter(&buf_dblwr->mutex); - if (buf_dblwr->b_reserved == 0) { - mutex_exit(&buf_dblwr->mutex); - /* This will finish the batch. Sync data files - to the disk. */ - fil_flush_file_spaces(); - mutex_enter(&buf_dblwr->mutex); + /* We can now reuse the doublewrite memory buffer: */ + buf_dblwr->first_free= 0; + buf_dblwr->batch_running= false; + os_event_set(buf_dblwr->b_event); + } - /* We can now reuse the doublewrite memory buffer: */ - buf_dblwr->first_free = 0; - buf_dblwr->batch_running = false; - os_event_set(buf_dblwr->b_event); - } + mutex_exit(&buf_dblwr->mutex); + return; + } - mutex_exit(&buf_dblwr->mutex); - break; - case BUF_FLUSH_SINGLE_PAGE: - { - const ulint size = TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; - ulint i; - mutex_enter(&buf_dblwr->mutex); - for (i = srv_doublewrite_batch_size; i < size; ++i) { - if (buf_dblwr->buf_block_arr[i] == bpage) { - buf_dblwr->s_reserved--; - buf_dblwr->buf_block_arr[i] = NULL; - buf_dblwr->in_use[i] = false; - break; - } - } + ulint size= TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; + mutex_enter(&buf_dblwr->mutex); + for (ulint i= srv_doublewrite_batch_size; i < size; ++i) + { + if (buf_dblwr->buf_block_arr[i].bpage != &bpage) + continue; + buf_dblwr->s_reserved--; + buf_dblwr->buf_block_arr[i].bpage= nullptr; + os_event_set(buf_dblwr->s_event); + mutex_exit(&buf_dblwr->mutex); + return; + } - /* The block we are looking for must exist as a - reserved block. */ - ut_a(i < size); - } - os_event_set(buf_dblwr->s_event); - mutex_exit(&buf_dblwr->mutex); - break; - case BUF_FLUSH_N_TYPES: - ut_error; - } + /* The block must exist as a reserved block. */ + ut_error; } #ifdef UNIV_DEBUG @@ -757,25 +732,26 @@ buf_dblwr_update( @param[in] s tablespace */ static void buf_dblwr_check_page_lsn(const page_t* page, const fil_space_t& s) { - /* Ignore page compressed or encrypted pages */ + /* Ignore page_compressed or encrypted pages */ if (s.is_compressed() || buf_page_get_key_version(page, s.flags)) return; const byte* lsn_start= FIL_PAGE_LSN + 4 + page; - const byte* lsn_end= page + - srv_page_size - (s.full_crc32() - ? FIL_PAGE_FCRC32_END_LSN - : FIL_PAGE_END_LSN_OLD_CHKSUM - 4); + const byte* lsn_end= page + srv_page_size - + (s.full_crc32() + ? FIL_PAGE_FCRC32_END_LSN + : FIL_PAGE_END_LSN_OLD_CHKSUM - 4); static_assert(FIL_PAGE_FCRC32_END_LSN % 4 == 0, "alignment"); static_assert(FIL_PAGE_LSN % 4 == 0, "alignment"); ut_ad(!memcmp_aligned<4>(lsn_start, lsn_end, 4)); } -static void buf_dblwr_check_page_lsn(const buf_page_t& b, const byte* page) +static void buf_dblwr_check_page_lsn(const buf_page_t &b, const byte *page) { - if (fil_space_t* space = fil_space_acquire_for_io(b.id.space())) { - buf_dblwr_check_page_lsn(page, *space); - space->release_for_io(); - } + if (fil_space_t *space= fil_space_acquire_for_io(b.id().space())) + { + buf_dblwr_check_page_lsn(page, *space); + space->release_for_io(); + } } #endif /* UNIV_DEBUG */ @@ -791,7 +767,7 @@ buf_dblwr_assert_on_corrupt_block( buf_page_print(block->frame); ib::fatal() << "Apparent corruption of an index page " - << block->page.id + << block->page.id() << " to be written to data file. We intentionally crash" " the server to prevent corrupt data from ending up in" " data files."; @@ -806,7 +782,7 @@ buf_dblwr_check_block( /*==================*/ const buf_block_t* block) /*!< in: block to check */ { - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); if (block->skip_flush_check) { return; @@ -855,44 +831,39 @@ buf_dblwr_check_block( /********************************************************************//** Writes a page that has already been written to the doublewrite buffer to the datafile. It is the job of the caller to sync the datafile. */ -static -void -buf_dblwr_write_block_to_datafile( -/*==============================*/ - const buf_page_t* bpage, /*!< in: page to write */ - bool sync) /*!< in: true if sync IO - is requested */ +static void +buf_dblwr_write_block_to_datafile(const buf_dblwr_t::element &e, bool sync) { - ut_a(buf_page_in_file(bpage)); - - ulint type = IORequest::WRITE; - IORequest request(type, const_cast(bpage)); + ut_ad(!sync || e.flush == IORequest::SINGLE_PAGE); + buf_page_t* bpage = e.bpage; + ut_a(bpage->in_file()); + IORequest request(IORequest::WRITE, bpage, e.flush); /* We request frame here to get correct buffer in case of encryption and/or page compression */ void * frame = buf_page_get_frame(bpage); - if (bpage->zip.data != NULL) { + fil_io_t fio; + + if (bpage->zip.data) { ut_ad(bpage->zip_size()); - fil_io(request, sync, bpage->id, bpage->zip_size(), 0, - bpage->zip_size(), - (void*) frame, - (void*) bpage); + fio = fil_io(request, sync, bpage->id(), bpage->zip_size(), 0, + bpage->zip_size(), frame, bpage); } else { + ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); ut_ad(!bpage->zip_size()); - /* Our IO API is common for both reads and writes and is - therefore geared towards a non-const parameter. */ + ut_d(buf_dblwr_check_page_lsn(*bpage, static_cast + (frame))); + fio = fil_io(request, + sync, bpage->id(), bpage->zip_size(), 0, + e.size, frame, bpage); + } - buf_block_t* block = reinterpret_cast( - const_cast(bpage)); - - ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_d(buf_dblwr_check_page_lsn(block->page, block->frame)); - fil_io(request, - sync, bpage->id, bpage->zip_size(), 0, bpage->real_size, - frame, block); + if (sync && fio.node) { + ut_ad(fio.err == DB_SUCCESS); + fio.node->space->release_for_io(); } } @@ -910,7 +881,7 @@ buf_dblwr_flush_buffered_writes() if (!srv_use_doublewrite_buf || buf_dblwr == NULL) { /* Sync the writes to the disk. */ - buf_dblwr_sync_datafiles(); + os_aio_wait_until_no_pending_writes(); /* Now we flush the data to disk (for example, with fsync) */ fil_flush_file_spaces(); return; @@ -960,12 +931,9 @@ try_again: i < buf_dblwr->first_free; len2 += srv_page_size, i++) { - const buf_block_t* block; + buf_page_t* bpage= buf_dblwr->buf_block_arr[i].bpage; - block = (buf_block_t*) buf_dblwr->buf_block_arr[i]; - - if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE - || block->page.zip.data) { + if (bpage->state() != BUF_BLOCK_FILE_PAGE || bpage->zip.data) { /* No simple validate for compressed pages exists. */ continue; @@ -973,17 +941,18 @@ try_again: /* Check that the actual page in the buffer pool is not corrupt and the LSN values are sane. */ - buf_dblwr_check_block(block); - ut_d(buf_dblwr_check_page_lsn(block->page, write_buf + len2)); + buf_dblwr_check_block(reinterpret_cast(bpage)); + ut_d(buf_dblwr_check_page_lsn(*bpage, write_buf + len2)); } /* Write out the first block of the doublewrite buffer */ len = std::min(TRX_SYS_DOUBLEWRITE_BLOCK_SIZE, buf_dblwr->first_free) << srv_page_size_shift; - fil_io(IORequestWrite, true, - page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), 0, - 0, len, (void*) write_buf, NULL); + fil_io_t fio = fil_io(IORequestWrite, true, + page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), 0, + 0, len, write_buf, nullptr); + fio.node->space->release_for_io(); if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { /* No unwritten pages in the second block. */ @@ -997,9 +966,10 @@ try_again: write_buf = buf_dblwr->write_buf + (TRX_SYS_DOUBLEWRITE_BLOCK_SIZE << srv_page_size_shift); - fil_io(IORequestWrite, true, - page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), 0, - 0, len, (void*) write_buf, NULL); + fio = fil_io(IORequestWrite, true, + page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), 0, + 0, len, write_buf, nullptr); + fio.node->space->release_for_io(); flush: /* increment the doublewrite flushed pages counter */ @@ -1031,218 +1001,146 @@ flush: } } -/********************************************************************//** -Posts a buffer page for writing. If the doublewrite memory buffer is -full, calls buf_dblwr_flush_buffered_writes and waits for for free -space to appear. */ -void -buf_dblwr_add_to_batch( -/*====================*/ - buf_page_t* bpage) /*!< in: buffer block to write */ +/** Schedule a page write. If the doublewrite memory buffer is full, +buf_dblwr_flush_buffered_writes() will be invoked to make space. +@param bpage buffer pool page to be written +@param flush type of flush +@param size payload size in bytes */ +void buf_dblwr_t::add_to_batch(buf_page_t *bpage, IORequest::flush_t flush, + size_t size) { - ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); + ut_ad(flush == IORequest::LRU || flush == IORequest::FLUSH_LIST); try_again: - mutex_enter(&buf_dblwr->mutex); + mutex_enter(&mutex); - ut_a(buf_dblwr->first_free <= srv_doublewrite_batch_size); + ut_a(first_free <= srv_doublewrite_batch_size); - if (buf_dblwr->batch_running) { + if (batch_running) + { + /* This not nearly as bad as it looks. There is only page_cleaner + thread which does background flushing in batches therefore it is + unlikely to be a contention point. The only exception is when a + user thread is forced to do a flush batch because of a sync + checkpoint. */ + int64_t sig_count= os_event_reset(b_event); + mutex_exit(&mutex); - /* This not nearly as bad as it looks. There is only - page_cleaner thread which does background flushing - in batches therefore it is unlikely to be a contention - point. The only exception is when a user thread is - forced to do a flush batch because of a sync - checkpoint. */ - int64_t sig_count = os_event_reset(buf_dblwr->b_event); - mutex_exit(&buf_dblwr->mutex); + os_event_wait_low(b_event, sig_count); + goto try_again; + } - os_event_wait_low(buf_dblwr->b_event, sig_count); - goto try_again; - } + if (first_free == srv_doublewrite_batch_size) + { + mutex_exit(&mutex); + buf_dblwr_flush_buffered_writes(); + goto try_again; + } - if (buf_dblwr->first_free == srv_doublewrite_batch_size) { - mutex_exit(&(buf_dblwr->mutex)); + byte *p= write_buf + srv_page_size * first_free; - buf_dblwr_flush_buffered_writes(); + /* We request frame here to get correct buffer in case of + encryption and/or page compression */ + void * frame = buf_page_get_frame(bpage); - goto try_again; - } + memcpy_aligned(p, frame, size); + ut_ad(!bpage->zip_size() || bpage->zip_size() == size); + buf_block_arr[first_free++] = { bpage, flush, size }; + b_reserved++; - byte* p = buf_dblwr->write_buf - + srv_page_size * buf_dblwr->first_free; + ut_ad(!batch_running); + ut_ad(first_free == b_reserved); + ut_ad(b_reserved <= srv_doublewrite_batch_size); - /* We request frame here to get correct buffer in case of - encryption and/or page compression */ - void * frame = buf_page_get_frame(bpage); + const bool need_flush= first_free == srv_doublewrite_batch_size; + mutex_exit(&mutex); - if (auto zip_size = bpage->zip_size()) { - UNIV_MEM_ASSERT_RW(bpage->zip.data, zip_size); - /* Copy the compressed page and clear the rest. */ - memcpy(p, frame, zip_size); - memset(p + zip_size, 0x0, srv_page_size - zip_size); - } else { - ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); - - UNIV_MEM_ASSERT_RW(frame, srv_page_size); - memcpy_aligned(p, frame, - srv_page_size); - } - - buf_dblwr->buf_block_arr[buf_dblwr->first_free] = bpage; - - buf_dblwr->first_free++; - buf_dblwr->b_reserved++; - - ut_ad(!buf_dblwr->batch_running); - ut_ad(buf_dblwr->first_free == buf_dblwr->b_reserved); - ut_ad(buf_dblwr->b_reserved <= srv_doublewrite_batch_size); - - if (buf_dblwr->first_free == srv_doublewrite_batch_size) { - mutex_exit(&(buf_dblwr->mutex)); - - buf_dblwr_flush_buffered_writes(); - - return; - } - - mutex_exit(&(buf_dblwr->mutex)); + if (need_flush) + buf_dblwr_flush_buffered_writes(); } -/********************************************************************//** -Writes a page to the doublewrite buffer on disk, sync it, then write +/** Write a page to the doublewrite buffer on disk, sync it, then write the page to the datafile and sync the datafile. This function is used for single page flushes. If all the buffers allocated for single page flushes in the doublewrite buffer are in use we wait here for one to become free. We are guaranteed that a slot will become free because any thread that is using a slot must also release the slot before leaving -this function. */ -void -buf_dblwr_write_single_page( -/*========================*/ - buf_page_t* bpage, /*!< in: buffer block to write */ - bool sync) /*!< in: true if sync IO requested */ +this function. +@param bpage buffer pool page to be written +@param sync whether synchronous operation is requested +@param size payload size in bytes */ +void buf_dblwr_t::write_single_page(buf_page_t *bpage, bool sync, size_t size) { - ulint n_slots; - ulint size; - ulint offset; - ulint i; + ut_ad(bpage->in_file()); + ut_ad(srv_use_doublewrite_buf); + ut_ad(this == buf_dblwr); - ut_a(buf_page_in_file(bpage)); - ut_a(srv_use_doublewrite_buf); - ut_a(buf_dblwr != NULL); + /* total number of slots available for single page flushes + starts from srv_doublewrite_batch_size to the end of the buffer. */ + ulint slots = TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; + ut_a(slots > srv_doublewrite_batch_size); + ulint n_slots= slots - srv_doublewrite_batch_size; - /* total number of slots available for single page flushes - starts from srv_doublewrite_batch_size to the end of the - buffer. */ - size = TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; - ut_a(size > srv_doublewrite_batch_size); - n_slots = size - srv_doublewrite_batch_size; - - if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { - - /* Check that the actual page in the buffer pool is - not corrupt and the LSN values are sane. */ - buf_dblwr_check_block((buf_block_t*) bpage); - - /* Check that the page as written to the doublewrite - buffer has sane LSN values. */ - if (!bpage->zip.data) { - ut_d(buf_dblwr_check_page_lsn( - *bpage, ((buf_block_t*) bpage)->frame)); - } - } + if (bpage->state() == BUF_BLOCK_FILE_PAGE) + { + /* Check that the actual page in the buffer pool is not corrupt + and the LSN values are sane. */ + buf_dblwr_check_block(reinterpret_cast(bpage)); +#ifdef UNIV_DEBUG + /* Check that the page as written to the doublewrite buffer has + sane LSN values. */ + if (!bpage->zip.data) + buf_dblwr_check_page_lsn(*bpage, reinterpret_cast + (bpage)->frame); +#endif + } retry: - mutex_enter(&buf_dblwr->mutex); - if (buf_dblwr->s_reserved == n_slots) { + mutex_enter(&mutex); + if (s_reserved == n_slots) + { + /* All slots are reserved. */ + int64_t sig_count = os_event_reset(s_event); + mutex_exit(&mutex); + os_event_wait_low(s_event, sig_count); + goto retry; + } - /* All slots are reserved. */ - int64_t sig_count = os_event_reset(buf_dblwr->s_event); - mutex_exit(&buf_dblwr->mutex); - os_event_wait_low(buf_dblwr->s_event, sig_count); + ulint i; + for (i = srv_doublewrite_batch_size; i < slots; ++i) + if (!buf_block_arr[i].bpage) + goto found; + /* We are guaranteed to find a slot. */ + ut_error; +found: + s_reserved++; + buf_block_arr[i]= { bpage, IORequest::SINGLE_PAGE, size }; - goto retry; - } + /* increment the doublewrite flushed pages counter */ + srv_stats.dblwr_pages_written.inc(); + srv_stats.dblwr_writes.inc(); - for (i = srv_doublewrite_batch_size; i < size; ++i) { + mutex_exit(&mutex); - if (!buf_dblwr->in_use[i]) { - break; - } - } + const ulint offset= i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE + ? block1 + i + : block2 + i - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; - /* We are guaranteed to find a slot. */ - ut_a(i < size); - buf_dblwr->in_use[i] = true; - buf_dblwr->s_reserved++; - buf_dblwr->buf_block_arr[i] = bpage; + /* We request frame here to get correct buffer in case of + encryption and/or page compression */ + void * frame = buf_page_get_frame(bpage); + ut_ad(!bpage->zip_size() || bpage->zip_size() == size); + fil_io_t fio= fil_io(IORequestWrite, true, page_id_t(TRX_SYS_SPACE, offset), + 0, 0, size, frame, nullptr); + fio.node->space->release_for_io(); - /* increment the doublewrite flushed pages counter */ - srv_stats.dblwr_pages_written.inc(); - srv_stats.dblwr_writes.inc(); + /* Now flush the doublewrite buffer data to disk */ + fil_flush(TRX_SYS_SPACE); - mutex_exit(&buf_dblwr->mutex); - - /* Lets see if we are going to write in the first or second - block of the doublewrite buffer. */ - if (i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { - offset = buf_dblwr->block1 + i; - } else { - offset = buf_dblwr->block2 + i - - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE; - } - - /* We deal with compressed and uncompressed pages a little - differently here. In case of uncompressed pages we can - directly write the block to the allocated slot in the - doublewrite buffer in the system tablespace and then after - syncing the system table space we can proceed to write the page - in the datafile. - In case of compressed page we first do a memcpy of the block - to the in-memory buffer of doublewrite before proceeding to - write it. This is so because we want to pad the remaining - bytes in the doublewrite page with zeros. */ - - /* We request frame here to get correct buffer in case of - encryption and/or page compression */ - void * frame = buf_page_get_frame(bpage); - - if (auto zip_size = bpage->zip_size()) { - memcpy(buf_dblwr->write_buf + srv_page_size * i, - frame, zip_size); - - memset(buf_dblwr->write_buf + srv_page_size * i - + zip_size, 0x0, - srv_page_size - zip_size); - - fil_io(IORequestWrite, - true, - page_id_t(TRX_SYS_SPACE, offset), - 0, - 0, - srv_page_size, - (void *)(buf_dblwr->write_buf + srv_page_size * i), - NULL); - } else { - /* It is a regular page. Write it directly to the - doublewrite buffer */ - fil_io(IORequestWrite, - true, - page_id_t(TRX_SYS_SPACE, offset), - 0, - 0, - srv_page_size, - (void*) frame, - NULL); - } - - /* Now flush the doublewrite buffer data to disk */ - fil_flush(TRX_SYS_SPACE); - - /* We know that the write has been flushed to disk now - and during recovery we will find it in the doublewrite buffer - blocks. Next do the write to the intended position. */ - buf_dblwr_write_block_to_datafile(bpage, sync); + /* We know that the write has been flushed to disk now + and during recovery we will find it in the doublewrite buffer + blocks. Next do the write to the intended position. */ + buf_dblwr_write_block_to_datafile({bpage, IORequest::SINGLE_PAGE, size}, + sync); } diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 87a4d2fecce..c67273cfec2 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -62,17 +62,6 @@ static volatile bool buf_load_should_start; static bool buf_load_abort_flag; -/* Used to temporary store dump info in order to avoid IO while holding -buffer pool mutex during dump and also to sort the contents of the dump -before reading the pages from disk during load. -We store the space id in the high 32 bits and page no in low 32 bits. */ -typedef ib_uint64_t buf_dump_t; - -/* Aux macros to create buf_dump_t and to extract space and page from it */ -#define BUF_DUMP_CREATE(space, page) ut_ull_create(space, page) -#define BUF_DUMP_SPACE(a) ((ulint) ((a) >> 32)) -#define BUF_DUMP_PAGE(a) ((ulint) ((a) & 0xFFFFFFFFUL)) - /** Start the buffer pool dump/load task and instructs it to start a dump. */ void buf_dump_start() { @@ -287,7 +276,7 @@ buf_dump( return; } const buf_page_t* bpage; - buf_dump_t* dump; + page_id_t* dump; ulint n_pages; ulint j; @@ -321,8 +310,8 @@ buf_dump( } } - dump = static_cast(ut_malloc_nokey( - n_pages * sizeof(*dump))); + dump = static_cast(ut_malloc_nokey( + n_pages * sizeof(*dump))); if (dump == NULL) { mutex_exit(&buf_pool.mutex); @@ -339,15 +328,15 @@ buf_dump( bpage != NULL && j < n_pages; bpage = UT_LIST_GET_NEXT(LRU, bpage)) { - ut_a(buf_page_in_file(bpage)); + ut_a(bpage->in_file()); + const page_id_t id(bpage->id()); - if (bpage->id.space() == SRV_TMP_SPACE_ID) { + if (id.space() == SRV_TMP_SPACE_ID) { /* Ignore the innodb_temporary tablespace. */ continue; } - dump[j++] = BUF_DUMP_CREATE(bpage->id.space(), - bpage->id.page_no()); + dump[j++] = id; } mutex_exit(&buf_pool.mutex); @@ -356,9 +345,8 @@ buf_dump( n_pages = j; for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) { - ret = fprintf(f, ULINTPF "," ULINTPF "\n", - BUF_DUMP_SPACE(dump[j]), - BUF_DUMP_PAGE(dump[j])); + ret = fprintf(f, "%u,%u\n", + dump[j].space(), dump[j].page_no()); if (ret < 0) { ut_free(dump); fclose(f); @@ -502,7 +490,7 @@ buf_load() char full_filename[OS_FILE_MAX_PATH]; char now[32]; FILE* f; - buf_dump_t* dump; + page_id_t* dump; ulint dump_n; ulint i; ulint space_id; @@ -556,7 +544,7 @@ buf_load() dump_n = std::min(dump_n, buf_pool.get_n_pages()); if (dump_n != 0) { - dump = static_cast(ut_malloc_nokey( + dump = static_cast(ut_malloc_nokey( dump_n * sizeof(*dump))); } else { fclose(f); @@ -613,7 +601,7 @@ buf_load() return; } - dump[i] = BUF_DUMP_CREATE(space_id, page_no); + dump[i] = page_id_t(space_id, page_no); } /* Set dump_n to the actual number of initialized elements, @@ -642,7 +630,7 @@ buf_load() /* Avoid calling the expensive fil_space_acquire_silent() for each page within the same tablespace. dump[] is sorted by (space, page), so all pages from a given tablespace are consecutive. */ - ulint cur_space_id = BUF_DUMP_SPACE(dump[0]); + ulint cur_space_id = dump[0].space(); fil_space_t* space = fil_space_acquire_silent(cur_space_id); ulint zip_size = space ? space->zip_size() : 0; @@ -654,7 +642,7 @@ buf_load() for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) { /* space_id for this iteration of the loop */ - const ulint this_space_id = BUF_DUMP_SPACE(dump[i]); + const ulint this_space_id = dump[i].space(); if (this_space_id == SRV_TMP_SPACE_ID) { /* Ignore the innodb_temporary tablespace. */ @@ -683,10 +671,7 @@ buf_load() continue; } - buf_read_page_background( - page_id_t(this_space_id, BUF_DUMP_PAGE(dump[i])), - zip_size, true); - + buf_read_page_background(dump[i], zip_size, true); if (buf_load_abort_flag) { if (space != NULL) { diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 54d01591202..af9302aa113 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -209,7 +209,7 @@ static inline void incr_flush_list_size_in_bytes(const buf_block_t* block) ut_ad(buf_pool.stat.flush_list_bytes <= buf_pool.curr_pool_size); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Validate the flush list. */ static void buf_flush_validate_low(); @@ -234,7 +234,7 @@ static void buf_flush_validate_skip() buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP; buf_flush_validate_low(); } -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ /******************************************************************//** Insert a block in the flush_rbt and returns a pointer to its @@ -306,29 +306,33 @@ buf_flush_block_cmp( const void* p1, /*!< in: block1 */ const void* p2) /*!< in: block2 */ { - int ret; - const buf_page_t* b1 = *(const buf_page_t**) p1; - const buf_page_t* b2 = *(const buf_page_t**) p2; + const buf_page_t* b1 = *static_cast(p1); + const buf_page_t* b2 = *static_cast(p2); ut_ad(b1 != NULL); ut_ad(b2 != NULL); ut_ad(mutex_own(&buf_pool.flush_list_mutex)); - ut_ad(b1->in_flush_list); - ut_ad(b2->in_flush_list); + const lsn_t m1 = b1->oldest_modification(), + m2 = b2->oldest_modification(); - if (b2->oldest_modification > b1->oldest_modification) { + ut_ad(m1); + ut_ad(m2); + + if (m2 > m1) { return(1); - } else if (b2->oldest_modification < b1->oldest_modification) { + } else if (m2 < m1) { return(-1); } - /* If oldest_modification is same then decide on the space. */ - ret = (int)(b2->id.space() - b1->id.space()); - - /* Or else decide ordering on the page number. */ - return(ret ? ret : (int) (b2->id.page_no() - b1->id.page_no())); + if (b2->id() > b1->id()) { + return 1; + } + if (b2->id() < b1->id()) { + return -1; + } + return 0; } /********************************************************************//** @@ -354,9 +358,7 @@ buf_flush_free_flush_rbt(void) /*==========================*/ { mutex_enter(&buf_pool.flush_list_mutex); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - buf_flush_validate_low(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ + ut_d(buf_flush_validate_low()); rbt_free(buf_pool.flush_rbt); buf_pool.flush_rbt = NULL; mutex_exit(&buf_pool.flush_list_mutex); @@ -369,15 +371,11 @@ void buf_flush_insert_into_flush_list(buf_block_t* block, lsn_t lsn) { ut_ad(!mutex_own(&buf_pool.mutex)); ut_ad(log_flush_order_mutex_own()); - ut_ad(buf_page_mutex_own(block)); ut_ad(lsn); mutex_enter(&buf_pool.flush_list_mutex); - ut_ad(!block->page.in_flush_list); - ut_d(block->page.in_flush_list = TRUE); - ut_ad(!block->page.oldest_modification); - block->page.oldest_modification = lsn; - UNIV_MEM_ASSERT_RW(block->page.zip.data + block->page.set_oldest_modification(lsn); + MEM_CHECK_DEFINED(block->page.zip.data ? block->page.zip.data : block->frame, block->physical_size()); incr_flush_list_size_in_bytes(block); @@ -391,11 +389,10 @@ void buf_flush_insert_into_flush_list(buf_block_t* block, lsn_t lsn) page frame of a compressed block may be discarded or created (copying the block->page to or from a buf_page_t that is dynamically allocated from buf_buddy_alloc()). Because those - transitions hold block->mutex and the flush list mutex (via + transitions hold buf_pool.flush_list_mutex (via buf_flush_relocate_on_flush_list()), there is no possibility of a race condition in the assertions below. */ ut_ad(block->page.in_LRU_list); - ut_ad(block->page.in_page_hash); /* buf_buddy_block_register() will take a block in the BUF_BLOCK_MEMORY state, not a file page. */ ut_ad(!block->page.in_zip_hash); @@ -409,76 +406,10 @@ void buf_flush_insert_into_flush_list(buf_block_t* block, lsn_t lsn) UT_LIST_ADD_FIRST(buf_pool.flush_list, &block->page); func_exit: -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - buf_flush_validate_skip(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - + ut_d(buf_flush_validate_skip()); mutex_exit(&buf_pool.flush_list_mutex); } -/********************************************************************//** -Returns TRUE if the file page block is immediately suitable for replacement, -i.e., the transition FILE_PAGE => NOT_USED allowed. -@return TRUE if can replace immediately */ -ibool -buf_flush_ready_for_replace( -/*========================*/ - buf_page_t* bpage) /*!< in: buffer control block, must be - buf_page_in_file(bpage) and in the LRU list */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(bpage->in_LRU_list); - - if (buf_page_in_file(bpage)) { - - return(bpage->oldest_modification == 0 - && bpage->buf_fix_count == 0 - && buf_page_get_io_fix(bpage) == BUF_IO_NONE); - } - - ib::fatal() << "Buffer block " << bpage << " state " << bpage->state - << " in the LRU list!"; - - return(FALSE); -} - -/********************************************************************//** -Returns true if the block is modified and ready for flushing. -@return true if can flush immediately */ -bool -buf_flush_ready_for_flush( -/*======================*/ - buf_page_t* bpage, /*!< in: buffer control block, must be - buf_page_in_file(bpage) */ - buf_flush_t flush_type)/*!< in: type of flush */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_a(buf_page_in_file(bpage)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(flush_type < BUF_FLUSH_N_TYPES); - - if (bpage->oldest_modification == 0 - || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { - return(false); - } - - ut_ad(bpage->in_flush_list); - - switch (flush_type) { - case BUF_FLUSH_LIST: - case BUF_FLUSH_LRU: - case BUF_FLUSH_SINGLE_PAGE: - return(true); - - case BUF_FLUSH_N_TYPES: - break; - } - - ut_error; - return(false); -} - /** Remove a block from the flush list of modified blocks. @param[in] bpage block to be removed from the flush list */ void buf_flush_remove(buf_page_t* bpage) @@ -493,36 +424,12 @@ void buf_flush_remove(buf_page_t* bpage) } #endif ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(bpage->in_flush_list); - mutex_enter(&buf_pool.flush_list_mutex); /* Important that we adjust the hazard pointer before removing the bpage from flush list. */ buf_pool.flush_hp.adjust(bpage); - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: - /* Clean compressed pages should not be on the flush list */ - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - ut_error; - return; - case BUF_BLOCK_ZIP_DIRTY: - buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE); - UT_LIST_REMOVE(buf_pool.flush_list, bpage); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - buf_LRU_insert_zip_clean(bpage); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - break; - case BUF_BLOCK_FILE_PAGE: - UT_LIST_REMOVE(buf_pool.flush_list, bpage); - break; - } + UT_LIST_REMOVE(buf_pool.flush_list, bpage); /* If the flush_rbt is active then delete from there as well. */ if (UNIV_LIKELY_NULL(buf_pool.flush_rbt)) { @@ -530,16 +437,20 @@ void buf_flush_remove(buf_page_t* bpage) } /* Must be done after we have removed it from the flush_rbt - because we assert on in_flush_list in comparison function. */ - ut_d(bpage->in_flush_list = FALSE); + because we assert on it in buf_flush_block_cmp(). */ + bpage->clear_oldest_modification(); + +#ifdef UNIV_DEBUG + if (bpage->state() == BUF_BLOCK_ZIP_PAGE) { + buf_LRU_insert_zip_clean(bpage); + } +#endif /* UNIV_DEBUG */ buf_pool.stat.flush_list_bytes -= bpage->physical_size(); - bpage->oldest_modification = 0; - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG buf_flush_validate_skip(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ mutex_exit(&buf_pool.flush_list_mutex); } @@ -565,8 +476,6 @@ buf_flush_relocate_on_flush_list( buf_page_t* prev_b = NULL; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - mutex_enter(&buf_pool.flush_list_mutex); /* FIXME: At this point we have both buf_pool and flush_list @@ -576,8 +485,7 @@ buf_flush_relocate_on_flush_list( is guaranteed to be in the flush list. We need to check if this will work without the assumption of block removing code having the buf_pool mutex. */ - ut_ad(bpage->in_flush_list); - ut_ad(dpage->in_flush_list); + ut_ad(dpage->oldest_modification()); /* If recovery is active we must swap the control blocks in the flush_rbt as well. */ @@ -591,14 +499,14 @@ buf_flush_relocate_on_flush_list( buf_pool.flush_hp.adjust(bpage); /* Must be done after we have removed it from the flush_rbt - because we assert on in_flush_list in comparison function. */ - ut_d(bpage->in_flush_list = FALSE); + because we assert on it in buf_flush_block_cmp(). */ + bpage->clear_oldest_modification(); prev = UT_LIST_GET_PREV(list, bpage); UT_LIST_REMOVE(buf_pool.flush_list, bpage); if (prev) { - ut_ad(prev->in_flush_list); + ut_ad(prev->oldest_modification()); UT_LIST_INSERT_AFTER( buf_pool.flush_list, prev, dpage); } else { UT_LIST_ADD_FIRST(buf_pool.flush_list, dpage); @@ -606,41 +514,81 @@ buf_flush_relocate_on_flush_list( /* Just an extra check. Previous in flush_list should be the same control block as in flush_rbt. */ - ut_a(buf_pool.flush_rbt == NULL || prev_b == prev); - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - buf_flush_validate_low(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - + ut_a(!buf_pool.flush_rbt || prev_b == prev); + ut_d(buf_flush_validate_low()); mutex_exit(&buf_pool.flush_list_mutex); } -/** Update the flush system data structures when a write is completed. -@param[in,out] bpage flushed page -@param[in] dblwr whether the doublewrite buffer was used */ -void buf_flush_write_complete(buf_page_t* bpage, bool dblwr) +/** Update the buf_pool data structures on write completion. +@param[in,out] bpage written page +@param[in] flush_type write request type +@param[in] dblwr whether the doublewrite buffer was used */ +static void buf_flush_write_complete(buf_page_t *bpage, + IORequest::flush_t flush_type, bool dblwr) { - ut_ad(bpage); + ut_ad(mutex_own(&buf_pool.mutex)); + buf_flush_remove(bpage); - buf_flush_remove(bpage); + switch (--buf_pool.n_flush[flush_type]) { +#ifdef UNIV_DEBUG + case ULINT_UNDEFINED: + ut_error; + break; +#endif + case 0: + if (!buf_pool.init_flush[flush_type]) + os_event_set(buf_pool.no_flush[flush_type]); + } - const buf_flush_t flush_type = buf_page_get_flush_type(bpage); - buf_pool.n_flush[flush_type]--; - ut_ad(buf_pool.n_flush[flush_type] != ULINT_MAX); + if (dblwr) + buf_dblwr_update(*bpage, flush_type == IORequest::SINGLE_PAGE); +} - ut_ad(mutex_own(&buf_pool.mutex)); +/** Complete write of a file page from buf_pool. +@param bpage written page +@param request write request +@param dblwr whether the doublewrite buffer was used +@param evict whether or not to evict the page from LRU list */ +void buf_page_write_complete(buf_page_t *bpage, const IORequest &request, + bool dblwr, bool evict) +{ + ut_ad(request.is_write()); + ut_ad(bpage->in_file()); + ut_ad(bpage->io_fix() == BUF_IO_WRITE); + ut_ad(bpage->id().space() != TRX_SYS_SPACE || + !buf_dblwr_page_inside(bpage->id().page_no())); - if (buf_pool.n_flush[flush_type] == 0 - && buf_pool.init_flush[flush_type] == FALSE) { + /* We do not need protect io_fix here by mutex to read it because + this and buf_page_write_complete() are the only functions where we can + change the value from BUF_IO_READ or BUF_IO_WRITE to some other + value, and our code ensures that this is the only thread that handles + the i/o for this block. */ + if (bpage->slot) + { + bpage->slot->release(); + bpage->slot= nullptr; + } - /* The running flush batch has ended */ + if (UNIV_UNLIKELY(MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE))) + buf_page_monitor(bpage, BUF_IO_WRITE); + DBUG_PRINT("ib_buf", ("write page %u:%u", + bpage->id().space(), bpage->id().page_no())); + mutex_enter(&buf_pool.mutex); + bpage->set_io_fix(BUF_IO_NONE); + buf_flush_write_complete(bpage, request.flush_type(), dblwr); - os_event_set(buf_pool.no_flush[flush_type]); - } + /* Because this thread which does the unlocking might not be the same that + did the locking, we use a pass value != 0 in unlock, which simply + removes the newest lock debug record, without checking the thread id. */ + if (bpage->state() == BUF_BLOCK_FILE_PAGE) + rw_lock_sx_unlock_gen(&((buf_block_t*) bpage)->lock, BUF_IO_WRITE); - if (dblwr) { - buf_dblwr_update(bpage, flush_type); - } + buf_pool.stat.n_pages_written++; + + if (evict) + buf_LRU_free_page(bpage, true); + + mutex_exit(&buf_pool.mutex); } /** Calculate a ROW_FORMAT=COMPRESSED page checksum and update the page. @@ -754,9 +702,9 @@ buf_flush_init_for_writing( ulint page_type = fil_page_get_type(page); ulint reset_type = page_type; - switch (block->page.id.page_no() % 16384) { + switch (block->page.id().page_no() % 16384) { case 0: - reset_type = block->page.id.page_no() == 0 + reset_type = block->page.id().page_no() == 0 ? FIL_PAGE_TYPE_FSP_HDR : FIL_PAGE_TYPE_XDES; break; @@ -764,10 +712,8 @@ buf_flush_init_for_writing( reset_type = FIL_PAGE_IBUF_BITMAP; break; case FSP_TRX_SYS_PAGE_NO: - if (block->page.id.page_no() - == TRX_SYS_PAGE_NO - && block->page.id.space() - == TRX_SYS_SPACE) { + if (block->page.id() + == page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO)) { reset_type = FIL_PAGE_TYPE_TRX_SYS; break; } @@ -802,7 +748,7 @@ buf_flush_init_for_writing( if (UNIV_UNLIKELY(page_type != reset_type)) { ib::info() << "Resetting invalid page " - << block->page.id << " type " + << block->page.id() << " type " << page_type << " to " << reset_type << " when flushing."; fil_page_set_type(page, reset_type); @@ -894,22 +840,21 @@ a page is written to disk. @param[in,out] space tablespace @param[in,out] bpage buffer page @param[in] s physical page frame that is being encrypted +@param[in,out] size payload size in bytes @return page frame to be written to file (may be src_frame or an encrypted/compressed copy of it) */ -static byte* buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s) +static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s, + size_t *size) { - if (bpage->status == buf_page_t::FREED) { - return s; - } - - ut_ad(space->id == bpage->id.space()); - bpage->real_size = srv_page_size; + ut_ad(bpage->status != buf_page_t::FREED); + ut_ad(space->id == bpage->id().space()); ut_d(fil_page_type_validate(space, s)); + const uint32_t page_no= bpage->id().page_no(); - switch (bpage->id.page_no()) { + switch (page_no) { case TRX_SYS_PAGE_NO: - if (bpage->id.space() != TRX_SYS_SPACE) + if (bpage->id().space() != TRX_SYS_SPACE) break; /* The TRX_SYS page is neither encrypted nor compressed, because it contains the address of the doublewrite buffer. */ @@ -970,8 +915,8 @@ static byte* buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s) { not_compressed: byte *tmp= space->purpose == FIL_TYPE_TEMPORARY - ? buf_tmp_page_encrypt(bpage->id.page_no(), s, d) - : fil_space_encrypt(space, bpage->id.page_no(), s, d); + ? buf_tmp_page_encrypt(page_no, s, d) + : fil_space_encrypt(space, page_no, s, d); slot->out_buf= d= tmp; @@ -984,14 +929,13 @@ not_compressed: buf_tmp_reserve_compression_buf(slot); byte *tmp= slot->comp_buf; ulint len= fil_page_compress(s, tmp, space->flags, - fil_space_get_block_size(space, - bpage->id.page_no()), + fil_space_get_block_size(space, page_no), encrypted); if (!len) goto not_compressed; - bpage->real_size= len; + *size= len; if (full_crc32) { @@ -1011,7 +955,7 @@ not_compressed: ut_d(fil_page_type_validate(space, tmp)); if (encrypted) - tmp = fil_space_encrypt(space, bpage->id.page_no(), tmp, d); + tmp = fil_space_encrypt(space, page_no, tmp, d); if (full_crc32) { @@ -1034,369 +978,389 @@ not_compressed: This function also resets the IO_FIX to IO_NONE and making the page status as NORMAL. It initiates the write to the file only after releasing the page from flush list and its associated mutex. -@param[in,out] bpage freed buffer page -@param[in] space tablespace object of the freed page */ -static void buf_flush_freed_page(buf_page_t *bpage, fil_space_t *space) +@param[in,out] bpage freed buffer page */ +static void buf_release_freed_page(buf_page_t *bpage) { - ut_ad(buf_page_in_file(bpage)); - const bool uncompressed= buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE; - BPageMutex *block_mutex= uncompressed - ? &reinterpret_cast(bpage)->mutex - : &buf_pool.zip_mutex; - + ut_ad(bpage->in_file()); + const bool uncompressed= bpage->state() == BUF_BLOCK_FILE_PAGE; mutex_enter(&buf_pool.mutex); - mutex_enter(block_mutex); - - buf_page_set_io_fix(bpage, BUF_IO_NONE); + bpage->set_io_fix(BUF_IO_NONE); bpage->status= buf_page_t::NORMAL; - buf_flush_write_complete(bpage, false); + buf_flush_remove(bpage); if (uncompressed) rw_lock_sx_unlock_gen(&reinterpret_cast(bpage)->lock, - BUF_IO_WRITE); + BUF_IO_WRITE); - buf_pool.stat.n_pages_written++; + buf_LRU_free_page(bpage, true); mutex_exit(&buf_pool.mutex); - const page_id_t page_id(bpage->id); - const auto zip_size= bpage->zip_size(); - mutex_exit(block_mutex); +} +/** Write a flushable page from buf_pool to a file. +buf_pool.mutex must be held. +@param bpage buffer control block +@param flush_type type of flush +@param space tablespace (or nullptr if not known) +@param sync whether this is a synchronous request + (only for flush_type=SINGLE_PAGE) +@return whether the page was flushed and buf_pool.mutex was released */ +bool buf_flush_page(buf_page_t *bpage, IORequest::flush_t flush_type, + fil_space_t *space, bool sync) +{ + ut_ad(bpage->in_file()); + ut_ad(bpage->ready_for_flush()); + ut_ad(!sync || flush_type == IORequest::SINGLE_PAGE); + ut_ad(mutex_own(&buf_pool.mutex)); + + rw_lock_t *rw_lock; + bool no_fix_count= bpage->buf_fix_count() == 0; + + if (bpage->state() != BUF_BLOCK_FILE_PAGE) + rw_lock= nullptr; + else if (!(no_fix_count || flush_type == IORequest::FLUSH_LIST) || + (!no_fix_count && srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP && + fsp_is_system_temporary(bpage->id().space()))) + /* This is a heuristic, to avoid expensive SX attempts. */ + /* For table residing in temporary tablespace sync is done + using IO_FIX and so before scheduling for flush ensure that + page is not fixed. */ + return false; + else + { + rw_lock= &reinterpret_cast(bpage)->lock; + if (flush_type != IORequest::FLUSH_LIST && + !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) + return false; + } + + /* We are committed to flushing by the time we get here */ + bpage->set_io_fix(BUF_IO_WRITE); + mutex_exit(&buf_pool.mutex); + + if (flush_type == IORequest::FLUSH_LIST && rw_lock && + !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) + { + if (!fsp_is_system_temporary(bpage->id().space())) + /* Avoid a potential deadlock with the doublewrite buffer, + which might be holding another buf_block_t::lock. */ + buf_dblwr_flush_buffered_writes(); + else + os_aio_wait_until_no_pending_writes(); + + rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE); + } + + /* We are holding rw_lock = buf_block_t::lock in SX mode except if + this is a ROW_FORMAT=COMPRESSED page whose uncompressed page frame + has been evicted from the buffer pool. + + Apart from possible rw_lock protection, bpage is also protected by + io_fix and oldest_modification()!=0. Thus, it cannot be relocated in + the buffer pool or removed from flush_list or LRU_list. */ +#if 0 /* rw_lock_own() does not hold because we passed BUF_IO_WRITE above. */ + ut_ad(!rw_lock || rw_lock_own(rw_lock, RW_LOCK_SX)); +#endif + + const fil_space_t * const provided_space= space; + if (!space) + { + space= fil_space_acquire_for_io(bpage->id().space()); + if (UNIV_UNLIKELY(!space)) + { + mutex_enter(&buf_pool.mutex); + bpage->status= buf_page_t::NORMAL; + bpage->set_io_fix(BUF_IO_NONE); + if (rw_lock) + rw_lock_sx_unlock_gen(rw_lock, BUF_IO_WRITE); + return false; + } + } + ut_ad((space->purpose == FIL_TYPE_TEMPORARY) == + (space == fil_system.temp_space)); + + const bool full_crc32= space->full_crc32(); + + DBUG_PRINT("ib_buf", ("flush %s %u page %u:%u", + sync ? "sync" : "async", (unsigned) flush_type, + bpage->id().space(), bpage->id().page_no())); + ut_ad(!mutex_own(&buf_pool.mutex)); + ut_ad(!mutex_own(&buf_pool.flush_list_mutex)); + ut_ad(bpage->io_fix() == BUF_IO_WRITE); + ut_ad(bpage->oldest_modification()); + ut_ad(bpage->state() == + (rw_lock ? BUF_BLOCK_FILE_PAGE : BUF_BLOCK_ZIP_PAGE)); + + /* Because bpage->status can only be changed while buf_block_t + exists, it cannot be modified for ROW_FORMAT=COMPRESSED pages + without first allocating the uncompressed page frame. Such + allocation cannot be completed due to our io_fix. So, bpage->status + is protected even if !rw_lock. */ + const auto status= bpage->status; + + if (status != buf_page_t::FREED) + { + switch (buf_pool.n_flush[flush_type]++) { + case 0: + os_event_reset(buf_pool.no_flush[flush_type]); + break; +#ifdef UNIV_DEBUG + case ULINT_UNDEFINED: + ut_error; + break; +#endif + } + } + + page_t *frame= bpage->zip.data; + size_t size, orig_size; + + if (UNIV_UNLIKELY(!rw_lock)) /* ROW_FORMAT=COMPRESSED */ + { + ut_ad(!space->full_crc32()); + ut_ad(!space->is_compressed()); /* not page_compressed */ + orig_size= size= bpage->zip_size(); + if (status != buf_page_t::FREED) + { + buf_flush_update_zip_checksum(frame, orig_size); + frame= buf_page_encrypt(space, bpage, frame, &size); + } + ut_ad(size == bpage->zip_size()); + } + else + { + buf_block_t *block= reinterpret_cast(bpage); + byte *page= block->frame; + orig_size= size= block->physical_size(); + + if (status != buf_page_t::FREED) + { + if (full_crc32) + { + /* innodb_checksum_algorithm=full_crc32 is not implemented for + ROW_FORMAT=COMPRESSED pages. */ + ut_ad(!frame); + page= buf_page_encrypt(space, bpage, page, &size); + } + + buf_flush_init_for_writing(block, page, frame ? &bpage->zip : nullptr, + full_crc32); + + if (!full_crc32) + page= buf_page_encrypt(space, bpage, frame ? frame : page, &size); + } + + frame= page; + } + + if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE)) + { + const lsn_t lsn= mach_read_from_8(frame + FIL_PAGE_LSN); + ut_ad(lsn); + ut_ad(lsn >= bpage->oldest_modification()); + ut_ad(!srv_read_only_mode); + log_write_up_to(lsn, true); + } + else + ut_ad(space->atomic_write_supported); + + bool use_doublewrite; + IORequest request(IORequest::WRITE, bpage, flush_type); + + ut_ad(status == bpage->status); + + switch (status) { + default: + ut_ad(status == buf_page_t::FREED); + buf_release_freed_page(bpage); + goto done; + case buf_page_t::NORMAL: + use_doublewrite= space->use_doublewrite(); + + if (use_doublewrite) + { + ut_ad(!srv_read_only_mode); + if (flush_type == IORequest::SINGLE_PAGE) + buf_dblwr->write_single_page(bpage, sync, size); + else + buf_dblwr->add_to_batch(bpage, flush_type, size); + break; + } + /* fall through */ + case buf_page_t::INIT_ON_FLUSH: + use_doublewrite= false; + if (size != orig_size) + request.set_punch_hole(); + /* FIXME: pass space to fil_io() */ + fil_io_t fio= fil_io(request, sync, bpage->id(), bpage->zip_size(), 0, + bpage->physical_size(), frame, bpage); + ut_ad(!fio.node || fio.node->space == space); + if (fio.node && sync) + fio.node->space->release_for_io(); + } + + if (sync) + { + ut_ad(bpage->io_fix() == BUF_IO_WRITE); + + /* When flushing single page synchronously, we flush the changes + only for the tablespace we are working on. */ + if (space->purpose != FIL_TYPE_TEMPORARY) + fil_flush(space); + + if (size != orig_size && space->punch_hole) + request.set_punch_hole(); + buf_page_write_complete(bpage, request, use_doublewrite, true/*evict*/); + } + +done: + if (!provided_space) + space->release_for_io(); + /* Increment the I/O operation count used for selecting LRU policy. */ + buf_LRU_stat_inc_io(); + return true; +} + +/** Check whether a page can be flushed from the buf_pool. +@param id page identifier +@param flush LRU or FLUSH_LIST +@return whether the page can be flushed */ +static bool buf_flush_check_neighbor(const page_id_t id, + IORequest::flush_t flush) +{ + ut_ad(flush == IORequest::LRU || flush == IORequest::FLUSH_LIST); + ut_ad(mutex_own(&buf_pool.mutex)); + + buf_page_t *bpage= buf_pool.page_hash_get_low(id, id.fold()); + + if (!bpage || buf_pool.watch_is_sentinel(*bpage)) + return false; + + /* We avoid flushing 'non-old' blocks in an LRU flush, because the + flushed blocks are soon freed */ + + return (flush != IORequest::LRU || bpage->is_old()) && + bpage->ready_for_flush(); +} + +/** Check which neighbors of a page can be flushed from the buf_pool. +@param space tablespace +@param id page identifier of a dirty page +@param flush LRU or FLUSH_LIST +@return last page number that can be flushed */ +static page_id_t buf_flush_check_neighbors(const fil_space_t &space, + page_id_t &id, + IORequest::flush_t flush) +{ + ut_ad(id.page_no() < space.size); + ut_ad(flush == IORequest::LRU || flush == IORequest::FLUSH_LIST); + /* When flushed, dirty blocks are searched in neighborhoods of this + size, and flushed along with the original page. */ + const ulint s= buf_pool.curr_size / 16; + const uint32_t read_ahead= buf_pool.read_ahead_area; + const uint32_t buf_flush_area= read_ahead > s + ? static_cast(s) : read_ahead; + page_id_t low= id - (id.page_no() % buf_flush_area); + page_id_t high= low + buf_flush_area; + high.set_page_no(std::min(high.page_no(), + static_cast(space.size - 1))); + + /* Determine the contiguous dirty area around id. */ + const ulint id_fold= id.fold(); + + mutex_enter(&buf_pool.mutex); + + if (id > low) + { + ulint fold= id_fold; + for (page_id_t i= id - 1;; --i) + { + fold--; + ut_ad(i.fold() == fold); + if (!buf_flush_check_neighbor(i, flush)) + { + low= i + 1; + break; + } + if (i == low) + break; + } + } + + page_id_t i= id; + id= low; + ulint fold= id_fold; + while (++i < high) + { + ++fold; + ut_ad(i.fold() == fold); + if (!buf_flush_check_neighbor(i, flush)) + break; + } + + mutex_exit(&buf_pool.mutex); + return i; +} + +/** Write punch-hole or zeroes of the freed ranges when +innodb_immediate_scrub_data_uncompressed from the freed ranges. +@param[in] space tablespace which contains freed ranges +@param[in] freed_ranges freed ranges of the page to be flushed */ +static void buf_flush_freed_pages(fil_space_t *space) +{ + ut_ad(space != NULL); + if (!srv_immediate_scrub_data_uncompressed && !space->is_compressed()) + return; + lsn_t flush_to_disk_lsn= log_sys.get_flushed_lsn(); + + std::unique_lock freed_lock(space->freed_range_mutex); + if (space->freed_ranges.empty() + || flush_to_disk_lsn < space->get_last_freed_lsn()) + { + freed_lock.unlock(); + return; + } + + range_set freed_ranges= std::move(space->freed_ranges); + freed_lock.unlock(); const bool punch_hole= #if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) space->is_compressed() || #endif false; - ut_ad(space->id == page_id.space()); - ut_ad(space->zip_size() == zip_size); + for (const auto &range : freed_ranges) + { + ulint page_size= space->zip_size(); + if (!page_size) + page_size= srv_page_size; - if (punch_hole || srv_immediate_scrub_data_uncompressed) - fil_io(IORequestWrite, punch_hole, page_id, zip_size, 0, - zip_size ? zip_size : srv_page_size, - const_cast(field_ref_zero), nullptr, false, punch_hole); - - space->release_for_io(); + if (punch_hole) + { + const auto len= (range.last - range.first + 1) * page_size; + const page_id_t page_id(space->id, range.first); + fil_io_t fio= fil_io(IORequestWrite, true, page_id, space->zip_size(), + 0, len, nullptr, nullptr, false, true); + if (fio.node) + fio.node->space->release_for_io(); + } + else if (srv_immediate_scrub_data_uncompressed) + { + for (auto i= range.first; i <= range.last; i++) + { + const page_id_t page_id(space->id, i); + fil_io(IORequestWrite, false, page_id, space->zip_size(), 0, + space->zip_size() ? space->zip_size() : srv_page_size, + const_cast(field_ref_zero), nullptr, false, false); + } + } + buf_pool.stat.n_pages_written+= (range.last - range.first + 1); + } } -/********************************************************************//** -Does an asynchronous write of a buffer page. NOTE: when the -doublewrite buffer is used, we must call -buf_dblwr_flush_buffered_writes after we have posted a batch of -writes! */ -static -void -buf_flush_write_block_low( -/*======================*/ - buf_page_t* bpage, /*!< in: buffer block to write */ - buf_flush_t flush_type, /*!< in: type of flush */ - bool sync) /*!< in: true if sync IO request */ -{ - fil_space_t* space = fil_space_acquire_for_io(bpage->id.space()); - if (!space) { - return; - } - ut_ad(space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_IMPORT - || space->purpose == FIL_TYPE_TABLESPACE); - ut_ad((space->purpose == FIL_TYPE_TEMPORARY) - == (space == fil_system.temp_space)); - - page_t* frame = NULL; - const bool full_crc32 = space->full_crc32(); - - DBUG_PRINT("ib_buf", ("flush %s %u page %u:%u", - sync ? "sync" : "async", (unsigned) flush_type, - bpage->id.space(), bpage->id.page_no())); - - ut_ad(buf_page_in_file(bpage)); - - /* We are not holding buf_pool.mutex or block_mutex here. - Nevertheless, it is safe to access bpage, because it is - io_fixed and oldest_modification != 0. Thus, it cannot be - relocated in the buffer pool or removed from flush_list or - LRU_list. */ - ut_ad(!mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(&buf_pool.flush_list_mutex)); - ut_ad(!buf_page_get_mutex(bpage)->is_owned()); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE); - ut_ad(bpage->oldest_modification != 0); - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: /* The page should be dirty. */ - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - ut_error; - break; - case BUF_BLOCK_ZIP_DIRTY: - frame = bpage->zip.data; - ut_a(page_zip_verify_checksum(frame, bpage->zip_size())); - break; - case BUF_BLOCK_FILE_PAGE: - frame = bpage->zip.data; - if (!frame) { - frame = ((buf_block_t*) bpage)->frame; - } - - /* Skip the encryption and compression for the - freed page */ - if (bpage->status == buf_page_t::FREED) { - break; - } - - byte* page = reinterpret_cast(bpage)->frame; - - if (full_crc32) { - page = buf_page_encrypt(space, bpage, page); - frame = page; - } - - buf_flush_init_for_writing( - reinterpret_cast(bpage), page, - bpage->zip.data ? &bpage->zip : NULL, full_crc32); - break; - } - - if (!full_crc32) { - frame = buf_page_encrypt(space, bpage, frame); - } - - if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE)) { - const lsn_t lsn = mach_read_from_8(frame + FIL_PAGE_LSN); - ut_ad(lsn); - ut_ad(lsn >= bpage->oldest_modification); - ut_ad(!srv_read_only_mode); - log_write_up_to(lsn, true); - } else { - ut_ad(space->atomic_write_supported); - } - - if (bpage->status == buf_page_t::FREED) { - buf_flush_freed_page(bpage, space); - return; - } - - const bool use_doublewrite = bpage->status != buf_page_t::INIT_ON_FLUSH - && space->use_doublewrite(); - - if (!use_doublewrite) { - ulint type = IORequest::WRITE; - - IORequest request(type, bpage); - - /* TODO: pass the tablespace to fil_io() */ - fil_io(request, - sync, bpage->id, bpage->zip_size(), 0, - bpage->physical_size(), - frame, bpage); - } else { - ut_ad(!srv_read_only_mode); - - if (flush_type == BUF_FLUSH_SINGLE_PAGE) { - buf_dblwr_write_single_page(bpage, sync); - } else { - ut_ad(!sync); - buf_dblwr_add_to_batch(bpage); - } - } - - /* When doing single page flushing the IO is done synchronously - and we flush the changes to disk only for the tablespace we - are working on. */ - if (sync) { - ut_ad(flush_type == BUF_FLUSH_SINGLE_PAGE); - if (space->purpose != FIL_TYPE_TEMPORARY) { - fil_flush(space); - } - - /* The tablespace could already have been dropped, - because fil_io(request, sync) would already have - decremented the node->n_pending. However, - buf_page_io_complete() only needs to look up the - tablespace during read requests, not during writes. */ - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE); -#ifdef UNIV_DEBUG - dberr_t err = -#endif - /* true means we want to evict this page from the - LRU list as well. */ - buf_page_io_complete(bpage, use_doublewrite, true); - - ut_ad(err == DB_SUCCESS); - } - - space->release_for_io(); - - /* Increment the counter of I/O operations used - for selecting LRU policy. */ - buf_LRU_stat_inc_io(); -} - -/** Write a flushable page asynchronously from the buffer pool to a file. -NOTE: 1. in simulated aio we must call os_aio_simulated_wake_handler_threads -after we have posted a batch of writes! 2. buf_page_get_mutex(bpage) must be -held upon entering this function. The LRU list mutex must be held if flush_type -== BUF_FLUSH_SINGLE_PAGE. Both mutexes will be released by this function if it -returns true. -@param[in] bpage buffer control block -@param[in] flush_type type of flush -@param[in] sync true if sync IO request -@return whether the page was flushed */ -bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync) -{ - BPageMutex* block_mutex; - - ut_ad(flush_type < BUF_FLUSH_N_TYPES); - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_in_file(bpage)); - ut_ad(!sync || flush_type == BUF_FLUSH_SINGLE_PAGE); - - block_mutex = buf_page_get_mutex(bpage); - ut_ad(mutex_own(block_mutex)); - - ut_ad(buf_flush_ready_for_flush(bpage, flush_type)); - - bool is_uncompressed = (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE); - ut_ad(is_uncompressed == (block_mutex != &buf_pool.zip_mutex)); - - rw_lock_t* rw_lock; - bool no_fix_count = bpage->buf_fix_count == 0; - - if (!is_uncompressed) { - rw_lock = NULL; - } else if (!(no_fix_count || flush_type == BUF_FLUSH_LIST) - || (!no_fix_count - && srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP - && fsp_is_system_temporary(bpage->id.space()))) { - /* This is a heuristic, to avoid expensive SX attempts. */ - /* For table residing in temporary tablespace sync is done - using IO_FIX and so before scheduling for flush ensure that - page is not fixed. */ - return false; - } else { - rw_lock = &reinterpret_cast(bpage)->lock; - if (flush_type != BUF_FLUSH_LIST - && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) { - return false; - } - } - - /* We are committed to flushing by the time we get here */ - - buf_page_set_io_fix(bpage, BUF_IO_WRITE); - - buf_page_set_flush_type(bpage, flush_type); - - if (buf_pool.n_flush[flush_type] == 0) { - os_event_reset(buf_pool.no_flush[flush_type]); - } - - ++buf_pool.n_flush[flush_type]; - ut_ad(buf_pool.n_flush[flush_type] != 0); - - mutex_exit(block_mutex); - - mutex_exit(&buf_pool.mutex); - - if (flush_type == BUF_FLUSH_LIST - && is_uncompressed - && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) { - - if (!fsp_is_system_temporary(bpage->id.space())) { - /* avoiding deadlock possibility involves - doublewrite buffer, should flush it, because - it might hold the another block->lock. */ - buf_dblwr_flush_buffered_writes(); - } else { - buf_dblwr_sync_datafiles(); - } - - rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE); - } - - /* Even though bpage is not protected by any mutex at this - point, it is safe to access bpage, because it is io_fixed and - oldest_modification != 0. Thus, it cannot be relocated in the - buffer pool or removed from flush_list or LRU_list. */ - - buf_flush_write_block_low(bpage, flush_type, sync); - return true; -} - -# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG -/** Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: block and LRU list mutexes must be held upon entering this function, and -they will be released by this function after flushing. This is loosely based on -buf_flush_batch() and buf_flush_page(). -@param[in,out] block buffer control block -@return whether the page was flushed and the mutex released */ -bool buf_flush_page_try(buf_block_t* block) -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(buf_page_mutex_own(block)); - - if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_SINGLE_PAGE)) { - return false; - } - - /* The following call will release the buf_pool and block mutex. */ - return buf_flush_page(&block->page, BUF_FLUSH_SINGLE_PAGE, true); -} -# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ - -/** Check the page is in buffer pool and can be flushed. +/** Flushes to disk all flushable pages within the flush area +and also write zeroes or punch the hole for the freed ranges of pages. @param[in] page_id page id -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST -@return true if the page can be flushed. */ -static -bool -buf_flush_check_neighbor( - const page_id_t page_id, - buf_flush_t flush_type) -{ - buf_page_t* bpage; - bool ret; - - ut_ad(flush_type == BUF_FLUSH_LRU - || flush_type == BUF_FLUSH_LIST); - - mutex_enter(&buf_pool.mutex); - - bpage = buf_page_hash_get(page_id); - - if (!bpage) { - - mutex_exit(&buf_pool.mutex); - return(false); - } - - ut_a(buf_page_in_file(bpage)); - - /* We avoid flushing 'non-old' blocks in an LRU flush, - because the flushed blocks are soon freed */ - - ret = false; - if (flush_type != BUF_FLUSH_LRU || buf_page_is_old(bpage)) { - BPageMutex* block_mutex = buf_page_get_mutex(bpage); - - mutex_enter(block_mutex); - if (buf_flush_ready_for_flush(bpage, flush_type)) { - ret = true; - } - mutex_exit(block_mutex); - } - mutex_exit(&buf_pool.mutex); - - return(ret); -} - -/** Flushes to disk all flushable pages within the flush area. -@param[in] page_id page id -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST +@param[in] flush LRU or FLUSH_LIST @param[in] n_flushed number of pages flushed so far in this batch @param[in] n_to_flush maximum number of pages we are allowed to flush @return number of pages flushed */ @@ -1404,86 +1368,30 @@ static ulint buf_flush_try_neighbors( const page_id_t page_id, - buf_flush_t flush_type, + IORequest::flush_t flush, ulint n_flushed, ulint n_to_flush) { - ulint i; - ulint low; - ulint high; ulint count = 0; - ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); + ut_ad(flush == IORequest::LRU || flush == IORequest::FLUSH_LIST); fil_space_t* space = fil_space_acquire_for_io(page_id.space()); if (!space) { return 0; } - if (UT_LIST_GET_LEN(buf_pool.LRU) < BUF_LRU_OLD_MIN_LEN - || !srv_flush_neighbors || !space->is_rotational()) { - /* If there is little space or neighbor flushing is - not enabled then just flush the victim. */ - low = page_id.page_no(); - high = page_id.page_no() + 1; - } else { - /* When flushed, dirty blocks are searched in - neighborhoods of this size, and flushed along with the - original page. */ + /* Flush the freed ranges while flushing the neighbors */ + buf_flush_freed_pages(space); - ulint buf_flush_area; + page_id_t id = page_id; + page_id_t high = (srv_flush_neighbors != 1 + || UT_LIST_GET_LEN(buf_pool.LRU) + < BUF_LRU_OLD_MIN_LEN + || !space->is_rotational()) + ? id + 1 /* Flush the minimum. */ + : buf_flush_check_neighbors(*space, id, flush); - buf_flush_area = ut_min( - buf_pool.read_ahead_area, - buf_pool.curr_size / 16); - - low = (page_id.page_no() / buf_flush_area) * buf_flush_area; - high = (page_id.page_no() / buf_flush_area + 1) * buf_flush_area; - - if (srv_flush_neighbors == 1) { - /* adjust 'low' and 'high' to limit - for contiguous dirty area */ - if (page_id.page_no() > low) { - for (i = page_id.page_no() - 1; i >= low; i--) { - if (!buf_flush_check_neighbor( - page_id_t(page_id.space(), i), - flush_type)) { - - break; - } - - if (i == low) { - /* Avoid overwrap when low == 0 - and calling - buf_flush_check_neighbor() with - i == (ulint) -1 */ - i--; - break; - } - } - low = i + 1; - } - - for (i = page_id.page_no() + 1; - i < high - && buf_flush_check_neighbor( - page_id_t(page_id.space(), i), - flush_type); - i++) { - /* do nothing */ - } - high = i; - } - } - - if (high > space->size) { - high = space->size; - } - - DBUG_PRINT("ib_buf", ("flush %u:%u..%u", - page_id.space(), - (unsigned) low, (unsigned) high)); - - for (ulint i = low; i < high; i++) { + for (; id < high; ++id) { buf_page_t* bpage; if ((count + n_flushed) >= n_to_flush) { @@ -1494,54 +1402,36 @@ buf_flush_try_neighbors( are flushing has not been flushed yet then we'll try to flush the victim that we selected originally. */ - if (i <= page_id.page_no()) { - i = page_id.page_no(); + if (id <= page_id) { + id = page_id; } else { break; } } - const page_id_t cur_page_id(page_id.space(), i); + const ulint fold = id.fold(); mutex_enter(&buf_pool.mutex); - bpage = buf_page_hash_get(cur_page_id); + bpage = buf_pool.page_hash_get_low(id, fold); if (bpage == NULL) { mutex_exit(&buf_pool.mutex); continue; } - ut_a(buf_page_in_file(bpage)); + ut_a(bpage->in_file()); /* We avoid flushing 'non-old' blocks in an LRU flush, because the flushed blocks are soon freed */ - if (flush_type != BUF_FLUSH_LRU - || i == page_id.page_no() - || buf_page_is_old(bpage)) { - - BPageMutex* block_mutex = buf_page_get_mutex(bpage); - - mutex_enter(block_mutex); - - if (buf_flush_ready_for_flush(bpage, flush_type) - && (i == page_id.page_no() - || bpage->buf_fix_count == 0)) { - - /* We also try to flush those - neighbors != offset */ - - if (buf_flush_page(bpage, flush_type, false)) { - ++count; - } else { - mutex_exit(block_mutex); - mutex_exit(&buf_pool.mutex); - } - - continue; - } else { - mutex_exit(block_mutex); + if (flush != IORequest::LRU + || id == page_id || bpage->is_old()) { + if (bpage->ready_for_flush() + && (id == page_id || bpage->buf_fix_count() == 0) + && buf_flush_page(bpage, flush, space, false)) { + ++count; + continue; } } mutex_exit(&buf_pool.mutex); @@ -1560,56 +1450,6 @@ buf_flush_try_neighbors( return(count); } -/** Check if the block is modified and ready for flushing. -If the the block is ready to flush then flush the page and try o flush -its neighbors. -@param[in] bpage buffer control block, -must be buf_page_in_file(bpage) -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST -@param[in] n_to_flush number of pages to flush -@param[in,out] count number of pages flushed -@return TRUE if buf_pool mutex was released during this function. -This does not guarantee that some pages were written as well. -Number of pages written are incremented to the count. */ -static -bool -buf_flush_page_and_try_neighbors( - buf_page_t* bpage, - buf_flush_t flush_type, - ulint n_to_flush, - ulint* count) -{ - ut_ad(mutex_own(&buf_pool.mutex)); - - bool flushed; - BPageMutex* block_mutex = buf_page_get_mutex(bpage); - - mutex_enter(block_mutex); - - ut_a(buf_page_in_file(bpage)); - - if (buf_flush_ready_for_flush(bpage, flush_type)) { - const page_id_t page_id = bpage->id; - - mutex_exit(block_mutex); - mutex_exit(&buf_pool.mutex); - - /* Try to flush also all the neighbors */ - *count += buf_flush_try_neighbors( - page_id, flush_type, *count, n_to_flush); - - mutex_enter(&buf_pool.mutex); - flushed = true; - } else { - mutex_exit(block_mutex); - flushed = false; - } - - ut_ad(mutex_own(&buf_pool.mutex)); - - return(flushed); -} - /*******************************************************************//** This utility moves the uncompressed frames of pages to the free list. Note that this function does not actually flush any data to disk. It @@ -1642,14 +1482,11 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max) released and reacquired */ ++count; block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); - + free_len = UT_LIST_GET_LEN(buf_pool.free); + lru_len = UT_LIST_GET_LEN(buf_pool.unzip_LRU); } else { - block = UT_LIST_GET_PREV(unzip_LRU, block); } - - free_len = UT_LIST_GET_LEN(buf_pool.free); - lru_len = UT_LIST_GET_LEN(buf_pool.unzip_LRU); } ut_ad(mutex_own(&buf_pool.mutex)); @@ -1671,90 +1508,67 @@ The calling thread is not allowed to own any latches on pages! @param[in] max desired number of blocks to make available in the free list (best effort; not guaranteed) @param[out] n counts of flushed and evicted pages */ -static void buf_flush_LRU_list_batch(ulint max, flush_counters_t* n) +static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) { - buf_page_t* bpage; - ulint scanned = 0; - ulint free_len = UT_LIST_GET_LEN(buf_pool.free); - ulint lru_len = UT_LIST_GET_LEN(buf_pool.LRU); - ulint withdraw_depth = 0; + ulint scanned= 0; + ulint free_limit= srv_LRU_scan_depth; + n->flushed = 0; + n->evicted = 0; + n->unzip_LRU_evicted = 0; + ut_ad(mutex_own(&buf_pool.mutex)); + if (buf_pool.withdraw_target && buf_pool.curr_size < buf_pool.old_size) + free_limit+= buf_pool.withdraw_target - UT_LIST_GET_LEN(buf_pool.withdraw); - n->flushed = 0; - n->evicted = 0; - n->unzip_LRU_evicted = 0; - ut_ad(mutex_own(&buf_pool.mutex)); - if (buf_pool.curr_size < buf_pool.old_size - && buf_pool.withdraw_target > 0) { - withdraw_depth = buf_pool.withdraw_target - - UT_LIST_GET_LEN(buf_pool.withdraw); - } + for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.LRU); + bpage && n->flushed + n->evicted < max && + UT_LIST_GET_LEN(buf_pool.LRU) > BUF_LRU_MIN_LEN && + UT_LIST_GET_LEN(buf_pool.free) < free_limit; + ++scanned, bpage= buf_pool.lru_hp.get()) + { + buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); + buf_pool.lru_hp.set(prev); - for (bpage = UT_LIST_GET_LAST(buf_pool.LRU); - bpage != NULL && n->flushed + n->evicted < max - && free_len < srv_LRU_scan_depth + withdraw_depth - && lru_len > BUF_LRU_MIN_LEN; - ++scanned, - bpage = buf_pool.lru_hp.get()) { + if (bpage->ready_for_replace()) + { + /* block is ready for eviction i.e., it is clean and is not + IO-fixed or buffer fixed. */ + if (buf_LRU_free_page(bpage, true)) + ++n->evicted; + } + else if (bpage->ready_for_flush()) + { + /* Block is ready for flush. Dispatch an IO request. The IO + helper thread will put it on free list in IO completion routine. */ + const page_id_t page_id(bpage->id()); + mutex_exit(&buf_pool.mutex); + n->flushed+= buf_flush_try_neighbors(page_id, IORequest::LRU, n->flushed, + max); + mutex_enter(&buf_pool.mutex); + } + else + /* Can't evict or dispatch this block. Go to previous. */ + ut_ad(buf_pool.lru_hp.is_hp(prev)); + } - buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); - buf_pool.lru_hp.set(prev); + buf_pool.lru_hp.set(nullptr); - BPageMutex* block_mutex = buf_page_get_mutex(bpage); + /* We keep track of all flushes happening as part of LRU flush. When + estimating the desired rate at which flush_list should be flushed, + we factor in this value. */ + buf_lru_flush_page_count+= n->flushed; - mutex_enter(block_mutex); + ut_ad(mutex_own(&buf_pool.mutex)); - if (buf_flush_ready_for_replace(bpage)) { - /* block is ready for eviction i.e., it is - clean and is not IO-fixed or buffer fixed. */ - mutex_exit(block_mutex); - if (buf_LRU_free_page(bpage, true)) { - ++n->evicted; - } - } else if (buf_flush_ready_for_flush(bpage, BUF_FLUSH_LRU)) { - /* Block is ready for flush. Dispatch an IO - request. The IO helper thread will put it on - free list in IO completion routine. */ - mutex_exit(block_mutex); - buf_flush_page_and_try_neighbors( - bpage, BUF_FLUSH_LRU, max, &n->flushed); - } else { - /* Can't evict or dispatch this block. Go to - previous. */ - ut_ad(buf_pool.lru_hp.is_hp(prev)); - mutex_exit(block_mutex); - } - - ut_ad(!mutex_own(block_mutex)); - ut_ad(mutex_own(&buf_pool.mutex)); - - free_len = UT_LIST_GET_LEN(buf_pool.free); - lru_len = UT_LIST_GET_LEN(buf_pool.LRU); - } - - buf_pool.lru_hp.set(NULL); - - /* We keep track of all flushes happening as part of LRU - flush. When estimating the desired rate at which flush_list - should be flushed, we factor in this value. */ - buf_lru_flush_page_count += n->flushed; - - ut_ad(mutex_own(&buf_pool.mutex)); - - if (n->evicted) { - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE, - MONITOR_LRU_BATCH_EVICT_COUNT, - MONITOR_LRU_BATCH_EVICT_PAGES, - n->evicted); - } - - if (scanned) { - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_LRU_BATCH_SCANNED, - MONITOR_LRU_BATCH_SCANNED_NUM_CALL, - MONITOR_LRU_BATCH_SCANNED_PER_CALL, - scanned); - } + if (n->evicted) + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE, + MONITOR_LRU_BATCH_EVICT_COUNT, + MONITOR_LRU_BATCH_EVICT_PAGES, + n->evicted); + if (scanned) + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_LRU_BATCH_SCANNED, + MONITOR_LRU_BATCH_SCANNED_NUM_CALL, + MONITOR_LRU_BATCH_SCANNED_PER_CALL, + scanned); } /** Flush and move pages from LRU or unzip_LRU list to the free list. @@ -1785,76 +1599,68 @@ The calling thread is not allowed to own any latches on pages! not guaranteed that the actual number is that big, though) @param[in] lsn_limit all blocks whose oldest_modification is smaller than this should be flushed (if their number does not exceed min_n) -@return number of blocks for which the write request was queued; -ULINT_UNDEFINED if there was a flush of the same type already -running */ +@return number of blocks for which the write request was queued */ static ulint buf_do_flush_list_batch(ulint min_n, lsn_t lsn_limit) { - ulint count = 0; - ulint scanned = 0; + ulint count= 0; + ulint scanned= 0; - ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(mutex_own(&buf_pool.mutex)); - /* Start from the end of the list looking for a suitable - block to be flushed. */ - mutex_enter(&buf_pool.flush_list_mutex); - ulint len = UT_LIST_GET_LEN(buf_pool.flush_list); + /* Start from the end of the list looking for a suitable block to be + flushed. */ + mutex_enter(&buf_pool.flush_list_mutex); + ulint len = UT_LIST_GET_LEN(buf_pool.flush_list); - /* In order not to degenerate this scan to O(n*n) we attempt - to preserve pointer of previous block in the flush list. To do - so we declare it a hazard pointer. Any thread working on the - flush list must check the hazard pointer and if it is removing - the same block then it must reset it. */ - for (buf_page_t* bpage = UT_LIST_GET_LAST(buf_pool.flush_list); - count < min_n && bpage != NULL && len > 0 - && bpage->oldest_modification < lsn_limit; - bpage = buf_pool.flush_hp.get(), - ++scanned) { + /* In order not to degenerate this scan to O(n*n) we attempt to + preserve pointer of previous block in the flush list. To do so we + declare it a hazard pointer. Any thread working on the flush list + must check the hazard pointer and if it is removing the same block + then it must reset it. */ + for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); + bpage && len && count < min_n; + bpage= buf_pool.flush_hp.get(), ++scanned, len--) + { + const lsn_t oldest_modification= bpage->oldest_modification(); + if (oldest_modification >= lsn_limit) + break; + ut_a(oldest_modification); - buf_page_t* prev; + buf_page_t *prev= UT_LIST_GET_PREV(list, bpage); + buf_pool.flush_hp.set(prev); + mutex_exit(&buf_pool.flush_list_mutex); - ut_a(bpage->oldest_modification > 0); - ut_ad(bpage->in_flush_list); + ut_ad(bpage->in_file()); + const bool flushed= bpage->ready_for_flush(); - prev = UT_LIST_GET_PREV(list, bpage); - buf_pool.flush_hp.set(prev); - mutex_exit(&buf_pool.flush_list_mutex); + if (flushed) + { + const page_id_t page_id(bpage->id()); + mutex_exit(&buf_pool.mutex); + count+= buf_flush_try_neighbors(page_id, IORequest::FLUSH_LIST, + count, min_n); + mutex_enter(&buf_pool.mutex); + } -#ifdef UNIV_DEBUG - bool flushed = -#endif /* UNIV_DEBUG */ - buf_flush_page_and_try_neighbors( - bpage, BUF_FLUSH_LIST, min_n, &count); + mutex_enter(&buf_pool.flush_list_mutex); + ut_ad(flushed || buf_pool.flush_hp.is_hp(prev)); + } - mutex_enter(&buf_pool.flush_list_mutex); + buf_pool.flush_hp.set(nullptr); + mutex_exit(&buf_pool.flush_list_mutex); - ut_ad(flushed || buf_pool.flush_hp.is_hp(prev)); - - --len; - } - - buf_pool.flush_hp.set(NULL); - mutex_exit(&buf_pool.flush_list_mutex); - - if (scanned) { - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_FLUSH_BATCH_SCANNED, - MONITOR_FLUSH_BATCH_SCANNED_NUM_CALL, - MONITOR_FLUSH_BATCH_SCANNED_PER_CALL, - scanned); - } - - if (count) { - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_FLUSH_BATCH_TOTAL_PAGE, - MONITOR_FLUSH_BATCH_COUNT, - MONITOR_FLUSH_BATCH_PAGES, - count); - } - - ut_ad(mutex_own(&buf_pool.mutex)); - - return(count); + if (scanned) + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BATCH_SCANNED, + MONITOR_FLUSH_BATCH_SCANNED_NUM_CALL, + MONITOR_FLUSH_BATCH_SCANNED_PER_CALL, + scanned); + if (count) + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BATCH_TOTAL_PAGE, + MONITOR_FLUSH_BATCH_COUNT, + MONITOR_FLUSH_BATCH_PAGES, + count); + ut_ad(mutex_own(&buf_pool.mutex)); + return count; } /** This utility flushes dirty blocks from the end of the LRU list or @@ -1863,45 +1669,39 @@ NOTE 1: in the case of an LRU flush the calling thread may own latches to pages: to avoid deadlocks, this function must be written so that it cannot end up waiting for these latches! NOTE 2: in the case of a flush list flush, the calling thread is not allowed to own any latches on pages! -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST; if -BUF_FLUSH_LIST, then the caller must not own any latches on pages +@param[in] lru true=LRU; false=FLUSH_LIST; +if !lru, then the caller must not own any latches on pages @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) -@param[in] lsn_limit in the case of BUF_FLUSH_LIST all blocks whose +@param[in] lsn_limit in the case of !lru all blocks whose @param[out] n counts of flushed and evicted pages oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored */ static void buf_flush_batch( - buf_flush_t flush_type, + bool lru, ulint min_n, lsn_t lsn_limit, flush_counters_t* n) { - ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); - ut_ad(flush_type == BUF_FLUSH_LRU - || !sync_check_iterate(dict_sync_check())); + ut_ad(lru || !sync_check_iterate(dict_sync_check())); mutex_enter(&buf_pool.mutex); /* Note: The buffer pool mutex is released and reacquired within the flush functions. */ - switch (flush_type) { - case BUF_FLUSH_LRU: + if (lru) { buf_do_LRU_batch(min_n, n); - break; - case BUF_FLUSH_LIST: + } else { n->flushed = buf_do_flush_list_batch(min_n, lsn_limit); n->evicted = 0; - break; - default: - ut_error; } mutex_exit(&buf_pool.mutex); - DBUG_LOG("ib_buf", "flush " << flush_type << " completed"); + DBUG_PRINT("ib_buf", + (lru ? "LRU flush completed" : "flush_list completed")); } /******************************************************************//** @@ -1925,101 +1725,84 @@ buf_flush_stats( } /** Start a buffer flush batch for LRU or flush list -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list @return whether the flush batch was started (was not already running) */ -static bool buf_flush_start(buf_flush_t flush_type) +static bool buf_flush_start(bool lru) { - ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); + IORequest::flush_t flush_type= lru ? IORequest::LRU : IORequest::FLUSH_LIST; + mutex_enter(&buf_pool.mutex); - mutex_enter(&buf_pool.mutex); + if (buf_pool.n_flush[flush_type] > 0 || buf_pool.init_flush[flush_type]) + { + /* There is already a flush batch of the same type running */ + mutex_exit(&buf_pool.mutex); + return false; + } - if (buf_pool.n_flush[flush_type] > 0 - || buf_pool.init_flush[flush_type] == TRUE) { - - /* There is already a flush batch of the same type running */ - - mutex_exit(&buf_pool.mutex); - - return(false); - } - - buf_pool.init_flush[flush_type] = TRUE; - - os_event_reset(buf_pool.no_flush[flush_type]); - - mutex_exit(&buf_pool.mutex); - - return(true); + buf_pool.init_flush[flush_type]= true; + os_event_reset(buf_pool.no_flush[flush_type]); + mutex_exit(&buf_pool.mutex); + return true; } /** End a buffer flush batch. -@param[in] flush_type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ -static void buf_flush_end(buf_flush_t flush_type) +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list */ +static void buf_flush_end(bool lru) { - mutex_enter(&buf_pool.mutex); + IORequest::flush_t flush_type= lru ? IORequest::LRU : IORequest::FLUSH_LIST; - buf_pool.init_flush[flush_type] = FALSE; + mutex_enter(&buf_pool.mutex); - buf_pool.try_LRU_scan = TRUE; + buf_pool.init_flush[flush_type]= false; + buf_pool.try_LRU_scan= true; - if (buf_pool.n_flush[flush_type] == 0) { + if (!buf_pool.n_flush[flush_type]) + /* The running flush batch has ended */ + os_event_set(buf_pool.no_flush[flush_type]); - /* The running flush batch has ended */ + mutex_exit(&buf_pool.mutex); - os_event_set(buf_pool.no_flush[flush_type]); - } - - mutex_exit(&buf_pool.mutex); - - if (!srv_read_only_mode) { - buf_dblwr_flush_buffered_writes(); - } + if (!srv_read_only_mode) + buf_dblwr_flush_buffered_writes(); } /** Wait until a flush batch ends. -@param[in] type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ -void buf_flush_wait_batch_end(buf_flush_t type) +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list */ +void buf_flush_wait_batch_end(bool lru) { - ut_ad(type == BUF_FLUSH_LRU || type == BUF_FLUSH_LIST); - thd_wait_begin(NULL, THD_WAIT_DISKIO); - os_event_wait(buf_pool.no_flush[type]); - thd_wait_end(NULL); + thd_wait_begin(nullptr, THD_WAIT_DISKIO); + os_event_wait(buf_pool.no_flush[lru + ? IORequest::LRU : IORequest::FLUSH_LIST]); + thd_wait_end(nullptr); } /** Do flushing batch of a given type. NOTE: The calling thread is not allowed to own any latches on pages! -@param[in] type flush type +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) -@param[in] lsn_limit in the case BUF_FLUSH_LIST all blocks whose +@param[in] lsn_limit if !lru, all blocks whose oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored @param[out] n_processed the number of pages which were processed is passed back to caller. Ignored if NULL @retval true if a batch was queued successfully. @retval false if another batch of same type was already running. */ -bool -buf_flush_do_batch( - buf_flush_t type, - ulint min_n, - lsn_t lsn_limit, - flush_counters_t* n) +bool buf_flush_do_batch(bool lru, ulint min_n, lsn_t lsn_limit, + flush_counters_t *n) { - ut_ad(type == BUF_FLUSH_LRU || type == BUF_FLUSH_LIST); + if (n) + n->flushed= 0; - if (n != NULL) { - n->flushed = 0; - } + if (!buf_flush_start(lru)) + return false; - if (!buf_flush_start(type)) { - return(false); - } + buf_flush_batch(lru, min_n, lsn_limit, n); + buf_flush_end(lru); - buf_flush_batch(type, min_n, lsn_limit, n); - buf_flush_end(type); - - return(true); + return true; } + /** Wait until a flush batch of the given lsn ends @param[in] new_oldest target oldest_modified_lsn to wait for */ void buf_flush_wait_flushed(lsn_t new_oldest) @@ -2032,18 +1815,17 @@ void buf_flush_wait_flushed(lsn_t new_oldest) mutex_enter(&buf_pool.flush_list_mutex); buf_page_t* bpage; - /* FIXME: Keep temporary tablespace pages in a separate flush list. We would only need to write out temporary pages if the page is about to be evicted from the buffer pool, and the page contents is still needed (the page has not been freed). */ for (bpage = UT_LIST_GET_LAST(buf_pool.flush_list); - bpage && fsp_is_system_temporary(bpage->id.space()); + bpage && fsp_is_system_temporary(bpage->id().space()); bpage = UT_LIST_GET_PREV(list, bpage)) { - ut_ad(bpage->in_flush_list); + ut_ad(bpage->oldest_modification()); } - lsn_t oldest = bpage ? bpage->oldest_modification : 0; + lsn_t oldest = bpage ? bpage->oldest_modification() : 0; mutex_exit(&buf_pool.flush_list_mutex); @@ -2062,7 +1844,7 @@ void buf_flush_wait_flushed(lsn_t new_oldest) NOTE: The calling thread is not allowed to own any latches on pages! @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) -@param[in] lsn_limit in the case BUF_FLUSH_LIST all blocks whose +@param[in] lsn_limit all blocks whose oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored @param[out] n_processed the number of pages which were processed is @@ -2073,8 +1855,7 @@ bool buf_flush_lists(ulint min_n, lsn_t lsn_limit, ulint *n_processed) { flush_counters_t n; - bool success = buf_flush_do_batch( - BUF_FLUSH_LIST, min_n, lsn_limit, &n); + bool success = buf_flush_do_batch(false, min_n, lsn_limit, &n); if (n.flushed) { buf_flush_stats(n.flushed, 0); @@ -2097,68 +1878,49 @@ is not fast enough to keep pace with the workload. @return true if success. */ bool buf_flush_single_page_from_LRU() { - ulint scanned; - buf_page_t* bpage; - ibool freed; + ulint scanned = 0; + bool freed = false; mutex_enter(&buf_pool.mutex); - for (bpage = buf_pool.single_scan_itr.start(), scanned = 0, - freed = false; - bpage != NULL; + for (buf_page_t* bpage = buf_pool.single_scan_itr.start(); bpage; ++scanned, bpage = buf_pool.single_scan_itr.get()) { ut_ad(mutex_own(&buf_pool.mutex)); buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); buf_pool.single_scan_itr.set(prev); - BPageMutex* block_mutex; - block_mutex = buf_page_get_mutex(bpage); + if (!bpage->ready_for_flush()) { // FIXME: ready_for_replace() + continue; + } - mutex_enter(block_mutex); - - if (buf_flush_ready_for_replace(bpage)) { + if (!bpage->buf_fix_count() + && buf_LRU_free_page(bpage, true)) { /* block is ready for eviction i.e., it is clean and is not IO-fixed or buffer fixed. */ - mutex_exit(block_mutex); - - if (buf_LRU_free_page(bpage, true)) { - mutex_exit(&buf_pool.mutex); - freed = true; - break; - } - - } else if (buf_flush_ready_for_flush( - bpage, BUF_FLUSH_SINGLE_PAGE)) { - + freed = true; + break; + } else { /* Block is ready for flush. Try and dispatch an IO request. We'll put it on free list in IO completion routine if it is not buffer fixed. The following call - will release the buffer pool and block mutex. + will release the buf_pool.mutex. Note: There is no guarantee that this page has actually been freed, only that it has been flushed to disk */ - freed = buf_flush_page(bpage, BUF_FLUSH_SINGLE_PAGE, - true); + freed = buf_flush_page(bpage, IORequest::SINGLE_PAGE, + nullptr, true); if (freed) { - break; + goto found; } - - mutex_exit(block_mutex); - } else { - mutex_exit(block_mutex); } - ut_ad(!mutex_own(block_mutex)); - } - if (!freed) { - /* Can't find a single flushable page. */ - ut_ad(!bpage); - mutex_exit(&buf_pool.mutex); } + mutex_exit(&buf_pool.mutex); +found: if (scanned) { MONITOR_INC_VALUE_CUMULATIVE( MONITOR_LRU_SINGLE_FLUSH_SCANNED, @@ -2207,7 +1969,7 @@ static ulint buf_flush_LRU_list() that can trigger an LRU flush at the same time. So, it is not possible that a batch triggered during last iteration is still running, */ - buf_flush_do_batch(BUF_FLUSH_LRU, scan_depth, 0, &n); + buf_flush_do_batch(true, scan_depth, 0, &n); return(n.flushed); } @@ -2215,13 +1977,8 @@ static ulint buf_flush_LRU_list() /** Wait for any possible LRU flushes to complete. */ void buf_flush_wait_LRU_batch_end() { - mutex_enter(&buf_pool.mutex); - bool wait = buf_pool.n_flush[BUF_FLUSH_LRU] - || buf_pool.init_flush[BUF_FLUSH_LRU]; - mutex_exit(&buf_pool.mutex); - if (wait) { - buf_flush_wait_batch_end(BUF_FLUSH_LRU); - } + if (buf_pool.n_flush[IORequest::LRU] || buf_pool.init_flush[IORequest::LRU]) + buf_flush_wait_batch_end(true); } /*********************************************************************//** @@ -2441,7 +2198,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in) sum_pages = 0; } - oldest_lsn = buf_pool_get_oldest_modification(); + oldest_lsn = buf_pool.get_oldest_modification(); ut_ad(oldest_lsn <= log_get_lsn()); @@ -2461,7 +2218,7 @@ page_cleaner_flush_pages_recommendation(ulint last_pages_in) for (buf_page_t* b = UT_LIST_GET_LAST(buf_pool.flush_list); b != NULL; b = UT_LIST_GET_PREV(list, b)) { - if (b->oldest_modification > target_lsn) { + if (b->oldest_modification() > target_lsn) { break; } ++pages_for_lsn; @@ -2559,7 +2316,7 @@ pc_sleep_if_needed( Requests for all slots to flush. @param min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big) -@param lsn_limit in the case BUF_FLUSH_LIST all blocks whose +@param lsn_limit in the case of buf_pool.flush_list all blocks whose oldest_modification is smaller than this should be flushed (if their number does not exceed min_n), otherwise ignored */ @@ -2638,7 +2395,7 @@ static ulint pc_flush_slot() list_tm = ut_time_ms(); page_cleaner.slot.succeeded_list = buf_flush_do_batch( - BUF_FLUSH_LIST, + false, page_cleaner.slot.n_pages_requested, page_cleaner.lsn_limit, &n); @@ -2790,25 +2547,18 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) break; } - switch (recv_sys.flush_type) { - case BUF_FLUSH_LRU: + if (recv_sys.flush_lru) { /* Flush pages from end of LRU if required */ pc_request(0, LSN_MAX); while (pc_flush_slot() > 0) {} pc_wait_finished(&n_flushed_lru, &n_flushed_list); - break; - - case BUF_FLUSH_LIST: + } else { /* Flush all pages */ do { pc_request(ULINT_MAX, LSN_MAX); while (pc_flush_slot() > 0) {} } while (!pc_wait_finished(&n_flushed_lru, &n_flushed_list)); - break; - - default: - ut_ad(0); } os_event_reset(recv_sys.flush_start); @@ -2828,7 +2578,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) ulint last_activity = srv_get_activity_count(); ulint last_pages = 0; - while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { + while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { ulint curr_time = ut_time_ms(); /* The page_cleaner skips sleep if the server is @@ -2845,7 +2595,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) ret_sleep = 0; } - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { break; } @@ -3014,7 +2764,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) ut_d(buf_flush_page_cleaner_disabled_loop()); } - ut_ad(srv_shutdown_state > 0); + ut_ad(srv_shutdown_state > SRV_SHUTDOWN_INITIATED); if (srv_fast_shutdown == 2 || srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { /* In very fast shutdown or when innodb failed to start, we @@ -3064,7 +2814,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) considering end of that batch as a finish of our final sweep and we'll come out of the loop leaving behind dirty pages in the flush_list */ - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); buf_flush_wait_LRU_batch_end(); bool success; @@ -3080,7 +2830,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) n_flushed = n_flushed_lru + n_flushed_list; - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); buf_flush_wait_LRU_batch_end(); } while (!success || n_flushed > 0); @@ -3136,7 +2886,7 @@ void buf_flush_sync() bool success; do { success = buf_flush_lists(ULINT_MAX, LSN_MAX, NULL); - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); } while (!success); } @@ -3155,13 +2905,13 @@ void buf_flush_request_force(lsn_t lsn_limit) os_event_set(buf_flush_event); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Functor to validate the flush list. */ struct Check { void operator()(const buf_page_t* elem) const { - ut_a(elem->in_flush_list); + ut_a(elem->oldest_modification()); } }; @@ -3185,17 +2935,15 @@ static void buf_flush_validate_low() } while (bpage != NULL) { - const lsn_t om = bpage->oldest_modification; - ut_ad(bpage->in_flush_list); - + const lsn_t om = bpage->oldest_modification(); /* A page in buf_pool.flush_list can be in BUF_BLOCK_REMOVE_HASH state. This happens when a page is in the middle of being relocated. In that case the original descriptor can have this state and still be in the flush list waiting to acquire the buf_pool.flush_list_mutex to complete the relocation. */ - ut_a(buf_page_in_file(bpage) - || buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH); + ut_a(bpage->in_file() + || bpage->state() == BUF_BLOCK_REMOVE_HASH); ut_a(om > 0); if (UNIV_LIKELY_NULL(buf_pool.flush_rbt)) { @@ -3211,7 +2959,7 @@ static void buf_flush_validate_low() bpage = UT_LIST_GET_NEXT(list, bpage); - ut_a(bpage == NULL || om >= bpage->oldest_modification); + ut_a(!bpage || om >= bpage->oldest_modification()); } /* By this time we must have exhausted the traversal of @@ -3226,5 +2974,4 @@ void buf_flush_validate() buf_flush_validate_low(); mutex_exit(&buf_pool.flush_list_mutex); } - -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 2ee0c02d964..41d1e40a730 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -125,37 +125,30 @@ least this many milliseconds ago. Not protected by any mutex or latch. */ uint buf_LRU_old_threshold_ms; /* @} */ -/******************************************************************//** -Takes a block out of the LRU list and page hash table. -If the block is compressed-only (BUF_BLOCK_ZIP_PAGE), +/** Remove bpage from buf_pool.LRU and buf_pool.page_hash. + +If bpage->state() == BUF_BLOCK_ZIP_PAGE && !bpage->oldest_modification(), the object will be freed. -The caller must hold buf_pool.mutex, the buf_page_get_mutex() mutex -and the appropriate hash_lock. This function will release the -buf_page_get_mutex() and the hash_lock. +@param bpage buffer block +@param id page identifier +@param hash_lock buf_pool.page_hash latch (will be released here) +@param zip whether bpage->zip of BUF_BLOCK_FILE_PAGE should be freed If a compressed page is freed other compressed pages may be relocated. @retval true if BUF_BLOCK_FILE_PAGE was removed from page_hash. The caller needs to free the page to the free list @retval false if BUF_BLOCK_ZIP_PAGE was removed from page_hash. In this case the block is already returned to the buddy allocator. */ -static MY_ATTRIBUTE((warn_unused_result)) -bool -buf_LRU_block_remove_hashed( -/*========================*/ - buf_page_t* bpage, /*!< in: block, must contain a file page and - be in a state where it can be freed; there - may or may not be a hash index to the page */ - bool zip); /*!< in: true if should remove also the - compressed page of an uncompressed page */ -/******************************************************************//** -Puts a file page whose has no hash index to the free list. */ -static -void -buf_LRU_block_free_hashed_page( -/*===========================*/ - buf_block_t* block); /*!< in: block, must contain a file page and - be in a state where it can be freed */ +static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id, + page_hash_latch *hash_lock, bool zip); + +/** Free a block to buf_pool */ +static void buf_LRU_block_free_hashed_page(buf_block_t *block) +{ + block->page.free_file_page(); + buf_LRU_block_free_non_file_page(block); +} /** Increase LRU size in bytes by the page size. @param[in] bpage control block */ @@ -210,157 +203,6 @@ bool buf_LRU_evict_from_unzip_LRU() } #ifdef BTR_CUR_HASH_ADAPT -/** Attempts to drop page hash index on a batch of pages belonging to a -particular space id. -@param[in] space_id space id -@param[in] arr array of page_no -@param[in] count number of entries in array */ -static -void -buf_LRU_drop_page_hash_batch(ulint space_id, const ulint* arr, ulint count) -{ - ut_ad(count <= BUF_LRU_DROP_SEARCH_SIZE); - - for (const ulint* const end = arr + count; arr != end; ) { - /* While our only caller - buf_LRU_drop_page_hash_for_tablespace() - is being executed for DROP TABLE or similar, - the table cannot be evicted from the buffer pool. */ - btr_search_drop_page_hash_when_freed( - page_id_t(space_id, *arr++)); - } -} - -/******************************************************************//** -When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page -hash index entries belonging to that table. This function tries to -do that in batch. Note that this is a 'best effort' attempt and does -not guarantee that ALL hash entries will be removed. -@param[in] id space id */ -static -void -buf_LRU_drop_page_hash_for_tablespace(ulint id) -{ - ulint* page_arr = static_cast(ut_malloc_nokey( - sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE)); - - ulint num_entries = 0; - - mutex_enter(&buf_pool.mutex); - -scan_again: - for (buf_page_t* bpage = UT_LIST_GET_LAST(buf_pool.LRU); - bpage != NULL; - /* No op */) { - - buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage); - - ut_a(buf_page_in_file(bpage)); - - if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE - || bpage->id.space() != id - || bpage->io_fix != BUF_IO_NONE) { - /* Compressed pages are never hashed. - Skip blocks of other tablespaces. - Skip I/O-fixed blocks (to be dealt with later). */ -next_page: - bpage = prev_bpage; - continue; - } - - buf_block_t* block = reinterpret_cast(bpage); - - mutex_enter(&block->mutex); - - /* This debug check uses a dirty read that could - theoretically cause false positives while - buf_pool.clear_hash_index() is executing. - (Other conflicting access paths to the adaptive hash - index should not be possible, because when a - tablespace is being discarded or dropped, there must - be no concurrect access to the contained tables.) */ - assert_block_ahi_valid(block); - - bool skip = bpage->buf_fix_count > 0 || !block->index; - - mutex_exit(&block->mutex); - - if (skip) { - /* Skip this block, because there are - no adaptive hash index entries - pointing to it, or because we cannot - drop them due to the buffer-fix. */ - goto next_page; - } - - /* Store the page number so that we can drop the hash - index in a batch later. */ - page_arr[num_entries] = bpage->id.page_no(); - ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE); - ++num_entries; - - if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) { - goto next_page; - } - - /* Array full. We release the buf_pool.mutex to obey - the latching order. */ - mutex_exit(&buf_pool.mutex); - - buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); - - num_entries = 0; - - mutex_enter(&buf_pool.mutex); - - /* Note that we released the buf_pool mutex above - after reading the prev_bpage during processing of a - page_hash_batch (i.e.: when the array was full). - Because prev_bpage could belong to a compressed-only - block, it may have been relocated, and thus the - pointer cannot be trusted. Because bpage is of type - buf_block_t, it is safe to dereference. - - bpage can change in the LRU list. This is OK because - this function is a 'best effort' to drop as many - search hash entries as possible and it does not - guarantee that ALL such entries will be dropped. */ - - /* If, however, bpage has been removed from LRU list - to the free list then we should restart the scan. - bpage->state is protected by buf_pool mutex. */ - if (bpage != NULL - && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { - - goto scan_again; - } - } - - mutex_exit(&buf_pool.mutex); - - /* Drop any remaining batch of search hashed pages. */ - buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); - ut_free(page_arr); -} - -/** Try to drop the adaptive hash index for a tablespace. -@param[in,out] table table -@return whether anything was dropped */ -bool buf_LRU_drop_page_hash_for_tablespace(dict_table_t* table) -{ - for (dict_index_t* index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - if (btr_search_info_get_ref_count(btr_search_get_info(index), - index)) { - buf_LRU_drop_page_hash_for_tablespace(table->space_id); - return true; - } - } - - return false; -} - /** While flushing (or removing dirty) pages from a tablespace we don't want to hog the CPU and resources. Release the buffer pool and block @@ -368,35 +210,30 @@ mutex and try to force a context switch. Then reacquire the same mutexes. The current page is "fixed" before the release of the mutexes and then "unfixed" again once we have reacquired the mutexes. @param[in,out] bpage current page */ -static void buf_flush_yield(buf_page_t* bpage) +static void buf_flush_yield(buf_page_t *bpage) { - BPageMutex* block_mutex; + mutex_exit(&buf_pool.flush_list_mutex); + ut_ad(bpage->oldest_modification()); + ut_ad(bpage->in_file()); + ut_ad(bpage->io_fix() == BUF_IO_NONE); + /** Make the block sticky, so that even after we release buf_pool.mutex: + (1) it cannot be removed from the buf_pool.flush_list + (2) bpage cannot be relocated in buf_pool + (3) bpage->in_LRU_list cannot change + However, bpage->LRU can change. */ + bpage->set_io_fix(BUF_IO_PIN); + mutex_exit(&buf_pool.mutex); - ut_ad(buf_page_in_file(bpage)); + /* Try and force a context switch. */ + os_thread_yield(); - block_mutex = buf_page_get_mutex(bpage); - - mutex_enter(block_mutex); - - /* "Fix" the block so that the position cannot be - changed after we release the buffer pool and - block mutexes. */ - buf_page_set_sticky(bpage); - - /* Now it is safe to release the buf_pool.mutex. */ - mutex_exit(&buf_pool.mutex); - - mutex_exit(block_mutex); - /* Try and force a context switch. */ - os_thread_yield(); - - mutex_enter(&buf_pool.mutex); - mutex_enter(block_mutex); - - /* "Unfix" the block now that we have both the - buffer pool and block mutex again. */ - buf_page_unset_sticky(bpage); - mutex_exit(block_mutex); + mutex_enter(&buf_pool.mutex); + bpage->io_unfix(); + mutex_enter(&buf_pool.flush_list_mutex); + /* Should not have been removed from the flush + list during the yield. However, this check is + not sufficient to catch a remove -> add. */ + ut_ad(bpage->oldest_modification()); } /******************************************************************//** @@ -419,23 +256,12 @@ buf_flush_try_yield( if (bpage != NULL && processed >= BUF_LRU_DROP_SEARCH_SIZE - && buf_page_get_io_fix(bpage) == BUF_IO_NONE) { + && bpage->io_fix() == BUF_IO_NONE) { - mutex_exit(&buf_pool.flush_list_mutex); - - /* Release the buffer pool and block mutex + /* Release the buf_pool.mutex to give the other threads a go. */ buf_flush_yield(bpage); - - mutex_enter(&buf_pool.flush_list_mutex); - - /* Should not have been removed from the flush - list during the yield. However, this check is - not sufficient to catch a remove -> add. */ - - ut_ad(bpage->in_flush_list); - return(true); } @@ -452,11 +278,11 @@ static bool buf_flush_or_remove_page(buf_page_t *bpage, bool flush) ut_ad(mutex_own(&buf_pool.mutex)); ut_ad(mutex_own(&buf_pool.flush_list_mutex)); - /* bpage->space and bpage->io_fix are protected by - buf_pool.mutex and block_mutex. It is safe to check - them while holding buf_pool.mutex only. */ + /* bpage->id and bpage->io_fix are protected by + buf_pool.mutex (and bpage->id additionally by hash_lock). + It is safe to check them while holding buf_pool.mutex only. */ - if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + if (bpage->io_fix() != BUF_IO_NONE) { /* We cannot remove this page during this scan yet; maybe the system is currently reading it @@ -465,11 +291,8 @@ static bool buf_flush_or_remove_page(buf_page_t *bpage, bool flush) } - BPageMutex* block_mutex; bool processed = false; - block_mutex = buf_page_get_mutex(bpage); - /* We have to release the flush_list_mutex to obey the latching order. We are however guaranteed that the page will stay in the flush_list and won't be relocated because @@ -478,37 +301,22 @@ static bool buf_flush_or_remove_page(buf_page_t *bpage, bool flush) mutex_exit(&buf_pool.flush_list_mutex); - mutex_enter(block_mutex); - - ut_ad(bpage->oldest_modification != 0); + ut_ad(bpage->oldest_modification()); if (!flush) { - buf_flush_remove(bpage); - - mutex_exit(block_mutex); - processed = true; - - } else if (buf_flush_ready_for_flush(bpage, BUF_FLUSH_SINGLE_PAGE)) { - - /* The following call will release the buffer pool - and block mutex. */ - processed = buf_flush_page( - bpage, BUF_FLUSH_SINGLE_PAGE, false); + } else if (bpage->ready_for_flush()) { + processed = buf_flush_page(bpage, IORequest::SINGLE_PAGE, + nullptr, false); if (processed) { mutex_enter(&buf_pool.mutex); - } else { - mutex_exit(block_mutex); } - } else { - mutex_exit(block_mutex); } mutex_enter(&buf_pool.flush_list_mutex); - ut_ad(!mutex_own(block_mutex)); ut_ad(mutex_own(&buf_pool.mutex)); return(processed); @@ -536,17 +344,19 @@ rescan: bpage != NULL; bpage = prev) { - ut_a(buf_page_in_file(bpage)); + ut_a(bpage->in_file()); /* Save the previous link because once we free the page we can't rely on the links. */ prev = UT_LIST_GET_PREV(list, bpage); - if (id != bpage->id.space()) { + const page_id_t bpage_id(bpage->id()); + + if (id != bpage_id.space()) { /* Skip this block, because it is for a different tablespace. */ - } else if (bpage->id.page_no() < first) { + } else if (bpage_id.page_no() < first) { /* Skip this block, because it is below the limit. */ } else if (!buf_flush_or_remove_page(bpage, flush)) { @@ -621,10 +431,9 @@ static void buf_flush_dirty_pages(ulint id, bool flush, ulint first) for (buf_page_t *bpage= UT_LIST_GET_FIRST(buf_pool.flush_list); bpage; bpage= UT_LIST_GET_NEXT(list, bpage)) { - ut_ad(buf_page_in_file(bpage)); - ut_ad(bpage->in_flush_list); - ut_ad(bpage->oldest_modification > 0); - ut_ad(id != bpage->id.space()); + ut_ad(bpage->in_file()); + ut_ad(bpage->oldest_modification()); + ut_ad(id != bpage->id().space()); } mutex_exit(&buf_pool.flush_list_mutex); @@ -652,7 +461,7 @@ void buf_LRU_flush_or_remove_pages(ulint id, bool flush, ulint first) } } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /********************************************************************//** Insert a compressed block into buf_pool.zip_clean in the LRU order. */ void @@ -661,7 +470,8 @@ buf_LRU_insert_zip_clean( buf_page_t* bpage) /*!< in: pointer to the block in question */ { ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE); + ut_ad(bpage->state() == BUF_BLOCK_ZIP_PAGE); + ut_ad(!bpage->oldest_modification()); /* Find the first successor of bpage in the LRU list that is in the zip_clean list. */ @@ -669,7 +479,8 @@ buf_LRU_insert_zip_clean( do { b = UT_LIST_GET_NEXT(LRU, b); - } while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE); + } while (b && (b->state() != BUF_BLOCK_ZIP_PAGE + || b->oldest_modification())); /* Insert bpage before b, i.e., after the predecessor of b. */ if (b != NULL) { @@ -682,7 +493,7 @@ buf_LRU_insert_zip_clean( UT_LIST_ADD_FIRST(buf_pool.zip_clean, bpage); } } -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ /** Try to free an uncompressed page of a compressed block from the unzip LRU list. The compressed page is preserved, and it need not be clean. @@ -698,23 +509,21 @@ static bool buf_LRU_free_from_unzip_LRU_list(bool scan_all) } ulint scanned = 0; + const ulint limit = scan_all ? ULINT_UNDEFINED : srv_LRU_scan_depth; bool freed = false; for (buf_block_t* block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); - block != NULL - && !freed - && (scan_all || scanned < srv_LRU_scan_depth); - ++scanned) { + block && scanned < limit; ++scanned) { + buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); - buf_block_t* prev_block; - - prev_block = UT_LIST_GET_PREV(unzip_LRU, block); - - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->in_unzip_LRU_list); ut_ad(block->page.in_LRU_list); freed = buf_LRU_free_page(&block->page, false); + if (freed) { + break; + } block = prev_block; } @@ -742,39 +551,28 @@ static bool buf_LRU_free_from_common_LRU_list(bool scan_all) bool freed = false; for (buf_page_t* bpage = buf_pool.lru_scan_itr.start(); - bpage != NULL - && !freed - && (scan_all || scanned < BUF_LRU_SEARCH_SCAN_THRESHOLD); + bpage && (scan_all || scanned < BUF_LRU_SEARCH_SCAN_THRESHOLD); ++scanned, bpage = buf_pool.lru_scan_itr.get()) { - buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); - BPageMutex* mutex = buf_page_get_mutex(bpage); - buf_pool.lru_scan_itr.set(prev); - mutex_enter(mutex); + const auto accessed = bpage->is_accessed(); + freed = bpage->ready_for_replace(); - ut_ad(buf_page_in_file(bpage)); - ut_ad(bpage->in_LRU_list); - - unsigned accessed = buf_page_is_accessed(bpage); - - if (buf_flush_ready_for_replace(bpage)) { - mutex_exit(mutex); + if (freed) { freed = buf_LRU_free_page(bpage, true); - } else { - mutex_exit(mutex); - } + if (!freed) { + continue; + } - if (freed && !accessed) { - /* Keep track of pages that are evicted without - ever being accessed. This gives us a measure of - the effectiveness of readahead */ - ++buf_pool.stat.n_ra_pages_evicted; + if (!accessed) { + /* Keep track of pages that are evicted without + ever being accessed. This gives us a measure of + the effectiveness of readahead */ + ++buf_pool.stat.n_ra_pages_evicted; + break; + } } - - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(!mutex_own(mutex)); } if (scanned) { @@ -800,15 +598,6 @@ bool buf_LRU_scan_and_free_block(bool scan_all) || buf_LRU_free_from_common_LRU_list(scan_all)); } -/** @return whether less than 1/4 of the buffer pool is available */ -bool buf_LRU_buf_pool_running_out() -{ - return !recv_recovery_is_on() - && UT_LIST_GET_LEN(buf_pool.free) - + UT_LIST_GET_LEN(buf_pool.LRU) - < ut_min(buf_pool.curr_size, buf_pool.old_size) / 4; -} - /** @return a buffer block from the buf_pool.free list @retval NULL if the free list is empty */ buf_block_t* buf_LRU_get_free_only() @@ -821,28 +610,23 @@ buf_block_t* buf_LRU_get_free_only() UT_LIST_GET_FIRST(buf_pool.free)); while (block != NULL) { - ut_ad(block->page.in_free_list); ut_d(block->page.in_free_list = FALSE); - ut_ad(!block->page.in_flush_list); + ut_ad(!block->page.oldest_modification()); ut_ad(!block->page.in_LRU_list); - ut_a(!buf_page_in_file(&block->page)); + ut_a(!block->page.in_file()); UT_LIST_REMOVE(buf_pool.free, &block->page); if (buf_pool.curr_size >= buf_pool.old_size || UT_LIST_GET_LEN(buf_pool.withdraw) >= buf_pool.withdraw_target || !buf_pool.will_be_withdrawn(block->page)) { - /* found valid free block */ - buf_page_mutex_enter(block); /* No adaptive hash index entries may point to a free block. */ assert_block_ahi_empty(block); - buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE); - UNIV_MEM_ALLOC(block->frame, srv_page_size); - - buf_page_mutex_exit(block); + block->page.set_state(BUF_BLOCK_MEMORY); + MEM_UNDEFINED(block->frame, srv_page_size); break; } @@ -850,7 +634,7 @@ buf_block_t* buf_LRU_get_free_only() UT_LIST_ADD_LAST( buf_pool.withdraw, &block->page); - ut_d(block->in_withdraw_list = TRUE); + ut_d(block->in_withdraw_list = true); block = reinterpret_cast( UT_LIST_GET_FIRST(buf_pool.free)); @@ -928,6 +712,7 @@ static void buf_LRU_check_size_of_non_data_objects() /** Get a free block from the buf_pool. The block is taken off the free list. If free list is empty, blocks are moved from the end of the LRU list to the free list. + This function is called from a user thread when it needs a clean block to read in a page. Note that we only ever get a block from the free list. Even when we flush a page or find a page in LRU scan @@ -947,17 +732,23 @@ we put it to free list to be used. * scan LRU list even if buf_pool.try_LRU_scan is not set * iteration > 1: * same as iteration 1 but sleep 10ms -@return the free control block, in state BUF_BLOCK_READY_FOR_USE */ -buf_block_t* buf_LRU_get_free_block() + +@param have_mutex whether buf_pool.mutex is already being held +@return the free control block, in state BUF_BLOCK_MEMORY */ +buf_block_t* buf_LRU_get_free_block(bool have_mutex) { buf_block_t* block = NULL; bool freed = false; ulint n_iterations = 0; ulint flush_failures = 0; - MONITOR_INC(MONITOR_LRU_GET_FREE_SEARCH); + if (have_mutex) { + ut_ad(mutex_own(&buf_pool.mutex)); + goto got_mutex; + } loop: mutex_enter(&buf_pool.mutex); +got_mutex: buf_LRU_check_size_of_non_data_objects(); @@ -970,7 +761,9 @@ loop: block = buf_LRU_get_free_only(); if (block != NULL) { - mutex_exit(&buf_pool.mutex); + if (!have_mutex) { + mutex_exit(&buf_pool.mutex); + } memset(&block->page.zip, 0, sizeof block->page.zip); block->skip_flush_check = false; return(block); @@ -978,7 +771,7 @@ loop: MONITOR_INC( MONITOR_LRU_GET_FREE_LOOPS ); freed = false; - if (buf_pool.try_LRU_scan || n_iterations > 0) { + if (n_iterations || buf_pool.try_LRU_scan) { /* If no block was in the free list, search from the end of the LRU list and try to free a block there. If we are doing for the first time we'll scan only @@ -991,7 +784,7 @@ loop: in scanning the LRU list. This flag is set to TRUE again when we flush a batch from this buffer pool. */ - buf_pool.try_LRU_scan = FALSE; + buf_pool.try_LRU_scan = false; /* Also tell the page_cleaner thread that there is work for it to do. */ @@ -1118,13 +911,13 @@ static void buf_LRU_old_adjust_len() ut_a(!LRU_old->old); #endif /* UNIV_LRU_DEBUG */ old_len = ++buf_pool.LRU_old_len; - buf_page_set_old(LRU_old, TRUE); + LRU_old->set_old(true); } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) { buf_pool.LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old); old_len = --buf_pool.LRU_old_len; - buf_page_set_old(LRU_old, FALSE); + LRU_old->set_old(false); } else { return; } @@ -1147,11 +940,10 @@ static void buf_LRU_old_init() bpage = UT_LIST_GET_PREV(LRU, bpage)) { ut_ad(bpage->in_LRU_list); - ut_ad(buf_page_in_file(bpage)); /* This loop temporarily violates the - assertions of buf_page_set_old(). */ - bpage->old = TRUE; + assertions of buf_page_t::set_old(). */ + bpage->old = true; } buf_pool.LRU_old = UT_LIST_GET_FIRST(buf_pool.LRU); @@ -1164,41 +956,26 @@ static void buf_LRU_old_init() @param[in] bpage control block */ static void buf_unzip_LRU_remove_block_if_needed(buf_page_t* bpage) { - ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); ut_ad(mutex_own(&buf_pool.mutex)); - if (buf_page_belongs_to_unzip_LRU(bpage)) { + if (bpage->belongs_to_unzip_LRU()) { buf_block_t* block = reinterpret_cast(bpage); ut_ad(block->in_unzip_LRU_list); - ut_d(block->in_unzip_LRU_list = FALSE); + ut_d(block->in_unzip_LRU_list = false); UT_LIST_REMOVE(buf_pool.unzip_LRU, block); } } -/** Adjust LRU hazard pointers if needed. -@param[in] bpage buffer page descriptor */ -void buf_LRU_adjust_hp(const buf_page_t* bpage) -{ - buf_pool.lru_hp.adjust(bpage); - buf_pool.lru_scan_itr.adjust(bpage); - buf_pool.single_scan_itr.adjust(bpage); -} - /** Removes a block from the LRU list. @param[in] bpage control block */ static inline void buf_LRU_remove_block(buf_page_t* bpage) { - ut_ad(mutex_own(&buf_pool.mutex)); - - ut_a(buf_page_in_file(bpage)); - - ut_ad(bpage->in_LRU_list); - /* Important that we adjust the hazard pointers before removing bpage from the LRU list. */ - buf_LRU_adjust_hp(bpage); + buf_page_t* prev_bpage = buf_pool.LRU_remove(bpage); /* If the LRU_old pointer is defined and points to just this block, move it backward one step */ @@ -1210,22 +987,16 @@ static inline void buf_LRU_remove_block(buf_page_t* bpage) by BUF_LRU_OLD_TOLERANCE from strict buf_pool.LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV of the LRU list length. */ - buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage); - ut_a(prev_bpage); #ifdef UNIV_LRU_DEBUG ut_a(!prev_bpage->old); #endif /* UNIV_LRU_DEBUG */ buf_pool.LRU_old = prev_bpage; - buf_page_set_old(prev_bpage, TRUE); + prev_bpage->set_old(true); buf_pool.LRU_old_len++; } - /* Remove the block from the LRU list */ - UT_LIST_REMOVE(buf_pool.LRU, bpage); - ut_d(bpage->in_LRU_list = FALSE); - buf_pool.stat.LRU_bytes -= bpage->physical_size(); buf_unzip_LRU_remove_block_if_needed(bpage); @@ -1239,8 +1010,8 @@ static inline void buf_LRU_remove_block(buf_page_t* bpage) bpage = UT_LIST_GET_NEXT(LRU, bpage)) { /* This loop temporarily violates the - assertions of buf_page_set_old(). */ - bpage->old = FALSE; + assertions of buf_page_t::set_old(). */ + bpage->old = false; } buf_pool.LRU_old = NULL; @@ -1252,8 +1023,7 @@ static inline void buf_LRU_remove_block(buf_page_t* bpage) ut_ad(buf_pool.LRU_old); /* Update the LRU_old_len field if necessary */ - if (buf_page_is_old(bpage)) { - + if (bpage->old) { buf_pool.LRU_old_len--; } @@ -1271,9 +1041,9 @@ buf_unzip_LRU_add_block( of the list, else put to the start */ { ut_ad(mutex_own(&buf_pool.mutex)); - ut_a(buf_page_belongs_to_unzip_LRU(&block->page)); + ut_a(block->page.belongs_to_unzip_LRU()); ut_ad(!block->in_unzip_LRU_list); - ut_d(block->in_unzip_LRU_list = TRUE); + ut_d(block->in_unzip_LRU_list = true); if (old) { UT_LIST_ADD_LAST(buf_pool.unzip_LRU, block); @@ -1286,18 +1056,15 @@ buf_unzip_LRU_add_block( Adds a block to the LRU list. Please make sure that the page_size is already set when invoking the function, so that we can get correct page_size from the buffer page when adding a block into LRU */ -UNIV_INLINE void -buf_LRU_add_block_low( -/*==================*/ +buf_LRU_add_block( buf_page_t* bpage, /*!< in: control block */ - ibool old) /*!< in: TRUE if should be put to the old blocks + bool old) /*!< in: true if should be put to the old blocks in the LRU list, else put to the start; if the LRU list is very short, the block is added to the start, regardless of this parameter */ { ut_ad(mutex_own(&buf_pool.mutex)); - ut_a(buf_page_in_file(bpage)); ut_ad(!bpage->in_LRU_list); if (!old || (UT_LIST_GET_LEN(buf_pool.LRU) < BUF_LRU_OLD_MIN_LEN)) { @@ -1332,7 +1099,7 @@ buf_LRU_add_block_low( /* Adjust the length of the old block list if necessary */ - buf_page_set_old(bpage, old); + bpage->set_old(old); buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool.LRU) == BUF_LRU_OLD_MIN_LEN) { @@ -1342,81 +1109,61 @@ buf_LRU_add_block_low( buf_LRU_old_init(); } else { - buf_page_set_old(bpage, buf_pool.LRU_old != NULL); + bpage->set_old(buf_pool.LRU_old != NULL); } /* If this is a zipped block with decompressed frame as well then put it on the unzip_LRU list */ - if (buf_page_belongs_to_unzip_LRU(bpage)) { + if (bpage->belongs_to_unzip_LRU()) { buf_unzip_LRU_add_block((buf_block_t*) bpage, old); } } -/******************************************************************//** -Adds a block to the LRU list. Please make sure that the page_size is -already set when invoking the function, so that we can get correct -page_size from the buffer page when adding a block into LRU */ -void -buf_LRU_add_block( -/*==============*/ - buf_page_t* bpage, /*!< in: control block */ - ibool old) /*!< in: TRUE if should be put to the old - blocks in the LRU list, else put to the start; - if the LRU list is very short, the block is - added to the start, regardless of this - parameter */ +/** Move a block to the start of the LRU list. */ +void buf_page_make_young(buf_page_t *bpage) { - buf_LRU_add_block_low(bpage, old); + ut_ad(bpage->in_file()); + + mutex_enter(&buf_pool.mutex); + + if (UNIV_UNLIKELY(bpage->old)) + buf_pool.stat.n_pages_made_young++; + + buf_LRU_remove_block(bpage); + buf_LRU_add_block(bpage, false); + + mutex_exit(&buf_pool.mutex); } -/******************************************************************//** -Moves a block to the start of the LRU list. */ -void -buf_LRU_make_block_young( -/*=====================*/ - buf_page_t* bpage) /*!< in: control block */ +/** Try to free a block. If bpage is a descriptor of a compressed-only +ROW_FORMAT=COMPRESSED page, the buf_page_t object will be freed as well. +The caller must hold buf_pool.mutex. +@param bpage block to be freed +@param zip whether to remove both copies of a ROW_FORMAT=COMPRESSED page +@retval true if freed and buf_pool.mutex may have been temporarily released +@retval false if the page was not freed */ +bool buf_LRU_free_page(buf_page_t *bpage, bool zip) { - ut_ad(mutex_own(&buf_pool.mutex)); - - if (bpage->old) { - buf_pool.stat.n_pages_made_young++; - } - - buf_LRU_remove_block(bpage); - buf_LRU_add_block_low(bpage, FALSE); -} - -/******************************************************************//** -Try to free a block. If bpage is a descriptor of a compressed-only -page, the descriptor object will be freed as well. - -NOTE: If this function returns true, it will temporarily -release buf_pool.mutex. Furthermore, the page frame will no longer be -accessible via bpage. - -The caller must hold buf_pool.mutex and must not hold any -buf_page_get_mutex() when calling this function. -@return true if freed, false otherwise. */ -bool -buf_LRU_free_page( -/*===============*/ - buf_page_t* bpage, /*!< in: block to be freed */ - bool zip) /*!< in: true if should remove also the - compressed page of an uncompressed page */ -{ - buf_page_t* b = NULL; - rw_lock_t* hash_lock = buf_page_hash_lock_get(bpage->id); - BPageMutex* block_mutex = buf_page_get_mutex(bpage); + const page_id_t id(bpage->id()); + buf_page_t* b = nullptr; ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); ut_ad(bpage->in_LRU_list); - rw_lock_x_lock(hash_lock); - mutex_enter(block_mutex); + /* First, perform a quick check before we acquire hash_lock. */ + if (!bpage->can_relocate()) { + return false; + } - if (!buf_page_can_relocate(bpage)) { + /* We must hold an exclusive hash_lock to prevent + bpage->can_relocate() from changing due to a concurrent + execution of buf_page_get_low(). */ + const ulint fold = id.fold(); + page_hash_latch* hash_lock = buf_pool.page_hash.lock_get(fold); + hash_lock->write_lock(); + if (UNIV_UNLIKELY(!bpage->can_relocate())) { /* Do not free buffer fixed and I/O-fixed blocks. */ goto func_exit; } @@ -1425,101 +1172,81 @@ buf_LRU_free_page( /* This would completely free the block. */ /* Do not completely free dirty blocks. */ - if (bpage->oldest_modification) { + if (bpage->oldest_modification()) { goto func_exit; } - } else if (bpage->oldest_modification > 0 - && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { - - ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY); - + } else if (bpage->oldest_modification() + && bpage->state() != BUF_BLOCK_FILE_PAGE) { func_exit: - rw_lock_x_unlock(hash_lock); - mutex_exit(block_mutex); + hash_lock->write_unlock(); return(false); - } else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { + } else if (bpage->state() == BUF_BLOCK_FILE_PAGE) { b = buf_page_alloc_descriptor(); ut_a(b); new (b) buf_page_t(*bpage); + b->set_state(BUF_BLOCK_ZIP_PAGE); } ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); ut_ad(bpage->in_LRU_list); - ut_ad(!bpage->in_flush_list == !bpage->oldest_modification); DBUG_PRINT("ib_buf", ("free page %u:%u", - bpage->id.space(), bpage->id.page_no())); + id.space(), id.page_no())); - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); - ut_ad(buf_page_can_relocate(bpage)); + ut_ad(bpage->can_relocate()); - if (!buf_LRU_block_remove_hashed(bpage, zip)) { + if (!buf_LRU_block_remove_hashed(bpage, id, hash_lock, zip)) { return(true); } - /* buf_LRU_block_remove_hashed() releases the hash_lock */ - ut_ad(!rw_lock_own_flagged(hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - - /* We have just freed a BUF_BLOCK_FILE_PAGE. If b != NULL + /* We have just freed a BUF_BLOCK_FILE_PAGE. If b != nullptr then it was a compressed page with an uncompressed frame and we are interested in freeing only the uncompressed frame. Therefore we have to reinsert the compressed page descriptor into the LRU and page_hash (and possibly flush_list). - if b == NULL then it was a regular page that has been freed */ + if !b then it was a regular page that has been freed */ - if (b != NULL) { + if (UNIV_LIKELY_NULL(b)) { buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, b); - rw_lock_x_lock(hash_lock); - - mutex_enter(block_mutex); - - ut_a(!buf_page_hash_get_low(b->id)); - - b->state = b->oldest_modification - ? BUF_BLOCK_ZIP_DIRTY - : BUF_BLOCK_ZIP_PAGE; + hash_lock->write_lock(); + ut_ad(!buf_pool.page_hash_get_low(id, fold)); ut_ad(b->zip_size()); - UNIV_MEM_DESC(b->zip.data, b->zip_size()); - - /* The fields in_page_hash and in_LRU_list of + /* The field in_LRU_list of the to-be-freed block descriptor should have been cleared in buf_LRU_block_remove_hashed(), which invokes buf_LRU_remove_block(). */ - ut_ad(!bpage->in_page_hash); ut_ad(!bpage->in_LRU_list); /* bpage->state was BUF_BLOCK_FILE_PAGE because - b != NULL. The type cast below is thus valid. */ + b != nullptr. The type cast below is thus valid. */ ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list); /* The fields of bpage were copied to b before buf_LRU_block_remove_hashed() was invoked. */ ut_ad(!b->in_zip_hash); - ut_ad(b->in_page_hash); ut_ad(b->in_LRU_list); + ut_ad(b->in_page_hash); - HASH_INSERT(buf_page_t, hash, buf_pool.page_hash, - b->id.fold(), b); + HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, b); /* Insert b where bpage was in the LRU list. */ - if (prev_b != NULL) { + if (prev_b) { ulint lru_len; ut_ad(prev_b->in_LRU_list); - ut_ad(buf_page_in_file(prev_b)); + ut_ad(prev_b->in_file()); UT_LIST_INSERT_AFTER(buf_pool.LRU, prev_b, b); incr_LRU_size_in_bytes(b); - if (buf_page_is_old(b)) { + if (b->is_old()) { buf_pool.LRU_old_len++; if (buf_pool.LRU_old == UT_LIST_GET_NEXT(LRU, b)) { @@ -1544,40 +1271,31 @@ func_exit: #ifdef UNIV_LRU_DEBUG /* Check that the "old" flag is consistent in the block and its neighbours. */ - buf_page_set_old(b, buf_page_is_old(b)); + b->set_old(b->is_old()); #endif /* UNIV_LRU_DEBUG */ } else { ut_d(b->in_LRU_list = FALSE); - buf_LRU_add_block_low(b, buf_page_is_old(b)); + buf_LRU_add_block(b, b->old); } - if (b->state == BUF_BLOCK_ZIP_PAGE) { -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG + if (!b->oldest_modification()) { +#ifdef UNIV_DEBUG buf_LRU_insert_zip_clean(b); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ } else { /* Relocate on buf_pool.flush_list. */ buf_flush_relocate_on_flush_list(bpage, b); } - bpage->zip.data = NULL; + bpage->zip.data = nullptr; page_zip_set_size(&bpage->zip, 0); - mutex_exit(block_mutex); - /* Prevent buf_page_get_gen() from decompressing the block while we release - buf_pool.mutex and block_mutex. */ - block_mutex = buf_page_get_mutex(b); - - mutex_enter(block_mutex); - - buf_page_set_sticky(b); - - mutex_exit(block_mutex); - - rw_lock_x_unlock(hash_lock); + hash_lock. */ + b->set_io_fix(BUF_IO_PIN); + hash_lock->write_unlock(); } mutex_exit(&buf_pool.mutex); @@ -1586,46 +1304,24 @@ func_exit: The page was declared uninitialized by buf_LRU_block_remove_hashed(). We need to flag the contents of the page valid (which it still is) in - order to avoid bogus Valgrind warnings.*/ + order to avoid bogus Valgrind or MSAN warnings.*/ + buf_block_t* block = reinterpret_cast(bpage); - UNIV_MEM_VALID(((buf_block_t*) bpage)->frame, - srv_page_size); - btr_search_drop_page_hash_index((buf_block_t*) bpage); - UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame, - srv_page_size); - - if (b != NULL) { - - /* Compute and stamp the compressed page - checksum while not holding any mutex. The - block is already half-freed - (BUF_BLOCK_REMOVE_HASH) and removed from - buf_pool.page_hash, thus inaccessible by any - other thread. */ +#ifdef HAVE_valgrind_or_MSAN + MEM_MAKE_DEFINED(block->frame, srv_page_size); +#endif /* HAVE_valgrind_or_MSAN */ + btr_search_drop_page_hash_index(block); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(block->frame, srv_page_size); +#endif /* HAVE_valgrind_or_MSAN */ + if (UNIV_LIKELY_NULL(b)) { ut_ad(b->zip_size()); - - const uint32_t checksum = page_zip_calc_checksum( - b->zip.data, - b->zip_size(), - static_cast( - srv_checksum_algorithm)); - - mach_write_to_4(b->zip.data + FIL_PAGE_SPACE_OR_CHKSUM, - checksum); + b->io_unfix(); } mutex_enter(&buf_pool.mutex); - - if (b != NULL) { - mutex_enter(block_mutex); - - buf_page_unset_sticky(b); - - mutex_exit(block_mutex); - } - - buf_LRU_block_free_hashed_page((buf_block_t*) bpage); + buf_LRU_block_free_hashed_page(block); return(true); } @@ -1639,29 +1335,15 @@ buf_LRU_block_free_non_file_page( { void* data; - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_mutex_own(block)); - - switch (buf_block_get_state(block)) { - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_READY_FOR_USE: - break; - default: - ut_error; - } - + ut_ad(block->page.state() == BUF_BLOCK_MEMORY); assert_block_ahi_empty(block); ut_ad(!block->page.in_free_list); - ut_ad(!block->page.in_flush_list); + ut_ad(!block->page.oldest_modification()); ut_ad(!block->page.in_LRU_list); - buf_block_set_state(block, BUF_BLOCK_NOT_USED); + block->page.set_state(BUF_BLOCK_NOT_USED); - UNIV_MEM_ALLOC(block->frame, srv_page_size); -#ifdef UNIV_DEBUG - /* Wipe contents of page to reveal possible stale pointers to it */ - memset(block->frame, '\0', srv_page_size); -#else + MEM_UNDEFINED(block->frame, srv_page_size); /* Wipe page_no and space_id */ static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment"); memset_aligned<4>(block->frame + FIL_PAGE_OFFSET, 0xfe, 4); @@ -1669,12 +1351,10 @@ buf_LRU_block_free_non_file_page( "not perfect alignment"); memset_aligned<2>(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xfe, 4); -#endif /* UNIV_DEBUG */ data = block->page.zip.data; if (data != NULL) { block->page.zip.data = NULL; - buf_page_mutex_exit(block); buf_pool_mutex_exit_forbid(); ut_ad(block->zip_size()); @@ -1682,8 +1362,6 @@ buf_LRU_block_free_non_file_page( buf_buddy_free(data, block->zip_size()); buf_pool_mutex_exit_allow(); - buf_page_mutex_enter(block); - page_zip_set_size(&block->page.zip, 0); } @@ -1694,66 +1372,53 @@ buf_LRU_block_free_non_file_page( UT_LIST_ADD_LAST( buf_pool.withdraw, &block->page); - ut_d(block->in_withdraw_list = TRUE); + ut_d(block->in_withdraw_list = true); } else { UT_LIST_ADD_FIRST(buf_pool.free, &block->page); - ut_d(block->page.in_free_list = TRUE); + ut_d(block->page.in_free_list = true); } - UNIV_MEM_FREE(block->frame, srv_page_size); + MEM_NOACCESS(block->frame, srv_page_size); } -/******************************************************************//** -Takes a block out of the LRU list and page hash table. -If the block is compressed-only (BUF_BLOCK_ZIP_PAGE), +/** Remove bpage from buf_pool.LRU and buf_pool.page_hash. + +If bpage->state() == BUF_BLOCK_ZIP_PAGE && !bpage->oldest_modification(), the object will be freed. -The caller must hold buf_pool.mutex, the buf_page_get_mutex() mutex -and the appropriate hash_lock. This function will release the -buf_page_get_mutex() and the hash_lock. +@param bpage buffer block +@param id page identifier +@param hash_lock buf_pool.page_hash latch (will be released here) +@param zip whether bpage->zip of BUF_BLOCK_FILE_PAGE should be freed If a compressed page is freed other compressed pages may be relocated. @retval true if BUF_BLOCK_FILE_PAGE was removed from page_hash. The caller needs to free the page to the free list @retval false if BUF_BLOCK_ZIP_PAGE was removed from page_hash. In this case the block is already returned to the buddy allocator. */ -static -bool -buf_LRU_block_remove_hashed( -/*========================*/ - buf_page_t* bpage, /*!< in: block, must contain a file page and - be in a state where it can be freed; there - may or may not be a hash index to the page */ - bool zip) /*!< in: true if should remove also the - compressed page of an uncompressed page */ +static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id, + page_hash_latch *hash_lock, bool zip) { - const buf_page_t* hashed_bpage; - rw_lock_t* hash_lock; - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(hash_lock->is_write_locked()); - hash_lock = buf_page_hash_lock_get(bpage->id); - - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); - - ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE); - ut_a(bpage->buf_fix_count == 0); + ut_a(bpage->io_fix() == BUF_IO_NONE); + ut_a(!bpage->buf_fix_count()); buf_LRU_remove_block(bpage); buf_pool.freed_page_clock += 1; - switch (buf_page_get_state(bpage)) { + switch (bpage->state()) { case BUF_BLOCK_FILE_PAGE: - UNIV_MEM_ASSERT_W(bpage, sizeof(buf_block_t)); - UNIV_MEM_ASSERT_W(((buf_block_t*) bpage)->frame, - srv_page_size); + MEM_CHECK_ADDRESSABLE(bpage, sizeof(buf_block_t)); + MEM_CHECK_ADDRESSABLE(((buf_block_t*) bpage)->frame, + srv_page_size); buf_block_modify_clock_inc((buf_block_t*) bpage); if (bpage->zip.data) { const page_t* page = ((buf_block_t*) bpage)->frame; - ut_a(!zip || bpage->oldest_modification == 0); + ut_a(!zip || !bpage->oldest_modification()); ut_ad(bpage->zip_size()); switch (fil_page_get_type(page)) { @@ -1804,69 +1469,31 @@ buf_LRU_block_remove_hashed( } /* fall through */ case BUF_BLOCK_ZIP_PAGE: - ut_a(bpage->oldest_modification == 0); - UNIV_MEM_ASSERT_W(bpage->zip.data, bpage->zip_size()); + ut_a(!bpage->oldest_modification()); + MEM_CHECK_ADDRESSABLE(bpage->zip.data, bpage->zip_size()); break; - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: ut_error; break; } - hashed_bpage = buf_page_hash_get_low(bpage->id); - if (bpage != hashed_bpage) { - ib::error() << "Page " << bpage->id - << " not found in the hash table"; - ib::error() -#ifdef UNIV_DEBUG - << "in_page_hash:" << bpage->in_page_hash - << " in_zip_hash:" << bpage->in_zip_hash - << " in_flush_list:" << bpage->in_flush_list - << " in_LRU_list:" << bpage->in_LRU_list -#endif - << " zip.data:" << bpage->zip.data - << " zip_size:" << bpage->zip_size() - << " page_state:" << buf_page_get_state(bpage); - - if (hashed_bpage) { - ib::error() << "In hash table we find block " - << hashed_bpage << " of " << hashed_bpage->id - << " which is not " << bpage; - } - - ut_d(mutex_exit(buf_page_get_mutex(bpage))); - ut_d(rw_lock_x_unlock(hash_lock)); - ut_d(mutex_exit(&buf_pool.mutex)); - ut_d(buf_pool.print()); - ut_d(buf_LRU_print()); - ut_d(buf_LRU_validate()); - ut_ad(0); - } - ut_ad(!bpage->in_zip_hash); - ut_ad(bpage->in_page_hash); - ut_d(bpage->in_page_hash = FALSE); + HASH_DELETE(buf_page_t, hash, &buf_pool.page_hash, id.fold(), bpage); - HASH_DELETE(buf_page_t, hash, buf_pool.page_hash, bpage->id.fold(), - bpage); - - switch (buf_page_get_state(bpage)) { + switch (bpage->state()) { case BUF_BLOCK_ZIP_PAGE: ut_ad(!bpage->in_free_list); - ut_ad(!bpage->in_flush_list); ut_ad(!bpage->in_LRU_list); ut_a(bpage->zip.data); ut_a(bpage->zip.ssize); + ut_ad(!bpage->oldest_modification()); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG UT_LIST_REMOVE(buf_pool.zip_clean, bpage); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - mutex_exit(&buf_pool.zip_mutex); - rw_lock_x_unlock(hash_lock); +#endif /* UNIV_DEBUG */ + hash_lock->write_unlock(); buf_pool_mutex_exit_forbid(); buf_buddy_free(bpage->zip.data, bpage->zip_size()); @@ -1884,11 +1511,12 @@ buf_LRU_block_remove_hashed( "not perfect alignment"); memset_aligned<2>(reinterpret_cast(bpage)->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4); - UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame, - srv_page_size); - buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(((buf_block_t*) bpage)->frame, srv_page_size); +#endif /* HAVE_valgrind_or_MSAN */ + bpage->set_state(BUF_BLOCK_REMOVE_HASH); - /* Question: If we release bpage and hash mutex here + /* Question: If we release hash_lock here then what protects us against: 1) Some other thread buffer fixing this page 2) Some other thread trying to read this page and @@ -1907,8 +1535,7 @@ buf_LRU_block_remove_hashed( and by the time we'll release it in the caller we'd have inserted the compressed only descriptor in the page_hash. */ - rw_lock_x_unlock(hash_lock); - mutex_exit(&((buf_block_t*) bpage)->mutex); + hash_lock->write_unlock(); if (zip && bpage->zip.data) { /* Free the compressed page. */ @@ -1916,7 +1543,7 @@ buf_LRU_block_remove_hashed( bpage->zip.data = NULL; ut_ad(!bpage->in_free_list); - ut_ad(!bpage->in_flush_list); + ut_ad(!bpage->oldest_modification()); ut_ad(!bpage->in_LRU_list); buf_pool_mutex_exit_forbid(); @@ -1929,10 +1556,7 @@ buf_LRU_block_remove_hashed( return(true); - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: break; @@ -1942,61 +1566,20 @@ buf_LRU_block_remove_hashed( return(false); } -/******************************************************************//** -Puts a file page whose has no hash index to the free list. */ -static -void -buf_LRU_block_free_hashed_page( -/*===========================*/ - buf_block_t* block) /*!< in: block, must contain a file page and - be in a state where it can be freed */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - - buf_page_mutex_enter(block); - - if (buf_pool.flush_rbt == NULL) { - block->page.id - = page_id_t(ULINT32_UNDEFINED, ULINT32_UNDEFINED); - } - - buf_block_set_state(block, BUF_BLOCK_MEMORY); - - buf_LRU_block_free_non_file_page(block); - buf_page_mutex_exit(block); -} - /** Remove one page from LRU list and put it to free list. -@param[in,out] bpage block, must contain a file page and be in - a freeable state; there may or may not be a - hash index to the page -@param[in] old_page_id page number before bpage->id was invalidated */ -void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id) +@param bpage file page to be freed +@param id page identifier +@param hash_lock buf_pool.page_hash latch (will be released here) */ +void buf_LRU_free_one_page(buf_page_t *bpage, const page_id_t id, + page_hash_latch *hash_lock) { - rw_lock_t* hash_lock = buf_page_hash_lock_get(old_page_id); - BPageMutex* block_mutex = buf_page_get_mutex(bpage); + while (bpage->buf_fix_count()) + /* Wait for other threads to release the fix count + before releasing the bpage from LRU list. */ + (void) LF_BACKOFF(); - ut_ad(mutex_own(&buf_pool.mutex)); - - rw_lock_x_lock(hash_lock); - - while (bpage->buf_fix_count > 0) { - /* Wait for other threads to release the fix count - before releasing the bpage from LRU list. */ - } - - mutex_enter(block_mutex); - - bpage->id = old_page_id; - - if (buf_LRU_block_remove_hashed(bpage, true)) { - buf_LRU_block_free_hashed_page((buf_block_t*) bpage); - } - - /* buf_LRU_block_remove_hashed() releases hash_lock and block_mutex */ - ut_ad(!rw_lock_own_flagged(hash_lock, - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - ut_ad(!mutex_own(block_mutex)); + if (buf_LRU_block_remove_hashed(bpage, id, hash_lock, true)) + buf_LRU_block_free_hashed_page(reinterpret_cast(bpage)); } /** Update buf_pool.LRU_old_ratio. @@ -2073,7 +1656,7 @@ func_exit: memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Validate the LRU list. */ void buf_LRU_validate() { @@ -2106,23 +1689,21 @@ void buf_LRU_validate() bpage != NULL; bpage = UT_LIST_GET_NEXT(LRU, bpage)) { - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: + switch (bpage->state()) { case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: ut_error; break; case BUF_BLOCK_FILE_PAGE: - ut_ad(((buf_block_t*) bpage)->in_unzip_LRU_list - == buf_page_belongs_to_unzip_LRU(bpage)); + ut_ad(reinterpret_cast(bpage) + ->in_unzip_LRU_list + == bpage->belongs_to_unzip_LRU()); case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: break; } - if (buf_page_is_old(bpage)) { + if (bpage->is_old()) { const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); const buf_page_t* next @@ -2131,10 +1712,10 @@ void buf_LRU_validate() if (!old_len++) { ut_a(buf_pool.LRU_old == bpage); } else { - ut_a(!prev || buf_page_is_old(prev)); + ut_a(!prev || prev->is_old()); } - ut_a(!next || buf_page_is_old(next)); + ut_a(!next || next->is_old()); } } @@ -2146,7 +1727,7 @@ void buf_LRU_validate() bpage != NULL; bpage = UT_LIST_GET_NEXT(list, bpage)) { - ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED); + ut_a(bpage->state() == BUF_BLOCK_NOT_USED); } CheckUnzipLRUAndLRUList::validate(); @@ -2157,47 +1738,44 @@ void buf_LRU_validate() ut_ad(block->in_unzip_LRU_list); ut_ad(block->page.in_LRU_list); - ut_a(buf_page_belongs_to_unzip_LRU(&block->page)); + ut_a(block->page.belongs_to_unzip_LRU()); } mutex_exit(&buf_pool.mutex); } -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ -#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG /** Dump the LRU list to stderr. */ void buf_LRU_print() { mutex_enter(&buf_pool.mutex); - for (const buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU); + for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU); bpage != NULL; bpage = UT_LIST_GET_NEXT(LRU, bpage)) { - - mutex_enter(buf_page_get_mutex(bpage)); + const page_id_t id(bpage->id()); fprintf(stderr, "BLOCK space %u page %u ", - bpage->id.space(), bpage->id.page_no()); + id.space(), id.page_no()); - if (buf_page_is_old(bpage)) { + if (bpage->is_old()) { fputs("old ", stderr); } - if (bpage->buf_fix_count) { - fprintf(stderr, "buffix count %u ", - uint32_t(bpage->buf_fix_count)); + if (const uint32_t buf_fix_count = bpage->buf_fix_count()) { + fprintf(stderr, "buffix count %u ", buf_fix_count); } - if (buf_page_get_io_fix(bpage)) { - fprintf(stderr, "io_fix %d ", - buf_page_get_io_fix(bpage)); + if (const auto io_fix = bpage->io_fix()) { + fprintf(stderr, "io_fix %d ", io_fix); } - if (bpage->oldest_modification) { + if (bpage->oldest_modification()) { fputs("modif. ", stderr); } - switch (buf_page_get_state(bpage)) { + switch (const auto state = bpage->state()) { const byte* frame; case BUF_BLOCK_FILE_PAGE: frame = buf_block_get_frame((buf_block_t*) bpage); @@ -2215,14 +1793,11 @@ void buf_LRU_print() break; default: - fprintf(stderr, "\n!state %d!\n", - buf_page_get_state(bpage)); + fprintf(stderr, "\n!state %d!\n", state); break; } - - mutex_exit(buf_page_get_mutex(bpage)); } mutex_exit(&buf_pool.mutex); } -#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG */ diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index b4bb5bc56a0..0f6e0e84e84 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -33,6 +33,7 @@ Created 11/5/1995 Heikki Tuuri #include "buf0buf.h" #include "buf0flu.h" #include "buf0lru.h" +#include "buf0buddy.h" #include "buf0dblwr.h" #include "ibuf0ibuf.h" #include "log0recv.h" @@ -46,43 +47,213 @@ read-ahead is not done: this is to prevent flooding the buffer pool with i/o-fixed buffer blocks */ #define BUF_READ_AHEAD_PEND_LIMIT 2 -/********************************************************************//** -Unfixes the pages, unlatches the page, -removes it from page_hash and removes it from LRU. */ -static -void -buf_read_page_handle_error( -/*=======================*/ - buf_page_t* bpage) /*!< in: pointer to the block */ +/** Remove the sentinel block for the watch before replacing it with a +real block. watch_unset() or watch_occurred() will notice +that the block has been replaced with the real block. +@param watch sentinel */ +inline void buf_pool_t::watch_remove(buf_page_t *watch) { - const bool uncompressed = (buf_page_get_state(bpage) - == BUF_BLOCK_FILE_PAGE); - const page_id_t old_page_id = bpage->id; + ut_ad(hash_lock_get(watch->id())->is_write_locked()); + ut_a(watch_is_sentinel(*watch)); + if (watch->buf_fix_count()) + { + ut_ad(watch->in_page_hash); + ut_d(watch->in_page_hash= false); + HASH_DELETE(buf_page_t, hash, &page_hash, watch->id().fold(), watch); + watch->set_buf_fix_count(0); + } + ut_ad(!watch->in_page_hash); + watch->set_state(BUF_BLOCK_NOT_USED); + watch->id_= page_id_t(~0ULL); +} - /* First unfix and release lock on the bpage */ - mutex_enter(&buf_pool.mutex); - mutex_enter(buf_page_get_mutex(bpage)); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); +/** Initialize a page for read to the buffer buf_pool. If the page is +(1) already in buf_pool, or +(2) if we specify to read only ibuf pages and the page is not an ibuf page, or +(3) if the space is deleted or being deleted, +then this function does nothing. +Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock +on the buffer frame. The io-handler must take care that the flag is cleared +and the lock released later. +@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... +@param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] unzip whether the uncompressed page is + requested (for ROW_FORMAT=COMPRESSED) +@return pointer to the block +@retval NULL in case of an error */ +static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id, + ulint zip_size, bool unzip) +{ + mtr_t mtr; - bpage->id.set_corrupt_id(); - /* Set BUF_IO_NONE before we remove the block from LRU list */ - buf_page_set_io_fix(bpage, BUF_IO_NONE); + if (mode == BUF_READ_IBUF_PAGES_ONLY) + { + /* It is a read-ahead within an ibuf routine */ + ut_ad(!ibuf_bitmap_page(page_id, zip_size)); + ibuf_mtr_start(&mtr); - if (uncompressed) { - rw_lock_x_unlock_gen( - &((buf_block_t*) bpage)->lock, - BUF_IO_READ); - } + if (!recv_no_ibuf_operations && !ibuf_page(page_id, zip_size, &mtr)) + { + ibuf_mtr_commit(&mtr); + return nullptr; + } + } + else + ut_ad(mode == BUF_READ_ANY_PAGE); - mutex_exit(buf_page_get_mutex(bpage)); + buf_page_t *bpage= nullptr; + buf_block_t *block= nullptr; + if (!zip_size || unzip || recv_recovery_is_on()) + { + block= buf_LRU_get_free_block(false); + block->initialise(page_id, zip_size); + /* We set a pass-type x-lock on the frame because then + the same thread which called for the read operation + (and is running now at this point of code) can wait + for the read to complete by waiting for the x-lock on + the frame; if the x-lock were recursive, the same + thread would illegally get the x-lock before the page + read is completed. The x-lock will be released + in buf_page_read_complete() by the io-handler thread. */ + rw_lock_x_lock_gen(&block->lock, BUF_IO_READ); + } - /* remove the block from LRU list */ - buf_LRU_free_one_page(bpage, old_page_id); + const ulint fold= page_id.fold(); - ut_ad(buf_pool.n_pend_reads > 0); - buf_pool.n_pend_reads--; + mutex_enter(&buf_pool.mutex); - mutex_exit(&buf_pool.mutex); + /* We must acquire hash_lock this early to prevent + a race condition with buf_pool_t::watch_remove() */ + page_hash_latch *hash_lock= buf_pool.page_hash.lock_get(fold); + hash_lock->write_lock(); + + buf_page_t *hash_page= buf_pool.page_hash_get_low(page_id, fold); + if (hash_page && !buf_pool.watch_is_sentinel(*hash_page)) + { + /* The page is already in the buffer pool. */ + hash_lock->write_unlock(); + if (block) + { + rw_lock_x_unlock_gen(&block->lock, BUF_IO_READ); + buf_LRU_block_free_non_file_page(block); + } + goto func_exit; + } + + if (UNIV_LIKELY(block != nullptr)) + { + bpage= &block->page; + + /* Insert into the hash table of file pages */ + if (hash_page) + { + /* Preserve the reference count. */ + auto buf_fix_count= hash_page->buf_fix_count(); + ut_a(buf_fix_count > 0); + block->page.add_buf_fix_count(buf_fix_count); + buf_pool.watch_remove(hash_page); + } + + block->page.set_io_fix(BUF_IO_READ); + block->page.set_state(BUF_BLOCK_FILE_PAGE); + ut_ad(!block->page.in_page_hash); + ut_d(block->page.in_page_hash= true); + HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, bpage); + hash_lock->write_unlock(); + + /* The block must be put to the LRU list, to the old blocks */ + buf_LRU_add_block(bpage, true/* to old blocks */); + + if (UNIV_UNLIKELY(zip_size)) + { + /* buf_pool.mutex may be released and reacquired by + buf_buddy_alloc(). We must defer this operation until after the + block descriptor has been added to buf_pool.LRU and + buf_pool.page_hash. */ + block->page.zip.data= static_cast + (buf_buddy_alloc(zip_size)); + + /* To maintain the invariant + block->in_unzip_LRU_list == block->page.belongs_to_unzip_LRU() + we have to add this block to unzip_LRU + after block->page.zip.data is set. */ + ut_ad(block->page.belongs_to_unzip_LRU()); + buf_unzip_LRU_add_block(block, TRUE); + } + } + else + { + hash_lock->write_unlock(); + + /* The compressed page must be allocated before the + control block (bpage), in order to avoid the + invocation of buf_buddy_relocate_block() on + uninitialized data. */ + bool lru= false; + void *data= buf_buddy_alloc(zip_size, &lru); + + hash_lock->write_lock(); + + /* If buf_buddy_alloc() allocated storage from the LRU list, + it released and reacquired buf_pool.mutex. Thus, we must + check the page_hash again, as it may have been modified. */ + if (UNIV_UNLIKELY(lru)) + { + hash_page= buf_pool.page_hash_get_low(page_id, fold); + + if (UNIV_UNLIKELY(hash_page && !buf_pool.watch_is_sentinel(*hash_page))) + { + /* The block was added by some other thread. */ + hash_lock->write_unlock(); + buf_buddy_free(data, zip_size); + goto func_exit; + } + } + + bpage= buf_page_alloc_descriptor(); + + page_zip_des_init(&bpage->zip); + page_zip_set_size(&bpage->zip, zip_size); + bpage->zip.data = (page_zip_t*) data; + + bpage->init(BUF_BLOCK_ZIP_PAGE, page_id); + + if (hash_page) + { + /* Preserve the reference count. It can be 0 if + buf_pool_t::watch_unset() is executing concurrently, + waiting for buf_pool.mutex, which we are holding. */ + bpage->add_buf_fix_count(hash_page->buf_fix_count()); + buf_pool.watch_remove(hash_page); + } + + ut_ad(!bpage->in_page_hash); + ut_d(bpage->in_page_hash= true); + HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, bpage); + bpage->set_io_fix(BUF_IO_READ); + hash_lock->write_unlock(); + + /* The block must be put to the LRU list, to the old blocks. + The zip size is already set into the page zip */ + buf_LRU_add_block(bpage, true/* to old blocks */); +#ifdef UNIV_DEBUG + buf_LRU_insert_zip_clean(bpage); +#endif /* UNIV_DEBUG */ + } + + mutex_exit(&buf_pool.mutex); + buf_pool.n_pend_reads++; + goto func_exit_no_mutex; +func_exit: + mutex_exit(&buf_pool.mutex); +func_exit_no_mutex: + if (mode == BUF_READ_IBUF_PAGES_ONLY) + ibuf_mtr_commit(&mtr); + + ut_ad(!bpage || bpage->in_file()); + + return bpage; } /** Low-level function which reads a page asynchronously from a file to the @@ -118,8 +289,7 @@ buf_read_page_low( *err = DB_SUCCESS; - if (page_id.space() == TRX_SYS_SPACE - && buf_dblwr_page_inside(page_id.page_no())) { + if (!page_id.space() && buf_dblwr_page_inside(page_id.page_no())) { ib::error() << "Trying to read doublewrite buffer page " << page_id; @@ -141,7 +311,7 @@ buf_read_page_low( or is being dropped; if we succeed in initing the page in the buffer pool for read, then DISCARD cannot proceed until the read has completed */ - bpage = buf_page_init_for_read(err, mode, page_id, zip_size, unzip); + bpage = buf_page_init_for_read(mode, page_id, zip_size, unzip); if (bpage == NULL) { @@ -152,7 +322,7 @@ buf_read_page_low( "read page " << page_id << " zip_size=" << zip_size << " unzip=" << unzip << ',' << (sync ? "sync" : "async")); - ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_file()); if (sync) { thd_wait_begin(NULL, THD_WAIT_DISKIO); @@ -163,23 +333,24 @@ buf_read_page_low( if (zip_size) { dst = bpage->zip.data; } else { - ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); + ut_a(bpage->state() == BUF_BLOCK_FILE_PAGE); dst = ((buf_block_t*) bpage)->frame; } - *err = fil_io( + fil_io_t fio = fil_io( IORequestRead, sync, page_id, zip_size, 0, zip_size ? zip_size : srv_page_size, dst, bpage, ignore); - if (sync) { - thd_wait_end(NULL); - } + *err= fio.err; - if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { - if (ignore || *err == DB_TABLESPACE_DELETED) { - buf_read_page_handle_error(bpage); + if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) { + if (ignore || fio.err == DB_TABLESPACE_DELETED) { + buf_pool.corrupted_evict(bpage); + if (sync && fio.node) { + fio.node->space->release_for_io(); + } return(0); } @@ -187,9 +358,11 @@ buf_read_page_low( } if (sync) { - /* The i/o is already completed when we arrive from - fil_read */ - *err = buf_page_io_complete(bpage); + thd_wait_end(NULL); + + /* The i/o was already completed in fil_io() */ + *err = buf_page_read_complete(bpage, *fio.node); + fio.node->space->release_for_io(); if (*err != DB_SUCCESS) { return(0); @@ -218,153 +391,79 @@ get read even if we return a positive value! */ ulint buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) { - ulint recent_blocks = 0; - ulint ibuf_mode; - ulint count; - ulint low, high; - dberr_t err = DB_SUCCESS; - ulint i; + if (!srv_random_read_ahead) + return 0; - if (!srv_random_read_ahead) { - /* Disabled by user */ - return(0); - } + if (srv_startup_is_before_trx_rollback_phase) + /* No read-ahead to avoid thread deadlocks */ + return 0; - if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); - } + if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) + /* If it is an ibuf bitmap page or trx sys hdr, we do no + read-ahead, as that could break the ibuf page access order */ + return 0; - if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) { + if (buf_pool.n_pend_reads > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT) + return 0; - /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ + fil_space_t* space= fil_space_acquire(page_id.space()); + if (!space) + return 0; - return(0); - } + const uint32_t buf_read_ahead_area= buf_pool.read_ahead_area; + ulint count= 5 + buf_read_ahead_area / 8; + const page_id_t low= page_id - (page_id.page_no() % buf_read_ahead_area); + page_id_t high= low + buf_read_ahead_area; + high.set_page_no(std::min(high.page_no(), + static_cast(space->size - 1))); - const ulint buf_read_ahead_random_area - = buf_pool.read_ahead_area; - low = (page_id.page_no() / buf_read_ahead_random_area) - * buf_read_ahead_random_area; + /* Count how many blocks in the area have been recently accessed, + that is, reside near the start of the LRU list. */ - high = (page_id.page_no() / buf_read_ahead_random_area + 1) - * buf_read_ahead_random_area; + for (page_id_t i= low; i < high; ++i) + { + const ulint fold= i.fold(); + page_hash_latch *hash_lock= buf_pool.page_hash.lock(fold); + const buf_page_t *bpage= buf_pool.page_hash_get_low(i, fold); + bool found= bpage && bpage->is_accessed() && buf_page_peek_if_young(bpage); + hash_lock->read_unlock(); + if (found && !--count) + goto read_ahead; + } - /* If DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ - if (fil_space_t* space = fil_space_acquire(page_id.space())) { - -#ifdef UNIV_DEBUG - if (srv_file_per_table) { - ulint size = 0; - const ulint physical_size = space->physical_size(); - - for (const fil_node_t* node = - UT_LIST_GET_FIRST(space->chain); - node != NULL; - node = UT_LIST_GET_NEXT(chain, node)) { - - size += ulint(os_file_get_size(node->handle) - / physical_size); - } - - ut_ad(size == space->size); - } -#endif /* UNIV_DEBUG */ - - if (high > space->size) { - high = space->size; - } - space->release(); - } else { - return(0); - } - - mutex_enter(&buf_pool.mutex); - - if (buf_pool.n_pend_reads - > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - mutex_exit(&buf_pool.mutex); - - return(0); - } - - /* Count how many blocks in the area have been recently accessed, - that is, reside near the start of the LRU list. */ - - for (i = low; i < high; i++) { - if (const buf_page_t* bpage = buf_page_hash_get( - page_id_t(page_id.space(), i))) { - if (buf_page_is_accessed(bpage) - && buf_page_peek_if_young(bpage) - && ++recent_blocks - >= 5 + buf_pool.read_ahead_area / 8) { - mutex_exit(&buf_pool.mutex); - goto read_ahead; - } - } - } - - mutex_exit(&buf_pool.mutex); - /* Do nothing */ - return(0); + space->release(); + return 0; read_ahead: - /* Read all the suitable blocks within the area */ + /* Read all the suitable blocks within the area */ + const ulint ibuf_mode= ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; - ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; - count = 0; + for (page_id_t i= low; i < high; ++i) + { + if (ibuf_bitmap_page(i, zip_size)) + continue; + dberr_t err; + count+= buf_read_page_low(&err, false, ibuf_mode, i, zip_size, false); + } - for (i = low; i < high; i++) { - /* It is only sensible to do read-ahead in the non-sync aio - mode: hence FALSE as the first parameter */ + if (count) + DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", + count, space->chain.start->name, + low.page_no())); + space->release(); - const page_id_t cur_page_id(page_id.space(), i); + /* Read ahead is considered one I/O operation for the purpose of + LRU policy decision. */ + buf_LRU_stat_inc_io(); - if (!ibuf_bitmap_page(cur_page_id, zip_size)) { - count += buf_read_page_low( - &err, false, - ibuf_mode, - cur_page_id, zip_size, false); - - switch (err) { - case DB_SUCCESS: - case DB_ERROR: - break; - case DB_TABLESPACE_DELETED: - ib::info() << "Random readahead trying to" - " access page " << cur_page_id - << " in nonexisting or" - " being-dropped tablespace"; - break; - default: - ut_error; - } - } - } - - - if (count) { - DBUG_PRINT("ib_buf", ("random read-ahead %u pages, %u:%u", - (unsigned) count, - (unsigned) page_id.space(), - (unsigned) page_id.page_no())); - } - - /* Read ahead is considered one I/O operation for the purpose of - LRU policy decision. */ - buf_LRU_stat_inc_io(); - - buf_pool.stat.n_ra_pages_read_rnd += count; - srv_stats.buf_pool_reads.add(count); - return(count); + buf_pool.stat.n_ra_pages_read_rnd+= count; + srv_stats.buf_pool_reads.add(count); + return count; } -/** High-level function which reads a page asynchronously from a file to the -buffer buf_pool if it is not already there. Sets the io_fix flag and sets -an exclusive lock on the buffer frame. The flag is cleared and the x-lock +/** High-level function which reads a page from a file to buf_pool +if it is not already there. Sets the io_fix and an exclusive lock +on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @@ -375,16 +474,9 @@ after decryption normal page checksum does not match. @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ dberr_t buf_read_page(const page_id_t page_id, ulint zip_size) { - ulint count; dberr_t err = DB_SUCCESS; - /* We do synchronous IO because our AIO completion code - is sub-optimal. See buf_page_io_complete(), we have to - acquire the buffer pool mutex before acquiring the block - mutex, required for updating the page state. The acquire - of the buffer pool mutex becomes an expensive bottleneck. */ - - count = buf_read_page_low( + ulint count = buf_read_page_low( &err, true, BUF_READ_ANY_PAGE, page_id, zip_size, false); srv_stats.buf_pool_reads.add(count); @@ -477,247 +569,155 @@ which could result in a deadlock if the OS does not support asynchronous io. ulint buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) { - buf_page_t* bpage; - buf_frame_t* frame; - buf_page_t* pred_bpage = NULL; - ulint pred_offset; - ulint succ_offset; - int asc_or_desc; - ulint new_offset; - ulint fail_count; - ulint low, high; - dberr_t err = DB_SUCCESS; - ulint i; - ulint threshold; + /* check if readahead is disabled */ + if (!srv_read_ahead_threshold) + return 0; - /* check if readahead is disabled */ - if (!srv_read_ahead_threshold) { - return(0); - } + if (srv_startup_is_before_trx_rollback_phase) + /* No read-ahead to avoid thread deadlocks */ + return 0; - if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); - } + if (buf_pool.n_pend_reads > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT) + return 0; - const ulint buf_read_ahead_linear_area - = buf_pool.read_ahead_area; - low = (page_id.page_no() / buf_read_ahead_linear_area) - * buf_read_ahead_linear_area; - high = (page_id.page_no() / buf_read_ahead_linear_area + 1) - * buf_read_ahead_linear_area; + const uint32_t buf_read_ahead_area= buf_pool.read_ahead_area; + const page_id_t low= page_id - (page_id.page_no() % buf_read_ahead_area); + const page_id_t high_1= low + (buf_read_ahead_area - 1); - if ((page_id.page_no() != low) && (page_id.page_no() != high - 1)) { - /* This is not a border page of the area: return */ + /* We will check that almost all pages in the area have been accessed + in the desired order. */ + const bool descending= page_id == low; - return(0); - } + if (!descending && page_id != high_1) + /* This is not a border page of the area */ + return 0; - if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) { + if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) + /* If it is an ibuf bitmap page or trx sys hdr, we do no + read-ahead, as that could break the ibuf page access order */ + return 0; - /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ + fil_space_t *space= fil_space_acquire(page_id.space()); + if (!space) + return 0; + if (high_1.page_no() >= space->size) + { + /* The area is not whole. */ + space->release(); + return 0; + } - return(0); - } + /* How many out of order accessed pages can we ignore + when working out the access pattern for linear readahead */ + ulint count= std::min(buf_pool_t::READ_AHEAD_PAGES - + srv_read_ahead_threshold, + uint32_t{buf_pool.read_ahead_area}); + page_id_t new_low= low, new_high_1= high_1; + unsigned prev_accessed= 0; + for (page_id_t i= low; i != high_1; ++i) + { + const ulint fold= i.fold(); + page_hash_latch *hash_lock= buf_pool.page_hash.lock(fold); + const buf_page_t* bpage= buf_pool.page_hash_get_low(i, fold); + if (i == page_id) + { + /* Read the natural predecessor and successor page addresses from + the page; NOTE that because the calling thread may have an x-latch + on the page, we do not acquire an s-latch on the page, this is to + prevent deadlocks. The hash_lock is only protecting the + buf_pool.page_hash for page i, not the bpage contents itself. */ + if (!bpage) + { +hard_fail: + hash_lock->read_unlock(); + space->release(); + return 0; + } + const byte *f; + switch (UNIV_EXPECT(bpage->state(), BUF_BLOCK_FILE_PAGE)) { + case BUF_BLOCK_FILE_PAGE: + f= reinterpret_cast(bpage)->frame; + break; + case BUF_BLOCK_ZIP_PAGE: + f= bpage->zip.data; + break; + default: + goto hard_fail; + } - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ - ulint space_size; + uint32_t prev= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_PREV)); + uint32_t next= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_NEXT)); + if (prev == FIL_NULL || next == FIL_NULL) + goto hard_fail; + page_id_t id= page_id; + if (descending && next - 1 == page_id.page_no()) + id.set_page_no(prev); + else if (!descending && prev + 1 == page_id.page_no()) + id.set_page_no(next); + else + goto hard_fail; /* Successor or predecessor not in the right order */ - if (fil_space_t* space = fil_space_acquire(page_id.space())) { - space_size = space->size; - space->release(); + new_low= id - (id.page_no() % buf_read_ahead_area); + new_high_1= new_low + (buf_read_ahead_area - 1); - if (high > space_size) { - /* The area is not whole */ - return(0); - } - } else { - return(0); - } + if (id != new_low && id != new_high_1) + /* This is not a border page of the area: return */ + goto hard_fail; + if (new_high_1.page_no() >= space->size) + /* The area is not whole */ + goto hard_fail; + } + else if (!bpage) + { +failed: + hash_lock->read_unlock(); + if (--count) + continue; + space->release(); + return 0; + } - mutex_enter(&buf_pool.mutex); + const unsigned accessed= bpage->is_accessed(); + if (!accessed) + goto failed; + /* Note that buf_page_t::is_accessed() returns the time of the + first access. If some blocks of the extent existed in the buffer + pool at the time of a linear access pattern, the first access + times may be nonmonotonic, even though the latest access times + were linear. The threshold (srv_read_ahead_factor) should help a + little against this. */ + bool fail= prev_accessed && + (descending ? prev_accessed > accessed : prev_accessed < accessed); + prev_accessed= accessed; + if (fail) + goto failed; + hash_lock->read_unlock(); + } - if (buf_pool.n_pend_reads - > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - mutex_exit(&buf_pool.mutex); + /* If we got this far, read-ahead can be sensible: do it */ + count= 0; + for (ulint ibuf_mode= ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; + new_low != new_high_1; ++new_low) + { + if (ibuf_bitmap_page(new_low, zip_size)) + continue; + dberr_t err; + count+= buf_read_page_low(&err, false, ibuf_mode, new_low, zip_size, + false); + } - return(0); - } + if (count) + DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", + count, space->chain.start->name, + new_low.page_no())); + space->release(); - /* Check that almost all pages in the area have been accessed; if - offset == low, the accesses must be in a descending order, otherwise, - in an ascending order. */ + /* Read ahead is considered one I/O operation for the purpose of + LRU policy decision. */ + buf_LRU_stat_inc_io(); - asc_or_desc = 1; - - if (page_id.page_no() == low) { - asc_or_desc = -1; - } - - /* How many out of order accessed pages can we ignore - when working out the access pattern for linear readahead */ - threshold = ut_min(static_cast(64 - srv_read_ahead_threshold), - buf_pool.read_ahead_area); - - fail_count = 0; - - for (i = low; i < high; i++) { - bpage = buf_page_hash_get(page_id_t(page_id.space(), i)); - - if (bpage == NULL || !buf_page_is_accessed(bpage)) { - /* Not accessed */ - fail_count++; - - } else if (pred_bpage) { - /* Note that buf_page_is_accessed() returns - the time of the first access. If some blocks - of the extent existed in the buffer pool at - the time of a linear access pattern, the first - access times may be nonmonotonic, even though - the latest access times were linear. The - threshold (srv_read_ahead_factor) should help - a little against this. */ - int res = ut_ulint_cmp( - buf_page_is_accessed(bpage), - buf_page_is_accessed(pred_bpage)); - /* Accesses not in the right order */ - if (res != 0 && res != asc_or_desc) { - fail_count++; - } - } - - if (fail_count > threshold) { - /* Too many failures: return */ - mutex_exit(&buf_pool.mutex); - return(0); - } - - if (bpage && buf_page_is_accessed(bpage)) { - pred_bpage = bpage; - } - } - - /* If we got this far, we know that enough pages in the area have - been accessed in the right order: linear read-ahead can be sensible */ - - bpage = buf_page_hash_get(page_id); - - if (bpage == NULL) { - mutex_exit(&buf_pool.mutex); - - return(0); - } - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_ZIP_PAGE: - frame = bpage->zip.data; - break; - case BUF_BLOCK_FILE_PAGE: - frame = ((buf_block_t*) bpage)->frame; - break; - default: - ut_error; - break; - } - - /* Read the natural predecessor and successor page addresses from - the page; NOTE that because the calling thread may have an x-latch - on the page, we do not acquire an s-latch on the page, this is to - prevent deadlocks. Even if we read values which are nonsense, the - algorithm will work. */ - - pred_offset = mach_read_from_4(my_assume_aligned<4>(FIL_PAGE_PREV - + frame)); - succ_offset = mach_read_from_4(my_assume_aligned<4>(FIL_PAGE_NEXT - + frame)); - mutex_exit(&buf_pool.mutex); - - if ((page_id.page_no() == low) - && (succ_offset == page_id.page_no() + 1)) { - - /* This is ok, we can continue */ - new_offset = pred_offset; - - } else if ((page_id.page_no() == high - 1) - && (pred_offset == page_id.page_no() - 1)) { - - /* This is ok, we can continue */ - new_offset = succ_offset; - } else { - /* Successor or predecessor not in the right order */ - - return(0); - } - - low = (new_offset / buf_read_ahead_linear_area) - * buf_read_ahead_linear_area; - high = (new_offset / buf_read_ahead_linear_area + 1) - * buf_read_ahead_linear_area; - - if ((new_offset != low) && (new_offset != high - 1)) { - /* This is not a border page of the area: return */ - - return(0); - } - - if (high > space_size) { - /* The area is not whole, return */ - - return(0); - } - - ulint count = 0; - - /* If we got this far, read-ahead can be sensible: do it */ - - ulint ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; - - for (i = low; i < high; i++) { - /* It is only sensible to do read-ahead in the non-sync - aio mode: hence FALSE as the first parameter */ - - const page_id_t cur_page_id(page_id.space(), i); - - if (!ibuf_bitmap_page(cur_page_id, zip_size)) { - count += buf_read_page_low( - &err, false, - ibuf_mode, cur_page_id, zip_size, false); - - switch (err) { - case DB_SUCCESS: - case DB_TABLESPACE_DELETED: - case DB_ERROR: - break; - case DB_PAGE_CORRUPTED: - case DB_DECRYPTION_FAILED: - ib::error() << "linear readahead failed to" - " read or decrypt " - << page_id_t(page_id.space(), i); - break; - default: - ut_error; - } - } - } - - if (count) { - DBUG_PRINT("ib_buf", ("linear read-ahead " ULINTPF " pages, " - "%u:%u", - count, - page_id.space(), - page_id.page_no())); - } - - /* Read ahead is considered one I/O operation for the purpose of - LRU policy decision. */ - buf_LRU_stat_inc_io(); - - buf_pool.stat.n_ra_pages_read += count; - return(count); + buf_pool.stat.n_ra_pages_read+= count; + return count; } /** Issues read requests for pages which recovery wants to read in. diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index af2ea0fd198..0fb9f5e66af 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -233,41 +233,20 @@ dtuple_validate( /*============*/ const dtuple_t* tuple) /*!< in: tuple */ { - const dfield_t* field; - ulint n_fields; - ulint len; - ulint i; - ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); +#ifdef HAVE_valgrind_or_MSAN + const ulint n_fields = dtuple_get_n_fields(tuple); - n_fields = dtuple_get_n_fields(tuple); - - /* We dereference all the data of each field to test - for memory traps */ - - for (i = 0; i < n_fields; i++) { - - field = dtuple_get_nth_field(tuple, i); - len = dfield_get_len(field); + for (ulint i = 0; i < n_fields; i++) { + const dfield_t* field = dtuple_get_nth_field(tuple, i); if (!dfield_is_null(field)) { - - const byte* data; - - data = static_cast(dfield_get_data(field)); -#ifndef UNIV_DEBUG_VALGRIND - ulint j; - - for (j = 0; j < len; j++) { - data++; - } -#endif /* !UNIV_DEBUG_VALGRIND */ - - UNIV_MEM_ASSERT_RW(data, len); + MEM_CHECK_DEFINED(dfield_get_data(field), + dfield_get_len(field)); } } - - ut_a(dtuple_check_typed(tuple)); +#endif /* HAVE_valgrind_or_MSAN */ + ut_ad(dtuple_check_typed(tuple)); return(TRUE); } @@ -748,14 +727,7 @@ ext_write: memcpy(data, dfield_get_data(dfield), local_prefix_len); /* Clear the extern field reference (BLOB pointer). */ memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE); -#if 0 - /* The following would fail the Valgrind checks in - page_cur_insert_rec_low() and page_cur_insert_rec_zip(). - The BLOB pointers in the record will be initialized after - the record and the BLOBs have been written. */ - UNIV_MEM_ALLOC(data + local_prefix_len, - BTR_EXTERN_FIELD_REF_SIZE); -#endif + dfield_set_data(dfield, data, local_len); dfield_set_ext(dfield); diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 79a3adc7aa6..833f2621de6 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -137,7 +137,7 @@ dict_hdr_create( block = fseg_create(fil_system.sys_space, 0, DICT_HDR + DICT_HDR_FSEG_HEADER, mtr); - ut_a(DICT_HDR_PAGE_NO == block->page.id.page_no()); + ut_a(block->page.id() == page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO)); buf_block_t* d = dict_hdr_get(mtr); diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index a5a7fe9f2d7..e00e59f79c4 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -26,7 +26,9 @@ Created 1/8/1996 Heikki Tuuri #include "dict0crea.h" #include "btr0pcur.h" -#include "btr0btr.h" +#ifdef BTR_CUR_HASH_ADAPT +# include "btr0sea.h" +#endif /* BTR_CUR_HASH_ADAPT */ #include "page0page.h" #include "mach0data.h" #include "dict0boot.h" @@ -1300,6 +1302,9 @@ dict_create_index_step( &node->table->fts->cache->init_lock); } +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!node->index->search_info->ref_count); +#endif /* BTR_CUR_HASH_ADAPT */ dict_index_remove_from_cache(node->table, node->index); node->index = NULL; @@ -1486,10 +1491,9 @@ dict_create_or_check_foreign_constraint_tables(void) "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS" - " failed: " << ut_strerr(err) << ". Tablespace is" + " failed: " << err << ". Tablespace is" " full. Dropping incompletely created tables."; ut_ad(err == DB_OUT_OF_FILE_SPACE @@ -1588,10 +1592,9 @@ dict_create_or_check_sys_virtual() "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_VIRTUAL" - " failed: " << ut_strerr(err) << ". Tablespace is" + " failed: " << err << ". Tablespace is" " full or too many transactions." " Dropping incompletely created tables."; @@ -1669,9 +1672,9 @@ dict_foreign_eval_sql( return(error); } - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Foreign key constraint creation failed: " - << ut_strerr(error); + << error; mutex_enter(&dict_foreign_err_mutex); ut_print_timestamp(ef); @@ -2122,10 +2125,9 @@ dict_create_or_check_sys_tablespace(void) "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_TABLESPACES and SYS_DATAFILES" - " has failed with error " << ut_strerr(err) + " has failed with error " << err << ". Dropping incompletely created tables."; ut_a(err == DB_OUT_OF_FILE_SPACE diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d129432d59c..a3b8d025b10 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -747,22 +747,28 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], memcpy(db_buf, name.m_name, db_len); db_buf[db_len]= 0; - size_t tbl_len= strlen(name.m_name + db_len); + size_t tbl_len= strlen(name.m_name + db_len + 1); + + const bool is_temp= tbl_len > TEMP_FILE_PREFIX_LENGTH && + !strncmp(name.m_name, TEMP_FILE_PREFIX, TEMP_FILE_PREFIX_LENGTH); + + if (is_temp); + else if (const char *is_part= static_cast + (memchr(name.m_name + db_len + 1, '#', tbl_len))) + tbl_len= static_cast(is_part - &name.m_name[db_len + 1]); + memcpy(tbl_buf, name.m_name + db_len + 1, tbl_len); - tbl_len--; + tbl_buf[tbl_len]= 0; + if (!dict_locked) mutex_exit(&dict_sys.mutex); *db_name_len= filename_to_tablename(db_buf, db_name, MAX_DATABASE_NAME_LEN + 1, true); - if (tbl_len > TEMP_FILE_PREFIX_LENGTH - && !strncmp(tbl_buf, TEMP_FILE_PREFIX, TEMP_FILE_PREFIX_LENGTH)) + if (is_temp) return false; - if (char* is_part= strchr(tbl_buf, '#')) - *is_part= '\0'; - *tbl_name_len= filename_to_tablename(tbl_buf, tbl_name, MAX_TABLE_NAME_LEN + 1, true); return true; @@ -883,7 +889,17 @@ is_unaccessible: size_t db1_len, tbl1_len; - table->parse_name(db_buf1, tbl_buf1, &db1_len, &tbl1_len); + if (!table->parse_name(db_buf1, tbl_buf1, &db1_len, &tbl1_len)) + { + /* The table was renamed to #sql prefix. + Release MDL (if any) for the old name and return. */ + if (*mdl) + { + mdl_context->release_lock(*mdl); + *mdl= nullptr; + } + return table; + } if (*mdl) { @@ -1018,9 +1034,9 @@ void dict_sys_t::create() const ulint hash_size = buf_pool_get_curr_size() / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE); - table_hash= hash_create(hash_size); - table_id_hash= hash_create(hash_size); - temp_id_hash= hash_create(hash_size); + table_hash.create(hash_size); + table_id_hash.create(hash_size); + temp_id_hash.create(hash_size); rw_lock_create(dict_operation_lock_key, &latch, SYNC_DICT_OPERATION); @@ -1182,24 +1198,24 @@ inline void dict_sys_t::add(dict_table_t* table) /* Look for a table with the same name: error if such exists */ { dict_table_t* table2; - HASH_SEARCH(name_hash, table_hash, fold, + HASH_SEARCH(name_hash, &table_hash, fold, dict_table_t*, table2, ut_ad(table2->cached), !strcmp(table2->name.m_name, table->name.m_name)); ut_a(table2 == NULL); #ifdef UNIV_DEBUG /* Look for the same table pointer with a different name */ - HASH_SEARCH_ALL(name_hash, table_hash, + HASH_SEARCH_ALL(name_hash, &table_hash, dict_table_t*, table2, ut_ad(table2->cached), table2 == table); ut_ad(table2 == NULL); #endif /* UNIV_DEBUG */ } - HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table); + HASH_INSERT(dict_table_t, name_hash, &table_hash, fold, table); /* Look for a table with the same id: error if such exists */ hash_table_t* id_hash = table->is_temporary() - ? temp_id_hash : table_id_hash; + ? &temp_id_hash : &table_id_hash; const ulint id_fold = ut_fold_ull(table->id); { dict_table_t* table2; @@ -1249,25 +1265,12 @@ dict_table_can_be_evicted( } #ifdef BTR_CUR_HASH_ADAPT + /* We cannot really evict the table if adaptive hash + index entries are pointing to any of its indexes. */ for (dict_index_t* index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { - - btr_search_t* info = btr_search_get_info(index); - - /* We are not allowed to free the in-memory index - struct dict_index_t until all entries in the adaptive - hash index that point to any of the page belonging to - his b-tree index are dropped. This is so because - dropping of these entries require access to - dict_index_t struct. To avoid such scenario we keep - a count of number of such pages in the search_info and - only free the dict_index_t struct when this count - drops to zero. - - See also: dict_index_remove_from_cache_low() */ - - if (btr_search_info_get_ref_count(info, index) > 0) { + if (index->n_ahi_pages()) { return(FALSE); } } @@ -1279,6 +1282,70 @@ dict_table_can_be_evicted( return(FALSE); } +#ifdef BTR_CUR_HASH_ADAPT +/** @return a clone of this */ +dict_index_t *dict_index_t::clone() const +{ + ut_ad(n_fields); + ut_ad(!(type & (DICT_IBUF | DICT_SPATIAL | DICT_FTS))); + ut_ad(online_status == ONLINE_INDEX_COMPLETE); + ut_ad(is_committed()); + ut_ad(!is_dummy); + ut_ad(!parser); + ut_ad(!online_log); + ut_ad(!rtr_track); + + const size_t size= sizeof *this + n_fields * sizeof(*fields) + +#ifdef BTR_CUR_ADAPT + sizeof *search_info + +#endif + 1 + strlen(name) + + n_uniq * (sizeof *stat_n_diff_key_vals + + sizeof *stat_n_sample_sizes + + sizeof *stat_n_non_null_key_vals); + + mem_heap_t* heap= mem_heap_create(size); + dict_index_t *index= static_cast(mem_heap_dup(heap, this, + sizeof *this)); + *index= *this; + rw_lock_create(index_tree_rw_lock_key, &index->lock, SYNC_INDEX_TREE); + index->heap= heap; + index->name= mem_heap_strdup(heap, name); + index->fields= static_cast + (mem_heap_dup(heap, fields, n_fields * sizeof *fields)); +#ifdef BTR_CUR_ADAPT + index->search_info= btr_search_info_create(index->heap); +#endif /* BTR_CUR_ADAPT */ + index->stat_n_diff_key_vals= static_cast + (mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_diff_key_vals)); + index->stat_n_sample_sizes= static_cast + (mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_sample_sizes)); + index->stat_n_non_null_key_vals= static_cast + (mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_non_null_key_vals)); + mutex_create(LATCH_ID_ZIP_PAD_MUTEX, &index->zip_pad.mutex); + return index; +} + +/** Clone this index for lazy dropping of the adaptive hash. +@return this or a clone */ +dict_index_t *dict_index_t::clone_if_needed() +{ + if (!search_info->ref_count) + return this; + dict_index_t *prev= UT_LIST_GET_PREV(indexes, this); + + UT_LIST_REMOVE(table->indexes, this); + UT_LIST_ADD_LAST(table->freed_indexes, this); + dict_index_t *index= clone(); + set_freed(); + if (prev) + UT_LIST_INSERT_AFTER(table->indexes, prev, index); + else + UT_LIST_ADD_FIRST(table->indexes, index); + return index; +} +#endif /* BTR_CUR_HASH_ADAPT */ + /**********************************************************************//** Make room in the table cache by evicting an unused table. The unused table should not be part of FK relationship and currently not used in any user @@ -1452,7 +1519,7 @@ dict_table_rename_in_cache( /* Look for a table with the same name: error if such exists */ dict_table_t* table2; - HASH_SEARCH(name_hash, dict_sys.table_hash, fold, + HASH_SEARCH(name_hash, &dict_sys.table_hash, fold, dict_table_t*, table2, ut_ad(table2->cached), (strcmp(table2->name.m_name, new_name) == 0)); DBUG_EXECUTE_IF("dict_table_rename_in_cache_failure", @@ -1546,7 +1613,7 @@ dict_table_rename_in_cache( } /* Remove table from the hash tables of tables */ - HASH_DELETE(dict_table_t, name_hash, dict_sys.table_hash, + HASH_DELETE(dict_table_t, name_hash, &dict_sys.table_hash, ut_fold_string(old_name), table); if (strlen(new_name) > strlen(table->name.m_name)) { @@ -1561,7 +1628,7 @@ dict_table_rename_in_cache( strcpy(table->name.m_name, new_name); /* Add table to hash table of tables */ - HASH_INSERT(dict_table_t, name_hash, dict_sys.table_hash, fold, + HASH_INSERT(dict_table_t, name_hash, &dict_sys.table_hash, fold, table); if (!rename_also_foreigns) { @@ -1829,12 +1896,12 @@ dict_table_change_id_in_cache( /* Remove the table from the hash table of id's */ - HASH_DELETE(dict_table_t, id_hash, dict_sys.table_id_hash, + HASH_DELETE(dict_table_t, id_hash, &dict_sys.table_id_hash, ut_fold_ull(table->id), table); table->id = new_id; /* Add the table back to the hash table */ - HASH_INSERT(dict_table_t, id_hash, dict_sys.table_id_hash, + HASH_INSERT(dict_table_t, id_hash, &dict_sys.table_id_hash, ut_fold_ull(table->id), table); } @@ -1879,11 +1946,11 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep) /* Remove table from the hash tables of tables */ - HASH_DELETE(dict_table_t, name_hash, table_hash, + HASH_DELETE(dict_table_t, name_hash, &table_hash, ut_fold_string(table->name.m_name), table); hash_table_t* id_hash = table->is_temporary() - ? temp_id_hash : table_id_hash; + ? &temp_id_hash : &table_id_hash; const ulint id_fold = ut_fold_ull(table->id); HASH_DELETE(dict_table_t, id_hash, id_hash, id_fold, table); @@ -1919,9 +1986,19 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep) mutex_free(&table->autoinc_mutex); - if (!keep) { - dict_mem_table_free(table); + if (keep) { + return; } + +#ifdef BTR_CUR_HASH_ADAPT + if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) { + table->vc_templ = NULL; + table->id = 0; + return; + } +#endif /* BTR_CUR_HASH_ADAPT */ + + dict_mem_table_free(table); } /****************************************************************//** @@ -2099,6 +2176,10 @@ dict_index_remove_from_cache_low( ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(mutex_own(&dict_sys.mutex)); + ut_ad(table->id); +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!index->freed()); +#endif /* BTR_CUR_HASH_ADAPT */ /* No need to acquire the dict_index_t::lock here because there can't be any active operations on this index (or table). */ @@ -2108,13 +2189,22 @@ dict_index_remove_from_cache_low( row_log_free(index->online_log); } + /* Remove the index from the list of indexes of the table */ + UT_LIST_REMOVE(table->indexes, index); + + /* The index is being dropped, remove any compression stats for it. */ + if (!lru_evict && DICT_TF_GET_ZIP_SSIZE(index->table->flags)) { + mutex_enter(&page_zip_stat_per_index_mutex); + page_zip_stat_per_index.erase(index->id); + mutex_exit(&page_zip_stat_per_index_mutex); + } + + /* Remove the index from affected virtual column index list */ + index->detach_columns(); + #ifdef BTR_CUR_HASH_ADAPT /* We always create search info whether or not adaptive hash index is enabled or not. */ - btr_search_t* info = btr_search_get_info(index); - ulint retries = 0; - ut_ad(info); - /* We are not allowed to free the in-memory index struct dict_index_t until all entries in the adaptive hash index that point to any of the page belonging to his b-tree index @@ -2124,31 +2214,15 @@ dict_index_remove_from_cache_low( only free the dict_index_t struct when this count drops to zero. See also: dict_table_can_be_evicted() */ - do { - if (!btr_search_info_get_ref_count(info, index) - || !buf_LRU_drop_page_hash_for_tablespace(table)) { - break; - } - - ut_a(++retries < 10000); - } while (srv_shutdown_state == SRV_SHUTDOWN_NONE || !lru_evict); + if (index->n_ahi_pages()) { + index->set_freed(); + UT_LIST_ADD_LAST(table->freed_indexes, index); + return; + } #endif /* BTR_CUR_HASH_ADAPT */ rw_lock_free(&index->lock); - /* The index is being dropped, remove any compression stats for it. */ - if (!lru_evict && DICT_TF_GET_ZIP_SSIZE(index->table->flags)) { - mutex_enter(&page_zip_stat_per_index_mutex); - page_zip_stat_per_index.erase(index->id); - mutex_exit(&page_zip_stat_per_index_mutex); - } - - /* Remove the index from the list of indexes of the table */ - UT_LIST_REMOVE(table->indexes, index); - - /* Remove the index from affected virtual column index list */ - index->detach_columns(); - dict_mem_index_free(index); } @@ -3687,7 +3761,7 @@ dict_index_get_if_in_cache_low( return(dict_index_find_on_id_low(index_id)); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /**********************************************************************//** Returns an index object if it is found in the dictionary cache. @return index, NULL if not found */ @@ -3710,9 +3784,7 @@ dict_index_get_if_in_cache( return(index); } -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_DEBUG /**********************************************************************//** Checks that a tuple has n_fields_cmp value in a sensible range, so that no comparison can occur with the page number field in a node pointer. @@ -4808,38 +4880,39 @@ void dict_sys_t::resize() mutex_enter(&mutex); /* all table entries are in table_LRU and table_non_LRU lists */ - hash_table_free(table_hash); - hash_table_free(table_id_hash); - hash_table_free(temp_id_hash); + table_hash.free(); + table_id_hash.free(); + temp_id_hash.free(); const ulint hash_size = buf_pool_get_curr_size() / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE); - table_hash = hash_create(hash_size); - table_id_hash = hash_create(hash_size); - temp_id_hash = hash_create(hash_size); + table_hash.create(hash_size); + table_id_hash.create(hash_size); + temp_id_hash.create(hash_size); - for (dict_table_t* table= UT_LIST_GET_FIRST(table_LRU); table; + for (dict_table_t *table= UT_LIST_GET_FIRST(table_LRU); table; table= UT_LIST_GET_NEXT(table_LRU, table)) { ut_ad(!table->is_temporary()); ulint fold= ut_fold_string(table->name.m_name); ulint id_fold= ut_fold_ull(table->id); - HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table); - HASH_INSERT(dict_table_t, id_hash, table_id_hash, id_fold, table); + HASH_INSERT(dict_table_t, name_hash, &table_hash, fold, table); + HASH_INSERT(dict_table_t, id_hash, &table_id_hash, id_fold, table); } - for (dict_table_t* table = UT_LIST_GET_FIRST(table_non_LRU); table; - table = UT_LIST_GET_NEXT(table_LRU, table)) { - ulint fold = ut_fold_string(table->name.m_name); - ulint id_fold = ut_fold_ull(table->id); + for (dict_table_t *table = UT_LIST_GET_FIRST(table_non_LRU); table; + table= UT_LIST_GET_NEXT(table_LRU, table)) + { + ulint fold= ut_fold_string(table->name.m_name); + ulint id_fold= ut_fold_ull(table->id); - HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table); + HASH_INSERT(dict_table_t, name_hash, &table_hash, fold, table); - hash_table_t* id_hash = table->is_temporary() - ? temp_id_hash : table_id_hash; + hash_table_t *id_hash= table->is_temporary() + ? &temp_id_hash : &table_id_hash; - HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table); + HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table); } mutex_exit(&mutex); @@ -4855,27 +4928,19 @@ void dict_sys_t::close() /* Free the hash elements. We don't remove them from the table because we are going to destroy the table anyway. */ - for (ulint i = 0; i < hash_get_n_cells(table_hash); i++) - { - dict_table_t* table = static_cast(HASH_GET_FIRST(table_hash, - i)); + for (ulint i= table_hash.n_cells; i--; ) + while (dict_table_t *table= static_cast + (HASH_GET_FIRST(&table_hash, i))) + dict_sys.remove(table); - while (table) - { - dict_table_t* prev_table = table; - table = static_cast(HASH_GET_NEXT(name_hash, prev_table)); - dict_sys.remove(prev_table); - } - } - - hash_table_free(table_hash); + table_hash.free(); /* table_id_hash contains the same elements as in table_hash, therefore we don't delete the individual elements. */ - hash_table_free(table_id_hash); + table_id_hash.free(); /* No temporary tables should exist at this point. */ - hash_table_free(temp_id_hash); + temp_id_hash.free(); mutex_exit(&mutex); mutex_free(&mutex); @@ -5075,10 +5140,7 @@ dict_index_zip_pad_update( beyond max pad size. */ if (info->pad + ZIP_PAD_INCR < (srv_page_size * zip_pad_max) / 100) { - /* Use atomics even though we have the mutex. - This is to ensure that we are able to read - info->pad atomically. */ - info->pad += ZIP_PAD_INCR; + info->pad.fetch_add(ZIP_PAD_INCR); MONITOR_INC(MONITOR_PAD_INCREMENTS); } @@ -5095,11 +5157,7 @@ dict_index_zip_pad_update( padding. */ if (info->n_rounds >= ZIP_PAD_SUCCESSFUL_ROUND_LIMIT && info->pad > 0) { - - /* Use atomics even though we have the mutex. - This is to ensure that we are able to read - info->pad atomically. */ - info->pad -= ZIP_PAD_INCR; + info->pad.fetch_sub(ZIP_PAD_INCR); info->n_rounds = 0; diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 7f933cde0f6..b8fdff89545 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -387,7 +387,7 @@ dict_process_sys_tables_rec_and_mtr_commit( ut_a(!rec_get_deleted_flag(rec, 0)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_S_FIX)); /* Get the table name */ table_name_t table_name(mem_heap_strdupl(heap, field, len)); @@ -899,7 +899,7 @@ dict_update_filepath( trx->dict_operation_lock_mode = 0; trx_free(trx); - if (err == DB_SUCCESS) { + if (UNIV_LIKELY(err == DB_SUCCESS)) { /* We just updated SYS_DATAFILES due to the contents in a link file. Make a note that we did this. */ ib::info() << "The InnoDB data dictionary table SYS_DATAFILES" @@ -909,7 +909,7 @@ dict_update_filepath( ib::warn() << "Error occurred while updating InnoDB data" " dictionary table SYS_DATAFILES for tablespace ID " << space_id << " to file " << filepath << ": " - << ut_strerr(err) << "."; + << err << "."; } return(err); @@ -1354,6 +1354,7 @@ static ulint dict_check_sys_tables() for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES); rec != NULL; + mtr.commit(), mtr.start(), rec = dict_getnext_system(&pcur, &mtr)) { const byte* field; ulint len; @@ -1530,7 +1531,7 @@ dict_load_column_low( ulint pos; ulint num_base; - ut_ad(table || column); + ut_ad(!table == !!column); if (rec_get_deleted_flag(rec, 0)) { return(dict_load_column_del); @@ -1637,7 +1638,7 @@ err_len: } num_base = mach_read_from_4(field); - if (column == NULL) { + if (table) { if (prtype & DATA_VIRTUAL) { #ifdef UNIV_DEBUG dict_v_col_t* vcol = diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index a6a7951a758..22a77a7a220 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -157,6 +157,9 @@ dict_mem_table_create( lock_table_lock_list_init(&table->locks); UT_LIST_INIT(table->indexes, &dict_index_t::indexes); +#ifdef BTR_CUR_HASH_ADAPT + UT_LIST_INIT(table->freed_indexes, &dict_index_t::indexes); +#endif /* BTR_CUR_HASH_ADAPT */ table->heap = heap; @@ -216,6 +219,10 @@ dict_mem_table_free( { ut_ad(table); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + ut_ad(UT_LIST_GET_LEN(table->indexes) == 0); +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(UT_LIST_GET_LEN(table->freed_indexes) == 0); +#endif /* BTR_CUR_HASH_ADAPT */ ut_d(table->cached = FALSE); if (dict_table_has_fts_index(table) diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index a63798dc321..797f76862fa 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -409,7 +409,7 @@ dict_stats_table_clone_create( t = (dict_table_t*) mem_heap_alloc(heap, sizeof(*t)); - UNIV_MEM_ASSERT_RW_ABORT(&table->id, sizeof(table->id)); + MEM_CHECK_DEFINED(&table->id, sizeof(table->id)); t->id = table->id; t->heap = heap; @@ -419,6 +419,9 @@ dict_stats_table_clone_create( t->corrupted = table->corrupted; UT_LIST_INIT(t->indexes, &dict_index_t::indexes); +#ifdef BTR_CUR_HASH_ADAPT + UT_LIST_INIT(t->freed_indexes, &dict_index_t::indexes); +#endif /* BTR_CUR_HASH_ADAPT */ for (index = dict_table_get_first_index(table); index != NULL; @@ -434,7 +437,7 @@ dict_stats_table_clone_create( idx = (dict_index_t*) mem_heap_alloc(heap, sizeof(*idx)); - UNIV_MEM_ASSERT_RW_ABORT(&index->id, sizeof(index->id)); + MEM_CHECK_DEFINED(&index->id, sizeof(index->id)); idx->id = index->id; idx->name = mem_heap_strdup(heap, index->name); @@ -580,23 +583,23 @@ dict_stats_assert_initialized_index( /*================================*/ const dict_index_t* index) /*!< in: index */ { - UNIV_MEM_ASSERT_RW_ABORT( + MEM_CHECK_DEFINED( index->stat_n_diff_key_vals, index->n_uniq * sizeof(index->stat_n_diff_key_vals[0])); - UNIV_MEM_ASSERT_RW_ABORT( + MEM_CHECK_DEFINED( index->stat_n_sample_sizes, index->n_uniq * sizeof(index->stat_n_sample_sizes[0])); - UNIV_MEM_ASSERT_RW_ABORT( + MEM_CHECK_DEFINED( index->stat_n_non_null_key_vals, index->n_uniq * sizeof(index->stat_n_non_null_key_vals[0])); - UNIV_MEM_ASSERT_RW_ABORT( + MEM_CHECK_DEFINED( &index->stat_index_size, sizeof(index->stat_index_size)); - UNIV_MEM_ASSERT_RW_ABORT( + MEM_CHECK_DEFINED( &index->stat_n_leaf_pages, sizeof(index->stat_n_leaf_pages)); } @@ -611,32 +614,32 @@ dict_stats_assert_initialized( { ut_a(table->stat_initialized); - UNIV_MEM_ASSERT_RW_ABORT(&table->stats_last_recalc, - sizeof(table->stats_last_recalc)); + MEM_CHECK_DEFINED(&table->stats_last_recalc, + sizeof table->stats_last_recalc); - UNIV_MEM_ASSERT_RW_ABORT(&table->stat_persistent, - sizeof(table->stat_persistent)); + MEM_CHECK_DEFINED(&table->stat_persistent, + sizeof table->stat_persistent); - UNIV_MEM_ASSERT_RW_ABORT(&table->stats_auto_recalc, - sizeof(table->stats_auto_recalc)); + MEM_CHECK_DEFINED(&table->stats_auto_recalc, + sizeof table->stats_auto_recalc); - UNIV_MEM_ASSERT_RW_ABORT(&table->stats_sample_pages, - sizeof(table->stats_sample_pages)); + MEM_CHECK_DEFINED(&table->stats_sample_pages, + sizeof table->stats_sample_pages); - UNIV_MEM_ASSERT_RW_ABORT(&table->stat_n_rows, - sizeof(table->stat_n_rows)); + MEM_CHECK_DEFINED(&table->stat_n_rows, + sizeof table->stat_n_rows); - UNIV_MEM_ASSERT_RW_ABORT(&table->stat_clustered_index_size, - sizeof(table->stat_clustered_index_size)); + MEM_CHECK_DEFINED(&table->stat_clustered_index_size, + sizeof table->stat_clustered_index_size); - UNIV_MEM_ASSERT_RW_ABORT(&table->stat_sum_of_other_index_sizes, - sizeof(table->stat_sum_of_other_index_sizes)); + MEM_CHECK_DEFINED(&table->stat_sum_of_other_index_sizes, + sizeof table->stat_sum_of_other_index_sizes); - UNIV_MEM_ASSERT_RW_ABORT(&table->stat_modified_counter, - sizeof(table->stat_modified_counter)); + MEM_CHECK_DEFINED(&table->stat_modified_counter, + sizeof table->stat_modified_counter); - UNIV_MEM_ASSERT_RW_ABORT(&table->stats_bg_flag, - sizeof(table->stats_bg_flag)); + MEM_CHECK_DEFINED(&table->stats_bg_flag, + sizeof table->stats_bg_flag); for (dict_index_t* index = dict_table_get_first_index(table); index != NULL; @@ -1017,8 +1020,7 @@ dict_stats_analyze_index_level( DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n", __func__, index->table->name, index->name, level); - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); n_uniq = dict_index_get_n_unique(index); @@ -1650,8 +1652,7 @@ dict_stats_analyze_index_for_n_prefix( n_prefix, n_diff_data->n_diff_on_level); #endif - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); /* Position pcur on the leftmost record on the leftmost page on the desired level. */ @@ -2303,20 +2304,19 @@ dict_stats_save_index_stat( pars_info_add_str_literal(pinfo, "database_name", db_utf8); pars_info_add_str_literal(pinfo, "table_name", table_utf8); pars_info_add_str_literal(pinfo, "index_name", index->name); - UNIV_MEM_ASSERT_RW_ABORT(&last_update, 4); + MEM_CHECK_DEFINED(&last_update, 4); pars_info_add_int4_literal(pinfo, "last_update", uint32(last_update)); - UNIV_MEM_ASSERT_RW_ABORT(stat_name, strlen(stat_name)); + MEM_CHECK_DEFINED(stat_name, strlen(stat_name)); pars_info_add_str_literal(pinfo, "stat_name", stat_name); - UNIV_MEM_ASSERT_RW_ABORT(&stat_value, 8); + MEM_CHECK_DEFINED(&stat_value, 8); pars_info_add_ull_literal(pinfo, "stat_value", stat_value); if (sample_size != NULL) { - UNIV_MEM_ASSERT_RW_ABORT(sample_size, 8); + MEM_CHECK_DEFINED(sample_size, 8); pars_info_add_ull_literal(pinfo, "sample_size", *sample_size); } else { pars_info_add_literal(pinfo, "sample_size", NULL, UNIV_SQL_NULL, DATA_FIXBINARY, 0); } - UNIV_MEM_ASSERT_RW_ABORT(stat_description, strlen(stat_description)); pars_info_add_str_literal(pinfo, "stat_description", stat_description); @@ -2346,14 +2346,14 @@ dict_stats_save_index_stat( ");\n" "END;", trx); - if (ret != DB_SUCCESS) { + if (UNIV_UNLIKELY(ret != DB_SUCCESS)) { if (innodb_index_stats_not_found == false && index->stats_error_printed == false) { ib::error() << "Cannot save index statistics for table " << index->table->name << ", index " << index->name << ", stat name \"" << stat_name << "\": " - << ut_strerr(ret); + << ret; index->stats_error_printed = true; } } @@ -2463,9 +2463,9 @@ dict_stats_save( ");\n" "END;", NULL); - if (ret != DB_SUCCESS) { + if (UNIV_UNLIKELY(ret != DB_SUCCESS)) { ib::error() << "Cannot save table statistics for table " - << table->name << ": " << ut_strerr(ret); + << table->name << ": " << ret; func_exit: dict_sys_unlock(); dict_stats_snapshot_free(table); @@ -3311,7 +3311,7 @@ dict_stats_update( " for table " << table->name << " from " TABLE_STATS_NAME_PRINT " and " - INDEX_STATS_NAME_PRINT ": " << ut_strerr(err) + INDEX_STATS_NAME_PRINT ": " << err << ". Using transient stats method instead."; } @@ -4028,6 +4028,9 @@ test_dict_stats_save() table.stat_clustered_index_size = TEST_CLUSTERED_INDEX_SIZE; table.stat_sum_of_other_index_sizes = TEST_SUM_OF_OTHER_INDEX_SIZES; UT_LIST_INIT(table.indexes, &dict_index_t::indexes); +#ifdef BTR_CUR_HASH_ADAPT + UT_LIST_INIT(table.freed_indexes, &dict_index_t::indexes); +#endif /* BTR_CUR_HASH_ADAPT */ UT_LIST_ADD_LAST(table.indexes, &index1); UT_LIST_ADD_LAST(table.indexes, &index2); ut_d(table.magic_n = DICT_TABLE_MAGIC_N); @@ -4177,6 +4180,9 @@ test_dict_stats_fetch_from_ps() /* craft a dummy dict_table_t */ table.name.m_name = (char*) (TEST_DATABASE_NAME "/" TEST_TABLE_NAME); UT_LIST_INIT(table.indexes, &dict_index_t::indexes); +#ifdef BTR_CUR_HASH_ADAPT + UT_LIST_INIT(table.freed_indexes, &dict_index_t::indexes); +#endif /* BTR_CUR_HASH_ADAPT */ UT_LIST_ADD_LAST(table.indexes, &index1); UT_LIST_ADD_LAST(table.indexes, &index2); ut_d(table.magic_n = DICT_TABLE_MAGIC_N); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index e253b692778..f8f03dd12d7 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -288,14 +288,9 @@ fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page) type == CRYPT_SCHEME_1) || iv_length != sizeof crypt_data->iv) { ib::error() << "Found non sensible crypt scheme: " - << type << "," << iv_length << " for space: " - << page_get_space_id(page) << " offset: " - << offset << " bytes: [" - << page[offset + 2 + MAGIC_SZ] - << page[offset + 3 + MAGIC_SZ] - << page[offset + 4 + MAGIC_SZ] - << page[offset + 5 + MAGIC_SZ] - << "]."; + << type << "," << iv_length + << " for space: " + << page_get_space_id(page); return NULL; } @@ -784,8 +779,10 @@ static bool fil_space_decrypt_for_non_full_checksum( } ib::fatal() << "Unable to decrypt data-block " - << " src: " << src << "srclen: " - << srclen << " buf: " << dst << "buflen: " + << " src: " << static_cast(src) + << "srclen: " + << srclen << " buf: " + << static_cast(dst) << "buflen: " << dstlen << " return-code: " << rc << " Can't continue!"; } @@ -1100,7 +1097,7 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space) do { ulint n_pages = 0; success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages); - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); sum_pages += n_pages; } while (!success); @@ -1163,6 +1160,7 @@ struct rotate_thread_t { case SRV_SHUTDOWN_EXIT_THREADS: /* srv_init_abort() must have been invoked */ case SRV_SHUTDOWN_CLEANUP: + case SRV_SHUTDOWN_INITIATED: return true; case SRV_SHUTDOWN_FLUSH_PHASE: case SRV_SHUTDOWN_LAST_PHASE: @@ -1786,6 +1784,12 @@ fil_crypt_rotate_page( mtr.write<1,mtr_t::FORCED>(*block, &frame[FIL_PAGE_SPACE_ID], frame[FIL_PAGE_SPACE_ID]); + /* This may be a freed page. Until + MDEV-21347 has been fixed, a page on which + BtrBulk::finish() invoked btr_page_free() may + be an inconsistent B-tree page. For now, + let us disable the flush-time check. */ + block->skip_flush_check = true; /* statistics */ state->crypt_stat.pages_modified++; @@ -1894,7 +1898,7 @@ fil_crypt_flush_space( do { success = buf_flush_lists(ULINT_MAX, end_lsn, &n_pages); - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); sum_pages += n_pages; } while (!success && !space->is_stopping()); @@ -2164,7 +2168,7 @@ static void fil_crypt_rotation_list_fill() space != NULL; space = UT_LIST_GET_NEXT(space_list, space)) { if (space->purpose != FIL_TYPE_TABLESPACE - || space->is_in_rotation_list() + || space->is_in_rotation_list || space->is_stopping() || UT_LIST_GET_LEN(space->chain) == 0) { continue; @@ -2211,6 +2215,7 @@ static void fil_crypt_rotation_list_fill() } fil_system.rotation_list.push_back(*space); + space->is_in_rotation_list = true; } } @@ -2437,7 +2442,7 @@ bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size) /* Compressed and encrypted pages do not have checksum. Assume not corrupted. Page verification happens after decompression in - buf_page_io_complete() using buf_page_is_corrupted(). */ + buf_page_read_complete() using buf_page_is_corrupted(). */ if (fil_page_get_type(page) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { return true; } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index b71626aa0cd..34afe458687 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -173,12 +173,6 @@ fil_system_t fil_system; UNIV_INTERN extern uint srv_fil_crypt_rotate_key_age; UNIV_INTERN extern ib_mutex_t fil_crypt_threads_mutex; -/** Determine if user has explicitly disabled fsync(). */ -# define fil_buffering_disabled(s) \ - ((s)->purpose == FIL_TYPE_TABLESPACE \ - && srv_file_flush_method \ - == SRV_O_DIRECT_NO_FSYNC) - /** Determine if the space id is a user tablespace id or not. @param[in] space_id Space ID to check @return true if it is a user tablespace ID */ @@ -249,67 +243,6 @@ fil_node_prepare_for_io( fil_node_t* node, /*!< in: file node */ fil_space_t* space); /*!< in: space */ -/** Update the data structures when an i/o operation finishes. -@param[in,out] node file node -@param[in] type IO context */ -static -void -fil_node_complete_io(fil_node_t* node, const IORequest& type); - -/** Reads data from a space to a buffer. Remember that the possible incomplete -blocks at the end of file are ignored: they are not taken into account when -calculating the byte offset within a space. -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] byte_offset remainder of offset in bytes; in aio this -must be divisible by the OS block size -@param[in] len how many bytes to read; this must not cross a -file boundary; in aio this must be a block size multiple -@param[in,out] buf buffer where to store data read; in aio this -must be appropriately aligned -@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do -i/o on a tablespace which does not exist */ -UNIV_INLINE -dberr_t -fil_read( - const page_id_t page_id, - ulint zip_size, - ulint byte_offset, - ulint len, - void* buf) -{ - return(fil_io(IORequestRead, true, page_id, zip_size, - byte_offset, len, buf, NULL)); -} - -/** Writes data to a space from a buffer. Remember that the possible incomplete -blocks at the end of file are ignored: they are not taken into account when -calculating the byte offset within a space. -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] byte_offset remainder of offset in bytes; in aio this -must be divisible by the OS block size -@param[in] len how many bytes to write; this must not cross -a file boundary; in aio this must be a block size multiple -@param[in] buf buffer from which to write; in aio this must -be appropriately aligned -@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do -i/o on a tablespace which does not exist */ -UNIV_INLINE -dberr_t -fil_write( - const page_id_t page_id, - ulint zip_size, - ulint byte_offset, - ulint len, - void* buf) -{ - ut_ad(!srv_read_only_mode); - - return(fil_io(IORequestWrite, true, page_id, zip_size, - byte_offset, len, buf, NULL)); -} - /*******************************************************************//** Returns the table space by a given id, NULL if not found. It is unsafe to dereference the returned pointer. It is fine to check @@ -324,7 +257,7 @@ fil_space_get_by_id( ut_ad(fil_system.is_initialised()); ut_ad(mutex_own(&fil_system.mutex)); - HASH_SEARCH(hash, fil_system.spaces, id, + HASH_SEARCH(hash, &fil_system.spaces, id, fil_space_t*, space, ut_ad(space->magic_n == FIL_SPACE_MAGIC_N), space->id == id); @@ -395,8 +328,7 @@ fil_space_is_flushed( node = UT_LIST_GET_NEXT(chain, node)) { if (node->needs_flush) { - - ut_ad(!fil_buffering_disabled(space)); + ut_ad(srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC); return(false); } } @@ -579,32 +511,41 @@ fail: /** Close the file handle. */ void fil_node_t::close() { - bool ret; + prepare_to_close_or_detach(); - ut_ad(mutex_own(&fil_system.mutex)); - ut_a(is_open()); - ut_a(n_pending == 0); - ut_a(n_pending_flushes == 0); - ut_a(!being_extended); - ut_a(!needs_flush - || space->purpose == FIL_TYPE_TEMPORARY - || srv_fast_shutdown == 2 - || !srv_was_started); + /* printf("Closing file %s\n", name); */ + int ret= os_file_close(handle); + ut_a(ret); + handle= OS_FILE_CLOSED; +} - ret = os_file_close(handle); - ut_a(ret); +pfs_os_file_t fil_node_t::detach() +{ + prepare_to_close_or_detach(); - /* printf("Closing file %s\n", name); */ + pfs_os_file_t result= handle; + handle= OS_FILE_CLOSED; + return result; +} - handle = OS_FILE_CLOSED; - ut_ad(!is_open()); - ut_a(fil_system.n_open > 0); - fil_system.n_open--; +void fil_node_t::prepare_to_close_or_detach() +{ + ut_ad(mutex_own(&fil_system.mutex)); + ut_a(is_open()); + ut_a(n_pending == 0); + ut_a(n_pending_flushes == 0); + ut_a(!being_extended); + ut_a(!needs_flush || space->purpose == FIL_TYPE_TEMPORARY || + srv_fast_shutdown == 2 || !srv_was_started); - if (fil_space_belongs_in_lru(space)) { - ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); - UT_LIST_REMOVE(fil_system.LRU, this); - } + ut_a(fil_system.n_open > 0); + fil_system.n_open--; + + if (fil_space_belongs_in_lru(space)) + { + ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); + UT_LIST_REMOVE(fil_system.LRU, this); + } } /** Tries to close a file in the LRU list. The caller must hold the fil_sys @@ -678,11 +619,10 @@ static void fil_flush_low(fil_space_t* space, bool metadata = false) ut_ad(space); ut_ad(!space->stop_new_ops); - if (fil_buffering_disabled(space)) { - + if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { /* No need to flush. User has explicitly disabled buffering. */ - ut_ad(!space->is_in_unflushed_spaces()); + ut_ad(!space->is_in_unflushed_spaces); ut_ad(fil_space_is_flushed(space)); ut_ad(space->n_pending_flushes == 0); @@ -735,10 +675,11 @@ static void fil_flush_low(fil_space_t* space, bool metadata = false) skip_flush: #endif /* _WIN32 */ if (!node->needs_flush) { - if (space->is_in_unflushed_spaces() + if (space->is_in_unflushed_spaces && fil_space_is_flushed(space)) { fil_system.unflushed_spaces.remove(*space); + space->is_in_unflushed_spaces = false; } } @@ -838,7 +779,7 @@ fil_space_extend_must_retry( const ulint pages_in_MiB = node->size & ~ulint((1U << (20U - srv_page_size_shift)) - 1); - fil_node_complete_io(node,IORequestRead); + node->complete_io(); /* Keep the last data file size info up to date, rounded to full megabytes */ @@ -863,14 +804,12 @@ fil_space_extend_must_retry( } } -/*******************************************************************//** -Reserves the fil_system.mutex and tries to make sure we can open at least one +/** Acquire fil_system.mutex and try to make sure we can open at least one file while holding it. This should be called before calling fil_node_prepare_for_io(), because that function may need to open a file. */ static -void +fil_space_t* fil_mutex_enter_and_prepare_for_io( -/*===============================*/ ulint space_id) /*!< in: space id */ { for (ulint count = 0;;) { @@ -878,8 +817,8 @@ fil_mutex_enter_and_prepare_for_io( fil_space_t* space = fil_space_get_by_id(space_id); - if (space == NULL) { - break; + if (!space) { + return nullptr; } fil_node_t* node = UT_LIST_GET_LAST(space->chain); @@ -959,7 +898,7 @@ fil_mutex_enter_and_prepare_for_io( } } - break; + return space; } } @@ -986,84 +925,114 @@ fil_space_extend( return(success); } -/** Prepare to free a file node object from a tablespace memory cache. -@param[in,out] node file node -@param[in] space tablespace */ -static -void -fil_node_close_to_free( - fil_node_t* node, - fil_space_t* space) +/** Prepare to free a file from fil_system. */ +pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) { - ut_ad(mutex_own(&fil_system.mutex)); - ut_a(node->magic_n == FIL_NODE_MAGIC_N); - ut_a(node->n_pending == 0); - ut_a(!node->being_extended); + ut_ad(mutex_own(&fil_system.mutex)); + ut_a(magic_n == FIL_NODE_MAGIC_N); + ut_a(!being_extended); - if (node->is_open()) { - /* We fool the assertion in fil_node_t::close() to think - there are no unflushed modifications in the file */ + while (is_open()) + { + if (space->is_in_unflushed_spaces) + { + ut_ad(srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC); + space->is_in_unflushed_spaces= false; + fil_system.unflushed_spaces.remove(*space); + } - node->needs_flush = false; + if (n_pending) + { + mutex_exit(&fil_system.mutex); + os_thread_sleep(100); + mutex_enter(&fil_system.mutex); + continue; + } - if (fil_buffering_disabled(space)) { + if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) + { + ut_ad(!space->is_in_unflushed_spaces); + ut_ad(fil_space_is_flushed(space)); + } + else if (space->is_in_unflushed_spaces && fil_space_is_flushed(space)) + { + space->is_in_unflushed_spaces= false; + fil_system.unflushed_spaces.remove(*space); + } - ut_ad(!space->is_in_unflushed_spaces()); - ut_ad(fil_space_is_flushed(space)); + if (fil_space_belongs_in_lru(space)) + { + ut_ad(UT_LIST_GET_LEN(fil_system.LRU) > 0); + UT_LIST_REMOVE(fil_system.LRU, this); + } + ut_a(!n_pending_flushes); + ut_a(!being_extended); + if (detach_handle) + { + auto result= handle; + handle= OS_FILE_CLOSED; + return result; + } + bool ret= os_file_close(handle); + ut_a(ret); + handle= OS_FILE_CLOSED; + break; + } - } else if (space->is_in_unflushed_spaces() - && fil_space_is_flushed(space)) { - - fil_system.unflushed_spaces.remove(*space); - } - - node->close(); - } + return OS_FILE_CLOSED; } -/** Detach a space object from the tablespace memory cache. -Closes the files in the chain but does not delete them. -There must not be any pending i/o's or flushes on the files. -@param[in,out] space tablespace */ -static -void -fil_space_detach( - fil_space_t* space) +/** Detach a tablespace from the cache and close the files. */ +std::vector fil_system_t::detach(fil_space_t *space, + bool detach_handle) { - ut_ad(mutex_own(&fil_system.mutex)); + ut_ad(mutex_own(&fil_system.mutex)); + HASH_DELETE(fil_space_t, hash, &spaces, space->id, space); - HASH_DELETE(fil_space_t, hash, fil_system.spaces, space->id, space); + if (space->is_in_unflushed_spaces) + { + ut_ad(srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC); + space->is_in_unflushed_spaces= false; + unflushed_spaces.remove(*space); + } - if (space->is_in_unflushed_spaces()) { + if (space->is_in_rotation_list) + { + space->is_in_rotation_list= false; + rotation_list.remove(*space); + } + UT_LIST_REMOVE(space_list, space); + if (space == sys_space) + sys_space= nullptr; + else if (space == temp_space) + temp_space= nullptr; - ut_ad(!fil_buffering_disabled(space)); - fil_system.unflushed_spaces.remove(*space); - } + ut_a(space->magic_n == FIL_SPACE_MAGIC_N); + ut_a(space->n_pending_flushes == 0); - if (space->is_in_rotation_list()) { - fil_system.rotation_list.remove(*space); - } + for (fil_node_t* node= UT_LIST_GET_FIRST(space->chain); node; + node= UT_LIST_GET_NEXT(chain, node)) + if (node->is_open()) + { + ut_ad(n_open > 0); + n_open--; + } - UT_LIST_REMOVE(fil_system.space_list, space); + std::vector handles; + handles.reserve(UT_LIST_GET_LEN(space->chain)); - ut_a(space->magic_n == FIL_SPACE_MAGIC_N); - ut_a(space->n_pending_flushes == 0); + for (fil_node_t* node= UT_LIST_GET_FIRST(space->chain); node; + node= UT_LIST_GET_NEXT(chain, node)) + { + auto handle= node->close_to_free(detach_handle); + if (handle != OS_FILE_CLOSED) + handles.push_back(handle); + } - for (fil_node_t* fil_node = UT_LIST_GET_FIRST(space->chain); - fil_node != NULL; - fil_node = UT_LIST_GET_NEXT(chain, fil_node)) { - - fil_node_close_to_free(fil_node, space); - } - - if (space == fil_system.sys_space) { - fil_system.sys_space = NULL; - } else if (space == fil_system.temp_space) { - fil_system.temp_space = NULL; - } + return handles; } -/** Free a tablespace object on which fil_space_detach() was invoked. +/** Free a tablespace object on which fil_system_t::detach() was invoked. There must not be any pending i/o's or flushes on the files. @param[in,out] space tablespace */ static @@ -1076,7 +1045,7 @@ fil_space_free_low( || space->max_lsn == 0); /* Wait for fil_space_t::release_for_io(); after - fil_space_detach(), the tablespace cannot be found, so + fil_system_t::detach(), the tablespace cannot be found, so fil_space_acquire_for_io() would return NULL */ while (space->pending_io()) { os_thread_sleep(100); @@ -1096,6 +1065,7 @@ fil_space_free_low( rw_lock_free(&space->latch); fil_space_destroy_crypt_data(&space->crypt_data); + space->~fil_space_t(); ut_free(space->name); ut_free(space); } @@ -1117,7 +1087,7 @@ fil_space_free( fil_space_t* space = fil_space_get_by_id(id); if (space != NULL) { - fil_space_detach(space); + fil_system.detach(space); } mutex_exit(&fil_system.mutex); @@ -1188,7 +1158,9 @@ fil_space_create( return(NULL); } - space = static_cast(ut_zalloc_nokey(sizeof(*space))); + /* FIXME: if calloc() is defined as an inline function that calls + memset() or bzero(), then GCC 6 -flifetime-dse can optimize it away */ + space= new (ut_zalloc_nokey(sizeof(*space))) fil_space_t; space->id = id; space->name = mem_strdup(name); @@ -1238,7 +1210,7 @@ fil_space_create( space->atomic_write_supported = true; } - HASH_INSERT(fil_space_t, hash, fil_system.spaces, id, space); + HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space); UT_LIST_ADD_LAST(fil_system.space_list, space); @@ -1256,6 +1228,7 @@ fil_space_create( /* Key rotation is not enabled, need to inform background encryption threads. */ fil_system.rotation_list.push_back(*space); + space->is_in_rotation_list = true; mutex_exit(&fil_system.mutex); os_event_set(fil_crypt_threads_event); } else { @@ -1327,9 +1300,7 @@ fil_space_t* fil_system_t::read_page0(ulint id) /* It is possible that the tablespace is dropped while we are not holding the mutex. */ - fil_mutex_enter_and_prepare_for_io(id); - - fil_space_t* space = fil_space_get_by_id(id); + fil_space_t* space = fil_mutex_enter_and_prepare_for_io(id); if (space == NULL || UT_LIST_GET_LEN(space->chain) == 0) { return(NULL); @@ -1351,7 +1322,7 @@ fil_space_t* fil_system_t::read_page0(ulint id) return(NULL); } - fil_node_complete_io(node, IORequestRead); + node->complete_io(); return space; } @@ -1472,7 +1443,7 @@ void fil_system_t::create(ulint hash_size) ut_ad(!is_initialised()); ut_ad(!(srv_page_size % FSP_EXTENT_SIZE)); ut_ad(srv_page_size); - ut_ad(!spaces); + ut_ad(!spaces.array); m_initialised = true; @@ -1483,7 +1454,7 @@ void fil_system_t::create(ulint hash_size) mutex_create(LATCH_ID_FIL_SYSTEM, &mutex); - spaces = hash_create(hash_size); + spaces.create(hash_size); fil_space_crypt_init(); #ifdef UNIV_LINUX @@ -1559,13 +1530,12 @@ void fil_system_t::close() if (is_initialised()) { m_initialised = false; - hash_table_free(spaces); - spaces = NULL; + spaces.free(); mutex_free(&mutex); fil_space_crypt_cleanup(); } - ut_ad(!spaces); + ut_ad(!spaces.array); } /** Opens all system tablespace data files. They stay open until the @@ -1629,25 +1599,24 @@ fil_open_system_tablespace_files() mutex_exit(&fil_system.mutex); } -/*******************************************************************//** -Closes all open files. There must not be any pending i/o's or not flushed -modifications in the files. */ -void -fil_close_all_files(void) -/*=====================*/ +/** Close all tablespace files at shutdown */ +void fil_close_all_files() { + if (!fil_system.is_initialised()) { + return; + } + fil_space_t* space; /* At shutdown, we should not have any files in this list. */ - ut_ad(fil_system.is_initialised()); ut_ad(srv_fast_shutdown == 2 || !srv_was_started || UT_LIST_GET_LEN(fil_system.named_spaces) == 0); + fil_flush_file_spaces(); mutex_enter(&fil_system.mutex); - for (space = UT_LIST_GET_FIRST(fil_system.space_list); - space != NULL; ) { + for (space = UT_LIST_GET_FIRST(fil_system.space_list); space; ) { fil_node_t* node; fil_space_t* prev_space = space; @@ -1655,13 +1624,31 @@ fil_close_all_files(void) node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (node->is_open()) { - node->close(); + if (!node->is_open()) { +next: + continue; } + + for (ulint count = 10000; count--; ) { + mutex_exit(&fil_system.mutex); + os_thread_sleep(100); + mutex_enter(&fil_system.mutex); + if (!node->is_open()) { + goto next; + } + if (!node->n_pending) { + node->close(); + goto next; + } + } + + ib::error() << "File '" << node->name + << "' has " << node->n_pending + << " operations"; } space = UT_LIST_GET_NEXT(space_list, space); - fil_space_detach(prev_space); + fil_system.detach(prev_space); fil_space_free_low(prev_space); } @@ -1703,15 +1690,17 @@ fil_write_flushed_lsn( lsn_t lsn) { byte* buf; - dberr_t err = DB_TABLESPACE_NOT_FOUND; + ut_ad(!srv_read_only_mode); buf = static_cast(aligned_malloc(srv_page_size, srv_page_size)); const page_id_t page_id(TRX_SYS_SPACE, 0); - err = fil_read(page_id, 0, 0, srv_page_size, buf); + fil_io_t fio = fil_io(IORequestRead, true, page_id, 0, 0, + srv_page_size, buf, NULL); - if (err == DB_SUCCESS) { + if (fio.err == DB_SUCCESS) { + fio.node->space->release_for_io(); mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, lsn); ulint fsp_flags = mach_read_from_4( @@ -1721,12 +1710,17 @@ fil_write_flushed_lsn( buf_flush_assign_full_crc32_checksum(buf); } - err = fil_write(page_id, 0, 0, srv_page_size, buf); + fio = fil_io(IORequestWrite, true, page_id, 0, 0, + srv_page_size, buf, NULL); fil_flush_file_spaces(); } + if (fio.node) { + fio.node->space->release_for_io(); + } + aligned_free(buf); - return(err); + return fio.err; } /** Acquire a tablespace when it could be dropped concurrently. @@ -2003,13 +1997,6 @@ fil_op_replay_rename( return(true); } -/** File operations for tablespace */ -enum fil_operation_t { - FIL_OPERATION_DELETE, /*!< delete a single-table tablespace */ - FIL_OPERATION_CLOSE, /*!< close a single-table tablespace */ - FIL_OPERATION_TRUNCATE /*!< truncate an undo tablespace */ -}; - /** Check for pending operations. @param[in] space tablespace @param[in] count number of attempts so far @@ -2024,7 +2011,8 @@ static ulint fil_check_pending_ops(const fil_space_t* space, ulint count) if (ulint n_pending_ops = space->n_pending_ops) { - if (count > 5000) { + /* Give a warning every 10 second, starting after 1 second */ + if ((count % 500) == 50) { ib::warn() << "Trying to delete" " tablespace '" << space->name << "' but there are " << n_pending_ops @@ -2044,7 +2032,6 @@ static ulint fil_check_pending_io( /*=================*/ - fil_operation_t operation, /*!< in: File operation */ fil_space_t* space, /*!< in/out: Tablespace to check */ fil_node_t** node, /*!< out: Node in space list */ ulint count) /*!< in: number of attempts so far */ @@ -2052,15 +2039,6 @@ fil_check_pending_io( ut_ad(mutex_own(&fil_system.mutex)); ut_ad(!space->referenced()); - switch (operation) { - case FIL_OPERATION_DELETE: - case FIL_OPERATION_CLOSE: - break; - case FIL_OPERATION_TRUNCATE: - space->is_being_truncated = true; - break; - } - /* The following code must change when InnoDB supports multiple datafiles per tablespace. */ ut_a(UT_LIST_GET_LEN(space->chain) == 1); @@ -2071,7 +2049,8 @@ fil_check_pending_io( ut_a(!(*node)->being_extended); - if (count > 1000) { + /* Give a warning every 10 second, starting after 1 second */ + if ((count % 500) == 50) { ib::warn() << "Trying to delete" " tablespace '" << space->name << "' but there are " @@ -2088,24 +2067,18 @@ fil_check_pending_io( /*******************************************************************//** Check pending operations on a tablespace. -@return DB_SUCCESS or error failure. */ +@return tablespace */ static -dberr_t +fil_space_t* fil_check_pending_operations( /*=========================*/ ulint id, /*!< in: space id */ - fil_operation_t operation, /*!< in: File operation */ - fil_space_t** space, /*!< out: tablespace instance - in memory */ + bool truncate, /*!< in: whether to truncate a file */ char** path) /*!< out/own: tablespace path */ { ulint count = 0; ut_a(!is_system_tablespace(id)); - ut_ad(space); - - *space = 0; - mutex_enter(&fil_system.mutex); fil_space_t* sp = fil_space_get_by_id(id); @@ -2123,32 +2096,31 @@ fil_check_pending_operations( /* Check for pending operations. */ do { - sp = fil_space_get_by_id(id); - count = fil_check_pending_ops(sp, count); mutex_exit(&fil_system.mutex); - if (count > 0) { - os_thread_sleep(20000); + if (count) { + os_thread_sleep(20000); // Wait 0.02 seconds + } else if (!sp) { + return nullptr; } mutex_enter(&fil_system.mutex); - } while (count > 0); + + sp = fil_space_get_by_id(id); + } while (count); /* Check for pending IO. */ for (;;) { - sp = fil_space_get_by_id(id); - - if (sp == NULL) { - mutex_exit(&fil_system.mutex); - return(DB_TABLESPACE_NOT_FOUND); + if (truncate) { + sp->is_being_truncated = true; } fil_node_t* node; - count = fil_check_pending_io(operation, sp, &node, count); + count = fil_check_pending_io(sp, &node, count); if (count == 0 && path) { *path = mem_strdup(node->name); @@ -2160,42 +2132,31 @@ fil_check_pending_operations( break; } - os_thread_sleep(20000); + os_thread_sleep(20000); // Wait 0.02 seconds mutex_enter(&fil_system.mutex); + sp = fil_space_get_by_id(id); + + if (!sp) { + mutex_exit(&fil_system.mutex); + break; + } } - ut_ad(sp); - - *space = sp; - return(DB_SUCCESS); + return sp; } -/*******************************************************************//** -Closes a single-table tablespace. The tablespace must be cached in the -memory cache. Free all pages used by the tablespace. -@return DB_SUCCESS or error */ -dberr_t -fil_close_tablespace( -/*=================*/ - trx_t* trx, /*!< in/out: Transaction covering the close */ - ulint id) /*!< in: space id */ +/** Close a single-table tablespace on failed IMPORT TABLESPACE. +The tablespace must be cached in the memory cache. +Free all pages used by the tablespace. */ +void fil_close_tablespace(ulint id) { - char* path = 0; - fil_space_t* space = 0; - dberr_t err; - - ut_a(!is_system_tablespace(id)); - - err = fil_check_pending_operations(id, FIL_OPERATION_CLOSE, - &space, &path); - - if (err != DB_SUCCESS) { - return(err); + ut_ad(!is_system_tablespace(id)); + char* path = nullptr; + fil_space_t* space = fil_check_pending_operations(id, false, &path); + if (!space) { + return; } - ut_a(space); - ut_a(path != 0); - rw_lock_x_lock(&space->latch); /* Invalidate in the buffer pool all pages belonging to the @@ -2211,23 +2172,17 @@ fil_close_tablespace( if (!fil_space_free(id, true)) { rw_lock_x_unlock(&space->latch); - err = DB_TABLESPACE_NOT_FOUND; - } else { - err = DB_SUCCESS; } /* If it is a delete then also delete any generated files, otherwise when we drop the database the remove directory will fail. */ - char* cfg_name = fil_make_filepath(path, NULL, CFG, false); - if (cfg_name != NULL) { + if (char* cfg_name = fil_make_filepath(path, NULL, CFG, false)) { os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL); ut_free(cfg_name); } ut_free(path); - - return(err); } /** Determine whether a table can be accessed in operations that are @@ -2254,18 +2209,20 @@ bool fil_table_accessible(const dict_table_t* table) /** Delete a tablespace and associated .ibd file. @param[in] id tablespace identifier @param[in] if_exists whether to ignore missing tablespace +@param[in,out] detached_handles return detached handles if not nullptr @return DB_SUCCESS or error */ -dberr_t fil_delete_tablespace(ulint id, bool if_exists) +dberr_t fil_delete_tablespace(ulint id, bool if_exists, + std::vector* detached_handles) { - char* path = 0; - fil_space_t* space = 0; + char* path = NULL; + ut_ad(!is_system_tablespace(id)); + ut_ad(!detached_handles || detached_handles->empty()); - ut_a(!is_system_tablespace(id)); + dberr_t err; + fil_space_t *space = fil_check_pending_operations(id, false, &path); - dberr_t err = fil_check_pending_operations( - id, FIL_OPERATION_DELETE, &space, &path); - - if (err != DB_SUCCESS) { + if (!space) { + err = DB_TABLESPACE_NOT_FOUND; if (!if_exists) { ib::error() << "Cannot delete tablespace " << id << " because it is not found" @@ -2275,9 +2232,6 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists) goto func_exit; } - ut_a(space); - ut_a(path != 0); - /* IMPORTANT: Because we have set space::stop_new_ops there can't be any new reads or flushes. We are here because node::n_pending was zero above. However, it is still @@ -2299,6 +2253,7 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists) To deal with potential read requests, we will check the ::stop_new_ops flag in fil_io(). */ + err = DB_SUCCESS; buf_LRU_flush_or_remove_pages(id, false); /* If it is a delete then also delete any generated files, otherwise @@ -2337,10 +2292,11 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists) ut_a(s == space); ut_a(!space->referenced()); ut_a(UT_LIST_GET_LEN(space->chain) == 1); - fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - ut_a(node->n_pending == 0); - - fil_space_detach(space); + auto handles = fil_system.detach(space, + detached_handles != nullptr); + if (detached_handles) { + *detached_handles = std::move(handles); + } mutex_exit(&fil_system.mutex); log_mutex_enter(); @@ -2377,17 +2333,9 @@ func_exit: @param[in] space_id undo tablespace id @return the tablespace @retval NULL if tablespace not found */ -fil_space_t* fil_truncate_prepare(ulint space_id) +fil_space_t *fil_truncate_prepare(ulint space_id) { - /* Stop all I/O on the tablespace and ensure that related - pages are flushed to disk. */ - fil_space_t* space; - if (fil_check_pending_operations(space_id, FIL_OPERATION_TRUNCATE, - &space, NULL) != DB_SUCCESS) { - return NULL; - } - ut_ad(space != NULL); - return space; + return fil_check_pending_operations(space_id, true, nullptr); } /*******************************************************************//** @@ -3784,82 +3732,24 @@ fil_node_prepare_for_io( } } - if (node->n_pending == 0 && fil_space_belongs_in_lru(space)) { - /* The node is in the LRU list, remove it */ - ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); + if (node->n_pending++ == 0 && fil_space_belongs_in_lru(space)) { UT_LIST_REMOVE(fil_system.LRU, node); } - node->n_pending++; - return(true); } -/** Update the data structures when an i/o operation finishes. -@param[in,out] node file node -@param[in] type IO context */ -static -void -fil_node_complete_io(fil_node_t* node, const IORequest& type) -{ - ut_ad(mutex_own(&fil_system.mutex)); - ut_a(node->n_pending > 0); - - --node->n_pending; - - ut_ad(type.validate()); - - if (type.is_write()) { - - ut_ad(!srv_read_only_mode - || node->space->purpose == FIL_TYPE_TEMPORARY); - - if (fil_buffering_disabled(node->space)) { - - /* We don't need to keep track of unflushed - changes as user has explicitly disabled - buffering. */ - ut_ad(!node->space->is_in_unflushed_spaces()); - ut_ad(node->needs_flush == false); - - } else { - node->needs_flush = true; - - if (!node->space->is_in_unflushed_spaces()) { - fil_system.unflushed_spaces.push_front( - *node->space); - } - } - } - - if (node->n_pending == 0 && fil_space_belongs_in_lru(node->space)) { - - /* The node must be put back to the LRU list */ - UT_LIST_ADD_FIRST(fil_system.LRU, node); - } -} - /** Report information about an invalid page access. */ -static -void -fil_report_invalid_page_access( - ulint block_offset, /*!< in: block offset */ - ulint space_id, /*!< in: space id */ - const char* space_name, /*!< in: space name */ - ulint byte_offset, /*!< in: byte offset */ - ulint len, /*!< in: I/O length */ - bool is_read) /*!< in: I/O type */ +ATTRIBUTE_COLD __attribute__((noreturn)) +static void +fil_report_invalid_page_access(const page_id_t id, const char *name, + ulint byte_offset, ulint len, bool is_read) { ib::fatal() - << "Trying to " << (is_read ? "read" : "write") - << " page number " << block_offset << " in" - " space " << space_id << ", space name " << space_name << "," - " which is outside the tablespace bounds. Byte offset " - << byte_offset << ", len " << len << - (space_id == 0 && !srv_was_started - ? "Please check that the configuration matches" - " the InnoDB system tablespace location (ibdata files)" - : ""); + << "Trying to " << (is_read ? "read " : "write ") + << id + << " which is outside the bounds of tablespace " << name + << ". Byte offset " << byte_offset << ", len " << len; } inline void IORequest::set_fil_node(fil_node_t* node) @@ -3887,12 +3777,11 @@ inline void IORequest::set_fil_node(fil_node_t* node) aligned @param[in] message message for aio handler if non-sync aio used, else ignored -@param[in] ignore whether to ignore out-of-bounds page_id +@param[in] ignore whether to ignore errors @param[in] punch_hole punch the hole to the file for page_compressed tablespace -@return DB_SUCCESS, or DB_TABLESPACE_DELETED - if we are trying to do i/o on a tablespace which does not exist */ -dberr_t +@return status and file descriptor */ +fil_io_t fil_io( const IORequest& type, bool sync, @@ -3950,23 +3839,18 @@ fil_io( srv_stats.data_written.add(len); } - /* Reserve the fil_system mutex and make sure that we can open at + /* Acquire fil_system.mutex and make sure that we can open at least one file while holding it, if the file is not already open */ + fil_space_t* space = fil_mutex_enter_and_prepare_for_io( + page_id.space()); - fil_mutex_enter_and_prepare_for_io(page_id.space()); - - fil_space_t* space = fil_space_get_by_id(page_id.space()); - - /* If we are deleting a tablespace we don't allow async read operations - on that. However, we do allow write operations and sync read operations. */ - if (space == NULL + if (!space || (req_type.is_read() && !sync && space->stop_new_ops && !space->is_being_truncated)) { mutex_exit(&fil_system.mutex); - if (!ignore) { ib::error() << "Trying to do I/O to a tablespace which" @@ -3976,7 +3860,7 @@ fil_io( << ", I/O length: " << len << " bytes"; } - return(DB_TABLESPACE_DELETED); + return {DB_TABLESPACE_DELETED, nullptr}; } ulint cur_page_no = page_id.page_no(); @@ -3987,12 +3871,11 @@ fil_io( if (node == NULL) { if (ignore) { mutex_exit(&fil_system.mutex); - return(DB_ERROR); + return {DB_ERROR, nullptr}; } fil_report_invalid_page_access( - page_id.page_no(), page_id.space(), - space->name, byte_offset, len, + page_id, space->name, byte_offset, len, req_type.is_read()); } else if (fil_is_user_tablespace_id(space->id) @@ -4014,48 +3897,42 @@ fil_io( } /* Open file if closed */ - if (!fil_node_prepare_for_io(node, space)) { - if (fil_is_user_tablespace_id(space->id)) { - mutex_exit(&fil_system.mutex); + if (UNIV_UNLIKELY(!fil_node_prepare_for_io(node, space))) { + ut_ad(fil_is_user_tablespace_id(space->id)); + mutex_exit(&fil_system.mutex); - if (!ignore) { - ib::error() - << "Trying to do I/O to a tablespace" - " which exists without .ibd data file." - " I/O type: " - << (req_type.is_read() - ? "read" : "write") - << ", page: " - << page_id_t(page_id.space(), - cur_page_no) - << ", I/O length: " << len << " bytes"; - } - - return(DB_TABLESPACE_DELETED); + if (!ignore) { + ib::error() + << "Trying to do I/O to a tablespace '" + << space->name + << "' which exists without .ibd data file." + " I/O type: " + << (req_type.is_read() + ? "read" : "write") + << ", page: " + << page_id + << ", I/O length: " << len << " bytes"; } - /* The tablespace is for log. Currently, we just assert here - to prevent handling errors along the way fil_io returns. - Also, if the log files are missing, it would be hard to - promise the server can continue running. */ - ut_a(0); + return {DB_TABLESPACE_DELETED, nullptr}; } - if (space->id && node->size <= cur_page_no) { + if (node->size <= cur_page_no) { if (ignore) { /* If we can tolerate the non-existent pages, we should return with DB_ERROR and let caller decide what to do. */ - fil_node_complete_io(node, req_type); + node->complete_io(req_type.is_write()); mutex_exit(&fil_system.mutex); - return(DB_ERROR); + return {DB_ERROR, nullptr}; } fil_report_invalid_page_access( - page_id.page_no(), page_id.space(), - space->name, byte_offset, len, req_type.is_read()); + page_id, space->name, byte_offset, len, + req_type.is_read()); } + space->acquire_for_io(); /* Now we have made the changes in the data structures of fil_system */ mutex_exit(&fil_system.mutex); @@ -4096,88 +3973,82 @@ fil_io( the decompression fails or the page is corrupt. */ ut_a(req_type.is_dblwr_recover() || err == DB_SUCCESS); - if (sync) { - /* The i/o operation is already completed when we return from - os_aio: */ - mutex_enter(&fil_system.mutex); - - fil_node_complete_io(node, req_type); - + node->complete_io(req_type.is_write()); mutex_exit(&fil_system.mutex); - ut_ad(fil_validate_skip()); } - - return(err); + return {err, node}; } #include -/**********************************************************************/ /** Callback for AIO completion */ void fil_aio_callback(os_aio_userdata_t *data) { - fil_node_t* node= data->node; - void* message = data->message; + ut_ad(fil_validate_skip()); - ut_ad(fil_validate_skip()); + fil_node_t *node= data->node; + if (UNIV_UNLIKELY(!node)) + { + ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); + return; + } - if (node == NULL) { - ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); - return; - } + ut_ad(data->type.validate()); - mutex_enter(&fil_system.mutex); + buf_page_t *bpage= static_cast(data->message); + if (!bpage) + { + /* Asynchronous single page writes from the doublewrite buffer, + or calls from buf_flush_freed_page() don't have access to the page. */ + ut_ad(data->type.is_write()); + ut_ad(!srv_read_only_mode); +write_completed: + mutex_enter(&fil_system.mutex); + node->complete_io(true); + mutex_exit(&fil_system.mutex); + node->space->release_for_io(); + return; + } - fil_node_complete_io(node, data->type); - const ulint space_id= node->space->id; - bool dblwr = node->space->use_doublewrite(); + if (data->type.is_write()) + { + ut_ad(!srv_read_only_mode || node->space->purpose == FIL_TYPE_TEMPORARY); + bool dblwr= node->space->use_doublewrite(); + if (dblwr && bpage->status == buf_page_t::INIT_ON_FLUSH) + { + bpage->status= buf_page_t::NORMAL; + dblwr= false; + } + buf_page_write_complete(bpage, data->type, dblwr, false); + goto write_completed; + } - mutex_exit(&fil_system.mutex); + ut_ad(data->type.is_read()); - ut_ad(fil_validate_skip()); + /* IMPORTANT: since i/o handling for reads will read also the insert + buffer in fil_system.sys_space, we have to be very careful not to + introduce deadlocks. We never close the system tablespace (0) data + files via fil_system.LRU and we use a dedicated I/O thread to serve + change buffer requests. */ + const page_id_t id(bpage->id()); - /* Do the i/o handling */ - /* IMPORTANT: since i/o handling for reads will read also the insert - buffer in tablespace 0, you have to be very careful not to introduce - deadlocks in the i/o system. We keep tablespace 0 data files always - open, and use a special i/o thread to serve insert buffer requests. */ + if (dberr_t err= buf_page_read_complete(bpage, *node)) + { + if (recv_recovery_is_on() && !srv_force_recovery) + recv_sys.found_corrupt_fs= true; + ib::error() << "Failed to read page " << id.page_no() + << " from file '" << node->name << "': " << err; + } - /* async single page writes from the dblwr buffer don't have - access to the page */ - buf_page_t* bpage = static_cast(message); - if (!bpage) { - return; - } - - ulint offset = bpage->id.page_no(); - if (dblwr && bpage->status == buf_page_t::INIT_ON_FLUSH) { - bpage->status = buf_page_t::NORMAL; - dblwr = false; - } - dberr_t err = buf_page_io_complete(bpage, dblwr); - if (err == DB_SUCCESS) { - return; - } - - ut_ad(data->type.is_read()); - if (recv_recovery_is_on() && !srv_force_recovery) { - recv_sys.found_corrupt_fs = true; - } - - if (fil_space_t* space = fil_space_acquire_for_io(space_id)) { - if (space == node->space) { - ib::error() << "Failed to read file '" << node->name - << "' at offset " << offset << ": " - << ut_strerr(err); - } - - space->release_for_io(); - } + mutex_enter(&fil_system.mutex); + node->complete_io(); + mutex_exit(&fil_system.mutex); + node->space->release_for_io(); } /**********************************************************************//** @@ -4240,7 +4111,7 @@ void fil_flush_file_spaces() n_space_ids = 0; - for (intrusive::list::iterator it + for (sized_ilist::iterator it = fil_system.unflushed_spaces.begin(), end = fil_system.unflushed_spaces.end(); it != end; ++it) { @@ -4290,10 +4161,20 @@ struct Check { Check check; ut_list_validate(space->chain, check); ut_a(space->size == check.size); - ut_ad(space->id != TRX_SYS_SPACE - || space == fil_system.sys_space); - ut_ad(space->id != SRV_TMP_SPACE_ID - || space == fil_system.temp_space); + + switch (space->id) { + case TRX_SYS_SPACE: + ut_ad(fil_system.sys_space == NULL + || fil_system.sys_space == space); + break; + case SRV_TMP_SPACE_ID: + ut_ad(fil_system.temp_space == NULL + || fil_system.temp_space == space); + break; + default: + break; + } + return(check.n_open); } }; @@ -4303,24 +4184,15 @@ Checks the consistency of the tablespace cache. @return true if ok */ bool fil_validate() { - fil_space_t* space; fil_node_t* fil_node; ulint n_open = 0; mutex_enter(&fil_system.mutex); - /* Look for spaces in the hash table */ - - for (ulint i = 0; i < hash_get_n_cells(fil_system.spaces); i++) { - - for (space = static_cast( - HASH_GET_FIRST(fil_system.spaces, i)); - space != 0; - space = static_cast( - HASH_GET_NEXT(hash, space))) { - - n_open += Check::validate(space); - } + for (fil_space_t *space = UT_LIST_GET_FIRST(fil_system.space_list); + space != NULL; + space = UT_LIST_GET_NEXT(space_list, space)) { + n_open += Check::validate(space); } ut_a(fil_system.n_open == n_open); @@ -4627,7 +4499,8 @@ fil_space_remove_from_keyrotation(fil_space_t* space) ut_ad(mutex_own(&fil_system.mutex)); ut_ad(space); - if (!space->referenced() && space->is_in_rotation_list()) { + if (!space->referenced() && space->is_in_rotation_list) { + space->is_in_rotation_list = false; ut_a(!fil_system.rotation_list.empty()); fil_system.rotation_list.remove(*space); } @@ -4657,8 +4530,8 @@ fil_space_t *fil_system_t::keyrotate_next(fil_space_t *prev_space, don't remove the last processed tablespace from the rotation list. */ const bool remove= (!recheck || prev_space->crypt_data) && !key_version == !srv_encrypt_tables; - intrusive::list::iterator it= - prev_space == NULL ? fil_system.rotation_list.end() : prev_space; + sized_ilist::iterator it= + prev_space ? prev_space : fil_system.rotation_list.end(); if (it == fil_system.rotation_list.end()) it= fil_system.rotation_list.begin(); @@ -4735,24 +4608,3 @@ fil_space_found_by_id( mutex_exit(&fil_system.mutex); return space; } - -/** Checks that this tablespace in a list of unflushed tablespaces. -@return true if in a list */ -bool fil_space_t::is_in_unflushed_spaces() const -{ - ut_ad(mutex_own(&fil_system.mutex)); - - return static_cast *>( - this) - ->next; -} - -/** Checks that this tablespace needs key rotation. -@return true if in a rotation list */ -bool fil_space_t::is_in_rotation_list() const -{ - ut_ad(mutex_own(&fil_system.mutex)); - - return static_cast *>(this) - ->next; -} diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index d3cdacf5125..d3f6a9af72f 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -27,7 +27,6 @@ Updated 14/02/2015 #include "fil0fil.h" #include "fil0pagecompress.h" -#include #include #include "mem0mem.h" diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 6f133b8db78..198d69206ec 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -328,7 +328,7 @@ Datafile::read_first_page(bool read_only_mode) ib::error() << "Cannot read first page of '" << m_filepath << "' " - << ut_strerr(err); + << err; break; } } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index ef162abf39a..94a11778beb 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -147,7 +147,7 @@ template inline void xdes_set_free(const buf_block_t &block, xdes_t *descr, ulint offset, mtr_t *mtr) { - ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX)); ut_ad(offset < FSP_EXTENT_SIZE); ut_ad(page_align(descr) == block.frame); compile_time_assert(XDES_BITS_PER_PAGE == 2); @@ -218,7 +218,7 @@ inline void xdes_set_state(const buf_block_t &block, xdes_t *descr, ut_ad(descr && mtr); ut_ad(state >= XDES_FREE); ut_ad(state <= XDES_FSEG); - ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX)); ut_ad(page_align(descr) == block.frame); ut_ad(mach_read_from_4(descr + XDES_STATE) <= XDES_FSEG); mtr->write<1>(block, XDES_STATE + 3 + descr, state); @@ -231,14 +231,11 @@ UNIV_INLINE ulint xdes_get_state( /*===========*/ - const xdes_t* descr, /*!< in: descriptor */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + const xdes_t* descr) /*!< in: descriptor */ { ulint state; - ut_ad(descr && mtr); - ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX)); - + ut_ad(descr); state = mach_read_from_4(descr + XDES_STATE); ut_ad(state - 1 < XDES_FSEG); return(state); @@ -248,7 +245,7 @@ xdes_get_state( Inits an extent descriptor to the free and clean state. */ inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr) { - ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_SX_FIX)); mtr->memset(&block, uint16_t(descr - block.frame) + XDES_BITMAP, XDES_SIZE - XDES_BITMAP, 0xff); xdes_set_state(block, descr, XDES_FREE, mtr); @@ -322,8 +319,8 @@ xdes_get_descriptor_with_space_hdr( ulint limit; ulint size; ulint descr_page_no; - ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains(mtr, header, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains(space->latch, MTR_MEMO_X_LOCK)); + ut_ad(mtr->memo_contains_flagged(header, MTR_MEMO_PAGE_SX_FIX)); /* Read free limit and space size */ limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + header->frame); @@ -406,7 +403,7 @@ xdes_get_descriptor_const( page_no_t offset, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_S_LOCK)); + ut_ad(mtr->memo_contains(space->latch, MTR_MEMO_S_LOCK)); ut_ad(offset < space->free_limit); ut_ad(offset < space->size_in_header); @@ -447,7 +444,7 @@ xdes_lst_get_descriptor( buf_block_t** block, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); + ut_ad(mtr->memo_contains(space->latch, MTR_MEMO_X_LOCK)); return fut_get_ptr(space->id, space->zip_size(), lst_node, RW_SX_LATCH, mtr, block) - XDES_FLST_NODE; @@ -474,12 +471,12 @@ xdes_get_offset( void fsp_apply_init_file_page(buf_block_t *block) { memset_aligned(block->frame, 0, srv_page_size); + const page_id_t id(block->page.id()); - mach_write_to_4(block->frame + FIL_PAGE_OFFSET, block->page.id.page_no()); + mach_write_to_4(block->frame + FIL_PAGE_OFFSET, id.page_no()); if (log_sys.is_physical()) memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8); - mach_write_to_4(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, - block->page.id.space()); + mach_write_to_4(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id.space()); if (page_zip_des_t* page_zip= buf_block_get_page_zip(block)) { memset_aligned(page_zip->data, 0, @@ -557,7 +554,7 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) mtr_x_lock_space(space, mtr); const auto savepoint = mtr->get_savepoint(); - buf_block_t* block = buf_page_create(page_id, zip_size, mtr); + buf_block_t* block = buf_page_create(space, 0, zip_size, mtr); mtr->sx_latch_at_savepoint(savepoint, block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -799,7 +796,7 @@ ATTRIBUTE_COLD void fil_block_reset_type(const buf_block_t& block, ulint type, mtr_t* mtr) { ib::info() - << "Resetting invalid page " << block.page.id << " type " + << "Resetting invalid page " << block.page.id() << " type " << fil_page_get_type(block.frame) << " to " << type << "."; mtr->write<2>(block, block.frame + FIL_PAGE_TYPE, type); } @@ -878,8 +875,9 @@ fsp_fill_free_list( if (i > 0) { const auto savepoint = mtr->get_savepoint(); - block= buf_page_create(page_id_t(space->id, i), - zip_size, mtr); + block= buf_page_create( + space, static_cast(i), + zip_size, mtr); mtr->sx_latch_at_savepoint(savepoint, block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -901,8 +899,9 @@ fsp_fill_free_list( ibuf_mtr.set_named_space(space); block = buf_page_create( - page_id_t(space->id, - i + FSP_IBUF_BITMAP_OFFSET), + space, + static_cast( + i + FSP_IBUF_BITMAP_OFFSET), zip_size, &ibuf_mtr); ibuf_mtr.sx_latch_at_savepoint(0, block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -983,7 +982,7 @@ fsp_alloc_free_extent( fil_block_check_type(*desc_block, FIL_PAGE_TYPE_XDES, mtr); } - if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) { + if (descr && (xdes_get_state(descr) == XDES_FREE)) { /* Ok, we can take this extent */ } else { /* Take the first extent in the free list */ @@ -1023,7 +1022,7 @@ static void fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr, ulint bit, mtr_t *mtr) { - ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG); + ut_ad(xdes_get_state(descr) == XDES_FREE_FRAG); ut_a(xdes_is_free(descr, bit)); xdes_set_free(*xdes, descr, bit, mtr); @@ -1062,8 +1061,9 @@ fsp_page_create( rw_lock_type_t rw_latch, mtr_t* mtr) { - buf_block_t* block = buf_page_create(page_id_t(space->id, offset), - space->zip_size(), mtr); + buf_block_t* block = buf_page_create( + space, static_cast(offset), + space->zip_size(), mtr); /* The latch may already have been acquired, so we cannot invoke mtr_t::x_latch_at_savepoint() or mtr_t::sx_latch_at_savepoint(). */ @@ -1116,7 +1116,7 @@ fsp_alloc_free_page( descr = xdes_get_descriptor_with_space_hdr(block, space, hint, &xdes, mtr); - if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) { + if (descr && (xdes_get_state(descr) == XDES_FREE_FRAG)) { /* Ok, we can take this extent */ } else { /* Else take the first extent in free_frag list */ @@ -1180,7 +1180,7 @@ fsp_alloc_free_page( ut_a(!is_system_tablespace(space_id)); if (page_no >= FSP_EXTENT_SIZE) { ib::error() << "Trying to extend a single-table" - " tablespace " << space << " , by single" + " tablespace " << space->name << " , by single" " page(s) though the space size " << space_size << ". Page no " << page_no << "."; return(NULL); @@ -1214,12 +1214,12 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr) /* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */ buf_block_t* header = fsp_get_header(space, mtr); - buf_block_t* xdes; + buf_block_t* xdes= 0; descr = xdes_get_descriptor_with_space_hdr(header, space, offset, &xdes, mtr); - state = xdes_get_state(descr, mtr); + state = xdes_get_state(descr); if (UNIV_UNLIKELY(state != XDES_FREE_FRAG && state != XDES_FULL_FRAG)) { @@ -1254,7 +1254,7 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr) return; } - mtr->free(page_id_t(space->id, offset)); + mtr->free(*space, static_cast(offset)); const ulint bit = offset % FSP_EXTENT_SIZE; @@ -1296,14 +1296,14 @@ static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr) @param[in,out] mtr mini-transaction */ static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr) { - ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); + ut_ad(mtr->memo_contains(space->latch, MTR_MEMO_X_LOCK)); buf_block_t *block= fsp_get_header(space, mtr); - buf_block_t *xdes; + buf_block_t *xdes= 0; xdes_t* descr= xdes_get_descriptor_with_space_hdr(block, space, offset, &xdes, mtr); - ut_a(xdes_get_state(descr, mtr) != XDES_FREE); + ut_a(xdes_get_state(descr) != XDES_FREE); xdes_init(*xdes, descr, mtr); @@ -1385,7 +1385,7 @@ static bool fsp_alloc_seg_inode_page(fil_space_t *space, buf_block_t *header, mtr_t *mtr) { - ut_ad(header->page.id.space() == space->id); + ut_ad(header->page.id().space() == space->id); buf_block_t *block= fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr); if (!block) @@ -1500,7 +1500,7 @@ static void fsp_free_seg_inode( /* There are no other used headers left on the page: free it */ flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, iblock, FSEG_INODE_PAGE_NODE, mtr); - fsp_free_page(space, iblock->page.id.page_no(), mtr); + fsp_free_page(space, iblock->page.id().page_no(), mtr); } } @@ -1563,21 +1563,15 @@ fseg_inode_get( return(inode); } -/**********************************************************************//** -Gets the page number from the nth fragment page slot. -@return page number, FIL_NULL if not in use */ -UNIV_INLINE -ulint -fseg_get_nth_frag_page_no( -/*======================*/ - fseg_inode_t* inode, /*!< in: segment inode */ - ulint n, /*!< in: slot index */ - mtr_t* mtr MY_ATTRIBUTE((unused))) - /*!< in/out: mini-transaction */ +/** Get the page number from the nth fragment page slot. +@param inode file segment findex +@param n slot index +@return page number +@retval FIL_NULL if not in use */ +static ulint fseg_get_nth_frag_page_no(const fseg_inode_t *inode, ulint n) { - ut_ad(inode && mtr); + ut_ad(inode); ut_ad(n < FSEG_FRAG_ARR_N_SLOTS); - ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX)); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); return(mach_read_from_4(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE)); @@ -1593,7 +1587,7 @@ inline void fseg_set_nth_frag_page_no(fseg_inode_t *inode, buf_block_t *iblock, ulint n, ulint page_no, mtr_t *mtr) { ut_ad(n < FSEG_FRAG_ARR_N_SLOTS); - ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(iblock, MTR_MEMO_PAGE_SX_FIX)); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); mtr->write<4>(*iblock, inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE, @@ -1607,16 +1601,13 @@ static ulint fseg_find_free_frag_page_slot( /*==========================*/ - fseg_inode_t* inode, /*!< in: segment inode */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + fseg_inode_t* inode) /*!< in: segment inode */ { ulint i; ulint page_no; - ut_ad(inode && mtr); - for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { - page_no = fseg_get_nth_frag_page_no(inode, i, mtr); + page_no = fseg_get_nth_frag_page_no(inode, i); if (page_no == FIL_NULL) { @@ -1634,17 +1625,14 @@ static ulint fseg_find_last_used_frag_page_slot( /*===============================*/ - fseg_inode_t* inode, /*!< in: segment inode */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + fseg_inode_t* inode) /*!< in: segment inode */ { ulint i; ulint page_no; - ut_ad(inode && mtr); - for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { page_no = fseg_get_nth_frag_page_no( - inode, FSEG_FRAG_ARR_N_SLOTS - i - 1, mtr); + inode, FSEG_FRAG_ARR_N_SLOTS - i - 1); if (page_no != FIL_NULL) { @@ -1655,23 +1643,16 @@ fseg_find_last_used_frag_page_slot( return(ULINT_UNDEFINED); } -/**********************************************************************//** -Calculates reserved fragment page slots. +/** Calculate reserved fragment page slots. +@param inode file segment index @return number of fragment pages */ -static -ulint -fseg_get_n_frag_pages( -/*==================*/ - fseg_inode_t* inode, /*!< in: segment inode */ - mtr_t* mtr) /*!< in/out: mini-transaction */ +static ulint fseg_get_n_frag_pages(const fseg_inode_t *inode) { ulint i; ulint count = 0; - ut_ad(inode && mtr); - for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) { - if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i, mtr)) { + if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i)) { count++; } } @@ -1791,7 +1772,7 @@ fseg_create( + block->frame, page_offset(inode)); mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO - + block->frame, iblock->page.id.page_no()); + + block->frame, iblock->page.id().page_no()); mtr->write<4,mtr_t::MAYBE_NOP>(*block, byte_offset + FSEG_HDR_SPACE + block->frame, space->id); @@ -1812,26 +1793,18 @@ static ulint fseg_n_reserved_pages_low( /*======================*/ - fseg_inode_t* inode, /*!< in: segment inode */ - ulint* used, /*!< out: number of pages used (not + const fseg_inode_t* inode, /*!< in: segment inode */ + ulint* used) /*!< out: number of pages used (not more than reserved) */ - mtr_t* mtr) /*!< in/out: mini-transaction */ { - ulint ret; - - ut_ad(inode && used && mtr); - ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX)); - *used = mach_read_from_4(inode + FSEG_NOT_FULL_N_USED) + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL) - + fseg_get_n_frag_pages(inode, mtr); + + fseg_get_n_frag_pages(inode); - ret = fseg_get_n_frag_pages(inode, mtr) + return fseg_get_n_frag_pages(inode) + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FREE) + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_NOT_FULL) + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL); - - return(ret); } /** Calculate the number of pages reserved by a segment, @@ -1847,9 +1820,9 @@ ulint fseg_n_reserved_pages(const buf_block_t &block, { ut_ad(page_align(header) == block.frame); return fseg_n_reserved_pages_low(fseg_inode_get(header, - block.page.id.space(), + block.page.id().space(), block.zip_size(), mtr), - used, mtr); + used); } /** Tries to fill the free list of a segment with consecutive free extents. @@ -1880,7 +1853,7 @@ fseg_fill_free_list( ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_d(space->modify_check(*mtr)); - reserved = fseg_n_reserved_pages_low(inode, &used, mtr); + reserved = fseg_n_reserved_pages_low(inode, &used); if (reserved < FSEG_FREE_LIST_LIMIT * FSP_EXTENT_SIZE) { @@ -1899,11 +1872,8 @@ fseg_fill_free_list( buf_block_t* xdes; descr = xdes_get_descriptor(space, hint, &xdes, mtr); - if ((descr == NULL) - || (XDES_FREE != xdes_get_state(descr, mtr))) { - + if (!descr || (XDES_FREE != xdes_get_state(descr))) { /* We cannot allocate the desired extent: stop */ - return; } @@ -2039,7 +2009,7 @@ fseg_alloc_free_page_low( ut_d(space->modify_check(*mtr)); ut_ad(fil_page_get_type(page_align(seg_inode)) == FIL_PAGE_INODE); - reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr); + reserved = fseg_n_reserved_pages_low(seg_inode, &used); buf_block_t* header = fsp_get_header(space, mtr); @@ -2055,7 +2025,7 @@ fseg_alloc_free_page_low( /* In the big if-else below we look for ret_page and ret_descr */ /*-------------------------------------------------------------*/ - if ((xdes_get_state(descr, mtr) == XDES_FSEG) + if ((xdes_get_state(descr) == XDES_FSEG) && mach_read_from_8(descr + XDES_ID) == seg_id && xdes_is_free(descr, hint % FSP_EXTENT_SIZE)) { take_hinted_page: @@ -2068,7 +2038,7 @@ take_hinted_page: we would have got (descr == NULL) above and reset the hint. */ goto got_hinted_page; /*-----------------------------------------------------------*/ - } else if (xdes_get_state(descr, mtr) == XDES_FREE + } else if (xdes_get_state(descr) == XDES_FREE && reserved - used < reserved / FSEG_FILLFACTOR && used >= FSEG_FRAG_LIMIT) { @@ -2113,7 +2083,7 @@ take_hinted_page: } ut_ad(!has_done_reservation || ret_page != FIL_NULL); /*-----------------------------------------------------------*/ - } else if ((xdes_get_state(descr, mtr) == XDES_FSEG) + } else if ((xdes_get_state(descr) == XDES_FSEG) && mach_read_from_8(descr + XDES_ID) == seg_id && (!xdes_is_full(descr))) { @@ -2158,12 +2128,12 @@ take_hinted_page: if (block != NULL) { /* Put the page in the fragment page array of the segment */ - n = fseg_find_free_frag_page_slot(seg_inode, mtr); + n = fseg_find_free_frag_page_slot(seg_inode); ut_a(n != ULINT_UNDEFINED); fseg_set_nth_frag_page_no( - seg_inode, iblock, n, block->page.id.page_no(), - mtr); + seg_inode, iblock, n, + block->page.id().page_no(), mtr); } /* fsp_alloc_free_page() invoked fsp_init_file_page() @@ -2485,8 +2455,6 @@ try_to_extend: @param[in] seg_inode segment inode @param[in,out] space tablespace @param[in] offset page number -@param[in] ahi whether we may need to drop the adaptive -hash index @param[in,out] mtr mini-transaction */ static void @@ -2495,9 +2463,6 @@ fseg_free_page_low( buf_block_t* iblock, fil_space_t* space, page_no_t offset, -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) { ib_id_t descr_id; @@ -2510,15 +2475,6 @@ fseg_free_page_low( ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(iblock->frame == page_align(seg_inode)); ut_d(space->modify_check(*mtr)); -#ifdef BTR_CUR_HASH_ADAPT - /* Drop search system page hash index if the page is found in - the pool and is hashed */ - - if (ahi) { - btr_search_drop_page_hash_when_freed( - page_id_t(space->id, offset)); - } -#endif /* BTR_CUR_HASH_ADAPT */ buf_block_t* xdes; xdes_t* descr = xdes_get_descriptor(space, offset, &xdes, mtr); @@ -2533,10 +2489,10 @@ fseg_free_page_low( << FORCE_RECOVERY_MSG; } - if (xdes_get_state(descr, mtr) != XDES_FSEG) { + if (xdes_get_state(descr) != XDES_FSEG) { /* The page is in the fragment pages of the segment */ for (ulint i = 0;; i++) { - if (fseg_get_nth_frag_page_no(seg_inode, i, mtr) + if (fseg_get_nth_frag_page_no(seg_inode, i) != offset) { continue; } @@ -2604,29 +2560,19 @@ fseg_free_page_low( fsp_free_extent(space, offset, mtr); } - mtr->free(page_id_t(space->id, offset)); + mtr->free(*space, static_cast(offset)); } -#ifndef BTR_CUR_HASH_ADAPT -# define fseg_free_page_low(inode, space, offset, ahi, mtr) \ - fseg_free_page_low(inode, space, offset, mtr) -#endif /* !BTR_CUR_HASH_ADAPT */ - /** Free a page in a file segment. @param[in,out] seg_header file segment header @param[in,out] space tablespace @param[in] offset page number -@param[in] ahi whether we may need to drop the adaptive -hash index @param[in,out] mtr mini-transaction */ void -fseg_free_page_func( +fseg_free_page( fseg_header_t* seg_header, fil_space_t* space, ulint offset, -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) { DBUG_ENTER("fseg_free_page"); @@ -2644,9 +2590,7 @@ fseg_free_page_func( fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); } - fseg_free_page_low(seg_inode, iblock, space, offset, ahi, mtr); - - buf_page_free(page_id_t(space->id, offset), mtr, __FILE__, __LINE__); + fseg_free_page_low(seg_inode, iblock, space, offset, mtr); DBUG_VOID_RETURN; } @@ -2683,8 +2627,6 @@ fseg_page_is_free(fil_space_t* space, unsigned page) @param[in,out] seg_inode segment inode @param[in,out] space tablespace @param[in] page page number in the extent -@param[in] ahi whether we may need to drop - the adaptive hash index @param[in,out] mtr mini-transaction */ MY_ATTRIBUTE((nonnull)) static @@ -2694,41 +2636,20 @@ fseg_free_extent( buf_block_t* iblock, fil_space_t* space, ulint page, -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) { - ulint first_page_in_extent; ut_ad(mtr != NULL); buf_block_t* xdes; xdes_t* descr = xdes_get_descriptor(space, page, &xdes, mtr); - ut_a(xdes_get_state(descr, mtr) == XDES_FSEG); + ut_a(xdes_get_state(descr) == XDES_FSEG); ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); ut_d(space->modify_check(*mtr)); - - first_page_in_extent = page - (page % FSP_EXTENT_SIZE); - -#ifdef BTR_CUR_HASH_ADAPT - if (ahi) { - for (ulint i = 0; i < FSP_EXTENT_SIZE; i++) { - if (!xdes_is_free(descr, i)) { - /* Drop search system page hash index - if the page is found in the pool and - is hashed */ - - btr_search_drop_page_hash_when_freed( - page_id_t(space->id, - first_page_in_extent + i)); - } - } - } -#endif /* BTR_CUR_HASH_ADAPT */ + const ulint first_page_in_extent = page - (page % FSP_EXTENT_SIZE); const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE); const uint16_t ioffset= uint16_t(seg_inode - iblock->frame); @@ -2756,33 +2677,24 @@ fseg_free_extent( for (ulint i = 0; i < FSP_EXTENT_SIZE; i++) { if (!xdes_is_free(descr, i)) { buf_page_free( - page_id_t(space->id, first_page_in_extent + i), + page_id_t(space->id, first_page_in_extent + 1), mtr, __FILE__, __LINE__); } } } -#ifndef BTR_CUR_HASH_ADAPT -# define fseg_free_extent(inode, iblock, space, page, ahi, mtr) \ - fseg_free_extent(inode, iblock, space, page, mtr) -#endif /* !BTR_CUR_HASH_ADAPT */ - /**********************************************************************//** Frees part of a segment. This function can be used to free a segment by repeatedly calling this function in different mini-transactions. Doing the freeing in a single mini-transaction might result in too big a mini-transaction. -@return true if freeing completed */ +@return whether the freeing was completed */ bool -fseg_free_step_func( +fseg_free_step( fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header resides on the first page of the frag list of the segment, this pointer becomes obsolete after the last freeing step */ -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, /*!< in: whether we may need to drop - the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint n; @@ -2822,12 +2734,12 @@ fseg_free_step_func( if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - fseg_free_extent(inode, iblock, space, page, ahi, mtr); + fseg_free_extent(inode, iblock, space, page, mtr); DBUG_RETURN(false); } /* Free a frag page */ - n = fseg_find_last_used_frag_page_slot(inode, mtr); + n = fseg_find_last_used_frag_page_slot(inode); if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ @@ -2838,10 +2750,10 @@ fseg_free_step_func( fseg_free_page_low( inode, iblock, space, - fseg_get_nth_frag_page_no(inode, n, mtr), - ahi, mtr); + fseg_get_nth_frag_page_no(inode, n), + mtr); - n = fseg_find_last_used_frag_page_slot(inode, mtr); + n = fseg_find_last_used_frag_page_slot(inode); if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ @@ -2856,15 +2768,11 @@ fseg_free_step_func( /**********************************************************************//** Frees part of a segment. Differs from fseg_free_step because this function leaves the header page unfreed. -@return true if freeing completed, except the header page */ +@return whether the freeing was completed, except for the header page */ bool -fseg_free_step_not_header_func( +fseg_free_step_not_header( fseg_header_t* header, /*!< in: segment header which must reside on the first fragment page of the segment */ -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, /*!< in: whether we may need to drop - the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint n; @@ -2891,30 +2799,24 @@ fseg_free_step_not_header_func( if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - - fseg_free_extent(inode, iblock, space, page, ahi, mtr); - - return(false); + fseg_free_extent(inode, iblock, space, page, mtr); + return false; } /* Free a frag page */ - n = fseg_find_last_used_frag_page_slot(inode, mtr); + n = fseg_find_last_used_frag_page_slot(inode); - if (n == ULINT_UNDEFINED) { - ut_error; - } + ut_a(n != ULINT_UNDEFINED); - page_no = fseg_get_nth_frag_page_no(inode, n, mtr); + page_no = fseg_get_nth_frag_page_no(inode, n); if (page_no == page_get_page_no(page_align(header))) { - - return(true); + return true; } - fseg_free_page_low(inode, iblock, space, page_no, ahi, mtr); - - return(false); + fseg_free_page_low(inode, iblock, space, page_no, mtr); + return false; } /** Returns the first extent descriptor for a segment. @@ -2958,12 +2860,7 @@ fseg_get_first_extent( #ifdef UNIV_BTR_PRINT /*******************************************************************//** Writes info of a segment. */ -static -void -fseg_print_low( -/*===========*/ - fseg_inode_t* inode, /*!< in: segment inode */ - mtr_t* mtr) /*!< in/out: mini-transaction */ +static void fseg_print_low(const fseg_inode_t *inode) { ulint space; ulint n_used; @@ -2976,15 +2873,14 @@ fseg_print_low( ulint page_no; ib_id_t seg_id; - ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX)); space = page_get_space_id(page_align(inode)); page_no = page_get_page_no(page_align(inode)); - reserved = fseg_n_reserved_pages_low(inode, &used, mtr); + reserved = fseg_n_reserved_pages_low(inode, &used); seg_id = mach_read_from_8(inode + FSEG_ID); n_used = mach_read_from_4(inode + FSEG_NOT_FULL_N_USED); - n_frag = fseg_get_n_frag_pages(inode, mtr); + n_frag = fseg_get_n_frag_pages(inode); n_free = flst_get_len(inode + FSEG_FREE); n_not_full = flst_get_len(inode + FSEG_NOT_FULL); n_full = flst_get_len(inode + FSEG_FULL); @@ -3017,7 +2913,7 @@ fseg_print( inode = fseg_inode_get(header, space_id, space->zip_size(), mtr); - fseg_print_low(inode, mtr); + fseg_print_low(inode); } #endif /* UNIV_BTR_PRINT */ diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index f0dea8ebde2..5d381fca033 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2020, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -906,9 +906,13 @@ SysTablespace::open_or_create( } else if (is_temp) { ut_ad(!fil_system.temp_space); ut_ad(space_id() == SRV_TMP_SPACE_ID); - space = fil_system.temp_space = fil_space_create( + space = fil_space_create( name(), SRV_TMP_SPACE_ID, flags(), FIL_TYPE_TEMPORARY, NULL); + + mutex_enter(&fil_system.mutex); + fil_system.temp_space = space; + mutex_exit(&fil_system.mutex); if (!space) { return DB_ERROR; } @@ -917,9 +921,13 @@ SysTablespace::open_or_create( } else { ut_ad(!fil_system.sys_space); ut_ad(space_id() == TRX_SYS_SPACE); - space = fil_system.sys_space = fil_space_create( + space = fil_space_create( name(), TRX_SYS_SPACE, it->flags(), FIL_TYPE_TABLESPACE, NULL); + + mutex_enter(&fil_system.mutex); + fil_system.sys_space = space; + mutex_exit(&fil_system.mutex); if (!space) { return DB_ERROR; } diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 410d60a5f4e..8ae10c2465d 100644 --- a/storage/innobase/fts/fts0config.cc +++ b/storage/innobase/fts/fts0config.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -317,9 +317,7 @@ fts_config_get_index_ulint( error = fts_config_get_index_value(trx, index, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - - ib::error() << "(" << ut_strerr(error) << ") reading `" - << name << "'"; + ib::error() << "(" << error << ") reading `" << name << "'"; } else { *int_value = strtoul((char*) value.f_str, NULL, 10); } @@ -357,9 +355,7 @@ fts_config_set_index_ulint( error = fts_config_set_index_value(trx, index, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - - ib::error() << "(" << ut_strerr(error) << ") writing `" - << name << "'"; + ib::error() << "(" << error << ") writing `" << name << "'"; } ut_free(value.f_str); @@ -391,8 +387,7 @@ fts_config_get_ulint( error = fts_config_get_value(trx, fts_table, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - ib::error() << "(" << ut_strerr(error) << ") reading `" - << name << "'"; + ib::error() << "(" << error << ") reading `" << name << "'"; } else { *int_value = strtoul((char*) value.f_str, NULL, 10); } @@ -430,8 +425,7 @@ fts_config_set_ulint( error = fts_config_set_value(trx, fts_table, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - ib::error() << "(" << ut_strerr(error) << ") writing `" - << name << "'"; + ib::error() << "(" << error << ") writing `" << name << "'"; } ut_free(value.f_str); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 18a9db369c4..145f5c27e5f 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -509,7 +509,7 @@ cleanup: for (;;) { dberr_t error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); stopword_info->status = STOPWORD_USER_TABLE; break; @@ -522,7 +522,7 @@ cleanup: trx->error_state = DB_SUCCESS; } else { - ib::error() << "Error '" << ut_strerr(error) + ib::error() << "Error '" << error << "' while reading user stopword" " table."; ret = FALSE; @@ -583,7 +583,7 @@ fts_cache_init( mutex_enter((ib_mutex_t*) &cache->deleted_lock); cache->deleted_doc_ids = ib_vector_create( - cache->sync_heap, sizeof(fts_update_t), 4); + cache->sync_heap, sizeof(doc_id_t), 4); mutex_exit((ib_mutex_t*) &cache->deleted_lock); /* Reset the cache data for all the FTS indexes. */ @@ -804,6 +804,29 @@ fts_check_cached_index( return(TRUE); } +/** Clear all fts resources when there is no internal DOC_ID +and there are no new fts index to add. +@param[in,out] table table where fts is to be freed +@param[in] trx transaction to drop all fts tables */ +void fts_clear_all(dict_table_t *table, trx_t *trx) +{ + if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) || + !table->fts || + !ib_vector_is_empty(table->fts->indexes)) + return; + + for (const dict_index_t *index= dict_table_get_first_index(table); + index; index= dict_table_get_next_index(index)) + if (index->type & DICT_FTS) + return; + + fts_optimize_remove_table(table); + + fts_drop_tables(trx, table); + fts_free(table); + DICT_TF2_FLAG_UNSET(table, DICT_TF2_FTS); +} + /*******************************************************************//** Drop auxiliary tables related to an FTS index @return DB_SUCCESS or error number */ @@ -820,30 +843,15 @@ fts_drop_index( ut_a(indexes); if ((ib_vector_size(indexes) == 1 - && (index == static_cast( - ib_vector_getp(table->fts->indexes, 0)))) - || ib_vector_is_empty(indexes)) { + && (index == static_cast( + ib_vector_getp(table->fts->indexes, 0))) + && DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) + || ib_vector_is_empty(indexes)) { doc_id_t current_doc_id; doc_id_t first_doc_id; DICT_TF2_FLAG_UNSET(table, DICT_TF2_FTS); - /* If Doc ID column is not added internally by FTS index, - we can drop all FTS auxiliary tables. Otherwise, we will - need to keep some common table such as CONFIG table, so - as to keep track of incrementing Doc IDs */ - if (!DICT_TF2_FLAG_IS_SET( - table, DICT_TF2_FTS_HAS_DOC_ID)) { - - err = fts_drop_tables(trx, table); - - err = fts_drop_index_tables(trx, index); - - fts_free(table); - - return(err); - } - current_doc_id = table->fts->cache->next_doc_id; first_doc_id = table->fts->cache->first_doc_id; fts_cache_clear(table->fts->cache); @@ -1435,9 +1443,9 @@ fts_drop_table( error = row_drop_table_for_mysql(table_name, trx, SQLCOM_DROP_DB, false, false); - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Unable to drop FTS index aux table " - << table_name << ": " << ut_strerr(error); + << table_name << ": " << error; } } else { error = DB_FAIL; @@ -2490,8 +2498,7 @@ fts_get_max_cache_size( error = fts_config_get_value( trx, fts_table, FTS_MAX_CACHE_SIZE_IN_MB, &value); - if (error == DB_SUCCESS) { - + if (UNIV_LIKELY(error == DB_SUCCESS)) { value.f_str[value.f_len] = 0; cache_size_in_mb = strtoul((char*) value.f_str, NULL, 10); @@ -2521,7 +2528,7 @@ fts_get_max_cache_size( cache_size_in_mb = FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB; } } else { - ib::error() << "(" << ut_strerr(error) << ") reading max" + ib::error() << "(" << error << ") reading max" " cache config value from config table"; } @@ -2592,11 +2599,11 @@ dberr_t fts_cmp_set_sync_doc_id( /*====================*/ const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id_cmp, /*!< in: Doc ID to compare */ + doc_id_t cmp_doc_id, /*!< in: Doc ID to compare */ ibool read_only, /*!< in: TRUE if read the synced_doc_id only */ doc_id_t* doc_id) /*!< out: larger document id - after comparing "doc_id_cmp" + after comparing "cmp_doc_id" to the one stored in CONFIG table */ { @@ -2667,10 +2674,10 @@ retry: goto func_exit; } - if (doc_id_cmp == 0 && *doc_id) { + if (cmp_doc_id == 0 && *doc_id) { cache->synced_doc_id = *doc_id - 1; } else { - cache->synced_doc_id = ut_max(doc_id_cmp, *doc_id); + cache->synced_doc_id = ut_max(cmp_doc_id, *doc_id); } mutex_enter(&cache->doc_id_lock); @@ -2681,7 +2688,7 @@ retry: } mutex_exit(&cache->doc_id_lock); - if (doc_id_cmp > *doc_id) { + if (cmp_doc_id > *doc_id) { error = fts_update_sync_doc_id( table, cache->synced_doc_id, trx); } @@ -2690,13 +2697,12 @@ retry: func_exit: - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); } else { *doc_id = 0; - ib::error() << "(" << ut_strerr(error) << ") while getting" - " next doc id."; + ib::error() << "(" << error << ") while getting next doc id."; fts_sql_rollback(trx); if (error == DB_DEADLOCK) { @@ -2771,12 +2777,11 @@ fts_update_sync_doc_id( fts_que_graph_free_check_lock(&fts_table, NULL, graph); if (local_trx) { - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); cache->synced_doc_id = doc_id; } else { - - ib::error() << "(" << ut_strerr(error) << ") while" + ib::error() << "(" << error << ") while" " updating last doc id."; fts_sql_rollback(trx); @@ -2803,7 +2808,7 @@ fts_doc_ids_create(void) fts_doc_ids->self_heap = ib_heap_allocator_create(heap); fts_doc_ids->doc_ids = static_cast(ib_vector_create( - fts_doc_ids->self_heap, sizeof(fts_update_t), 32)); + fts_doc_ids->self_heap, sizeof(doc_id_t), 32)); return(fts_doc_ids); } @@ -3878,7 +3883,7 @@ fts_sync_add_deleted_cache( ut_a(ib_vector_size(doc_ids) > 0); - ib_vector_sort(doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(doc_ids, fts_doc_id_cmp); info = pars_info_create(); @@ -3896,13 +3901,13 @@ fts_sync_add_deleted_cache( "BEGIN INSERT INTO $table_name VALUES (:doc_id);"); for (i = 0; i < n_elems && error == DB_SUCCESS; ++i) { - fts_update_t* update; + doc_id_t* update; doc_id_t write_doc_id; - update = static_cast(ib_vector_get(doc_ids, i)); + update = static_cast(ib_vector_get(doc_ids, i)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); fts_bind_doc_id(info, "doc_id", &write_doc_id); error = fts_eval_sql(sync->trx, graph); @@ -4000,14 +4005,14 @@ fts_sync_write_words( n_nodes += ib_vector_size(word->nodes); - if (error != DB_SUCCESS && !print_error) { - ib::error() << "(" << ut_strerr(error) << ") writing" + if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) { + ib::error() << "(" << error << ") writing" " word node to FTS auxiliary index table."; print_error = TRUE; } } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { printf("Avg number of nodes: %lf\n", (double) n_nodes / (double) (n_words > 1 ? n_words : 1)); } @@ -4033,7 +4038,7 @@ fts_sync_begin( sync->trx = trx_create(); trx_start_internal(sync->trx); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS SYNC for table " << sync->table->name << ", deleted count: " << ib_vector_size(cache->deleted_doc_ids) @@ -4056,7 +4061,7 @@ fts_sync_index( trx->op_info = "doing SYNC index"; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "SYNC words: " << rbt_size(index_cache->words); } @@ -4153,18 +4158,14 @@ fts_sync_commit( fts_cache_init(cache); rw_lock_x_unlock(&cache->lock); - if (error == DB_SUCCESS) { - + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); - - } else if (error != DB_SUCCESS) { - + } else { fts_sql_rollback(trx); - - ib::error() << "(" << ut_strerr(error) << ") during SYNC."; + ib::error() << "(" << error << ") during SYNC."; } - if (fts_enable_diag_print && elapsed_time) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && elapsed_time) { ib::info() << "SYNC for table " << sync->table->name << ": SYNC time: " << (time(NULL) - sync->start_time) @@ -4910,7 +4911,7 @@ fts_get_rows_count( for (;;) { error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; /* Exit the loop. */ @@ -4923,7 +4924,7 @@ fts_get_rows_count( trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading FTS table."; break; /* Exit the loop. */ @@ -5193,12 +5194,12 @@ fts_cache_append_deleted_doc_ids( for (ulint i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) { - fts_update_t* update; + doc_id_t* update; - update = static_cast( + update = static_cast( ib_vector_get(cache->deleted_doc_ids, i)); - ib_vector_push(vector, &update->doc_id); + ib_vector_push(vector, &update); } mutex_exit((ib_mutex_t*) &cache->deleted_lock); @@ -6946,7 +6947,7 @@ fts_drop_orphaned_tables(void) for (;;) { dberr_t error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_check_and_drop_orphaned_tables(trx, tables); break; /* Exit the loop. */ } else { @@ -6960,7 +6961,7 @@ fts_drop_orphaned_tables(void) trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading SYS_TABLES."; break; /* Exit the loop. */ diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index fd2156c006e..490cbcd4546 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -42,6 +42,7 @@ ib_wqueue_t* fts_optimize_wq; static void fts_optimize_callback(void *); static void timer_callback(void*); static tpool::timer* timer; + static tpool::task_group task_group(1); static tpool::task task(fts_optimize_callback,0, &task_group); @@ -530,7 +531,7 @@ fts_index_fetch_nodes( for (;;) { error = fts_eval_sql(trx, *graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; /* Exit the loop. */ @@ -543,7 +544,7 @@ fts_index_fetch_nodes( trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading FTS index."; break; /* Exit the loop. */ @@ -865,7 +866,7 @@ fts_index_fetch_words( error = fts_eval_sql(optim->trx, graph); } - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { //FIXME fts_sql_commit(optim->trx); break; } else { @@ -882,7 +883,7 @@ fts_index_fetch_words( optim->trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading document."; break; /* Exit the loop. */ @@ -925,7 +926,7 @@ fts_fetch_doc_ids( int i = 0; sel_node_t* sel_node = static_cast(row); fts_doc_ids_t* fts_doc_ids = static_cast(user_arg); - fts_update_t* update = static_cast( + doc_id_t* update = static_cast( ib_vector_push(fts_doc_ids->doc_ids, NULL)); for (exp = sel_node->select_list; @@ -941,8 +942,7 @@ fts_fetch_doc_ids( /* Note: The column numbers below must match the SELECT. */ switch (i) { case 0: /* DOC_ID */ - update->fts_indexes = NULL; - update->doc_id = fts_read_doc_id( + *update = fts_read_doc_id( static_cast(data)); break; @@ -1010,7 +1010,7 @@ fts_table_fetch_doc_ids( mutex_exit(&dict_sys.mutex); if (error == DB_SUCCESS) { - ib_vector_sort(doc_ids->doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(doc_ids->doc_ids, fts_doc_id_cmp); } if (alloc_bk_trx) { @@ -1027,7 +1027,7 @@ Do a binary search for a doc id in the array int fts_bsearch( /*========*/ - fts_update_t* array, /*!< in: array to sort */ + doc_id_t* array, /*!< in: array to sort */ int lower, /*!< in: the array lower bound */ int upper, /*!< in: the array upper bound */ doc_id_t doc_id) /*!< in: the doc id to search for */ @@ -1041,9 +1041,9 @@ fts_bsearch( while (lower < upper) { int i = (lower + upper) >> 1; - if (doc_id > array[i].doc_id) { + if (doc_id > array[i]) { lower = i + 1; - } else if (doc_id < array[i].doc_id) { + } else if (doc_id < array[i]) { upper = i - 1; } else { return(i); /* Found. */ @@ -1052,7 +1052,7 @@ fts_bsearch( } if (lower == upper && lower < orig_size) { - if (doc_id == array[lower].doc_id) { + if (doc_id == array[lower]) { return(lower); } else if (lower == 0) { return(-1); @@ -1079,7 +1079,7 @@ fts_optimize_lookup( { int pos; int upper = static_cast(ib_vector_size(doc_ids)); - fts_update_t* array = (fts_update_t*) doc_ids->data; + doc_id_t* array = (doc_id_t*) doc_ids->data; pos = fts_bsearch(array, static_cast(lower), upper, first_doc_id); @@ -1092,10 +1092,10 @@ fts_optimize_lookup( /* If i is 1, it could be first_doc_id is less than either the first or second array item, do a double check */ - if (i == 1 && array[0].doc_id <= last_doc_id - && first_doc_id < array[0].doc_id) { + if (i == 1 && array[0] <= last_doc_id + && first_doc_id < array[0]) { pos = 0; - } else if (i < upper && array[i].doc_id <= last_doc_id) { + } else if (i < upper && array[i] <= last_doc_id) { /* Check if the "next" doc id is within the first & last doc id of the node. */ @@ -1234,12 +1234,12 @@ test_again: delta for decoding the entries following this document's entries. */ if (*del_pos >= 0 && *del_pos < (int) ib_vector_size(del_vec)) { - fts_update_t* update; + doc_id_t* update; - update = (fts_update_t*) ib_vector_get( + update = (doc_id_t*) ib_vector_get( del_vec, ulint(*del_pos)); - del_doc_id = update->doc_id; + del_doc_id = *update; } if (enc->src_ilist_ptr == src_node->ilist && doc_id == 0) { @@ -1362,12 +1362,6 @@ fts_optimize_word( enc.src_last_doc_id = 0; enc.src_ilist_ptr = NULL; - if (fts_enable_diag_print) { - word->text.f_str[word->text.f_len] = 0; - ib::info() << "FTS_OPTIMIZE: optimize \"" << word->text.f_str - << "\""; - } - while (i < size) { ulint copied; fts_node_t* src_node; @@ -1445,11 +1439,6 @@ fts_optimize_write_word( ut_ad(fts_table->charset); - if (fts_enable_diag_print) { - ib::info() << "FTS_OPTIMIZE: processed \"" << word->f_str - << "\""; - } - pars_info_bind_varchar_literal( info, "word", word->f_str, word->f_len); @@ -1467,8 +1456,8 @@ fts_optimize_write_word( error = fts_eval_sql(trx, graph); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) << ") during optimize," + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") during optimize," " when deleting a word from the FTS index."; } @@ -1491,8 +1480,8 @@ fts_optimize_write_word( error = fts_write_node( trx, &graph, fts_table, word, node); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) << ")" + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ")" " during optimize, while adding a" " word to the FTS index."; } @@ -1881,9 +1870,8 @@ fts_optimize_index_completed( error = fts_config_set_index_value( optim->trx, index, FTS_LAST_OPTIMIZED_WORD, &word); - if (error != DB_SUCCESS) { - - ib::error() << "(" << ut_strerr(error) << ") while updating" + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") while updating" " last optimized word!"; } @@ -2025,7 +2013,7 @@ fts_optimize_purge_deleted_doc_ids( ulint i; pars_info_t* info; que_t* graph; - fts_update_t* update; + doc_id_t* update; doc_id_t write_doc_id; dberr_t error = DB_SUCCESS; char deleted[MAX_FULL_NAME_LEN]; @@ -2035,11 +2023,11 @@ fts_optimize_purge_deleted_doc_ids( ut_a(ib_vector_size(optim->to_delete->doc_ids) > 0); - update = static_cast( + update = static_cast( ib_vector_get(optim->to_delete->doc_ids, 0)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); /* This is required for the SQL parser to work. It must be able to find the following variables. So we do it twice. */ @@ -2061,11 +2049,11 @@ fts_optimize_purge_deleted_doc_ids( /* Delete the doc ids that were copied at the start. */ for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) { - update = static_cast(ib_vector_get( + update = static_cast(ib_vector_get( optim->to_delete->doc_ids, i)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); fts_bind_doc_id(info, "doc_id1", &write_doc_id); @@ -2435,7 +2423,7 @@ fts_optimize_table( fts_optimize_t* optim = NULL; fts_t* fts = table->fts; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS start optimize " << table->name; } @@ -2487,7 +2475,7 @@ fts_optimize_table( if (error == DB_SUCCESS && optim->n_completed == ib_vector_size(fts->indexes)) { - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS_OPTIMIZE: Completed" " Optimize, cleanup DELETED table"; } @@ -2510,7 +2498,7 @@ fts_optimize_table( fts_optimize_free(optim); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS end optimize " << table->name; } @@ -2709,7 +2697,7 @@ static bool fts_optimize_del_table(const dict_table_t* table) slot = static_cast(ib_vector_get(fts_slots, i)); if (slot->table == table) { - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS Optimize Removing table " << table->name; } @@ -2836,8 +2824,7 @@ static void fts_optimize_callback(void *) static ulint n_tables = ib_vector_size(fts_slots); static ulint n_optimize = 0; - while (!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) { - + while (!done && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { /* If there is no message in the queue and we have tables to optimize then optimize the tables. */ @@ -3015,8 +3002,7 @@ fts_optimize_shutdown() /* We tell the OPTIMIZE thread to switch to state done, we can't delete the work queue here because the add thread needs deregister the FTS tables. */ - delete timer; - timer = NULL; + timer->disarm(); task_group.cancel_pending(&task); msg = fts_optimize_create_msg(FTS_MSG_STOP, NULL); @@ -3027,6 +3013,8 @@ fts_optimize_shutdown() os_event_destroy(fts_opt_shutdown_event); fts_opt_thd = NULL; + delete timer; + timer = NULL; } /** Sync the table during commit phase diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index c912f5e0764..db972b5dbff 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -731,10 +731,10 @@ fts_query_union_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's not already in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) != 0) { fts_ranking_t ranking; @@ -762,10 +762,10 @@ fts_query_remove_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) == 0) { ut_free(rbt_remove_node(query->doc_ids, parent.last)); @@ -792,10 +792,10 @@ fts_query_change_ranking( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) == 0) { fts_ranking_t* ranking; @@ -829,7 +829,7 @@ fts_query_intersect_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; fts_ranking_t* ranking= NULL; /* There are three types of intersect: @@ -841,7 +841,7 @@ fts_query_intersect_doc_id( if it matches 'b' and it's in doc_ids.(multi_exist = true). */ /* Check if the doc id is deleted and it's in our set */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0) { + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0) { fts_ranking_t new_ranking; if (rbt_search(query->doc_ids, &parent, &doc_id) != 0) { @@ -2448,9 +2448,8 @@ fts_query_match_document( get_doc, match->doc_id, NULL, FTS_FETCH_DOC_BY_ID_EQUAL, fts_query_fetch_document, &phrase); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) - << ") matching document."; + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") matching document."; } else { *found = phrase.found; } @@ -2496,8 +2495,8 @@ fts_query_is_in_proximity_range( &get_doc, match[0]->doc_id, NULL, FTS_FETCH_DOC_BY_ID_EQUAL, fts_query_fetch_document, &phrase); - if (err != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(err) << ") in verification" + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::error() << "(" << err << ") in verification" " phase of proximity search"; } @@ -3503,14 +3502,6 @@ fts_query_calculate_idf( word_freq->doc_count)); } } - - if (fts_enable_diag_print) { - ib::info() << "'" << word_freq->word.f_str << "' -> " - << query->total_docs << "/" - << word_freq->doc_count << " " - << std::setw(6) << std::setprecision(5) - << word_freq->idf; - } } } @@ -3651,8 +3642,8 @@ fts_query_prepare_result( if (query->flags == FTS_OPT_RANKING) { fts_word_freq_t* word_freq; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = - (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = + (doc_id_t*) query->deleted->doc_ids->data; node = rbt_first(query->word_freqs); ut_ad(node); @@ -3667,7 +3658,7 @@ fts_query_prepare_result( doc_freq = rbt_value(fts_doc_freq_t, node); /* Don't put deleted docs into result */ - if (fts_bsearch(array, 0, static_cast(size), + if (fts_bsearch(updates, 0, static_cast(size), doc_freq->doc_id) >= 0) { /* one less matching doc count */ --word_freq->doc_count; @@ -3886,7 +3877,7 @@ fts_query_parse( } else { query->root = state.root; - if (fts_enable_diag_print && query->root != NULL) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && query->root) { fts_ast_node_print(query->root); } } @@ -4018,7 +4009,7 @@ fts_query( DEBUG_SYNC_C("fts_deleted_doc_ids_append"); /* Sort the vector so that we can do a binary search over the ids. */ - ib_vector_sort(query.deleted->doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(query.deleted->doc_ids, fts_doc_id_cmp); /* Convert the query string to lower case before parsing. We own the ut_malloc'ed result and so remember to free it before return. */ @@ -4110,7 +4101,7 @@ fts_query( ut_free(lc_query_str); - if (fts_enable_diag_print && (*result)) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && (*result)) { ulint diff_time = ut_time_ms() - start_time_ms; ib::info() << "FTS Search Processing time: " @@ -4266,7 +4257,7 @@ fts_expand_query( query->total_size += SIZEOF_RBT_CREATE; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { fts_print_doc_id(query); } diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index 0a54d51b462..e084f0b7935 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -90,18 +90,16 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); ut_ad(aoffset < add->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN)); mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U); /* Update first and last fields of base node */ flst_write_addr(*base, base->frame + boffset + FLST_FIRST, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); memcpy(base->frame + boffset + FLST_LAST, base->frame + boffset + FLST_FIRST, FIL_ADDR_SIZE); /* Initialize FLST_LAST by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source) @@ -132,37 +130,34 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset, ut_ad(boffset < base->physical_size()); ut_ad(coffset < cur->physical_size()); ut_ad(aoffset < add->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(cur, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); flst_write_addr(*add, add->frame + aoffset + FLST_PREV, - cur->page.id.page_no(), coffset, mtr); + cur->page.id().page_no(), coffset, mtr); flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, next_addr.page, next_addr.boffset, mtr); if (next_addr.page == FIL_NULL) flst_write_addr(*base, base->frame + boffset + FLST_LAST, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); else { buf_block_t *block; - flst_node_t *next= fut_get_ptr(add->page.id.space(), add->zip_size(), + flst_node_t *next= fut_get_ptr(add->page.id().space(), add->zip_size(), next_addr, RW_SX_LATCH, mtr, &block); flst_write_addr(*block, next + FLST_PREV, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); } flst_write_addr(*cur, cur->frame + coffset + FLST_NEXT, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); byte *len= &base->frame[boffset + FLST_LEN]; mtr->write<4>(*base, len, mach_read_from_4(len) + 1); @@ -186,37 +181,34 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset, ut_ad(boffset < base->physical_size()); ut_ad(coffset < cur->physical_size()); ut_ad(aoffset < add->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(cur, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); flst_write_addr(*add, add->frame + aoffset + FLST_PREV, prev_addr.page, prev_addr.boffset, mtr); flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, - cur->page.id.page_no(), coffset, mtr); + cur->page.id().page_no(), coffset, mtr); if (prev_addr.page == FIL_NULL) flst_write_addr(*base, base->frame + boffset + FLST_FIRST, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); else { buf_block_t *block; - flst_node_t *prev= fut_get_ptr(add->page.id.space(), add->zip_size(), + flst_node_t *prev= fut_get_ptr(add->page.id().space(), add->zip_size(), prev_addr, RW_SX_LATCH, mtr, &block); flst_write_addr(*block, prev + FLST_NEXT, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); } flst_write_addr(*cur, cur->frame + coffset + FLST_PREV, - add->page.id.page_no(), aoffset, mtr); + add->page.id().page_no(), aoffset, mtr); byte *len= &base->frame[boffset + FLST_LEN]; mtr->write<4>(*base, len, mach_read_from_4(len) + 1); @@ -247,12 +239,10 @@ void flst_add_last(buf_block_t *base, uint16_t boffset, ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); ut_ad(aoffset < add->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); if (!flst_get_len(base->frame + boffset)) flst_add_to_empty(base, boffset, add, aoffset, mtr); @@ -260,9 +250,9 @@ void flst_add_last(buf_block_t *base, uint16_t boffset, { fil_addr_t addr= flst_get_last(base->frame + boffset); buf_block_t *cur= add; - const flst_node_t *c= addr.page == add->page.id.page_no() + const flst_node_t *c= addr.page == add->page.id().page_no() ? add->frame + addr.boffset - : fut_get_ptr(add->page.id.space(), add->zip_size(), addr, + : fut_get_ptr(add->page.id().space(), add->zip_size(), addr, RW_SX_LATCH, mtr, &cur); flst_insert_after(base, boffset, cur, static_cast(c - cur->frame), @@ -282,12 +272,10 @@ void flst_add_first(buf_block_t *base, uint16_t boffset, ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); ut_ad(aoffset < add->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); if (!flst_get_len(base->frame + boffset)) flst_add_to_empty(base, boffset, add, aoffset, mtr); @@ -295,9 +283,9 @@ void flst_add_first(buf_block_t *base, uint16_t boffset, { fil_addr_t addr= flst_get_first(base->frame + boffset); buf_block_t *cur= add; - const flst_node_t *c= addr.page == add->page.id.page_no() + const flst_node_t *c= addr.page == add->page.id().page_no() ? add->frame + addr.boffset - : fut_get_ptr(add->page.id.space(), add->zip_size(), addr, + : fut_get_ptr(add->page.id().space(), add->zip_size(), addr, RW_SX_LATCH, mtr, &cur); flst_insert_before(base, boffset, cur, static_cast(c - cur->frame), @@ -316,12 +304,10 @@ void flst_remove(buf_block_t *base, uint16_t boffset, { ut_ad(boffset < base->physical_size()); ut_ad(coffset < cur->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(cur, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); const fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); const fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); @@ -332,9 +318,9 @@ void flst_remove(buf_block_t *base, uint16_t boffset, else { buf_block_t *block= cur; - flst_node_t *prev= prev_addr.page == cur->page.id.page_no() + flst_node_t *prev= prev_addr.page == cur->page.id().page_no() ? cur->frame + prev_addr.boffset - : fut_get_ptr(cur->page.id.space(), cur->zip_size(), prev_addr, + : fut_get_ptr(cur->page.id().space(), cur->zip_size(), prev_addr, RW_SX_LATCH, mtr, &block); flst_write_addr(*block, prev + FLST_NEXT, next_addr.page, next_addr.boffset, mtr); @@ -346,9 +332,9 @@ void flst_remove(buf_block_t *base, uint16_t boffset, else { buf_block_t *block= cur; - flst_node_t *next= next_addr.page == cur->page.id.page_no() + flst_node_t *next= next_addr.page == cur->page.id().page_no() ? cur->frame + next_addr.boffset - : fut_get_ptr(cur->page.id.space(), cur->zip_size(), next_addr, + : fut_get_ptr(cur->page.id().space(), cur->zip_size(), next_addr, RW_SX_LATCH, mtr, &block); flst_write_addr(*block, next + FLST_PREV, prev_addr.page, prev_addr.boffset, mtr); @@ -364,9 +350,8 @@ void flst_remove(buf_block_t *base, uint16_t boffset, void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) { ut_ad(boffset < base->physical_size()); - ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, - MTR_MEMO_PAGE_X_FIX | - MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); /* We use two mini-transaction handles: the first is used to lock the base node, and prevent other threads from modifying the list. @@ -381,7 +366,7 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) for (uint32_t i= len; i--; ) { mtr2.start(); - const flst_node_t *node= fut_get_ptr(base->page.id.space(), + const flst_node_t *node= fut_get_ptr(base->page.id().space(), base->zip_size(), addr, RW_SX_LATCH, &mtr2); addr= flst_get_next_addr(node); @@ -395,7 +380,7 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) for (uint32_t i= len; i--; ) { mtr2.start(); - const flst_node_t *node= fut_get_ptr(base->page.id.space(), + const flst_node_t *node= fut_get_ptr(base->page.id().space(), base->zip_size(), addr, RW_SX_LATCH, &mtr2); addr= flst_get_prev_addr(node); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index abb7c20c1db..778202a11c6 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -577,9 +577,9 @@ rtr_adjust_upper_level( level = btr_page_get_level(buf_block_get_frame(block)); ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block))); - page_no = block->page.id.page_no(); + page_no = block->page.id().page_no(); - new_page_no = new_block->page.id.page_no(); + new_page_no = new_block->page.id().page_no(); /* Set new mbr for the old page on the upper level. */ /* Look up the index for the node pointer to page */ @@ -653,7 +653,7 @@ rtr_adjust_upper_level( lock_prdt_update_parent(block, new_block, &prdt, &new_prdt, index->table->space_id, - page_cursor->block->page.id.page_no()); + page_cursor->block->page.id().page_no()); mem_heap_free(heap); @@ -668,7 +668,7 @@ rtr_adjust_upper_level( ut_a(page_is_comp(next_block->frame) == page_is_comp(block->frame)); ut_a(btr_page_get_prev(next_block->frame) - == block->page.id.page_no()); + == block->page.id().page_no()); #endif /* UNIV_BTR_DEBUG */ btr_page_set_prev(next_block, new_page_no, mtr); @@ -915,8 +915,8 @@ func_start: mem_heap_empty(*heap); *offsets = NULL; - ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(cursor->index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); ut_ad(!dict_index_is_online_ddl(cursor->index) || (flags & BTR_CREATE_FLAG) || dict_index_is_clust(cursor->index)); @@ -928,10 +928,10 @@ func_start: page_zip = buf_block_get_page_zip(block); current_ssn = page_get_ssn_id(page); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_get_n_recs(page) >= 1); - page_no = block->page.id.page_no(); + page_no = block->page.id().page_no(); if (!page_has_prev(page) && !page_is_leaf(page)) { first_rec = page_rec_get_next( @@ -1395,9 +1395,9 @@ rtr_page_copy_rec_list_end_no_locks( ins_rec = page_cur_insert_rec_low(&page_cur, index, cur1_rec, offsets1, mtr); if (UNIV_UNLIKELY(!ins_rec)) { - fprintf(stderr, "page number %ld and %ld\n", - (long)new_block->page.id.page_no(), - (long)block->page.id.page_no()); + fprintf(stderr, "page number %u and %u\n", + new_block->page.id().page_no(), + block->page.id().page_no()); ib::fatal() << "rec offset " << page_offset(rec) << ", cur1 offset " @@ -1515,7 +1515,7 @@ rtr_page_copy_rec_list_start_no_locks( ins_rec = page_cur_insert_rec_low(&page_cur, index, cur1_rec, offsets1, mtr); if (UNIV_UNLIKELY(!ins_rec)) { - ib::fatal() << new_block->page.id + ib::fatal() << new_block->page.id() << "rec offset " << page_offset(rec) << ", cur1 offset " << page_offset(page_cur_get_rec(&cur1)) @@ -1653,7 +1653,7 @@ rtr_check_same_block( mem_heap_t* heap) /*!< in: memory heap */ { - ulint page_no = childb->page.id.page_no(); + ulint page_no = childb->page.id().page_no(); rec_offs* offsets; rec_t* rec = page_rec_get_next(page_get_infimum_rec( buf_block_get_frame(parentb))); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 4128be7f27d..853db180277 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -139,10 +139,10 @@ rtr_pcur_getnext_from_path( || latch_mode & BTR_MODIFY_LEAF); mtr_s_lock_index(index, mtr); } else { - ut_ad(mtr_memo_contains_flagged(mtr, &index->lock, - MTR_MEMO_SX_LOCK - | MTR_MEMO_S_LOCK - | MTR_MEMO_X_LOCK)); + ut_ad(mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_SX_LOCK + | MTR_MEMO_S_LOCK + | MTR_MEMO_X_LOCK)); } const ulint zip_size = index->table->space->zip_size(); @@ -599,15 +599,14 @@ rtr_pcur_open_low( n_fields = dtuple_get_n_fields(tuple); if (latch_mode & BTR_ALREADY_S_LATCHED) { - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_S_LOCK)); + ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_S_LOCK)); tree_latched = true; } if (latch_mode & BTR_MODIFY_TREE) { - ut_ad(mtr_memo_contains_flagged(mtr, &index->lock, - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); tree_latched = true; } @@ -674,7 +673,7 @@ rtr_page_get_father( ulint page_no = btr_node_ptr_get_child_page_no(cursor->page_cur.rec, offsets); - ut_ad(page_no == block->page.id.page_no()); + ut_ad(page_no == block->page.id().page_no()); #else rtr_page_get_father_block( NULL, heap, index, block, mtr, sea_cur, cursor); @@ -707,11 +706,8 @@ static void rtr_get_father_node( /* Try to optimally locate the parent node. Level should always less than sea_cur->tree_height unless the root is splitting */ if (sea_cur && sea_cur->tree_height > level) { - - ut_ad(mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); ret = rtr_cur_restore_position( BTR_CONT_MODIFY_TREE, sea_cur, level, mtr); @@ -820,12 +816,12 @@ rtr_page_get_father_node_ptr( dict_index_t* index; rtr_mbr_t mbr; - page_no = btr_cur_get_block(cursor)->page.id.page_no(); + page_no = btr_cur_get_block(cursor)->page.id().page_no(); index = btr_cur_get_index(cursor); ut_ad(srv_read_only_mode - || mtr_memo_contains_flagged(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); + || mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); ut_ad(dict_index_get_page(index) != page_no); @@ -1198,7 +1194,7 @@ rtr_check_discard_page( the root page */ buf_block_t* block) /*!< in: block of page to be discarded */ { - const ulint pageno = block->page.id.page_no(); + const ulint pageno = block->page.id().page_no(); mutex_enter(&index->rtr_track->rtr_active_mutex); @@ -1219,7 +1215,7 @@ rtr_check_discard_page( if (rtr_info->matches) { mutex_enter(&rtr_info->matches->rtr_match_mutex); - if ((&rtr_info->matches->block)->page.id.page_no() + if ((&rtr_info->matches->block)->page.id().page_no() == pageno) { if (!rtr_info->matches->matched_recs->empty()) { rtr_info->matches->matched_recs->clear(); @@ -1235,8 +1231,8 @@ rtr_check_discard_page( mutex_exit(&index->rtr_track->rtr_active_mutex); lock_mutex_enter(); - lock_prdt_page_free_from_discard(block, lock_sys.prdt_hash); - lock_prdt_page_free_from_discard(block, lock_sys.prdt_page_hash); + lock_prdt_page_free_from_discard(block, &lock_sys.prdt_hash); + lock_prdt_page_free_from_discard(block, &lock_sys.prdt_page_hash); lock_mutex_exit(); } @@ -1494,7 +1490,7 @@ rtr_non_leaf_insert_stack_push( { node_seq_t new_seq; btr_pcur_t* my_cursor; - ulint page_no = block->page.id.page_no(); + ulint page_no = block->page.id().page_no(); my_cursor = static_cast( ut_malloc_nokey(sizeof(*my_cursor))); @@ -1510,7 +1506,7 @@ rtr_non_leaf_insert_stack_push( my_cursor, mbr_inc); } -/** Copy a buf_block_t strcuture, except "block->lock" and "block->mutex". +/** Copy a buf_block_t, except "block->lock". @param[in,out] matches copy to match->block @param[in] block block to copy */ static @@ -1519,13 +1515,11 @@ rtr_copy_buf( matched_rec_t* matches, const buf_block_t* block) { - /* Copy all members of "block" to "matches->block" except "mutex" - and "lock". We skip "mutex" and "lock" because they are not used + /* Copy all members of "block" to "matches->block" except "lock". + We skip "lock" because it is not used from the dummy buf_block_t we create here and because memcpy()ing - them generates (valid) compiler warnings that the vtable pointer - will be copied. It is also undefined what will happen with the - newly memcpy()ed mutex if the source mutex was acquired by - (another) thread while it was copied. */ + it generates (valid) compiler warnings that the vtable pointer + will be copied. */ new (&matches->block.page) buf_page_t(block->page); matches->block.frame = block->frame; matches->block.unzip_LRU = block->unzip_LRU; @@ -1533,7 +1527,6 @@ rtr_copy_buf( ut_d(matches->block.in_unzip_LRU_list = block->in_unzip_LRU_list); ut_d(matches->block.in_withdraw_list = block->in_withdraw_list); - /* Skip buf_block_t::mutex */ /* Skip buf_block_t::lock */ matches->block.lock_hash_val = block->lock_hash_val; matches->block.modify_clock = block->modify_clock; @@ -1697,7 +1690,7 @@ rtr_cur_search_with_match( const rec_t* best_rec; const rec_t* last_match_rec = NULL; bool match_init = false; - ulint space = block->page.id.space(); + ulint space = block->page.id().space(); page_cur_mode_t orig_mode = mode; const rec_t* first_rec = NULL; diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc deleted file mode 100644 index de271eabc31..00000000000 --- a/storage/innobase/ha/ha0ha.cc +++ /dev/null @@ -1,488 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/********************************************************************//** -@file ha/ha0ha.cc -The hash table with external chains - -Created 8/22/1994 Heikki Tuuri -*************************************************************************/ - -#include "ha0ha.h" - -#ifdef UNIV_DEBUG -# include "buf0buf.h" -#endif /* UNIV_DEBUG */ -#include "btr0sea.h" -#include "page0page.h" - -/*************************************************************//** -Creates a hash table with at least n array cells. The actual number -of cells is chosen to be a prime number slightly bigger than n. -@return own: created table */ -hash_table_t* -ib_create( -/*======*/ - ulint n, /*!< in: number of array cells */ - latch_id_t id, /*!< in: latch ID */ - ulint n_sync_obj, - /*!< in: number of mutexes to protect the - hash table: must be a power of 2, or 0 */ - ulint type) /*!< in: type of datastructure for which - MEM_HEAP_FOR_PAGE_HASH */ -{ - hash_table_t* table; - - ut_a(type == MEM_HEAP_FOR_BTR_SEARCH - || type == MEM_HEAP_FOR_PAGE_HASH); - - ut_ad(ut_is_2pow(n_sync_obj)); - table = hash_create(n); - - /* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail, - but in practise it never should in this case, hence the asserts. */ - - if (n_sync_obj == 0) { - table->heap = mem_heap_create_typed( - std::min( - 4096, - MEM_MAX_ALLOC_IN_BUF / 2 - - MEM_BLOCK_HEADER_SIZE - MEM_SPACE_NEEDED(0)), - type); - ut_a(table->heap); - - return(table); - } - - if (type == MEM_HEAP_FOR_PAGE_HASH) { - /* We create a hash table protected by rw_locks for - buf_pool.page_hash. */ - hash_create_sync_obj( - table, HASH_TABLE_SYNC_RW_LOCK, id, n_sync_obj); - } else { - hash_create_sync_obj( - table, HASH_TABLE_SYNC_MUTEX, id, n_sync_obj); - } - - table->heaps = static_cast( - ut_malloc_nokey(n_sync_obj * sizeof(void*))); - - for (ulint i = 0; i < n_sync_obj; i++) { - table->heaps[i] = mem_heap_create_typed( - std::min( - 4096, - MEM_MAX_ALLOC_IN_BUF / 2 - - MEM_BLOCK_HEADER_SIZE - MEM_SPACE_NEEDED(0)), - type); - ut_a(table->heaps[i]); - } - - return(table); -} - -/** Recreate a hash table with at least n array cells. The actual number -of cells is chosen to be a prime number slightly bigger than n. -The new cells are all cleared. The heaps are recreated. -The sync objects are reused. -@param[in,out] table hash table to be resuzed (to be freed later) -@param[in] n number of array cells -@return resized new table */ -hash_table_t* -ib_recreate( - hash_table_t* table, - ulint n) -{ - /* This function is for only page_hash for now */ - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - ut_ad(table->n_sync_obj > 0); - - hash_table_t* new_table = hash_create(n); - - new_table->type = table->type; - new_table->n_sync_obj = table->n_sync_obj; - new_table->sync_obj = table->sync_obj; - - for (ulint i = 0; i < table->n_sync_obj; i++) { - mem_heap_free(table->heaps[i]); - } - ut_free(table->heaps); - - new_table->heaps = static_cast( - ut_malloc_nokey(new_table->n_sync_obj * sizeof(void*))); - - for (ulint i = 0; i < new_table->n_sync_obj; i++) { - new_table->heaps[i] = mem_heap_create_typed( - std::min( - 4096, - MEM_MAX_ALLOC_IN_BUF / 2 - - MEM_BLOCK_HEADER_SIZE - MEM_SPACE_NEEDED(0)), - MEM_HEAP_FOR_PAGE_HASH); - ut_a(new_table->heaps[i]); - } - - return(new_table); -} - -/*************************************************************//** -Empties a hash table and frees the memory heaps. */ -void -ha_clear( -/*=====*/ - hash_table_t* table) /*!< in, own: hash table */ -{ - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); -#ifdef BTR_CUR_HASH_ADAPT - ut_ad(!table->adaptive || btr_search_own_all(RW_LOCK_X)); -#endif /* BTR_CUR_HASH_ADAPT */ - - for (ulint i = 0; i < table->n_sync_obj; i++) { - mem_heap_free(table->heaps[i]); - } - - ut_free(table->heaps); - - switch (table->type) { - case HASH_TABLE_SYNC_MUTEX: - for (ulint i = 0; i < table->n_sync_obj; ++i) { - mutex_destroy(&table->sync_obj.mutexes[i]); - } - ut_free(table->sync_obj.mutexes); - table->sync_obj.mutexes = NULL; - break; - - case HASH_TABLE_SYNC_RW_LOCK: - for (ulint i = 0; i < table->n_sync_obj; ++i) { - rw_lock_free(&table->sync_obj.rw_locks[i]); - } - - ut_free(table->sync_obj.rw_locks); - table->sync_obj.rw_locks = NULL; - break; - - case HASH_TABLE_SYNC_NONE: - /* do nothing */ - break; - } - - table->n_sync_obj = 0; - table->type = HASH_TABLE_SYNC_NONE; - - - /* Clear the hash table. */ - ulint n = hash_get_n_cells(table); - - for (ulint i = 0; i < n; i++) { - hash_get_nth_cell(table, i)->node = NULL; - } -} - -#ifdef BTR_CUR_HASH_ADAPT -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** Maximum number of records in a page */ -static const ulint MAX_N_POINTERS - = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES; -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - -/*************************************************************//** -Inserts an entry into a hash table. If an entry with the same fold number -is found, its node is updated to point to the new data, and no new node -is inserted. If btr_search_enabled is set to FALSE, we will only allow -updating existing nodes, but no new node is allowed to be added. -@return TRUE if succeed, FALSE if no more memory could be allocated */ -ibool -ha_insert_for_fold_func( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of data; if a node with - the same fold value already exists, it is - updated to point to the same data, and no new - node is created! */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* block, /*!< in: buffer block containing the data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* data) /*!< in: data, must not be NULL */ -{ - hash_cell_t* cell; - ha_node_t* node; - ha_node_t* prev_node; - ulint hash; - - ut_ad(data); - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - ut_a(block->frame == page_align(data)); -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - hash_assert_can_modify(table, fold); - ut_ad(btr_search_enabled); - - hash = hash_calc_hash(fold, table); - - cell = hash_get_nth_cell(table, hash); - - prev_node = static_cast(cell->node); - - while (prev_node != NULL) { - if (prev_node->fold == fold) { -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - if (table->adaptive) { - buf_block_t* prev_block = prev_node->block; - ut_a(prev_block->frame - == page_align(prev_node->data)); - ut_a(prev_block->n_pointers-- < MAX_N_POINTERS); - ut_a(block->n_pointers++ < MAX_N_POINTERS); - } - - prev_node->block = block; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - prev_node->data = data; - - return(TRUE); - } - - prev_node = prev_node->next; - } - - /* We have to allocate a new chain node */ - - node = static_cast( - mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t))); - - if (node == NULL) { - /* It was a btr search type memory heap and at the moment - no more memory could be allocated: return */ - - ut_ad(hash_get_heap(table, fold)->type & MEM_HEAP_BTR_SEARCH); - - return(FALSE); - } - - ha_node_set_data(node, block, data); - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - if (table->adaptive) { - ut_a(block->n_pointers++ < MAX_N_POINTERS); - } -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - - node->fold = fold; - - node->next = NULL; - - prev_node = static_cast(cell->node); - - if (prev_node == NULL) { - - cell->node = node; - - return(TRUE); - } - - while (prev_node->next != NULL) { - - prev_node = prev_node->next; - } - - prev_node->next = node; - - return(TRUE); -} - -#ifdef UNIV_DEBUG -/** Verify if latch corresponding to the hash table is x-latched -@param[in] table hash table */ -static -void -ha_btr_search_latch_x_locked(const hash_table_t* table) -{ - ulint i; - for (i = 0; i < btr_ahi_parts; ++i) { - if (btr_search_sys->hash_tables[i] == table) { - break; - } - } - - ut_ad(i < btr_ahi_parts); - ut_ad(rw_lock_own(btr_search_latches[i], RW_LOCK_X)); -} -#endif /* UNIV_DEBUG */ - -/***********************************************************//** -Deletes a hash node. */ -void -ha_delete_hash_node( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ha_node_t* del_node) /*!< in: node to be deleted */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_d(ha_btr_search_latch_x_locked(table)); - ut_ad(btr_search_enabled); -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - if (table->adaptive) { - ut_a(del_node->block->frame == page_align(del_node->data)); - ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS); - } -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - - HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node); -} - -/*********************************************************//** -Looks for an element when we know the pointer to the data, and updates -the pointer to data, if found. -@return TRUE if found */ -ibool -ha_search_and_update_if_found_func( -/*===============================*/ - hash_table_t* table, /*!< in/out: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data, /*!< in: pointer to the data */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* new_block,/*!< in: block containing new_data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* new_data)/*!< in: new pointer to the data */ -{ - ha_node_t* node; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - hash_assert_can_modify(table, fold); -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - ut_a(new_block->frame == page_align(new_data)); -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - - ut_d(ha_btr_search_latch_x_locked(table)); - - if (!btr_search_enabled) { - return(FALSE); - } - - node = ha_search_with_data(table, fold, data); - - if (node) { -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - if (table->adaptive) { - ut_a(node->block->n_pointers-- < MAX_N_POINTERS); - ut_a(new_block->n_pointers++ < MAX_N_POINTERS); - } - - node->block = new_block; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - node->data = new_data; - - return(TRUE); - } - - return(FALSE); -} - -/*****************************************************************//** -Removes from the chain determined by fold all nodes whose data pointer -points to the page given. */ -void -ha_remove_all_nodes_to_page( -/*========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: fold value */ - const page_t* page) /*!< in: buffer page */ -{ - ha_node_t* node; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - hash_assert_can_modify(table, fold); - ut_ad(btr_search_enabled); - - node = ha_chain_get_first(table, fold); - - while (node) { - if (page_align(ha_node_get_data(node)) == page) { - - /* Remove the hash node */ - - ha_delete_hash_node(table, node); - - /* Start again from the first node in the chain - because the deletion may compact the heap of - nodes and move other nodes! */ - - node = ha_chain_get_first(table, fold); - } else { - node = ha_chain_get_next(node); - } - } -#ifdef UNIV_DEBUG - /* Check that all nodes really got deleted */ - - node = ha_chain_get_first(table, fold); - - while (node) { - ut_a(page_align(ha_node_get_data(node)) != page); - - node = ha_chain_get_next(node); - } -#endif /* UNIV_DEBUG */ -} - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/*************************************************************//** -Validates a given range of the cells in hash table. -@return TRUE if ok */ -ibool -ha_validate( -/*========*/ - hash_table_t* table, /*!< in: hash table */ - ulint start_index, /*!< in: start index */ - ulint end_index) /*!< in: end index */ -{ - ibool ok = TRUE; - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_a(start_index <= end_index); - ut_a(start_index < hash_get_n_cells(table)); - ut_a(end_index < hash_get_n_cells(table)); - - for (i = start_index; i <= end_index; i++) { - ha_node_t* node; - hash_cell_t* cell; - - cell = hash_get_nth_cell(table, i); - - for (node = static_cast(cell->node); - node != 0; - node = node->next) { - - if (hash_calc_hash(node->fold, table) != i) { - ib::error() << "Hash table node fold value " - << node->fold << " does not match the" - " cell number " << i << "."; - - ok = FALSE; - } - } - } - - return(ok); -} -#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ -#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/ha/ha0storage.cc b/storage/innobase/ha/ha0storage.cc index 8857b81f2d2..acde71b0557 100644 --- a/storage/innobase/ha/ha0storage.cc +++ b/storage/innobase/ha/ha0storage.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -53,7 +54,7 @@ ha_storage_get( HASH_SEARCH( next, /* node->"next" */ - storage->hash, /* the hash table */ + &storage->hash, /* the hash table */ fold, /* key */ ha_storage_node_t*, /* type of node->next */ node, /* auxiliary variable */ @@ -127,7 +128,7 @@ ha_storage_put_memlim( HASH_INSERT( ha_storage_node_t, /* type used in the hash chain */ next, /* node->"next" */ - storage->hash, /* the hash table */ + &storage->hash, /* the hash table */ fold, /* key */ node); /* add this data to the hash */ diff --git a/storage/innobase/ha/hash0hash.cc b/storage/innobase/ha/hash0hash.cc deleted file mode 100644 index 51f3db09922..00000000000 --- a/storage/innobase/ha/hash0hash.cc +++ /dev/null @@ -1,200 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file ha/hash0hash.cc -The simple hash table utility - -Created 5/20/1997 Heikki Tuuri -*******************************************************/ - -#include "hash0hash.h" -#include "mem0mem.h" -#include "sync0sync.h" - -/************************************************************//** -Reserves all the locks of a hash table, in an ascending order. */ -void -hash_lock_x_all( -/*============*/ - hash_table_t* table) /*!< in: hash table */ -{ - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - - for (ulint i = 0; i < table->n_sync_obj; i++) { - - rw_lock_t* lock = table->sync_obj.rw_locks + i; - - ut_ad(!rw_lock_own(lock, RW_LOCK_S)); - ut_ad(!rw_lock_own(lock, RW_LOCK_X)); - - rw_lock_x_lock(lock); - } -} - -/************************************************************//** -Releases all the locks of a hash table, in an ascending order. */ -void -hash_unlock_x_all( -/*==============*/ - hash_table_t* table) /*!< in: hash table */ -{ - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - - for (ulint i = 0; i < table->n_sync_obj; i++) { - - rw_lock_t* lock = table->sync_obj.rw_locks + i; - - ut_ad(rw_lock_own(lock, RW_LOCK_X)); - - rw_lock_x_unlock(lock); - } -} - -/************************************************************//** -Releases all but passed in lock of a hash table, */ -void -hash_unlock_x_all_but( -/*==================*/ - hash_table_t* table, /*!< in: hash table */ - rw_lock_t* keep_lock) /*!< in: lock to keep */ -{ - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - - for (ulint i = 0; i < table->n_sync_obj; i++) { - - rw_lock_t* lock = table->sync_obj.rw_locks + i; - - ut_ad(rw_lock_own(lock, RW_LOCK_X)); - - if (keep_lock != lock) { - rw_lock_x_unlock(lock); - } - } -} - -/*************************************************************//** -Creates a hash table with >= n array cells. The actual number of cells is -chosen to be a prime number slightly bigger than n. -@return own: created table */ -hash_table_t* -hash_create( -/*========*/ - ulint n) /*!< in: number of array cells */ -{ - hash_cell_t* array; - ulint prime; - hash_table_t* table; - - prime = ut_find_prime(n); - - table = static_cast( - ut_malloc_nokey(sizeof(hash_table_t))); - - array = static_cast( - ut_malloc_nokey(sizeof(hash_cell_t) * prime)); - - /* The default type of hash_table is HASH_TABLE_SYNC_NONE i.e.: - the caller is responsible for access control to the table. */ - table->type = HASH_TABLE_SYNC_NONE; - table->array = array; - table->n_cells = prime; -#ifdef BTR_CUR_HASH_ADAPT -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - table->adaptive = FALSE; -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -#endif /* BTR_CUR_HASH_ADAPT */ - table->n_sync_obj = 0; - table->sync_obj.mutexes = NULL; - table->heaps = NULL; - table->heap = NULL; - ut_d(table->magic_n = HASH_TABLE_MAGIC_N); - - /* Initialize the cell array */ - hash_table_clear(table); - - return(table); -} - -/*************************************************************//** -Frees a hash table. */ -void -hash_table_free( -/*============*/ - hash_table_t* table) /*!< in, own: hash table */ -{ - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - ut_free(table->array); - ut_free(table); -} - -/*************************************************************//** -Creates a sync object array to protect a hash table. -::sync_obj can be mutexes or rw_locks depening on the type of -hash table. */ -void -hash_create_sync_obj( -/*=================*/ - hash_table_t* table, /*!< in: hash table */ - enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX - or HASH_TABLE_SYNC_RW_LOCK */ - latch_id_t id, /*!< in: latch ID */ - ulint n_sync_obj)/*!< in: number of sync objects, - must be a power of 2 */ -{ - ut_a(n_sync_obj > 0); - ut_a(ut_is_2pow(n_sync_obj)); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - table->type = type; - - switch (table->type) { - case HASH_TABLE_SYNC_MUTEX: - table->sync_obj.mutexes = static_cast( - ut_malloc_nokey(n_sync_obj * sizeof(ib_mutex_t))); - - for (ulint i = 0; i < n_sync_obj; i++) { - mutex_create(id, table->sync_obj.mutexes + i); - } - - break; - - case HASH_TABLE_SYNC_RW_LOCK: { - - latch_level_t level = sync_latch_get_level(id); - - ut_a(level != SYNC_UNKNOWN); - - table->sync_obj.rw_locks = static_cast( - ut_malloc_nokey(n_sync_obj * sizeof(rw_lock_t))); - - for (ulint i = 0; i < n_sync_obj; i++) { - rw_lock_create(hash_table_locks_key, - table->sync_obj.rw_locks + i, level); - } - - break; - } - - case HASH_TABLE_SYNC_NONE: - ut_error; - } - - table->n_sync_obj = n_sync_obj; -} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8448d9291ff..9344ec660b9 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -55,6 +55,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include "field.h" +#include "scope.h" #include "srv0srv.h" // MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system; @@ -519,11 +520,7 @@ performance schema instrumented if "UNIV_PFS_MUTEX" is defined */ static PSI_mutex_info all_innodb_mutexes[] = { PSI_KEY(autoinc_mutex), -# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK - PSI_KEY(buffer_block_mutex), -# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ PSI_KEY(buf_pool_mutex), - PSI_KEY(buf_pool_zip_mutex), PSI_KEY(cache_last_read_mutex), PSI_KEY(dict_foreign_err_mutex), PSI_KEY(dict_sys_mutex), @@ -535,7 +532,6 @@ static PSI_mutex_info all_innodb_mutexes[] = { PSI_KEY(fts_optimize_mutex), PSI_KEY(fts_doc_id_mutex), PSI_KEY(log_flush_order_mutex), - PSI_KEY(hash_table_mutex), PSI_KEY(ibuf_bitmap_mutex), PSI_KEY(ibuf_mutex), PSI_KEY(ibuf_pessimistic_insert_mutex), @@ -595,8 +591,7 @@ static PSI_rwlock_info all_innodb_rwlocks[] = { PSI_RWLOCK_KEY(trx_purge_latch), PSI_RWLOCK_KEY(index_tree_rw_lock), PSI_RWLOCK_KEY(index_online_log), - PSI_RWLOCK_KEY(dict_table_stats), - PSI_RWLOCK_KEY(hash_table_locks) + PSI_RWLOCK_KEY(dict_table_stats) }; # endif /* UNIV_PFS_RWLOCK */ @@ -2673,6 +2668,7 @@ ha_innobase::ha_innobase( | HA_CAN_FULLTEXT_HINTS */ | HA_CAN_EXPORT + | HA_ONLINE_ANALYZE | HA_CAN_RTREEKEYS | HA_CAN_TABLES_WITHOUT_ROLLBACK | HA_CAN_ONLINE_BACKUPS @@ -3192,7 +3188,7 @@ ha_innobase::reset_template(void) /* Force table to be freed in close_thread_table(). */ DBUG_EXECUTE_IF("free_table_in_fts_query", if (m_prebuilt->in_fts_query) { - table->m_needs_reopen = true; + table->mark_table_for_reopen(); } ); @@ -3507,7 +3503,7 @@ static int innodb_init_params() pages, even for larger pages */ if (srv_page_size > UNIV_PAGE_SIZE_DEF && innobase_buffer_pool_size < (24 * 1024 * 1024)) { - ib::info() << "innodb_page_size=" + ib::error() << "innodb_page_size=" << srv_page_size << " requires " << "innodb_buffer_pool_size > 24M current " << innobase_buffer_pool_size; @@ -4819,9 +4815,8 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) { DBUG_ENTER("innobase_kill_query"); - if (trx_t *trx= thd_to_trx(thd)) + if (trx_t* trx= thd_to_trx(thd)) { - ut_ad(trx->mysql_thd == thd); #ifdef WITH_WSREP if (trx->is_wsrep() && wsrep_thd_is_aborting(thd)) /* if victim has been signaled by BF thread and/or aborting is already @@ -4829,8 +4824,29 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) Also, BF thread should own trx mutex for the victim. */ DBUG_VOID_RETURN; #endif /* WITH_WSREP */ - /* Cancel a pending lock request if there are any */ - lock_trx_handle_wait(trx); + lock_mutex_enter(); + trx_sys.trx_list.freeze(); + trx_mutex_enter(trx); + /* It is possible that innobase_close_connection() is concurrently + being executed on our victim. Even if the trx object is later + reused for another client connection or a background transaction, + its trx->mysql_thd will differ from our thd. + + trx_sys.trx_list is thread-safe. It's freezed to 'protect' + trx_t. However, trx_t::commit_in_memory() changes a trx_t::state + of autocommit non-locking transactions without any protection. + + At this point, trx may have been reallocated for another client + connection, or for a background operation. In that case, either + trx_t::state or trx_t::mysql_thd should not match our expectations. */ + bool cancel= trx->mysql_thd == thd && trx->state == TRX_STATE_ACTIVE && + !trx->lock.was_chosen_as_deadlock_victim; + trx_sys.trx_list.unfreeze(); + if (!cancel); + else if (lock_t *lock= trx->lock.wait_lock) + lock_cancel_waiting_and_release(lock); + lock_mutex_exit(); + trx_mutex_exit(trx); } DBUG_VOID_RETURN; @@ -7017,7 +7033,9 @@ build_template_field( ut_ad(clust_index->table == index->table); templ = prebuilt->mysql_template + prebuilt->n_template++; - UNIV_MEM_INVALID(templ, sizeof *templ); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(templ, sizeof *templ); +#endif /* HAVE_valgrind_or_MSAN */ templ->is_virtual = !field->stored_in_db(); if (!templ->is_virtual) { @@ -8128,7 +8146,9 @@ calc_row_difference( /* The field has changed */ ufield = uvect->fields + n_changed; - UNIV_MEM_INVALID(ufield, sizeof *ufield); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(ufield, sizeof *ufield); +#endif /* HAVE_valgrind_or_MSAN */ /* Let us use a dummy dfield to make the conversion from the MySQL column format to the InnoDB format */ @@ -9497,7 +9517,7 @@ ha_innobase::ft_init_ext( const CHARSET_INFO* char_set = key->charset(); const char* query = key->ptr(); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { { ib::info out; out << "keynr=" << keynr << ", '"; @@ -10551,6 +10571,7 @@ create_table_info_t::create_table_def() } heap = mem_heap_create(1000); + auto _ = make_scope_exit([heap]() { mem_heap_free(heap); }); ut_d(bool have_vers_start = false); ut_d(bool have_vers_end = false); @@ -10587,7 +10608,6 @@ create_table_info_t::create_table_def() table->name.m_name, field->field_name.str); err_col: dict_mem_table_free(table); - mem_heap_free(heap); ut_ad(trx_state_eq(m_trx, TRX_STATE_NOT_STARTED)); DBUG_RETURN(HA_ERR_GENERIC); } @@ -10615,7 +10635,6 @@ err_col: " must be below 256." " Unsupported code " ULINTPF ".", charset_no); - mem_heap_free(heap); dict_mem_table_free(table); DBUG_RETURN(ER_CANT_CREATE_TABLE); @@ -10770,8 +10789,6 @@ err_col: DBUG_SUICIDE();); } - mem_heap_free(heap); - DBUG_EXECUTE_IF("ib_create_err_tablespace_exist", err = DB_TABLESPACE_EXISTS;); @@ -12118,7 +12135,7 @@ public: *(ptr++) = ' '; } } else { - ut_ad((size_t)(ptr - buf) < MAX_TEXT - 4); + ut_ad((size_t)(ptr - buf) <= MAX_TEXT - 4); memcpy(ptr, "...", 3); ptr += 3; break; @@ -12143,7 +12160,8 @@ create_table_info_t::create_foreign_keys() static const unsigned MAX_COLS_PER_FK = 500; const char* column_names[MAX_COLS_PER_FK]; const char* ref_column_names[MAX_COLS_PER_FK]; - char create_name[MAX_TABLE_NAME_LEN + 1]; + char create_name[MAX_DATABASE_NAME_LEN + 1 + + MAX_TABLE_NAME_LEN + 1]; dict_index_t* index = NULL; fkerr_t index_error = FK_SUCCESS; dict_index_t* err_index = NULL; @@ -12183,14 +12201,18 @@ create_table_info_t::create_foreign_keys() } char* bufend = innobase_convert_name( - create_name, MAX_TABLE_NAME_LEN, n, strlen(n), m_thd); + create_name, sizeof create_name, n, strlen(n), m_thd); create_name[bufend - create_name] = '\0'; number = highest_id_so_far + 1; mem_heap_free(heap); operation = "Alter "; + } else if (strstr(name, "#P#") || strstr(name, "#p#")) { + /* Partitioned table */ + create_name[0] = '\0'; } else { char* bufend = innobase_convert_name(create_name, - MAX_TABLE_NAME_LEN, name, + sizeof create_name, + name, strlen(name), m_thd); create_name[bufend - create_name] = '\0'; } @@ -12224,6 +12246,9 @@ create_table_info_t::create_foreign_keys() m_form->s->table_name.str); return (DB_CANNOT_ADD_CONSTRAINT); + } else if (!*create_name) { + ut_ad("should be unreachable" == 0); + return DB_CANNOT_ADD_CONSTRAINT; } Foreign_key* fk = static_cast(key); @@ -13322,6 +13347,19 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(0); } +/** + @return 1 if frm file exists + @return 0 if it doesn't exists +*/ + +static bool frm_file_exists(const char *path) +{ + char buff[FN_REFLEN]; + strxnmov(buff, FN_REFLEN, path, reg_ext, NullS); + return !access(buff, F_OK); +} + + /** Drops a table from an InnoDB database. Before calling this function, MySQL calls innobase_commit to commit the transaction of the current user. @@ -13422,7 +13460,9 @@ inline int ha_innobase::delete_table(const char* name, enum_sql_command sqlcom) } } - if (err == DB_TABLE_NOT_FOUND) { + if (err == DB_TABLE_NOT_FOUND && + frm_file_exists(name)) + { /* Test to drop all tables which matches db/tablename + '#'. Only partitions can have '#' as non-first character in the table name! @@ -17634,7 +17674,7 @@ innodb_adaptive_hash_index_update(THD*, st_mysql_sys_var*, void*, if (*(my_bool*) save) { btr_search_enable(); } else { - btr_search_disable(true); + btr_search_disable(); } mysql_mutex_lock(&LOCK_global_system_variables); } @@ -17733,7 +17773,7 @@ func_exit: space->zip_size(), RW_X_LATCH, &mtr); if (block != NULL) { - ib::info() << "Dirtying page: " << block->page.id; + ib::info() << "Dirtying page: " << block->page.id(); mtr.write<1,mtr_t::FORCED>(*block, block->frame + FIL_PAGE_SPACE_ID, block->frame[FIL_PAGE_SPACE_ID]); @@ -18205,7 +18245,7 @@ static bool innodb_buffer_pool_evict_uncompressed() for (buf_block_t* block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); block != NULL; ) { buf_block_t* prev_block = UT_LIST_GET_PREV(unzip_LRU, block); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(block->in_unzip_LRU_list); ut_ad(block->page.in_LRU_list); @@ -18907,86 +18947,129 @@ wsrep_abort_slave_trx( (long long)bf_seqno, (long long)victim_seqno); abort(); } + /*******************************************************************//** This function is used to kill one transaction in BF. */ + +/** This function is used to kill one transaction. + +This transaction was open on this node (not-yet-committed), and a +conflicting writeset from some other node that was being applied +caused a locking conflict. First committed (from other node) +wins, thus open transaction is rolled back. BF stands for +brute-force: any transaction can get aborted by galera any time +it is necessary. + +This conflict can happen only when the replicated writeset (from +other node) is being applied, not when it’s waiting in the queue. +If our local transaction reached its COMMIT and this conflicting +writeset was in the queue, then it should fail the local +certification test instead. + +A brute force abort is only triggered by a locking conflict +between a writeset being applied by an applier thread (slave thread) +and an open transaction on the node, not by a Galera writeset +comparison as in the local certification failure. + +@param[in] bf_thd Brute force (BF) thread +@param[in,out] victim_trx Vimtim trx to be killed +@param[in] signal Should victim be signaled */ +UNIV_INTERN int -wsrep_innobase_kill_one_trx(THD *bf_thd_ptr, const trx_t *bf_trx, - trx_t *victim_trx, bool signal) +wsrep_innobase_kill_one_trx(THD* bf_thd, trx_t *victim_trx, + bool signal) { - ut_ad(lock_mutex_own()); - ut_ad(trx_mutex_own(victim_trx)); - ut_ad(bf_thd_ptr); - ut_ad(victim_trx); + ut_ad(bf_thd); + ut_ad(victim_trx); + ut_ad(lock_mutex_own()); + ut_ad(trx_mutex_own(victim_trx)); DBUG_ENTER("wsrep_innobase_kill_one_trx"); - THD *bf_thd = bf_thd_ptr ? (THD*) bf_thd_ptr : NULL; - THD *thd = (THD *) victim_trx->mysql_thd; - int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; - if (!thd) { - DBUG_PRINT("wsrep", ("no thd for conflicting lock")); - WSREP_WARN("no THD for trx: " TRX_ID_FMT, victim_trx->id); - DBUG_RETURN(1); - } + THD *thd= (THD *) victim_trx->mysql_thd; + ut_ad(thd); + /* Note that bf_trx might not exist here e.g. on MDL conflict + case (test: galera_concurrent_ctas). Similarly, BF thread + could be also acquiring MDL-lock causing victim to be + aborted. However, we have not yet called innobase_trx_init() + for BF transaction (test: galera_many_columns)*/ + trx_t* bf_trx= thd_to_trx(bf_thd); + DBUG_ASSERT(wsrep_on(bf_thd)); - if (!bf_thd) { - DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); - WSREP_WARN("no BF THD for trx: " TRX_ID_FMT, - bf_trx ? bf_trx->id : 0); - DBUG_RETURN(1); - } - WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); wsrep_thd_LOCK(thd); - WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF - "), victim: (%lu) trx: " TRX_ID_FMT, - signal, bf_seqno, - thd_get_thread_id(thd), - victim_trx->id); - WSREP_DEBUG("Aborting query: %s conf %s trx: %lld", - (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", - wsrep_thd_transaction_state_str(thd), - wsrep_thd_transaction_id(thd)); + WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); - /* - * we mark with was_chosen_as_deadlock_victim transaction, - * which is already marked as BF victim - * lock_sys is held until this vicitm has aborted - */ - victim_trx->lock.was_chosen_as_wsrep_victim = TRUE; + WSREP_DEBUG("Aborter %s trx_id: " TRX_ID_FMT " thread: %ld " + "seqno: %lld client_state: %s client_mode: %s transaction_mode: %s " + "query: %s", + wsrep_thd_is_BF(bf_thd, false) ? "BF" : "normal", + bf_trx ? bf_trx->id : TRX_ID_MAX, + thd_get_thread_id(bf_thd), + wsrep_thd_trx_seqno(bf_thd), + wsrep_thd_client_state_str(bf_thd), + wsrep_thd_client_mode_str(bf_thd), + wsrep_thd_transaction_state_str(bf_thd), + wsrep_thd_query(bf_thd)); + WSREP_DEBUG("Victim %s trx_id: " TRX_ID_FMT " thread: %ld " + "seqno: %lld client_state: %s client_mode: %s transaction_mode: %s " + "query: %s", + wsrep_thd_is_BF(thd, false) ? "BF" : "normal", + victim_trx->id, + thd_get_thread_id(thd), + wsrep_thd_trx_seqno(thd), + wsrep_thd_client_state_str(thd), + wsrep_thd_client_mode_str(thd), + wsrep_thd_transaction_state_str(thd), + wsrep_thd_query(thd)); + + /* Mark transaction as a victim for Galera abort */ + victim_trx->lock.was_chosen_as_wsrep_victim= true; + + /* Note that we need to release this as it will be acquired + below in wsrep-lib */ wsrep_thd_UNLOCK(thd); + if (wsrep_thd_bf_abort(bf_thd, thd, signal)) { - if (victim_trx->lock.wait_lock) { + lock_t* wait_lock = victim_trx->lock.wait_lock; + if (wait_lock) { + DBUG_ASSERT(victim_trx->is_wsrep()); WSREP_DEBUG("victim has wait flag: %lu", thd_get_thread_id(thd)); - lock_t* wait_lock = victim_trx->lock.wait_lock; - if (wait_lock) { - WSREP_DEBUG("canceling wait lock"); - victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; - lock_cancel_waiting_and_release(wait_lock); - } + WSREP_DEBUG("canceling wait lock"); + victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; + lock_cancel_waiting_and_release(wait_lock); } } DBUG_RETURN(0); } +/** This function forces the victim transaction to abort. Aborting the + transaction does NOT end it, it still has to be rolled back. + + @param bf_thd brute force THD asking for the abort + @param victim_thd victim THD to be aborted + + @return 0 victim was aborted + @return -1 victim thread was aborted (no transaction) +*/ static int wsrep_abort_transaction( -/*====================*/ handlerton*, THD *bf_thd, THD *victim_thd, my_bool signal) { DBUG_ENTER("wsrep_innobase_abort_thd"); + ut_ad(bf_thd); + ut_ad(victim_thd); trx_t* victim_trx = thd_to_trx(victim_thd); - trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s", wsrep_thd_query(bf_thd), @@ -18996,7 +19079,7 @@ wsrep_abort_transaction( if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx, + int rcode= wsrep_innobase_kill_one_trx(bf_thd, victim_trx, signal); trx_mutex_exit(victim_trx); lock_mutex_exit(); @@ -19169,7 +19252,7 @@ static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size, static MYSQL_SYSVAR_UINT(purge_threads, srv_n_purge_threads, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "Number of tasks for purging transaction history", - NULL, NULL, 4, 1, 32, 0); + NULL, NULL, 4, 1, innodb_purge_threads_MAX, 0); static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, @@ -19418,11 +19501,6 @@ static MYSQL_SYSVAR_ULONG(buffer_pool_chunk_size, srv_buf_pool_chunk_unit, 128 * 1024 * 1024, 1024 * 1024, LONG_MAX, 1024 * 1024); #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG -static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks, - PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, - "Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2", - NULL, NULL, 16, 1, MAX_PAGE_HASH_LOCKS, 0); - static MYSQL_SYSVAR_ULONG(doublewrite_batch_size, srv_doublewrite_batch_size, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "Number of pages reserved in doublewrite buffer for batch flushing", @@ -20098,7 +20176,7 @@ static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads, "Number of threads performing background key rotation ", NULL, innodb_encryption_threads_update, - srv_n_fil_crypt_threads, 0, UINT_MAX32, 0); + 0, 0, 255, 0); static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, srv_fil_crypt_rotate_key_age, @@ -20311,7 +20389,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(merge_threshold_set_all_debug), #endif /* UNIV_DEBUG */ #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG - MYSQL_SYSVAR(page_hash_locks), MYSQL_SYSVAR(doublewrite_batch_size), #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ MYSQL_SYSVAR(status_output), diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 61bc6eec47e..f878a483019 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1018,15 +1018,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx @return whether the table will be rebuilt */ bool need_rebuild () const { return(old_table != new_table); } - /** Clear uncommmitted added indexes after a failed operation. */ - void clear_added_indexes() - { - for (ulint i = 0; i < num_to_add_index; i++) { - if (!add_index[i]->is_committed()) { - add_index[i]->detach_columns(); - } - } - } + /** Clear uncommmitted added indexes after a failed operation. */ + void clear_added_indexes() + { + for (ulint i= 0; i < num_to_add_index; i++) + add_index[i]->detach_columns(true); + } /** Convert table-rebuilding ALTER to instant ALTER. */ void prepare_instant() @@ -5908,7 +5905,7 @@ empty_table: /* The table is empty. */ ut_ad(fil_page_index_page_check(block->frame)); ut_ad(!page_has_siblings(block->frame)); - ut_ad(block->page.id.page_no() == index->page); + ut_ad(block->page.id().page_no() == index->page); /* MDEV-17383: free metadata BLOBs! */ btr_page_empty(block, NULL, index, 0, &mtr); if (index->is_instant()) { @@ -6189,6 +6186,7 @@ prepare_inplace_alter_table_dict( create_table_info_t info(ctx->prebuilt->trx->mysql_thd, altered_table, ha_alter_info->create_info, NULL, NULL, srv_file_per_table); + ut_d(bool stats_wait = false); /* The primary index would be rebuilt if a FTS Doc ID column is to be added, and the primary index definition @@ -6240,6 +6238,7 @@ prepare_inplace_alter_table_dict( XXX what may happen if bg stats opens the table after we have unlocked data dictionary below? */ dict_stats_wait_bg_to_stop_using_table(user_table, ctx->trx); + ut_d(stats_wait = true); online_retry_drop_indexes_low(ctx->new_table, ctx->trx); @@ -7122,7 +7121,8 @@ error_handled: /* n_ref_count must be 1, because purge cannot be executing on this very table as we are holding dict_sys.latch X-latch. */ - DBUG_ASSERT(user_table->get_ref_count() == 1 || ctx->online); + ut_ad(!stats_wait || ctx->online + || user_table->get_ref_count() == 1); online_retry_drop_indexes_with_trx(user_table, ctx->trx); } else { @@ -10383,6 +10383,7 @@ commit_cache_norebuild( dict_index_remove_from_cache(index->table, index); } + fts_clear_all(ctx->old_table, trx); trx_commit_for_mysql(trx); } @@ -11117,21 +11118,14 @@ foreign_fail: || (ctx0->is_instant() && m_prebuilt->table->n_v_cols && ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) { + /* FIXME: this workaround does not seem to work with + partitioned tables */ DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1); trx_commit_for_mysql(m_prebuilt->trx); -#ifdef BTR_CUR_HASH_ADAPT - if (btr_search_enabled) { - btr_search_disable(false); - btr_search_enable(); - } -#endif /* BTR_CUR_HASH_ADAPT */ - char tb_name[FN_REFLEN]; + char tb_name[NAME_LEN * 2 + 1 + 1]; strcpy(tb_name, m_prebuilt->table->name.m_name); - - tb_name[strlen(m_prebuilt->table->name.m_name)] = 0; - dict_table_close(m_prebuilt->table, true, false); if (ctx0->is_instant()) { for (unsigned i = ctx0->old_n_v_cols; i--; ) { @@ -11257,7 +11251,7 @@ foreign_fail: trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); dberr_t error = row_merge_drop_table(trx, ctx->old_table); - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Inplace alter table " << ctx->old_table->name << " dropping copy of the old table failed error " << error diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index da0ca1e85d9..0f1fe0bf814 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -114,10 +114,9 @@ currently cached in the buffer pool. It will be used to populate table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */ struct buf_page_info_t{ ulint block_id; /*!< Buffer Pool block ID */ - unsigned space_id:32; /*!< Tablespace ID */ - unsigned page_num:32; /*!< Page number/offset */ + /** page identifier */ + page_id_t id; unsigned access_time:32; /*!< Time of first access */ - unsigned flush_type:2; /*!< Flush type */ unsigned io_fix:2; /*!< type of pending I/O operation */ uint32_t fix_count; /*!< Count of how manyfold this block is bufferfixed */ @@ -131,7 +130,7 @@ struct buf_page_info_t{ buf_pool.freed_page_clock */ unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS; /*!< Compressed page size */ - unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */ + unsigned page_state:3; /*!< Page state */ unsigned page_type:I_S_PAGE_TYPE_BITS; /*!< Page type */ unsigned num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2; /*!< Number of records on Page */ @@ -2966,7 +2965,7 @@ i_s_fts_index_table_fill_selected( for (;;) { error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; @@ -2980,7 +2979,7 @@ i_s_fts_index_table_fill_selected( trx->error_state = DB_SUCCESS; } else { ib::error() << "Error occurred while reading" - " FTS index: " << ut_strerr(error); + " FTS index: " << error; break; } } @@ -3840,17 +3839,16 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats = STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; -/** These must correspond to the last values of buf_page_state */ +/** These must correspond to the first values of buf_page_state */ static const LEX_CSTRING page_state_values[] = { - { STRING_WITH_LEN("NOT_USED") }, - { STRING_WITH_LEN("READY_FOR_USE") }, - { STRING_WITH_LEN("FILE_PAGE") }, - { STRING_WITH_LEN("MEMORY") }, - { STRING_WITH_LEN("REMOVE_HASH") } + { STRING_WITH_LEN("NOT_USED") }, + { STRING_WITH_LEN("MEMORY") }, + { STRING_WITH_LEN("REMOVE_HASH") }, + { STRING_WITH_LEN("FILE_PAGE") }, }; -static const TypelibBuffer<5> page_state_values_typelib(page_state_values); +static const TypelibBuffer<4> page_state_values_typelib(page_state_values); static const LEX_CSTRING io_values[] = { @@ -3973,17 +3971,16 @@ i_s_innodb_buffer_page_fill( page_info->block_id, true)); OK(fields[IDX_BUFFER_PAGE_SPACE]->store( - page_info->space_id, true)); + page_info->id.space(), true)); OK(fields[IDX_BUFFER_PAGE_NUM]->store( - page_info->page_num, true)); + page_info->id.page_no(), true)); OK(field_store_string( fields[IDX_BUFFER_PAGE_TYPE], i_s_page_type[page_info->page_type].type_str)); - OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( - page_info->flush_type, true)); + OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(0, true)); OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( page_info->fix_count, true)); @@ -4058,15 +4055,10 @@ i_s_innodb_buffer_page_fill( page_info->zip_ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize : 0, true)); - compile_time_assert(BUF_PAGE_STATE_BITS == 3); - /* First three states are for compression pages and - are not states we would get as we scan pages through - buffer blocks */ OK(fields[IDX_BUFFER_PAGE_STATE]->store( - page_info->page_state >= BUF_BLOCK_NOT_USED - ? page_info->page_state - (BUF_BLOCK_NOT_USED - 1) - : 0, true)); + 1 + std::min(page_info->page_state, + BUF_BLOCK_FILE_PAGE), true)); OK(fields[IDX_BUFFER_PAGE_IO_FIX]->store( 1 + page_info->io_fix, true)); @@ -4135,14 +4127,6 @@ i_s_innodb_set_page_type( page_info->page_type = page_type & 0xf; } - - if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB - || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) { - page_info->page_num = mach_read_from_4( - frame + FIL_PAGE_OFFSET); - page_info->space_id = mach_read_from_4( - frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - } } /*******************************************************************//** Scans pages in the buffer cache, and collect their general information @@ -4161,35 +4145,40 @@ i_s_innodb_buffer_page_get_info( { page_info->block_id = pos; - page_info->page_state = buf_page_get_state(bpage) & 7; + compile_time_assert(BUF_BLOCK_NOT_USED == 0); + compile_time_assert(BUF_BLOCK_MEMORY == 1); + compile_time_assert(BUF_BLOCK_REMOVE_HASH == 2); + compile_time_assert(BUF_BLOCK_FILE_PAGE == 3); + compile_time_assert(BUF_BLOCK_ZIP_PAGE == 4); - /* Only fetch information for buffers that map to a tablespace, - that is, buffer page with state BUF_BLOCK_ZIP_PAGE, - BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */ - if (buf_page_in_file(bpage)) { + auto state = bpage->state(); + page_info->page_state= int{state} & 7; + + switch (state) { + default: + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + break; + case BUF_BLOCK_FILE_PAGE: + case BUF_BLOCK_ZIP_PAGE: const byte* frame; - page_info->space_id = bpage->id.space(); + page_info->id = bpage->id(); - page_info->page_num = bpage->id.page_no(); + page_info->fix_count = bpage->buf_fix_count(); - page_info->flush_type = bpage->flush_type; - - page_info->fix_count = bpage->buf_fix_count; - - page_info->oldest_mod = bpage->oldest_modification; + page_info->oldest_mod = bpage->oldest_modification(); page_info->access_time = bpage->access_time; page_info->zip_ssize = bpage->zip.ssize; - page_info->io_fix = bpage->io_fix & 3; + page_info->io_fix = bpage->io_fix() & 3; page_info->is_old = bpage->old; page_info->freed_page_clock = bpage->freed_page_clock; - switch (buf_page_get_io_fix(bpage)) { + switch (bpage->io_fix()) { case BUF_IO_NONE: case BUF_IO_WRITE: case BUF_IO_PIN: @@ -4200,7 +4189,7 @@ i_s_innodb_buffer_page_get_info( return; } - if (page_info->page_state == BUF_BLOCK_FILE_PAGE) { + if (state == BUF_BLOCK_FILE_PAGE) { const buf_block_t*block; block = reinterpret_cast(bpage); @@ -4219,8 +4208,6 @@ i_s_innodb_buffer_page_get_info( page_info->newest_mod = mach_read_from_8(FIL_PAGE_LSN + frame); i_s_innodb_set_page_type(page_info, frame); - } else { - page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; } } @@ -4404,7 +4391,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = Column("PAGE_TYPE", Varchar(64), NULLABLE), #define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5 - Column("FLUSH_TYPE", ULonglong(), NOT_NULL), + Column("FLUSH_TYPE", ULong(), NOT_NULL), #define IDX_BUF_LRU_PAGE_FIX_COUNT 6 Column("FIX_COUNT", ULong(), NOT_NULL), @@ -4488,17 +4475,16 @@ i_s_innodb_buf_page_lru_fill( page_info->block_id, true)); OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store( - page_info->space_id, true)); + page_info->id.space(), true)); OK(fields[IDX_BUF_LRU_PAGE_NUM]->store( - page_info->page_num, true)); + page_info->id.page_no(), true)); OK(field_store_string( fields[IDX_BUF_LRU_PAGE_TYPE], i_s_page_type[page_info->page_type].type_str)); - OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( - page_info->flush_type, true)); + OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(0, true)); OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( page_info->fix_count, true)); @@ -4574,8 +4560,7 @@ i_s_innodb_buf_page_lru_fill( ? 512 << page_info->zip_ssize : 0, true)); OK(fields[IDX_BUF_LRU_PAGE_STATE]->store( - page_info->page_state == BUF_BLOCK_ZIP_PAGE - || page_info->page_state == BUF_BLOCK_ZIP_DIRTY, + page_info->page_state == BUF_BLOCK_ZIP_PAGE, true)); OK(fields[IDX_BUF_LRU_PAGE_IO_FIX]->store( @@ -4622,15 +4607,13 @@ static int i_s_innodb_fill_buffer_lru(THD *thd, TABLE_LIST *tables, Item *) /* Print error message if malloc fail */ info_buffer = (buf_page_info_t*) my_malloc(PSI_INSTRUMENT_ME, - lru_len * sizeof *info_buffer, MYF(MY_WME)); + lru_len * sizeof *info_buffer, MYF(MY_WME | MY_ZEROFILL)); if (!info_buffer) { status = 1; goto exit; } - memset(info_buffer, 0, lru_len * sizeof *info_buffer); - /* Walk through Pool's LRU list and print the buffer page information */ bpage = UT_LIST_GET_LAST(buf_pool.LRU); @@ -6588,9 +6571,7 @@ i_s_dict_fill_sys_tablespaces( break; default: - ib::error() - << "File '" << filepath << "' " - << ut_strerr(err); + ib::error() << "File '" << filepath << "' " << err; break; } @@ -7055,7 +7036,7 @@ i_s_tablespaces_encryption_fill_table( RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); /* deny access to user without PROCESS_ACL privilege */ - if (check_global_access(thd, SUPER_ACL)) { + if (check_global_access(thd, PROCESS_ACL)) { DBUG_RETURN(0); } @@ -7201,20 +7182,12 @@ i_s_innodb_mutexes_fill_table( #ifdef JAN_TODO_FIXME ib_mutex_t* mutex; - ulint block_mutex_oswait_count = 0; - ib_mutex_t* block_mutex = NULL; for (mutex = UT_LIST_GET_FIRST(os_mutex_list); mutex != NULL; mutex = UT_LIST_GET_NEXT(list, mutex)) { if (mutex->count_os_wait == 0) { continue; } - if (buf_pool.is_block_mutex(mutex)) { - block_mutex = mutex; - block_mutex_oswait_count += mutex->count_os_wait; - continue; - } - OK(field_store_string(fields[MUTEXES_NAME], mutex->cmutex_name)); OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(mutex->cfile_name))); @@ -7225,20 +7198,6 @@ i_s_innodb_mutexes_fill_table( OK(schema_table_store_record(thd, tables->table)); } - if (block_mutex) { - char buf1[IO_SIZE]; - - snprintf(buf1, sizeof buf1, "combined %s", - innobase_basename(block_mutex->cfile_name)); - - OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name)); - OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1)); - OK(fields[MUTEXES_CREATE_LINE]->store(block_mutex->cline, true)); - fields[MUTEXES_CREATE_LINE]->set_notnull(); - OK(fields[MUTEXES_OS_WAITS]->store((longlong)block_mutex_oswait_count), true); - OK(schema_table_store_record(thd, tables->table)); - } - mutex_exit(&mutex_list_mutex); #endif /* JAN_TODO_FIXME */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index a9474295af8..9ae9eb6580c 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -576,7 +576,7 @@ ibuf_bitmap_page_get_bits_low( ut_ad(ut_is_2pow(zip_size)); ut_ad(bit < IBUF_BITS_PER_PAGE); compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); - ut_ad(mtr_memo_contains_page(mtr, page, latch_type)); + ut_ad(mtr->memo_contains_page_flagged(page, latch_type)); bit_offset = (page_id.page_no() & (size - 1)) * IBUF_BITS_PER_PAGE + bit; @@ -620,7 +620,7 @@ ibuf_bitmap_page_set_bits( static_assert(bit < IBUF_BITS_PER_PAGE, "wrong bit"); compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->is_named_space(page_id.space())); bit_offset = (page_id.page_no() % physical_size) @@ -730,7 +730,7 @@ ibuf_set_free_bits_low( ulint val, /*!< in: value to set: < 4 */ mtr_t* mtr) /*!< in/out: mtr */ { - ut_ad(mtr->is_named_space(block->page.id.space())); + ut_ad(mtr->is_named_space(block->page.id().space())); if (!page_is_leaf(block->frame)) { return; } @@ -738,11 +738,11 @@ ibuf_set_free_bits_low( #ifdef UNIV_IBUF_DEBUG ut_a(val <= ibuf_index_page_calc_free(block)); #endif /* UNIV_IBUF_DEBUG */ + const page_id_t id(block->page.id()); ibuf_bitmap_page_set_bits( - ibuf_bitmap_get_map_page(block->page.id, block->zip_size(), - mtr), - block->page.id, block->physical_size(), val, mtr); + ibuf_bitmap_get_map_page(id, block->zip_size(), mtr), + id, block->physical_size(), val, mtr); } /************************************************************************//** @@ -768,10 +768,11 @@ ibuf_set_free_bits_func( mtr_t mtr; mtr.start(); - const fil_space_t* space = mtr.set_named_space_id( - block->page.id.space()); + const page_id_t id(block->page.id()); - buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id, + const fil_space_t* space = mtr.set_named_space_id(id.space()); + + buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(id, block->zip_size(), &mtr); @@ -784,7 +785,7 @@ ibuf_set_free_bits_func( ulint old_val; old_val = ibuf_bitmap_page_get_bits( - bitmap_page, block->page.id, + bitmap_page, id, IBUF_BITMAP_FREE, &mtr); ut_a(old_val <= max_val); } @@ -793,7 +794,7 @@ ibuf_set_free_bits_func( #endif /* UNIV_IBUF_DEBUG */ ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->physical_size(), + bitmap_page, id, block->physical_size(), val, &mtr); mtr.commit(); @@ -841,7 +842,7 @@ ibuf_update_free_bits_low( ulint after; ut_a(!is_buf_block_get_page_zip(block)); - ut_ad(mtr->is_named_space(block->page.id.space())); + ut_ad(mtr->is_named_space(block->page.id().space())); before = ibuf_index_page_calc_free_bits(srv_page_size, max_ins_size); @@ -886,9 +887,9 @@ ibuf_update_free_bits_zip( } ibuf_bitmap_page_set_bits( - ibuf_bitmap_get_map_page(block->page.id, block->zip_size(), + ibuf_bitmap_get_map_page(block->page.id(), block->zip_size(), mtr), - block->page.id, block->physical_size(), after, mtr); + block->page.id(), block->physical_size(), after, mtr); } /**********************************************************************//** @@ -907,8 +908,8 @@ ibuf_update_free_bits_for_two_pages_low( { ulint state; - ut_ad(mtr->is_named_space(block1->page.id.space())); - ut_ad(block1->page.id.space() == block2->page.id.space()); + ut_ad(mtr->is_named_space(block1->page.id().space())); + ut_ad(block1->page.id().space() == block2->page.id().space()); /* As we have to x-latch two random bitmap pages, we have to acquire the bitmap mutex to prevent a deadlock with a similar operation @@ -1045,9 +1046,8 @@ ibuf_rec_get_page_no_func( const byte* field; ulint len; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1084,8 +1084,8 @@ ibuf_rec_get_space_func( const byte* field; ulint len; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1134,8 +1134,8 @@ ibuf_rec_get_info_func( ulint info_len_local; ulint counter_local; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); fields = rec_get_n_fields_old(rec); ut_a(fields > IBUF_REC_FIELD_USER); @@ -1208,8 +1208,8 @@ ibuf_rec_get_op_type_func( { ulint len; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1398,8 +1398,8 @@ ibuf_build_entry_from_ibuf_rec_func( ulint comp; dict_index_t* index; - ut_ad(mtr_memo_contains_page_flagged(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(ibuf_rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len); @@ -1523,8 +1523,8 @@ ibuf_rec_get_volume_func( ibuf_op_t op; ulint info_len; - ut_ad(mtr_memo_contains_page_flagged(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(ibuf_rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); @@ -1877,7 +1877,7 @@ static bool ibuf_add_free_page() /* Set the bit indicating that this page is now an ibuf tree page (level 2 page) */ - const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no()); + const page_id_t page_id(block->page.id()); buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); mutex_exit(&ibuf_mutex); @@ -1951,7 +1951,7 @@ ibuf_remove_free_page(void) compile_time_assert(IBUF_SPACE_ID == 0); fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, - fil_system.sys_space, page_no, false, &mtr); + fil_system.sys_space, page_no, &mtr); const page_id_t page_id(IBUF_SPACE_ID, page_no); @@ -2062,8 +2062,8 @@ ibuf_get_merge_page_nos_func( ulint limit; ulint n_pages; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); *n_stored = 0; @@ -2422,7 +2422,7 @@ ibuf_merge_pages( and the whole B-tree must be empty. InnoDB does not allow empty B-tree pages other than the root. */ ut_ad(ibuf.empty); - ut_ad(btr_pcur_get_block(&pcur)->page.id + ut_ad(btr_pcur_get_block(&pcur)->page.id() == page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO)); ibuf_mtr_commit(&mtr); @@ -2481,7 +2481,7 @@ ibuf_merge_space( and the whole B-tree must be empty. InnoDB does not allow empty B-tree pages other than the root. */ ut_ad(ibuf.empty); - ut_ad(btr_pcur_get_block(&pcur)->page.id + ut_ad(btr_pcur_get_block(&pcur)->page.id() == page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO)); } else { @@ -2528,7 +2528,7 @@ static ulint ibuf_merge(ulint* n_pages) when a slow shutdown is being executed. During a slow shutdown, the insert buffer merge must be completed. */ - if (ibuf.empty && !srv_shutdown_state) { + if (ibuf.empty && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { return(0); #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG } else if (ibuf_debug) { @@ -2662,8 +2662,8 @@ ibuf_get_volume_buffered_count_func( const byte* types; ulint n_fields; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); n_fields = rec_get_n_fields_old(rec); @@ -3037,8 +3037,8 @@ ibuf_get_entry_counter_low_func( ulint len; ut_ad(ibuf_inside(mtr)); - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(rec_get_n_fields_old(rec) > 2); field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); @@ -3112,7 +3112,7 @@ ibuf_get_entry_counter_func( in the node pointer */ { ut_ad(ibuf_inside(mtr)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_validate(page_align(rec), ibuf.index)); if (page_rec_is_supremum(rec)) { @@ -3291,7 +3291,7 @@ ibuf_insert_low( const ulint physical_size = zip_size ? zip_size : srv_page_size; if (op == IBUF_OP_DELETE - && (min_n_recs < 2 || buf_pool_watch_occurred(page_id))) { + && (min_n_recs < 2 || buf_pool.watch_occurred(page_id))) { /* The page could become empty after the record is deleted, or the page has been read in to the buffer pool. Refuse to buffer the operation. */ @@ -3323,7 +3323,7 @@ fail_exit: buffer pool, but we do not have to care about it, since we are holding a latch on the insert buffer leaf page that contains buffered changes for (space, page_no). If the page enters the - buffer pool, buf_page_io_complete() for (space, page_no) will + buffer pool, buf_page_read_complete() for (space, page_no) will have to acquire a latch on the same insert buffer leaf page, which it cannot do until we have buffered the IBUF_OP_DELETE and done mtr_commit(&mtr) to release the latch. */ @@ -3335,7 +3335,7 @@ fail_exit: /* We check if the index page is suitable for buffered entries */ - if (buf_page_hash_get(page_id) + if (buf_pool.page_hash_contains(page_id) || lock_rec_expl_exist_on_page(page_id.space(), page_id.page_no())) { @@ -3404,10 +3404,10 @@ fail_exit: ibuf_entry, &ins_rec, &dummy_big_rec, 0, thr, &mtr); block = btr_cur_get_block(cursor); - ut_ad(block->page.id.space() == IBUF_SPACE_ID); + ut_ad(block->page.id().space() == IBUF_SPACE_ID); /* If this is the root page, update ibuf.empty. */ - if (block->page.id.page_no() == FSP_IBUF_TREE_ROOT_PAGE_NO) { + if (block->page.id().page_no() == FSP_IBUF_TREE_ROOT_PAGE_NO) { const page_t* root = buf_block_get_frame(block); ut_ad(page_get_space_id(root) == IBUF_SPACE_ID); @@ -3447,7 +3447,7 @@ fail_exit: ibuf.empty = page_is_empty(root); block = btr_cur_get_block(cursor); - ut_ad(block->page.id.space() == IBUF_SPACE_ID); + ut_ad(block->page.id().space() == IBUF_SPACE_ID); } if (offsets_heap) { @@ -3576,9 +3576,9 @@ check_watch: would always trigger the buffer pool watch during purge and thus prevent the buffering of delete operations. We assume that the issuer of IBUF_OP_DELETE has called - buf_pool_watch_set(space, page_no). */ + buf_pool_t::watch_set(). */ - if (buf_page_get_also_watch(page_id)) { + if (buf_pool.page_hash_contains(page_id)) { /* A buffer pool watch has been set or the page has been read into the buffer pool. Do not buffer the request. If a purge operation @@ -3669,13 +3669,13 @@ ibuf_insert_to_index_page_low( "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" "InnoDB: that table.\n", stderr); - ib::error() << "page " << block->page.id << ", size " + ib::error() << "page " << block->page.id() << ", size " << block->physical_size() << ", bitmap bits " << ibuf_bitmap_page_get_bits( - ibuf_bitmap_get_map_page(block->page.id, + ibuf_bitmap_get_map_page(block->page.id(), block->zip_size(), mtr)->frame, - block->page.id, block->zip_size(), + block->page.id(), block->zip_size(), IBUF_BITMAP_FREE, mtr); ib::error() << BUG_REPORT_MSG; @@ -3707,8 +3707,8 @@ ibuf_insert_to_index_page( DBUG_ENTER("ibuf_insert_to_index_page"); DBUG_PRINT("ibuf", ("page " UINT32PF ":" UINT32PF, - block->page.id.space(), - block->page.id.page_no())); + block->page.id().space(), + block->page.id().page_no())); ut_ad(!dict_index_is_online_ddl(index));// this is an ibuf_dummy index ut_ad(ibuf_inside(mtr)); @@ -3720,7 +3720,7 @@ ibuf_insert_to_index_page( ut_ad(!block->index); assert_block_ahi_empty(block); #endif /* BTR_CUR_HASH_ADAPT */ - ut_ad(mtr->is_named_space(block->page.id.space())); + ut_ad(mtr->is_named_space(block->page.id().space())); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) != (ibool)!!page_is_comp(page))) { @@ -3905,7 +3905,7 @@ ibuf_set_del_mark( "InnoDB: record ", stderr); rec_print(stderr, page_cur_get_rec(&page_cur), index); - ib::error() << "page " << block->page.id << " (" + ib::error() << "page " << block->page.id() << " (" << page_get_n_recs(page) << " records, index id " << btr_page_get_index_id(page) << ")."; @@ -3968,8 +3968,8 @@ ibuf_delete( " (%u records, index id %llu)\n" "InnoDB: Submit a detailed bug report" " to https://jira.mariadb.org/\n", - block->page.id.space(), - block->page.id.page_no(), + block->page.id().space(), + block->page.id().page_no(), (unsigned) page_get_n_recs(page), (ulonglong) btr_page_get_index_id(page)); @@ -4203,8 +4203,8 @@ ibuf_merge_or_delete_for_page( ulint mops[IBUF_OP_COUNT]; ulint dops[IBUF_OP_COUNT]; - ut_ad(!block || page_id == block->page.id); - ut_ad(!block || buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(!block || page_id == block->page.id()); + ut_ad(!block || block->page.state() == BUF_BLOCK_FILE_PAGE); ut_ad(!block || block->page.status == buf_page_t::NORMAL); if (trx_sys_hdr_page(page_id) @@ -4788,20 +4788,20 @@ ibuf_set_bitmap_for_bulk_load( free_val = ibuf_index_page_calc_free(block); mtr.start(); - fil_space_t* space = mtr.set_named_space_id(block->page.id.space()); + fil_space_t* space = mtr.set_named_space_id(block->page.id().space()); - buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id, + buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id(), space->zip_size(), &mtr); free_val = reset ? 0 : ibuf_index_page_calc_free(block); /* FIXME: update the bitmap byte only once! */ ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->physical_size(), + bitmap_page, block->page.id(), block->physical_size(), free_val, &mtr); ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->physical_size(), + bitmap_page, block->page.id(), block->physical_size(), false, &mtr); mtr.commit(); diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index cd97a4e0142..5d2faa1e298 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -129,7 +129,7 @@ btr_leaf_page_release( || latch_mode == BTR_MODIFY_LEAF || latch_mode == BTR_NO_LATCHES); - ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)); + ut_ad(!mtr->memo_contains_flagged(block, MTR_MEMO_MODIFY)); mtr_memo_type_t mode; switch (latch_mode) { diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index efd7da6a2d0..8a45b714936 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -129,8 +129,8 @@ btr_cur_compress_recommendation( { const page_t* page; - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); page = btr_cur_get_page(cursor); @@ -147,7 +147,7 @@ btr_cur_compress_recommendation( root page. */ return cursor->index->page - != btr_cur_get_block(cursor)->page.id.page_no(); + != btr_cur_get_block(cursor)->page.id().page_no(); } return(FALSE); @@ -167,8 +167,8 @@ btr_cur_can_delete_without_compress( { page_t* page; - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor), + MTR_MEMO_PAGE_X_FIX)); page = btr_cur_get_page(cursor); @@ -182,7 +182,7 @@ btr_cur_can_delete_without_compress( compression if this is not the root page. */ return cursor->index->page - == btr_cur_get_block(cursor)->page.id.page_no(); + == btr_cur_get_block(cursor)->page.id().page_no(); } return(TRUE); diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index 1ffc2eb4d76..bceb35a6969 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 4c3c3359262..d93da475a1f 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -445,14 +445,14 @@ btr_pcur_open_low( #endif /* BTR_CUR_HASH_ADAPT */ file, line, mtr, autoinc); - if (err != DB_SUCCESS) { - ib::warn() << " Error code: " << err - << " btr_pcur_open_low " + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::warn() << "btr_pcur_open_low" << " level: " << level << " called from file: " << file << " line: " << line << " table: " << index->table->name - << " index: " << index->name; + << " index: " << index->name + << " error: " << err; } cursor->pos_state = BTR_PCUR_IS_POSITIONED; diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index cc62c4cad77..f09920b1816 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -30,32 +30,17 @@ Created 2/17/1996 Heikki Tuuri #include "dict0dict.h" #ifdef BTR_CUR_HASH_ADAPT #include "ha0ha.h" +#include "sync0sync.h" -/** Creates and initializes the adaptive search system at a database start. -@param[in] hash_size hash table size. */ -void btr_search_sys_create(ulint hash_size); +#define btr_search_sys_create() btr_search_sys.create() +#define btr_search_sys_free() btr_search_sys.free() -/** Resize hash index hash table. -@param[in] hash_size hash index hash table size */ -void btr_search_sys_resize(ulint hash_size); +/** Disable the adaptive hash search system and empty the index. */ +void btr_search_disable(); -/** Frees the adaptive search system at a database shutdown. */ -void btr_search_sys_free(); - -/** Disable the adaptive hash search system and empty the index. -@param need_mutex need to acquire dict_sys.mutex */ -void btr_search_disable(bool need_mutex); -/** Enable the adaptive hash search system. */ -void btr_search_enable(); - -/** Returns the value of ref_count. The value is protected by latch. -@param[in] info search info -@param[in] index index identifier -@return ref_count value. */ -ulint -btr_search_info_get_ref_count( - btr_search_t* info, - dict_index_t* index); +/** Enable the adaptive hash search system. +@param resize whether buf_pool_t::resize() is the caller */ +void btr_search_enable(bool resize= false); /*********************************************************************//** Updates the search info. */ @@ -174,19 +159,8 @@ static inline bool btr_search_own_any(); /** Unlock all search latches from shared mode. */ static inline void btr_search_s_unlock_all(); -/** Get the latch based on index attributes. -A latch is selected from an array of latches using pair of index-id, space-id. -@param[in] index index handler -@return latch */ -static inline rw_lock_t* btr_get_search_latch(const dict_index_t* index); - -/** Get the hash-table based on index attributes. -A table is selected from an array of tables using pair of index-id, space-id. -@param[in] index index handler -@return hash table */ -static inline hash_table_t* btr_get_search_table(const dict_index_t* index); #else /* BTR_CUR_HASH_ADAPT */ -# define btr_search_sys_create(size) +# define btr_search_sys_create() # define btr_search_sys_free() # define btr_search_drop_page_hash_index(block) # define btr_search_s_lock_all(index) @@ -195,7 +169,6 @@ static inline hash_table_t* btr_get_search_table(const dict_index_t* index); # define btr_search_move_or_delete_hash_entries(new_block, block) # define btr_search_update_hash_on_insert(cursor, ahi_latch) # define btr_search_update_hash_on_delete(cursor) -# define btr_search_sys_resize(hash_size) #endif /* BTR_CUR_HASH_ADAPT */ #ifdef BTR_CUR_ADAPT @@ -273,17 +246,121 @@ struct btr_search_t{ #ifdef BTR_CUR_HASH_ADAPT /** The hash index system */ -struct btr_search_sys_t{ - hash_table_t** hash_tables; /*!< the adaptive hash tables, - mapping dtuple_fold values - to rec_t pointers on index pages */ +struct btr_search_sys_t +{ + /** Partition of the hash table */ + struct partition + { + /** latches protecting hash_table */ + rw_lock_t latch; + /** mapping of dtuple_fold() to rec_t* in buf_block_t::frame */ + hash_table_t table; + /** memory heap for table */ + mem_heap_t *heap; + + char pad[(CPU_LEVEL1_DCACHE_LINESIZE - sizeof(rw_lock_t) - + sizeof(hash_table_t) - sizeof(mem_heap_t)) & + (CPU_LEVEL1_DCACHE_LINESIZE - 1)]; + + void init() + { + memset((void*) this, 0, sizeof *this); + rw_lock_create(btr_search_latch_key, &latch, SYNC_SEARCH_SYS); + } + + void alloc(ulint hash_size) + { + table.create(hash_size); + heap= mem_heap_create_typed(std::min(4096, + MEM_MAX_ALLOC_IN_BUF / 2 + - MEM_BLOCK_HEADER_SIZE + - MEM_SPACE_NEEDED(0)), + MEM_HEAP_FOR_BTR_SEARCH); + } + + void clear() + { + mem_heap_free(heap); + heap= nullptr; + ut_free(table.array); + } + + void free() + { + rw_lock_free(&latch); + if (heap) + clear(); + } + }; + + /** Partitions of the adaptive hash index */ + partition *parts; + + /** Get an adaptive hash index partition */ + partition *get_part(index_id_t id, ulint space_id) const + { + return parts + ut_fold_ulint_pair(ulint(id), space_id) % btr_ahi_parts; + } + + /** Get an adaptive hash index partition */ + partition *get_part(const dict_index_t &index) const + { + ut_ad(index.table->space->id == index.table->space_id); + return get_part(ulint(index.id), index.table->space_id); + } + + /** Get the search latch for the adaptive hash index partition */ + rw_lock_t *get_latch(const dict_index_t &index) const + { return &get_part(index)->latch; } + + /** Create and initialize at startup */ + void create() + { + parts= static_cast(ut_malloc(btr_ahi_parts * sizeof *parts, + mem_key_ahi)); + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].init(); + if (btr_search_enabled) + btr_search_enable(); + } + + void alloc(ulint hash_size) + { + hash_size/= btr_ahi_parts; + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].alloc(hash_size); + } + + /** Clear when disabling the adaptive hash index */ + void clear() { for (ulong i= 0; i < btr_ahi_parts; ++i) parts[i].clear(); } + + /** Free at shutdown */ + void free() + { + if (parts) + { + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].free(); + ut_free(parts); + parts= nullptr; + } + } }; -/** Latches protecting access to adaptive hash index. */ -extern rw_lock_t** btr_search_latches; - /** The adaptive hash index */ -extern btr_search_sys_t* btr_search_sys; +extern btr_search_sys_t btr_search_sys; + +/** @return number of leaf pages pointed to by the adaptive hash index */ +inline ulint dict_index_t::n_ahi_pages() const +{ + if (!btr_search_enabled) + return 0; + rw_lock_t *latch = &btr_search_sys.get_part(*this)->latch; + rw_lock_s_lock(latch); + ulint ref_count= search_info->ref_count; + rw_lock_s_unlock(latch); + return ref_count; +} #ifdef UNIV_SEARCH_PERF_STAT /** Number of successful adaptive hash index lookups */ diff --git a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic index 17bc7e555bd..40eb5d86ead 100644 --- a/storage/innobase/include/btr0sea.ic +++ b/storage/innobase/include/btr0sea.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -88,7 +88,7 @@ btr_search_info_update( static inline void btr_search_x_lock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_lock(btr_search_latches[i]); + rw_lock_x_lock(&btr_search_sys.parts[i].latch); } } @@ -96,7 +96,7 @@ static inline void btr_search_x_lock_all() static inline void btr_search_x_unlock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_unlock(btr_search_latches[i]); + rw_lock_x_unlock(&btr_search_sys.parts[i].latch); } } @@ -104,7 +104,7 @@ static inline void btr_search_x_unlock_all() static inline void btr_search_s_lock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_lock(btr_search_latches[i]); + rw_lock_s_lock(&btr_search_sys.parts[i].latch); } } @@ -112,7 +112,7 @@ static inline void btr_search_s_lock_all() static inline void btr_search_s_unlock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_unlock(btr_search_latches[i]); + rw_lock_s_unlock(&btr_search_sys.parts[i].latch); } } @@ -124,7 +124,7 @@ static inline void btr_search_s_unlock_all() static inline bool btr_search_own_all(ulint mode) { for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (!rw_lock_own(btr_search_latches[i], mode)) { + if (!rw_lock_own(&btr_search_sys.parts[i].latch, mode)) { return(false); } } @@ -138,7 +138,7 @@ static inline bool btr_search_own_all(ulint mode) static inline bool btr_search_own_any(ulint mode) { for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (rw_lock_own(btr_search_latches[i], mode)) { + if (rw_lock_own(&btr_search_sys.parts[i].latch, mode)) { return(true); } } @@ -149,7 +149,7 @@ static inline bool btr_search_own_any(ulint mode) static inline bool btr_search_own_any() { for (ulint i = btr_ahi_parts; i--; ) { - if (rw_lock_own_flagged(btr_search_latches[i], + if (rw_lock_own_flagged(&btr_search_sys.parts[i].latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)) { return true; } @@ -157,34 +157,4 @@ static inline bool btr_search_own_any() return false; } #endif /* UNIV_DEBUG */ - -/** Get the adaptive hash search index latch for a b-tree. -@param[in] index b-tree index -@return latch */ -static inline rw_lock_t* btr_get_search_latch(const dict_index_t* index) -{ - ut_ad(index != NULL); - ut_ad(!index->table->space - || index->table->space->id == index->table->space_id); - - ulint ifold = ut_fold_ulint_pair(ulint(index->id), - index->table->space_id); - - return(btr_search_latches[ifold % btr_ahi_parts]); -} - -/** Get the hash-table based on index attributes. -A table is selected from an array of tables using pair of index-id, space-id. -@param[in] index index handler -@return hash table */ -static inline hash_table_t* btr_get_search_table(const dict_index_t* index) -{ - ut_ad(index != NULL); - ut_ad(index->table->space->id == index->table->space_id); - - ulint ifold = ut_fold_ulint_pair(ulint(index->id), - index->table->space_id); - - return(btr_search_sys->hash_tables[ifold % btr_ahi_parts]); -} #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h index bd1cc06aca6..cba31074413 100644 --- a/storage/innobase/include/buf0buddy.h +++ b/storage/innobase/include/buf0buddy.h @@ -50,16 +50,14 @@ buf_buddy_get_slot(ulint size) } /** Allocate a ROW_FORMAT=COMPRESSED block. -@param[in] i index of buf_pool.zip_free[] or BUF_BUDDY_SIZES -@param[out] lru whether buf_pool.mutex was temporarily released +@param i index of buf_pool.zip_free[] or BUF_BUDDY_SIZES +@param lru assigned to true if buf_pool.mutex was temporarily released @return allocated block, never NULL */ byte *buf_buddy_alloc_low(ulint i, bool *lru) MY_ATTRIBUTE((malloc)); /** Allocate a ROW_FORMAT=COMPRESSED block. -The caller must not hold buf_pool.mutex nor buf_pool.zip_mutex nor any -block->mutex. -@param[in] size compressed page size -@param[out] lru whether buf_pool.mutex was temporarily released +@param size compressed page size in bytes +@param lru assigned to true if buf_pool.mutex was temporarily released @return allocated block, never NULL */ inline byte *buf_buddy_alloc(ulint size, bool *lru= nullptr) { diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index fc1880573b5..e316e1b7dab 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -70,41 +70,25 @@ struct fil_addr_t; #define BUF_EVICT_IF_IN_POOL 20 /*!< evict a clean block if found */ /* @} */ -#define BUF_POOL_WATCH_SIZE (srv_n_purge_threads + 1) - /*!< Maximum number of concurrent - buffer pool watches */ -#define MAX_PAGE_HASH_LOCKS 1024 /*!< The maximum number of - page_hash locks */ - # ifdef UNIV_DEBUG extern my_bool buf_disable_resize_buffer_pool_debug; /*!< if TRUE, resizing buffer pool is not allowed. */ # endif /* UNIV_DEBUG */ -/** @brief States of a control block -@see buf_page_t - -The enumeration values must be 0..7. */ -enum buf_page_state { - BUF_BLOCK_POOL_WATCH, /*!< a sentinel for the buffer pool - watch, element of buf_pool.watch[] */ - BUF_BLOCK_ZIP_PAGE, /*!< contains a clean - compressed page */ - BUF_BLOCK_ZIP_DIRTY, /*!< contains a compressed - page that is in the - buf_pool.flush_list */ - - BUF_BLOCK_NOT_USED, /*!< is in the free list; - must be after the BUF_BLOCK_ZIP_ - constants for compressed-only pages - @see buf_block_state_valid() */ - BUF_BLOCK_READY_FOR_USE, /*!< when buf_LRU_get_free_block - returns a block, it is in this state */ - BUF_BLOCK_FILE_PAGE, /*!< contains a buffered file page */ - BUF_BLOCK_MEMORY, /*!< contains some main memory - object */ - BUF_BLOCK_REMOVE_HASH /*!< hash index should be removed - before putting to the free list */ +/** buf_page_t::state() values, distinguishing buf_page_t and buf_block_t */ +enum buf_page_state +{ + /** available in buf_pool.free or buf_pool.watch */ + BUF_BLOCK_NOT_USED, + /** allocated for something else than a file page */ + BUF_BLOCK_MEMORY, + /** a previously allocated file page, in transit to NOT_USED */ + BUF_BLOCK_REMOVE_HASH, + /** a buf_block_t that is also in buf_pool.LRU */ + BUF_BLOCK_FILE_PAGE, + /** the buf_page_t of a ROW_FORMAT=COMPRESSED page + whose uncompressed page frame has been evicted */ + BUF_BLOCK_ZIP_PAGE }; /** This structure defines information we will fetch from each buffer pool. It @@ -198,11 +182,6 @@ UNIV_INLINE ulint buf_pool_get_curr_size(void); /*========================*/ -/** -@return the smallest oldest_modification lsn for any page. -@retval 0 if all modified persistent pages have been flushed */ -lsn_t -buf_pool_get_oldest_modification(); /********************************************************************//** Allocates a buf_page_t descriptor. This function must succeed. In case @@ -223,8 +202,7 @@ buf_page_free_descriptor( /** Allocate a buffer block. @return own: the allocated block, in state BUF_BLOCK_MEMORY */ -buf_block_t* -buf_block_alloc(); +inline buf_block_t *buf_block_alloc(); /********************************************************************//** Frees a buffer block which does not contain a file page. */ UNIV_INLINE @@ -359,12 +337,14 @@ buf_page_get_low( from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => FILE_PAGE (the other is buf_page_get_gen). -@param[in] page_id page id +@param[in,out] space space object +@param[in] offset offset of the tablespace @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction @return pointer to the block, page bufferfixed */ buf_block_t* -buf_page_create(const page_id_t page_id, ulint zip_size, mtr_t *mtr); +buf_page_create(fil_space_t *space, uint32_t offset, + ulint zip_size, mtr_t *mtr); /********************************************************************//** Releases a compressed-only page acquired with buf_page_get_zip(). */ @@ -382,15 +362,8 @@ buf_page_release_latch( buf_block_t* block, /*!< in: buffer block */ ulint rw_latch); /*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ -/********************************************************************//** -Moves a page to the start of the buffer pool LRU list. This high-level -function can be used to prevent an important page from slipping out of -the buffer pool. */ -void -buf_page_make_young( -/*================*/ - buf_page_t* bpage); /*!< in: buffer block of a file page */ - +/** Move a block to the start of the LRU list. */ +void buf_page_make_young(buf_page_t *bpage); /** Mark the page status as FREED for the given tablespace id and page number. If the page is not in buffer pool then ignore it. @param[in] page_id page_id @@ -642,16 +615,6 @@ buf_block_get_lock_hash_val( buf_block_t* buf_pool_contains_zip(const void* data); #endif /* UNIV_DEBUG */ -/*********************************************************************** -FIXME_FTS: Gets the frame the pointer is pointing to. */ -UNIV_INLINE -buf_frame_t* -buf_frame_align( -/*============*/ - /* out: pointer to frame */ - byte* ptr); /* in: pointer to a frame */ - - /** Dump a page to stderr. @param[in] read_buf database page @param[in] zip_size compressed page size, or 0 */ @@ -683,10 +646,6 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info); /** Refresh the statistics used to print per-second averages. */ void buf_refresh_io_stats(); -/** Check that there currently are no I/O operations pending. -@return number of pending i/o */ -ulint buf_pool_check_no_pending_io(); - /** Invalidate all pages in the buffer pool. All pages must be in a replaceable state (not modified or latched). */ void buf_pool_invalidate(); @@ -710,207 +669,6 @@ buf_block_dbg_add_level( #else /* UNIV_DEBUG */ # define buf_block_dbg_add_level(block, level) /* nothing */ #endif /* UNIV_DEBUG */ -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_page_get_state( -/*===============*/ - const buf_page_t* bpage); /*!< in: pointer to the control - block */ -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_block_get_state( -/*================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_page_set_state( -/*===============*/ - buf_page_t* bpage, /*!< in/out: pointer to control block */ - enum buf_page_state state); /*!< in: state */ -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_block_set_state( -/*================*/ - buf_block_t* block, /*!< in/out: pointer to control block */ - enum buf_page_state state); /*!< in: state */ -/*********************************************************************//** -Determines if a block is mapped to a tablespace. -@return TRUE if mapped */ -UNIV_INLINE -ibool -buf_page_in_file( -/*=============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ - MY_ATTRIBUTE((warn_unused_result)); - -/*********************************************************************//** -Determines if a block should be on unzip_LRU list. -@return TRUE if block belongs to unzip_LRU */ -UNIV_INLINE -ibool -buf_page_belongs_to_unzip_LRU( -/*==========================*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ - MY_ATTRIBUTE((warn_unused_result)); - -/*********************************************************************//** -Gets the mutex of a block. -@return pointer to mutex protecting bpage */ -UNIV_INLINE -BPageMutex* -buf_page_get_mutex( -/*===============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ - MY_ATTRIBUTE((warn_unused_result)); - -/*********************************************************************//** -Get the flush type of a page. -@return flush type */ -UNIV_INLINE -buf_flush_t -buf_page_get_flush_type( -/*====================*/ - const buf_page_t* bpage) /*!< in: buffer page */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Set the flush type of a page. */ -UNIV_INLINE -void -buf_page_set_flush_type( -/*====================*/ - buf_page_t* bpage, /*!< in: buffer page */ - buf_flush_t flush_type); /*!< in: flush type */ - -/** Map a block to a file page. -@param[in,out] block pointer to control block -@param[in] page_id page id */ -UNIV_INLINE -void -buf_block_set_file_page( - buf_block_t* block, - const page_id_t page_id); - -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_page_get_io_fix( -/*================*/ - const buf_page_t* bpage) /*!< in: pointer to the control block */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_block_get_io_fix( -/*================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_page_set_io_fix( -/*================*/ - buf_page_t* bpage, /*!< in/out: control block */ - enum buf_io_fix io_fix);/*!< in: io_fix state */ -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_block_set_io_fix( -/*=================*/ - buf_block_t* block, /*!< in/out: control block */ - enum buf_io_fix io_fix);/*!< in: io_fix state */ -/*********************************************************************//** -Makes a block sticky. A sticky block implies that even after we release -the buf_pool.mutex and the block->mutex: -* it cannot be removed from the flush_list -* the block descriptor cannot be relocated -* it cannot be removed from the LRU list -Note that: -* the block can still change its position in the LRU list -* the next and previous pointers can change. */ -UNIV_INLINE -void -buf_page_set_sticky( -/*================*/ - buf_page_t* bpage); /*!< in/out: control block */ -/*********************************************************************//** -Removes stickiness of a block. */ -UNIV_INLINE -void -buf_page_unset_sticky( -/*==================*/ - buf_page_t* bpage); /*!< in/out: control block */ -/********************************************************************//** -Determine if a buffer block can be relocated in memory. The block -can be dirty, but it must not be I/O-fixed or bufferfixed. */ -UNIV_INLINE -ibool -buf_page_can_relocate( -/*==================*/ - const buf_page_t* bpage) /*!< control block being relocated */ - MY_ATTRIBUTE((warn_unused_result)); - -/*********************************************************************//** -Determine if a block has been flagged old. -@return TRUE if old */ -UNIV_INLINE -ibool -buf_page_is_old( -/*============*/ - const buf_page_t* bpage) /*!< in: control block */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Flag a block old. */ -UNIV_INLINE -void -buf_page_set_old( -/*=============*/ - buf_page_t* bpage, /*!< in/out: control block */ - bool old); /*!< in: old */ -/*********************************************************************//** -Determine the time of first access of a block in the buffer pool. -@return ut_time_ms() at the time of first access, 0 if not accessed */ -UNIV_INLINE -unsigned -buf_page_is_accessed( -/*=================*/ - const buf_page_t* bpage) /*!< in: control block */ - MY_ATTRIBUTE((warn_unused_result)); -/*********************************************************************//** -Flag a block accessed. */ -UNIV_INLINE -void -buf_page_set_accessed( -/*==================*/ - buf_page_t* bpage) /*!< in/out: control block */ - MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** -Gets the buf_block_t handle of a buffered file block if an uncompressed -page frame exists, or NULL. Note: even though bpage is not declared a -const we don't update its value. -@return control block, or NULL */ -UNIV_INLINE -buf_block_t* -buf_page_get_block( -/*===============*/ - buf_page_t* bpage) /*!< in: control block, or NULL */ - MY_ATTRIBUTE((warn_unused_result)); #ifdef UNIV_DEBUG /*********************************************************************//** @@ -934,137 +692,21 @@ if applicable. */ #define is_buf_block_get_page_zip(block) \ UNIV_LIKELY_NULL((block)->page.zip.data) -/** Initialize a page for read to the buffer buf_pool. If the page is -(1) already in buf_pool, or -(2) if we specify to read only ibuf pages and the page is not an ibuf page, or -(3) if the space is deleted or being deleted, -then this function does nothing. -Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock -on the buffer frame. The io-handler must take care that the flag is cleared -and the lock released later. -@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED -@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] unzip whether the uncompressed page is - requested (for ROW_FORMAT=COMPRESSED) -@return pointer to the block -@retval NULL in case of an error */ -buf_page_t* -buf_page_init_for_read( - dberr_t* err, - ulint mode, - const page_id_t page_id, - ulint zip_size, - bool unzip); +/** Monitor the buffer page read/write activity, and increment corresponding +counter value in MONITOR_MODULE_BUF_PAGE. +@param bpage buffer page whose read or write was completed +@param io_type BUF_IO_READ or BUF_IO_WRITE */ +ATTRIBUTE_COLD __attribute__((nonnull)) +void buf_page_monitor(const buf_page_t *bpage, buf_io_fix io_type); -/** Complete a read or write request of a file page to or from the buffer pool. -@param[in,out] bpage page to complete -@param[in] dblwr whether the doublewrite buffer was used (on write) -@param[in] evict whether or not to evict the page from LRU list +/** Complete a read request of a file page to buf_pool. +@param bpage recently read page +@param node data file @return whether the operation succeeded -@retval DB_SUCCESS always when writing, or if a read page was OK -@retval DB_PAGE_CORRUPTED if the checksum fails on a page read -@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but - after decryption normal page checksum does - not match */ -UNIV_INTERN -dberr_t -buf_page_io_complete( - buf_page_t* bpage, - bool dblwr = false, - bool evict = false) - MY_ATTRIBUTE((nonnull)); - -/** Returns the control block of a file page, NULL if not found. -@param[in] page_id page id -@return block, NULL if not found */ -inline buf_page_t *buf_page_hash_get_low(const page_id_t page_id); - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@param[in] watch if true, return watch sentinel also. -@return pointer to the bpage or NULL; if NULL, lock is also NULL or -a watch sentinel. */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_locked( - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode, - bool watch = false); - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@return pointer to the block or NULL; if NULL, lock is also NULL. */ -UNIV_INLINE -buf_block_t* -buf_block_hash_get_locked( - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode); - -/* There are four different ways we can try to get a bpage or block -from the page hash: -1) Caller already holds the appropriate page hash lock: in the case call -buf_page_hash_get_low() function. -2) Caller wants to hold page hash lock in x-mode -3) Caller wants to hold page hash lock in s-mode -4) Caller doesn't want to hold page hash lock */ -#define buf_page_hash_get_s_locked(page_id, l) \ - buf_page_hash_get_locked(page_id, l, RW_LOCK_S) -#define buf_page_hash_get_x_locked(page_id, l) \ - buf_page_hash_get_locked(page_id, l, RW_LOCK_X) -#define buf_page_hash_get(page_id) \ - buf_page_hash_get_locked(page_id, NULL, 0) -#define buf_page_get_also_watch(page_id) \ - buf_page_hash_get_locked(page_id, NULL, 0, true) - -#define buf_block_hash_get_s_locked(page_id, l) \ - buf_block_hash_get_locked(page_id, l, RW_LOCK_S) -#define buf_block_hash_get_x_locked(page_id, l) \ - buf_block_hash_get_locked(page_id, l, RW_LOCK_X) -#define buf_block_hash_get(page_id) \ - buf_block_hash_get_locked(page_id, NULL, 0) - -/** Determine if a block is a sentinel for a buffer pool watch. -@param[in] bpage block -@return whether bpage a sentinel for a buffer pool watch */ -bool buf_pool_watch_is_sentinel(const buf_page_t* bpage) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - -/** Stop watching if the page has been read in. -buf_pool_watch_set(space,offset) must have returned NULL before. -@param[in] page_id page id */ -void buf_pool_watch_unset(const page_id_t page_id); - -/** Check if the page has been read in. -This may only be called after buf_pool_watch_set(space,offset) -has returned NULL and before invoking buf_pool_watch_unset(space,offset). -@param[in] page_id page id -@return FALSE if the given page was not read in, TRUE if it was */ -bool buf_pool_watch_occurred(const page_id_t page_id) -MY_ATTRIBUTE((warn_unused_result)); +@retval DB_SUCCESS always when writing, or if a read page was OK +@retval DB_PAGE_CORRUPTED if the checksum fails on a page read +@retval DB_DECRYPTION_FAILED if the page cannot be decrypted */ +dberr_t buf_page_read_complete(buf_page_t *bpage, const fil_node_t &node); /** Calculate aligned buffer pool size based on srv_buf_pool_chunk_unit, if needed. @@ -1128,40 +770,37 @@ public: /** The common buffer control block structure for compressed and uncompressed frames */ -/** Number of bits used for buffer page states. */ -#define BUF_PAGE_STATE_BITS 3 +class buf_pool_t; + +class buf_page_t +{ + friend buf_pool_t; + friend buf_block_t; + /** @name General fields */ + /* @{ */ + +public: // FIXME: fix fil_iterate() + /** Page id. Protected by buf_pool.hash_lock_get(id) when + the page is in buf_pool.page_hash. */ + page_id_t id_; +private: + /** Count of how manyfold this block is currently bufferfixed. */ + Atomic_counter buf_fix_count_; + + /** type of pending I/O operation; protected by buf_pool.mutex + if in_LRU_list */ + Atomic_relaxed io_fix_; + /** Block state. @see in_file(). + State transitions between in_file() states and to + BUF_BLOCK_REMOVE_HASH are protected by buf_pool.hash_lock_get(id) + when the block is in buf_pool.page_hash. + Other transitions when in_LRU_list are protected by buf_pool.mutex. */ + buf_page_state state_; -class buf_page_t { public: - /** @name General fields - None of these bit-fields must be modified without holding - buf_page_get_mutex() [buf_block_t::mutex or - buf_pool.zip_mutex], since they can be stored in the same - machine word. Some of these fields are additionally protected - by buf_pool.mutex. */ - /* @{ */ - - /** Page id. Protected by buf_pool mutex. */ - page_id_t id; - buf_page_t* hash; /*!< node used in chaining to - buf_pool.page_hash or - buf_pool.zip_hash */ - - /** Count of how manyfold this block is currently bufferfixed. */ - Atomic_counter buf_fix_count; - - /** type of pending I/O operation; also protected by - buf_pool.mutex for writes only */ - buf_io_fix io_fix; - - /** Block state. @see buf_page_in_file */ - buf_page_state state; - - unsigned flush_type:2; /*!< if this block is currently being - flushed to disk, this tells the - flush_type. - @see buf_flush_t */ - /* @} */ + /** buf_pool.page_hash link; protected by buf_pool.hash_lock_get(id) */ + buf_page_t *hash; + /* @} */ page_zip_des_t zip; /*!< compressed page; zip.data (but not the data it points to) is also protected by buf_pool.mutex; @@ -1169,97 +808,50 @@ public: zip.data == NULL means an active buf_pool.watch */ - ulint real_size; /*!< Real size of the page - Normal pages == srv_page_size - page compressed pages, payload - size alligned to sector boundary. - */ - buf_tmp_buffer_t* slot; /*!< Slot for temporary memory used for encryption/compression or NULL */ #ifdef UNIV_DEBUG - /** whether the page is in buf_pool.page_hash; - protected by buf_pool.mutex(!) and the hash bucket rw-latch */ - ibool in_page_hash; - ibool in_zip_hash; /*!< TRUE if in buf_pool.zip_hash */ + /** whether this->list is in buf_pool.zip_hash; protected by buf_pool.mutex */ + bool in_zip_hash; + /** whether this->LRU is in buf_pool.LRU (in_file() holds); + protected by buf_pool.mutex */ + bool in_LRU_list; + /** whether this is in buf_pool.page_hash (in_file() holds); + protected by buf_pool.mutex */ + bool in_page_hash; + /** whether this->list is in buf_pool.free (state() == BUF_BLOCK_NOT_USED); + protected by buf_pool.flush_list_mutex */ + bool in_free_list; #endif /* UNIV_DEBUG */ + /** list member in one of the lists of buf_pool; protected by + buf_pool.mutex or buf_pool.flush_list_mutex - /** @name Page flushing fields - All these are protected by buf_pool.mutex. */ - /* @{ */ + state() == BUF_BLOCK_NOT_USED: buf_pool.free or buf_pool.withdraw - UT_LIST_NODE_T(buf_page_t) list; - /*!< based on state, this is a - list node, protected either by - buf_pool.mutex or by - buf_pool.flush_list_mutex, - in one of the following lists in - buf_pool: + state() == BUF_BLOCK_FILE_PAGE || + (state() == BUF_BLOCK_ZIP_PAGE && !oldest_modification()): + buf_pool.flush_list (protected by buf_pool.flush_list_mutex) - - BUF_BLOCK_NOT_USED: free, withdraw - - BUF_BLOCK_FILE_PAGE: flush_list - - BUF_BLOCK_ZIP_DIRTY: flush_list - - BUF_BLOCK_ZIP_PAGE: zip_clean + state() == BUF_BLOCK_ZIP_PAGE && !oldest_modification(): buf_pool.zip_clean - If bpage is part of flush_list - then the node pointers are - covered by buf_pool.flush_list_mutex. - Otherwise these pointers are - protected by buf_pool.mutex. + The contents is undefined if + !oldest_modification() && state() == BUF_BLOCK_FILE_PAGE, + or if state() is not any of the above. */ + UT_LIST_NODE_T(buf_page_t) list; - The contents of the list node - is undefined if !in_flush_list - && state == BUF_BLOCK_FILE_PAGE, - or if state is one of - BUF_BLOCK_MEMORY, - BUF_BLOCK_REMOVE_HASH or - BUF_BLOCK_READY_IN_USE. */ - -#ifdef UNIV_DEBUG - ibool in_flush_list; /*!< TRUE if in buf_pool.flush_list; - when buf_pool.flush_list_mutex is - free, the following should hold: - in_flush_list - == (state == BUF_BLOCK_FILE_PAGE - || state == BUF_BLOCK_ZIP_DIRTY) - Writes to this field must be - covered by both block->mutex - and buf_pool.flush_list_mutex. Hence - reads can happen while holding - any one of the two mutexes */ - ibool in_free_list; /*!< TRUE if in buf_pool.free; when - buf_pool.mutex is free, the following - should hold: in_free_list - == (state == BUF_BLOCK_NOT_USED) */ -#endif /* UNIV_DEBUG */ - - lsn_t oldest_modification; - /*!< log sequence number of - the START of the log entry - written of the oldest - modification to this block - which has not yet been flushed - on disk; zero if all - modifications are on disk. - Writes to this field must be - covered by both block->mutex - and buf_pool.flush_list_mutex. Hence - reads can happen while holding - any one of the two mutexes */ - /* @} */ - /** @name LRU replacement algorithm fields - These fields are protected by buf_pool.mutex only (not - buf_pool.zip_mutex or buf_block_t::mutex). */ +private: + /** log sequence number of the START of the log entry written of the + oldest modification to this block which has not yet been written + to the data file; 0 if no modifications are pending. */ + Atomic_counter oldest_modification_; +public: + /** @name LRU replacement algorithm fields. + Protected by buf_pool.mutex. */ /* @{ */ UT_LIST_NODE_T(buf_page_t) LRU; /*!< node of the LRU list */ -#ifdef UNIV_DEBUG - ibool in_LRU_list; /*!< TRUE if the page is in - the LRU list; used in - debugging */ -#endif /* UNIV_DEBUG */ unsigned old:1; /*!< TRUE if the block is in the old blocks in buf_pool.LRU_old */ unsigned freed_page_clock:31;/*!< the value of @@ -1271,11 +863,9 @@ public: purposes without holding any mutex or latch */ /* @} */ - unsigned access_time; /*!< time of first access, or + Atomic_counter access_time; /*!< time of first access, or 0 if the block was never accessed - in the buffer pool. Protected by - block mutex for buf_page_in_file() - blocks. + in the buffer pool. For state==BUF_BLOCK_MEMORY blocks, this field can be repurposed @@ -1286,10 +876,10 @@ public: the field is protected by recv_sys_t::mutex. */ /** Change buffer entries for the page exist. - Protected by io_fix==BUF_IO_READ or by buf_block_t::lock. */ + Protected by io_fix()==BUF_IO_READ or by buf_block_t::lock. */ bool ibuf_exist; - /** Block initialization status. Can be modified while holding io_fix + /** Block initialization status. Can be modified while holding io_fix() or buf_block_t::lock X-latch */ enum { /** the page was read normally and should be flushed normally */ @@ -1304,10 +894,92 @@ public: FREED } status; - void fix() { buf_fix_count++; } + buf_page_t() : id_(0) + { + static_assert(BUF_BLOCK_NOT_USED == 0, "compatibility"); + memset((void*) this, 0, sizeof *this); + } + + /** Initialize some fields */ + void init() + { + io_fix_= BUF_IO_NONE; + buf_fix_count_= 0; + old= 0; + freed_page_clock= 0; + access_time= 0; + oldest_modification_= 0; + slot= nullptr; + ibuf_exist= false; + status= NORMAL; + ut_d(in_zip_hash= false); + ut_d(in_free_list= false); + ut_d(in_LRU_list= false); + ut_d(in_page_hash= false); + HASH_INVALIDATE(this, hash); + } + + /** Initialize some more fields */ + void init(buf_page_state state, page_id_t id, uint32_t buf_fix_count= 0) + { + init(); + state_= state; + id_= id; + buf_fix_count_= buf_fix_count; + } + + /** Initialize some more fields */ + void init(page_id_t id, uint32_t buf_fix_count= 0) + { + init(); + id_= id; + buf_fix_count_= buf_fix_count; + } + +public: + const page_id_t &id() const { return id_; } + buf_page_state state() const { return state_; } + uint32_t buf_fix_count() const { return buf_fix_count_; } + buf_io_fix io_fix() const { return io_fix_; } + void io_unfix() + { + ut_d(const auto old_io_fix= io_fix()); + ut_ad(old_io_fix == BUF_IO_READ || old_io_fix == BUF_IO_PIN); + io_fix_= BUF_IO_NONE; + } + + /** @return if this belongs to buf_pool.unzip_LRU */ + bool belongs_to_unzip_LRU() const + { + return zip.data && state() != BUF_BLOCK_ZIP_PAGE; + } + + inline void add_buf_fix_count(uint32_t count); + inline void set_buf_fix_count(uint32_t count); + inline void set_state(buf_page_state state); + inline void set_io_fix(buf_io_fix io_fix); + inline void set_corrupt_id(); + + /** @return the oldest modification */ + lsn_t oldest_modification() const { return oldest_modification_; } + /** Set oldest_modification when adding to buf_pool.flush_list */ + inline void set_oldest_modification(lsn_t lsn); + /** Clear oldest_modification when removing from buf_pool.flush_list */ + inline void clear_oldest_modification(); + + /** Prepare to release a file page to buf_pool.free. */ + void free_file_page() + { + ut_ad(state() == BUF_BLOCK_REMOVE_HASH); + ut_d(oldest_modification_= 0); /* for buf_LRU_free_page(this, false) */ + set_corrupt_id(); + ut_d(set_state(BUF_BLOCK_MEMORY)); + } + + void fix() { buf_fix_count_++; } uint32_t unfix() { - uint32_t count= buf_fix_count--; + uint32_t count= buf_fix_count_--; ut_ad(count != 0); return count - 1; } @@ -1324,6 +996,47 @@ public: { return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : 0; } + + /** @return whether the block is mapped to a data file */ + bool in_file() const + { + switch (state_) { + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_FILE_PAGE: + return true; + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + return false; + } + + ut_error; + return false; + } + + /** @return whether the block is modified and ready for flushing */ + inline bool ready_for_flush() const; + /** @return whether the state can be changed to BUF_BLOCK_NOT_USED */ + bool ready_for_replace() const + { return !oldest_modification() && can_relocate(); } + /** @return whether the block can be relocated in memory. + The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ + inline bool can_relocate() const; + /** @return whether the block has been flagged old in buf_pool.LRU */ + inline bool is_old() const; + /** Set whether a block is old in buf_pool.LRU */ + inline void set_old(bool old); + /** Flag a page accessed in buf_pool + @return whether this is not the first access */ + bool set_accessed() + { + if (is_accessed()) return true; + access_time= static_cast(ut_time_ms()); + return false; + } + /** @return ut_time_ms() at the time of first access of a block in buf_pool + @retval 0 if not accessed */ + unsigned is_accessed() const { ut_ad(in_file()); return access_time; } }; /** The buffer control block structure */ @@ -1343,21 +1056,25 @@ struct buf_block_t{ srv_page_size */ BPageLock lock; /*!< read-write lock of the buffer frame */ +#ifdef UNIV_DEBUG + /** whether page.list is in buf_pool.withdraw + ((state() == BUF_BLOCK_NOT_USED)) and the buffer pool is being shrunk; + protected by buf_pool.mutex */ + bool in_withdraw_list; + /** whether unzip_LRU is in buf_pool.unzip_LRU + (state() == BUF_BLOCK_FILE_PAGE and zip.data != nullptr); + protected by buf_pool.mutex */ + bool in_unzip_LRU_list; +#endif UT_LIST_NODE_T(buf_block_t) unzip_LRU; /*!< node of the decompressed LRU list; a block is in the unzip_LRU list - if page.state == BUF_BLOCK_FILE_PAGE + if page.state() == BUF_BLOCK_FILE_PAGE and page.zip.data != NULL */ -#ifdef UNIV_DEBUG - ibool in_unzip_LRU_list;/*!< TRUE if the page is in the - decompressed LRU list; - used in debugging */ - ibool in_withdraw_list; -#endif /* UNIV_DEBUG */ uint32_t lock_hash_val; /*!< hashed value of the page address in the record lock hash table; protected by buf_block_t::lock - (or buf_block_t::mutex, buf_pool.mutex + (or buf_pool.mutex in buf_page_get_gen(), buf_page_init_for_read() and buf_page_create()) */ @@ -1411,7 +1128,7 @@ struct buf_block_t{ assigning block->index = NULL (and block->n_pointers = 0) is allowed whenever btr_search_own_all(RW_LOCK_X). - Another exception is that ha_insert_for_fold_func() may + Another exception is that ha_insert_for_fold() may decrement n_pointers without holding the appropriate latch in btr_search_latches[]. Thus, n_pointers must be protected by atomic memory access. @@ -1439,7 +1156,7 @@ struct buf_block_t{ # define assert_block_ahi_empty(block) \ ut_a((block)->n_pointers == 0) # define assert_block_ahi_empty_on_init(block) do { \ - UNIV_MEM_VALID(&(block)->n_pointers, sizeof (block)->n_pointers); \ + MEM_MAKE_DEFINED(&(block)->n_pointers, sizeof (block)->n_pointers); \ assert_block_ahi_empty(block); \ } while (0) # define assert_block_ahi_valid(block) \ @@ -1481,15 +1198,16 @@ struct buf_block_t{ debug utilities in sync0rw */ /* @} */ # endif - BPageMutex mutex; /*!< mutex protecting this block: - state (also protected by the buffer - pool mutex), io_fix, buf_fix_count, - and accessed; we introduce this new - mutex in InnoDB-5.1 to relieve - contention on the buffer pool mutex */ - void fix() { page.fix(); } - uint32_t unfix() { return page.unfix(); } + uint32_t unfix() + { + uint32_t fix_count= page.unfix(); + ut_ad(fix_count || page.io_fix() != BUF_IO_NONE || + page.state() == BUF_BLOCK_ZIP_PAGE || + !rw_lock_own_flagged(&lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S | + RW_LOCK_FLAG_SX)); + return fix_count; + } /** @return the physical size, in bytes */ ulint physical_size() const { return page.physical_size(); } @@ -1497,16 +1215,14 @@ struct buf_block_t{ /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes @retval 0 if not compressed */ ulint zip_size() const { return page.zip_size(); } + + /** Initialize the block. + @param page_id page identifier + @param zip_size ROW_FORMAT=COMPRESSED page size, or 0 + @param fix initial buf_fix_count() */ + void initialise(const page_id_t page_id, ulint zip_size, uint32_t fix= 0); }; -/** Check if a buf_block_t object is in a valid state -@param block buffer block -@return TRUE if valid */ -#define buf_block_state_valid(block) \ -(buf_block_get_state(block) >= BUF_BLOCK_NOT_USED \ - && (buf_block_get_state(block) <= BUF_BLOCK_REMOVE_HASH)) - - /**********************************************************************//** Compute the hash fold value for blocks in buf_pool.zip_hash. */ /* @{ */ @@ -1528,11 +1244,11 @@ public: buf_page_t *get() const { ut_ad(mutex_own(m_mutex)); return m_hp; } /** Set current value - @param bpage buffer block to be set as hp */ + @param bpage buffer block to be set as hp */ void set(buf_page_t *bpage) { ut_ad(mutex_own(m_mutex)); - ut_ad(!bpage || buf_page_in_file(bpage)); + ut_ad(!bpage || bpage->in_file()); m_hp= bpage; } @@ -1575,7 +1291,7 @@ public: if (is_hp(bpage)) m_hp= UT_LIST_GET_PREV(list, m_hp); - ut_ad(!m_hp || m_hp->in_flush_list); + ut_ad(!m_hp || m_hp->oldest_modification()); } }; @@ -1655,7 +1371,7 @@ struct buf_pool_stat_t{ pages that are evicted without being accessed */ ulint n_pages_made_young; /*!< number of pages made young, in - calls to buf_LRU_make_block_young() */ + buf_page_make_young() */ ulint n_pages_not_made_young; /*!< number of pages not made young because the first access was not long enough ago, in @@ -1833,6 +1549,10 @@ public: return false; } + /** Release and evict a corrupted page. + @param bpage page that was being read */ + void corrupted_evict(buf_page_t *bpage); + #ifdef UNIV_DEBUG /** Find a block that points to a ROW_FORMAT=COMPRESSED page @param data pointer to the start of a ROW_FORMAT=COMPRESSED page frame @@ -1860,14 +1580,17 @@ public: This function does not return if the block is not identified. @param ptr pointer to within a page frame @return pointer to block, never NULL */ - inline buf_block_t* block_from_ahi(const byte *ptr) const; + inline buf_block_t *block_from_ahi(const byte *ptr) const; #endif /* BTR_CUR_HASH_ADAPT */ - bool is_block_mutex(const BPageMutex *m) const - { return is_block_field(reinterpret_cast(m)); } bool is_block_lock(const BPageLock *l) const { return is_block_field(reinterpret_cast(l)); } + /** + @return the smallest oldest_modification lsn for any page + @retval 0 if all modified persistent pages have been flushed */ + lsn_t get_oldest_modification(); + /** Determine if a buffer block was created by chunk_t::create(). @param block block descriptor (not dereferenced) @return whether block has been created by chunk_t::create() */ @@ -1878,29 +1601,211 @@ public: is_block_field(reinterpret_cast(block)); } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG + /** Get the page_hash latch for a page */ + page_hash_latch *hash_lock_get(const page_id_t id) const + { + return page_hash.lock_get(id.fold()); + } + + /** Look up a block descriptor. + @param id page identifier + @param fold id.fold() + @return block descriptor, possibly in watch[] + @retval nullptr if not found*/ + buf_page_t *page_hash_get_low(const page_id_t id, const ulint fold) + { + ut_ad(id.fold() == fold); + ut_ad(mutex_own(&mutex) || page_hash.lock_get(fold)->is_locked()); + buf_page_t *bpage; + /* Look for the page in the hash table */ + HASH_SEARCH(hash, &page_hash, fold, buf_page_t*, bpage, + ut_ad(bpage->in_page_hash), id == bpage->id()); + return bpage; + } +private: + /** Look up a block descriptor. + @tparam exclusive whether the latch is to be acquired exclusively + @tparam watch whether to allow watch_is_sentinel() + @param page_id page identifier + @param fold page_id.fold() + @param hash_lock pointer to the acquired latch (to be released by caller) + @return pointer to the block + @retval nullptr if no block was found; !lock || !*lock will also hold */ + template + buf_page_t *page_hash_get_locked(const page_id_t page_id, ulint fold, + page_hash_latch **hash_lock) + { + ut_ad(hash_lock || !exclusive); + page_hash_latch *latch= page_hash.lock(fold); + buf_page_t *bpage= page_hash_get_low(page_id, fold); + if (!bpage || watch_is_sentinel(*bpage)) + { + latch->release(); + if (hash_lock) + *hash_lock= nullptr; + return watch ? bpage : nullptr; + } + + ut_ad(bpage->in_file()); + ut_ad(page_id == bpage->id()); + + if (hash_lock) + *hash_lock= latch; /* to be released by the caller */ + else + latch->release(); + return bpage; + } +public: + /** Look up a block descriptor. + @tparam exclusive whether the latch is to be acquired exclusively + @param page_id page identifier + @param fold page_id.fold() + @param hash_lock pointer to the acquired latch (to be released by caller) + @return pointer to the block + @retval nullptr if no block was found; !lock || !*lock will also hold */ + template + buf_page_t *page_hash_get_locked(const page_id_t page_id, ulint fold, + page_hash_latch **hash_lock) + { return page_hash_get_locked(page_id, fold, hash_lock); } + + /** @return whether the buffer pool contains a page + @tparam watch whether to allow watch_is_sentinel() + @param page_id page identifier */ + template + bool page_hash_contains(const page_id_t page_id) + { + return page_hash_get_locked(page_id, page_id.fold(), nullptr); + } + + /** Determine if a block is a sentinel for a buffer pool watch. + @param bpage page descriptor + @return whether bpage a sentinel for a buffer pool watch */ + bool watch_is_sentinel(const buf_page_t &bpage) + { + ut_ad(mutex_own(&mutex) || hash_lock_get(bpage.id())->is_locked()); + ut_ad(bpage.in_file()); + + if (&bpage < &watch[0] || &bpage >= &watch[UT_ARR_SIZE(watch)]) + { + ut_ad(bpage.state() != BUF_BLOCK_ZIP_PAGE || bpage.zip.data); + return false; + } + + ut_ad(bpage.state() == BUF_BLOCK_ZIP_PAGE); + ut_ad(!bpage.in_zip_hash); + ut_ad(!bpage.zip.data); + return true; + } + + /** Check if a watched page has been read. + This may only be called after !watch_set() and before invoking watch_unset(). + @param id page identifier + @return whether the page was read to the buffer pool */ + bool watch_occurred(const page_id_t id) + { + const ulint fold= id.fold(); + page_hash_latch *hash_lock= page_hash.lock(fold); + /* The page must exist because watch_set() increments buf_fix_count. */ + buf_page_t *bpage= page_hash_get_low(id, fold); + const bool is_sentinel= watch_is_sentinel(*bpage); + hash_lock->read_unlock(); + return !is_sentinel; + } + + /** Register a watch for a page identifier. The caller must hold an + exclusive page hash latch. The *hash_lock may be released, + relocated, and reacquired. + @param id page identifier + @param hash_lock exclusively held page_hash latch + @return a buffer pool block corresponding to id + @retval nullptr if the block was not present, and a watch was installed */ + inline buf_page_t *watch_set(const page_id_t id, + page_hash_latch **hash_lock); + + /** Stop watching whether a page has been read in. + watch_set(id) must have returned nullptr before. + @param id page identifier */ + void watch_unset(const page_id_t id) + { + const ulint fold= id.fold(); + page_hash_latch *hash_lock= page_hash.lock(fold); + /* The page must exist because watch_set() increments buf_fix_count. */ + buf_page_t *watch= page_hash_get_low(id, fold); + if (watch->unfix() == 0 && watch_is_sentinel(*watch)) + { + /* The following is based on watch_remove(). */ + ut_ad(watch->in_page_hash); + ut_d(watch->in_page_hash= false); + HASH_DELETE(buf_page_t, hash, &page_hash, fold, watch); + hash_lock->write_unlock(); + // Now that the watch is detached from page_hash, release it to watch[]. + mutex_enter(&mutex); + /* It is possible that watch_remove() already removed the watch. */ + if (watch->id_ == id) + { + ut_ad(!watch->buf_fix_count()); + ut_ad(watch->state() == BUF_BLOCK_ZIP_PAGE); + watch->set_state(BUF_BLOCK_NOT_USED); + } + mutex_exit(&mutex); + } + else + hash_lock->write_unlock(); + } + + /** Remove the sentinel block for the watch before replacing it with a + real block. watch_unset() or watch_occurred() will notice + that the block has been replaced with the real block. + @param watch sentinel */ + inline void watch_remove(buf_page_t *watch); + + /** @return whether less than 1/4 of the buffer pool is available */ + bool running_out() const + { + return !recv_recovery_is_on() && + UNIV_UNLIKELY(UT_LIST_GET_LEN(free) + UT_LIST_GET_LEN(LRU) < + std::min(curr_size, old_size) / 4); + } + +#ifdef UNIV_DEBUG /** Validate the buffer pool. */ void validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#endif /* UNIV_DEBUG */ +#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG /** Write information of the buf_pool to the error log. */ void print(); -#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG */ + + /** Remove a block from the LRU list. + @return the predecessor in the LRU list */ + buf_page_t *LRU_remove(buf_page_t *bpage) + { + ut_ad(mutex_own(&mutex)); + ut_ad(bpage->in_LRU_list); + ut_ad(bpage->in_page_hash); + ut_ad(!bpage->in_zip_hash); + ut_ad(bpage->in_file()); + lru_hp.adjust(bpage); + lru_scan_itr.adjust(bpage); + single_scan_itr.adjust(bpage); + ut_d(bpage->in_LRU_list= false); + buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); + UT_LIST_REMOVE(LRU, bpage); + return prev; + } + + /** Number of pages to read ahead */ + static constexpr uint32_t READ_AHEAD_PAGES= 64; /** @name General fields */ /* @{ */ BufPoolMutex mutex; /*!< Buffer pool mutex */ - BufPoolZipMutex zip_mutex; /*!< Zip mutex, protects compressed - only pages (of type buf_page_t, not - buf_block_t */ ulint curr_pool_size; /*!< Current pool size in bytes */ ulint LRU_old_ratio; /*!< Reserve this much of the buffer pool for "old" blocks */ #ifdef UNIV_DEBUG ulint buddy_n_frames; /*!< Number of frames allocated from the buffer pool to the buddy system */ -#endif -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG ulint mutex_exit_forbidden; /*!< Forbid release mutex */ #endif ut_allocator allocator; /*!< Allocator used for @@ -1911,30 +1816,105 @@ public: chunk_t* chunks; /*!< buffer pool chunks */ chunk_t* chunks_old; /*!< old buffer pool chunks to be freed after resizing buffer pool */ - ulint curr_size; /*!< current pool size in pages */ - ulint old_size; /*!< previous pool size in pages */ - ulint read_ahead_area;/*!< size in pages of the area which - the read-ahead algorithms read if - invoked */ - hash_table_t* page_hash; /*!< hash table of buf_page_t or - buf_block_t file pages, - buf_page_in_file() == TRUE, - indexed by (space_id, offset). - page_hash is protected by an - array of mutexes. - Changes in page_hash are protected - by buf_pool.mutex and the relevant - page_hash mutex. Lookups can happen - while holding the buf_pool.mutex or - the relevant page_hash mutex. */ - hash_table_t* page_hash_old; /*!< old pointer to page_hash to be - freed after resizing buffer pool */ - hash_table_t* zip_hash; /*!< hash table of buf_block_t blocks - whose frames are allocated to the - zip buddy system, - indexed by block->frame */ - ulint n_pend_reads; /*!< number of pending read - operations */ + /** current pool size in pages */ + Atomic_counter curr_size; + /** previous pool size in pages */ + Atomic_counter old_size; + /** read-ahead request size in pages */ + Atomic_counter read_ahead_area; + + /** Hash table with singly-linked overflow lists. @see hash_table_t */ + struct page_hash_table + { + /** Number of array[] elements per page_hash_latch. + Must be one less than a power of 2. */ + static constexpr size_t ELEMENTS_PER_LATCH= 1023; + + /** number of payload elements in array[] */ + Atomic_relaxed n_cells; + /** the hash array, with pad(n_cells) elements */ + hash_cell_t *array; + + /** Create the hash table. + @param n the lower bound of n_cells */ + void create(ulint n); + + /** Free the hash table. */ + void free() { ut_free(array); array= nullptr; } + + /** @return the index of an array element */ + ulint calc_hash(ulint fold) const { return calc_hash(fold, n_cells); } + /** @return raw array index converted to padded index */ + static ulint pad(ulint h) { return 1 + (h / ELEMENTS_PER_LATCH) + h; } + private: + /** @return the hash value before any ELEMENTS_PER_LATCH padding */ + static ulint hash(ulint fold, ulint n) { return ut_hash_ulint(fold, n); } + + /** @return the index of an array element */ + static ulint calc_hash(ulint fold, ulint n_cells) + { + return pad(hash(fold, n_cells)); + } + /** Get a page_hash latch. */ + page_hash_latch *lock_get(ulint fold, ulint n) const + { + static_assert(!((ELEMENTS_PER_LATCH + 1) & ELEMENTS_PER_LATCH), + "must be one less than a power of 2"); + return reinterpret_cast + (&array[calc_hash(fold, n) & ~ELEMENTS_PER_LATCH]); + } + public: + /** Get a page_hash latch. */ + page_hash_latch *lock_get(ulint fold) const + { return lock_get(fold, n_cells); } + + /** Acquire an array latch, tolerating concurrent buf_pool_t::resize() + @tparam exclusive whether the latch is to be acquired exclusively + @param fold hash bucket key */ + template page_hash_latch *lock(ulint fold) + { + for (;;) + { + auto n= n_cells; + page_hash_latch *latch= lock_get(fold, n); + latch->acquire(); + /* Our latch prevents n_cells from changing. */ + if (UNIV_LIKELY(n == n_cells)) + return latch; + /* Retry, because buf_pool_t::resize_hash() affected us. */ + latch->release(); + } + } + + /** Exclusively aqcuire all latches */ + inline void write_lock_all(); + + /** Release all latches */ + inline void write_unlock_all(); + }; + +private: + /** Former page_hash that has been deleted during resize(); + singly-linked list via freed_page_hash->array[1] */ + page_hash_table *freed_page_hash; + + /** Lock all page_hash, also freed_page_hash. */ + inline void write_lock_all_page_hash(); + /** Release all page_hash, also freed_page_hash. */ + inline void write_unlock_all_page_hash(); + /** Resize page_hash and zip_hash. */ + inline void resize_hash(); + +public: + /** Hash table of file pages (buf_page_t::in_file() holds), + indexed by page_id_t. Protected by both mutex and page_hash.lock_get(). */ + page_hash_table page_hash; + + /** map of block->frame to buf_block_t blocks that belong + to buf_buddy_alloc(); protected by buf_pool.mutex */ + hash_table_t zip_hash; + /** number of pending read operations */ + Atomic_counter n_pend_reads; Atomic_counter n_pend_unzip; /*!< number of pending decompressions */ @@ -1968,13 +1948,12 @@ public: UT_LIST_BASE_NODE_T(buf_page_t) flush_list; /*!< base node of the modified block list */ - ibool init_flush[BUF_FLUSH_N_TYPES]; - /*!< this is TRUE when a flush of the - given type is being initialized */ - ulint n_flush[BUF_FLUSH_N_TYPES]; - /*!< this is the number of pending - writes in the given flush type */ - os_event_t no_flush[BUF_FLUSH_N_TYPES]; + /** set if a flush of the type is being initialized */ + Atomic_relaxed init_flush[3]; + /** Number of pending writes of a flush type. + The sum of these is approximately the sum of BUF_IO_WRITE blocks. */ + Atomic_counter n_flush[3]; + os_event_t no_flush[3]; /*!< this is in the set state when there is no flush batch of the given type running; @@ -2003,13 +1982,13 @@ public: to read this for heuristic purposes without holding any mutex or latch */ - ibool try_LRU_scan; /*!< Set to FALSE when an LRU + bool try_LRU_scan; /*!< Cleared when an LRU scan for free block fails. This flag is used to avoid repeated scans of LRU list when we know that there is no free block available in the scan depth for - eviction. Set to TRUE whenever + eviction. Set whenever we flush a batch from the buffer pool. Protected by the buf_pool.mutex */ @@ -2071,10 +2050,11 @@ public: frames and buf_page_t descriptors of blocks that exist in the buffer pool only in compressed form. */ /* @{ */ -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG + /** unmodified ROW_FORMAT=COMPRESSED pages; + protected by buf_pool.mutex */ UT_LIST_BASE_NODE_T(buf_page_t) zip_clean; - /*!< unmodified compressed pages */ -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ UT_LIST_BASE_NODE_T(buf_buddy_free_t) zip_free[BUF_BUDDY_SIZES_MAX]; /*!< buddy free lists */ #if BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN @@ -2082,14 +2062,26 @@ public: #endif /* @} */ - buf_page_t* watch; - /*!< Sentinel records for buffer - pool watches. Protected by - buf_pool.mutex. */ - - + /** Sentinels to detect if pages are read into the buffer pool while + a delete-buffering operation is pending. Protected by mutex. */ + buf_page_t watch[innodb_purge_threads_MAX + 1]; /** Reserve a buffer. */ buf_tmp_buffer_t *io_buf_reserve() { return io_buf.reserve(); } + + /** @return whether any I/O is pending */ + bool any_io_pending() const + { + return n_pend_reads || + n_flush[IORequest::LRU] || n_flush[IORequest::FLUSH_LIST] || + n_flush[IORequest::SINGLE_PAGE]; + } + /** @return total amount of pending I/O */ + ulint io_pending() const + { + return n_pend_reads + + n_flush[IORequest::LRU] + n_flush[IORequest::FLUSH_LIST] + + n_flush[IORequest::SINGLE_PAGE]; + } private: /** Temporary memory for page_compressed and encrypted I/O */ struct io_buf_t @@ -2143,71 +2135,161 @@ private: /** The InnoDB buffer pool */ extern buf_pool_t buf_pool; -/** @name Accessors for buffer pool mutexes -Use these instead of accessing buffer pool mutexes directly. */ -/* @{ */ - -/** Test if block->mutex is owned. */ -#define buf_page_mutex_own(b) (b)->mutex.is_owned() - -/** Acquire the block->mutex. */ -#define buf_page_mutex_enter(b) do { \ - mutex_enter(&(b)->mutex); \ -} while (0) - -/** Release the trx->mutex. */ -#define buf_page_mutex_exit(b) do { \ - (b)->mutex.exit(); \ -} while (0) - - -/** Get appropriate page_hash_lock. */ -UNIV_INLINE -rw_lock_t* -buf_page_hash_lock_get(const page_id_t& page_id) +inline void page_hash_latch::read_lock() { - return hash_get_lock(buf_pool.page_hash, page_id.fold()); + ut_ad(!mutex_own(&buf_pool.mutex)); + if (!read_trylock()) + read_lock_wait(); } -/** If not appropriate page_hash_lock, relock until appropriate. */ -# define buf_page_hash_lock_s_confirm(hash_lock, page_id)\ - hash_lock_s_confirm(hash_lock, buf_pool.page_hash, (page_id).fold()) +inline void page_hash_latch::write_lock() +{ + if (!write_trylock()) + write_lock_wait(); +} -# define buf_page_hash_lock_x_confirm(hash_lock, page_id)\ - hash_lock_x_confirm(hash_lock, buf_pool.page_hash, (page_id).fold()) +inline void buf_page_t::add_buf_fix_count(uint32_t count) +{ + ut_ad(mutex_own(&buf_pool.mutex)); + buf_fix_count_+= count; +} + +inline void buf_page_t::set_buf_fix_count(uint32_t count) +{ + ut_ad(mutex_own(&buf_pool.mutex)); + buf_fix_count_= count; +} + +inline void buf_page_t::set_state(buf_page_state state) +{ + ut_ad(mutex_own(&buf_pool.mutex)); +#ifdef UNIV_DEBUG + switch (state) { + case BUF_BLOCK_REMOVE_HASH: + /* buf_pool_t::corrupted_evict() invokes set_corrupt_id() + before buf_LRU_free_one_page(), so we cannot assert that + we are holding the hash_lock. */ + break; + case BUF_BLOCK_MEMORY: + if (!in_file()) break; + /* fall through */ + case BUF_BLOCK_FILE_PAGE: + ut_ad(buf_pool.hash_lock_get(id_)->is_write_locked()); + break; + case BUF_BLOCK_NOT_USED: + if (!in_file()) break; + /* fall through */ + case BUF_BLOCK_ZIP_PAGE: + ut_ad(buf_pool.hash_lock_get(id_)->is_write_locked() || + (this >= &buf_pool.watch[0] && + this <= &buf_pool.watch[UT_ARR_SIZE(buf_pool.watch)])); + break; + } +#endif + state_= state; +} + +inline void buf_page_t::set_io_fix(buf_io_fix io_fix) +{ + ut_ad(mutex_own(&buf_pool.mutex)); + io_fix_= io_fix; +} + +inline void buf_page_t::set_corrupt_id() +{ + ut_ad(!oldest_modification()); +#ifdef UNIV_DEBUG + switch (state()) { + case BUF_BLOCK_REMOVE_HASH: + break; + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_FILE_PAGE: + ut_ad(buf_pool.hash_lock_get(id_)->is_write_locked()); + break; + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_MEMORY: + ut_ad("invalid state" == 0); + } +#endif + id_= page_id_t(~0ULL); +} + +/** Set oldest_modification when adding to buf_pool.flush_list */ +inline void buf_page_t::set_oldest_modification(lsn_t lsn) +{ + ut_ad(mutex_own(&buf_pool.flush_list_mutex)); + ut_ad(!oldest_modification()); + oldest_modification_= lsn; +} + +/** Clear oldest_modification when removing from buf_pool.flush_list */ +inline void buf_page_t::clear_oldest_modification() +{ + ut_ad(mutex_own(&buf_pool.flush_list_mutex)); + ut_d(const auto state= state_); + ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_ZIP_PAGE || + state == BUF_BLOCK_REMOVE_HASH); + ut_ad(oldest_modification()); + oldest_modification_= 0; +} + +/** @return whether the block is modified and ready for flushing */ +inline bool buf_page_t::ready_for_flush() const +{ + ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(in_LRU_list); + ut_a(in_file()); + return oldest_modification() && io_fix_ == BUF_IO_NONE; +} + +/** @return whether the block can be relocated in memory. +The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ +inline bool buf_page_t::can_relocate() const +{ + ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(in_file()); + ut_ad(in_LRU_list); + return io_fix_ == BUF_IO_NONE && !buf_fix_count_; +} + +/** @return whether the block has been flagged old in buf_pool.LRU */ +inline bool buf_page_t::is_old() const +{ + ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(in_file()); + ut_ad(in_LRU_list); + return old; +} + +/** Set whether a block is old in buf_pool.LRU */ +inline void buf_page_t::set_old(bool old) +{ + ut_ad(mutex_own(&buf_pool.mutex)); + ut_ad(in_LRU_list); + +#ifdef UNIV_LRU_DEBUG + ut_a((buf_pool.LRU_old_len == 0) == (buf_pool.LRU_old == nullptr)); + /* If a block is flagged "old", the LRU_old list must exist. */ + ut_a(!old || buf_pool.LRU_old); + + if (UT_LIST_GET_PREV(LRU, this) && UT_LIST_GET_NEXT(LRU, this)) + { + const buf_page_t *prev= UT_LIST_GET_PREV(LRU, this); + const buf_page_t *next = UT_LIST_GET_NEXT(LRU, this); + if (prev->old == next->old) + ut_a(prev->old == old); + else + { + ut_a(!prev->old); + ut_a(buf_pool.LRU_old == (old ? this : next)); + } + } +#endif /* UNIV_LRU_DEBUG */ + + this->old= old; +} #ifdef UNIV_DEBUG -/** Test if page_hash lock is held in s-mode. */ -# define buf_page_hash_lock_held_s(bpage) \ - rw_lock_own(buf_page_hash_lock_get((bpage)->id), RW_LOCK_S) - -/** Test if page_hash lock is held in x-mode. */ -# define buf_page_hash_lock_held_x(bpage) \ - rw_lock_own(buf_page_hash_lock_get((bpage)->id), RW_LOCK_X) - -/** Test if page_hash lock is held in x or s-mode. */ -# define buf_page_hash_lock_held_s_or_x(bpage)\ - (buf_page_hash_lock_held_s(bpage) \ - || buf_page_hash_lock_held_x(bpage)) - -# define buf_block_hash_lock_held_s(block) \ - buf_page_hash_lock_held_s(&(block)->page) - -# define buf_block_hash_lock_held_x(block) \ - buf_page_hash_lock_held_x(&(block)->page) - -# define buf_block_hash_lock_held_s_or_x(block) \ - buf_page_hash_lock_held_s_or_x(&(block)->page) -#else /* UNIV_DEBUG */ -# define buf_page_hash_lock_held_s(p) (TRUE) -# define buf_page_hash_lock_held_x(p) (TRUE) -# define buf_page_hash_lock_held_s_or_x(p) (TRUE) -# define buf_block_hash_lock_held_s(p) (TRUE) -# define buf_block_hash_lock_held_x(p) (TRUE) -# define buf_block_hash_lock_held_s_or_x(p) (TRUE) -#endif /* UNIV_DEBUG */ - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** Forbid the release of the buffer pool mutex. */ # define buf_pool_mutex_exit_forbid() do { \ ut_ad(mutex_own(&buf_pool.mutex)); \ @@ -2224,15 +2306,12 @@ buf_page_hash_lock_get(const page_id_t& page_id) /** Allow the release of the buffer pool mutex. */ # define buf_pool_mutex_exit_allow() ((void) 0) #endif -/* @} */ /********************************************************************** Let us list the consistency conditions for different control block states. NOT_USED: is in free list, not in LRU list, not in flush list, nor page hash table -READY_FOR_USE: is not in free list, LRU list, or flush list, nor page - hash table MEMORY: is not in free list, LRU list, or flush list, nor page hash table FILE_PAGE: space and offset are defined, is in page hash table @@ -2260,9 +2339,8 @@ FILE_PAGE: space and offset are defined, is in page hash table State transitions: -NOT_USED => READY_FOR_USE -READY_FOR_USE => MEMORY -READY_FOR_USE => FILE_PAGE +NOT_USED => MEMORY +MEMORY => FILE_PAGE MEMORY => NOT_USED FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if (1) buf_fix_count == 0, @@ -2284,7 +2362,7 @@ inline buf_page_t *LRUItr::start() return m_hp; } -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Functor to validate the LRU list. */ struct CheckInLRUList { void operator()(const buf_page_t* elem) const @@ -2324,7 +2402,7 @@ struct CheckUnzipLRUAndLRUList { CheckUnzipLRUAndLRUList()); } }; -#endif /* UNIV_DEBUG || defined UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ #include "buf0buf.ic" diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 7b74705d5c7..242c9cbb65d 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -101,7 +101,7 @@ inline bool buf_page_peek_if_too_old(const buf_page_t *bpage) either the warm-up phase or an in-memory workload. */ return(FALSE); } else if (buf_LRU_old_threshold_ms && bpage->old) { - unsigned access_time = buf_page_is_accessed(bpage); + uint32_t access_time = bpage->is_accessed(); /* It is possible that the below comparison returns an unexpected result. 2^32 milliseconds pass in about 50 days, @@ -109,7 +109,7 @@ inline bool buf_page_peek_if_too_old(const buf_page_t *bpage) is e.g. 50 days + 15 ms, then the below will behave as if it is 15 ms. This is known and fixing it would require to increase buf_page_t::access_time from 32 to 64 bits. */ - if (access_time > 0 + if (access_time && ((ib_uint32_t) (ut_time_ms() - access_time)) >= buf_LRU_old_threshold_ms) { return(TRUE); @@ -122,452 +122,6 @@ inline bool buf_page_peek_if_too_old(const buf_page_t *bpage) } } -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_page_get_state( -/*===============*/ - const buf_page_t* bpage) /*!< in: pointer to the control block */ -{ - enum buf_page_state state = bpage->state; - -#ifdef UNIV_DEBUG - switch (state) { - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_FILE_PAGE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - break; - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - - return(state); -} -/*********************************************************************//** -Gets the state of a block. -@return state */ -UNIV_INLINE -enum buf_page_state -buf_block_get_state( -/*================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ -{ - return(buf_page_get_state(&block->page)); -} - -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_page_set_state( -/*===============*/ - buf_page_t* bpage, /*!< in/out: pointer to control block */ - enum buf_page_state state) /*!< in: state */ -{ -#ifdef UNIV_DEBUG - enum buf_page_state old_state = buf_page_get_state(bpage); - - switch (old_state) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - break; - case BUF_BLOCK_ZIP_PAGE: - ut_ad(state == BUF_BLOCK_ZIP_DIRTY); - break; - case BUF_BLOCK_ZIP_DIRTY: - ut_ad(state == BUF_BLOCK_ZIP_PAGE); - break; - case BUF_BLOCK_NOT_USED: - ut_ad(state == BUF_BLOCK_READY_FOR_USE); - break; - case BUF_BLOCK_READY_FOR_USE: - ut_ad(state == BUF_BLOCK_MEMORY - || state == BUF_BLOCK_FILE_PAGE - || state == BUF_BLOCK_NOT_USED); - break; - case BUF_BLOCK_MEMORY: - ut_ad(state == BUF_BLOCK_NOT_USED); - break; - case BUF_BLOCK_FILE_PAGE: - ut_ad(state == BUF_BLOCK_NOT_USED - || state == BUF_BLOCK_REMOVE_HASH - || state == BUF_BLOCK_FILE_PAGE); - if (state == BUF_BLOCK_REMOVE_HASH) { - ut_ad(!bpage->in_page_hash); - ut_ad(!bpage->in_zip_hash); - ut_ad(!bpage->in_LRU_list); - ut_ad(!bpage->in_free_list); - } - break; - case BUF_BLOCK_REMOVE_HASH: - ut_ad(state == BUF_BLOCK_MEMORY); - break; - } -#endif /* UNIV_DEBUG */ - bpage->state = state; -} - -/*********************************************************************//** -Sets the state of a block. */ -UNIV_INLINE -void -buf_block_set_state( -/*================*/ - buf_block_t* block, /*!< in/out: pointer to control block */ - enum buf_page_state state) /*!< in: state */ -{ - buf_page_set_state(&block->page, state); -} - -/*********************************************************************//** -Determines if a block is mapped to a tablespace. -@return TRUE if mapped */ -UNIV_INLINE -ibool -buf_page_in_file( -/*=============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - break; - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - case BUF_BLOCK_FILE_PAGE: - return(TRUE); - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - break; - } - - return(FALSE); -} - -/*********************************************************************//** -Determines if a block should be on unzip_LRU list. -@return TRUE if block belongs to unzip_LRU */ -UNIV_INLINE -ibool -buf_page_belongs_to_unzip_LRU( -/*==========================*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - ut_ad(buf_page_in_file(bpage)); - - return(bpage->zip.data - && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); -} - -/*********************************************************************//** -Gets the mutex of a block. -@return pointer to mutex protecting bpage */ -UNIV_INLINE -BPageMutex* -buf_page_get_mutex( -/*===============*/ - const buf_page_t* bpage) /*!< in: pointer to control block */ -{ - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_POOL_WATCH: - ut_error; - return(NULL); - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - return(&buf_pool.zip_mutex); - default: - return(&((buf_block_t*) bpage)->mutex); - } -} - -/*********************************************************************//** -Get the flush type of a page. -@return flush type */ -UNIV_INLINE -buf_flush_t -buf_page_get_flush_type( -/*====================*/ - const buf_page_t* bpage) /*!< in: buffer page */ -{ - buf_flush_t flush_type = (buf_flush_t) bpage->flush_type; - -#ifdef UNIV_DEBUG - switch (flush_type) { - case BUF_FLUSH_LRU: - case BUF_FLUSH_LIST: - case BUF_FLUSH_SINGLE_PAGE: - return(flush_type); - case BUF_FLUSH_N_TYPES: - ut_error; - } - ut_error; -#endif /* UNIV_DEBUG */ - return(flush_type); -} -/*********************************************************************//** -Set the flush type of a page. */ -UNIV_INLINE -void -buf_page_set_flush_type( -/*====================*/ - buf_page_t* bpage, /*!< in: buffer page */ - buf_flush_t flush_type) /*!< in: flush type */ -{ - bpage->flush_type = flush_type & 3; - ut_ad(buf_page_get_flush_type(bpage) == flush_type); -} - -/** Map a block to a file page. -@param[in,out] block pointer to control block -@param[in] page_id page id */ -UNIV_INLINE -void -buf_block_set_file_page( - buf_block_t* block, - const page_id_t page_id) -{ - buf_block_set_state(block, BUF_BLOCK_FILE_PAGE); - block->page.id = page_id; -} - -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_page_get_io_fix( -/*================*/ - const buf_page_t* bpage) /*!< in: pointer to the control block */ -{ - ut_ad(bpage != NULL); - - enum buf_io_fix io_fix = bpage->io_fix; - -#ifdef UNIV_DEBUG - switch (io_fix) { - case BUF_IO_NONE: - case BUF_IO_READ: - case BUF_IO_WRITE: - case BUF_IO_PIN: - return(io_fix); - } - ut_error; -#endif /* UNIV_DEBUG */ - return(io_fix); -} - -/*********************************************************************//** -Gets the io_fix state of a block. -@return io_fix state */ -UNIV_INLINE -enum buf_io_fix -buf_block_get_io_fix( -/*=================*/ - const buf_block_t* block) /*!< in: pointer to the control block */ -{ - return(buf_page_get_io_fix(&block->page)); -} - -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_page_set_io_fix( -/*================*/ - buf_page_t* bpage, /*!< in/out: control block */ - enum buf_io_fix io_fix) /*!< in: io_fix state */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - - bpage->io_fix = io_fix; - ut_ad(buf_page_get_io_fix(bpage) == io_fix); -} - -/*********************************************************************//** -Sets the io_fix state of a block. */ -UNIV_INLINE -void -buf_block_set_io_fix( -/*=================*/ - buf_block_t* block, /*!< in/out: control block */ - enum buf_io_fix io_fix) /*!< in: io_fix state */ -{ - buf_page_set_io_fix(&block->page, io_fix); -} - -/*********************************************************************//** -Makes a block sticky. A sticky block implies that even after we release -the buf_pool.mutex and the block->mutex: -* it cannot be removed from the flush_list -* the block descriptor cannot be relocated -* it cannot be removed from the LRU list -Note that: -* the block can still change its position in the LRU list -* the next and previous pointers can change. */ -UNIV_INLINE -void -buf_page_set_sticky( -/*================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); - - bpage->io_fix = BUF_IO_PIN; -} - -/*********************************************************************//** -Removes stickiness of a block. */ -UNIV_INLINE -void -buf_page_unset_sticky( -/*==================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); - - bpage->io_fix = BUF_IO_NONE; -} - -/********************************************************************//** -Determine if a buffer block can be relocated in memory. The block -can be dirty, but it must not be I/O-fixed or bufferfixed. */ -UNIV_INLINE -ibool -buf_page_can_relocate( -/*==================*/ - const buf_page_t* bpage) /*!< control block being relocated */ -{ - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_ad(buf_page_in_file(bpage)); - ut_ad(bpage->in_LRU_list); - - return(buf_page_get_io_fix(bpage) == BUF_IO_NONE - && bpage->buf_fix_count == 0); -} - -/*********************************************************************//** -Determine if a block has been flagged old. -@return TRUE if old */ -UNIV_INLINE -ibool -buf_page_is_old( -/*============*/ - const buf_page_t* bpage) /*!< in: control block */ -{ - /* Buffer page mutex is not strictly required here for heuristic - purposes even if LRU mutex is not being held. Keep the assertion - for not since all the callers hold it. */ - ut_ad(mutex_own(buf_page_get_mutex(bpage)) - || mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_in_file(bpage)); - - return(bpage->old); -} - -/*********************************************************************//** -Flag a block old. */ -UNIV_INLINE -void -buf_page_set_old( -/*=============*/ - buf_page_t* bpage, /*!< in/out: control block */ - bool old) /*!< in: old */ -{ - ut_a(buf_page_in_file(bpage)); - ut_ad(mutex_own(&buf_pool.mutex)); - ut_ad(bpage->in_LRU_list); - -#ifdef UNIV_LRU_DEBUG - ut_a((buf_pool.LRU_old_len == 0) == (buf_pool.LRU_old == NULL)); - /* If a block is flagged "old", the LRU_old list must exist. */ - ut_a(!old || buf_pool.LRU_old); - - if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { - const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); - const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); - if (prev->old == next->old) { - ut_a(prev->old == old); - } else { - ut_a(!prev->old); - ut_a(buf_pool.LRU_old == (old ? bpage : next)); - } - } -#endif /* UNIV_LRU_DEBUG */ - - bpage->old = old; -} - -/*********************************************************************//** -Determine the time of first access of a block in the buffer pool. -@return ut_time_ms() at the time of first access, 0 if not accessed */ -UNIV_INLINE -unsigned -buf_page_is_accessed( -/*=================*/ - const buf_page_t* bpage) /*!< in: control block */ -{ - ut_ad(buf_page_in_file(bpage)); - - return(bpage->access_time); -} - -/*********************************************************************//** -Flag a block accessed. */ -UNIV_INLINE -void -buf_page_set_accessed( -/*==================*/ - buf_page_t* bpage) /*!< in/out: control block */ -{ - ut_ad(!mutex_own(&buf_pool.mutex)); - ut_ad(mutex_own(buf_page_get_mutex(bpage))); - ut_a(buf_page_in_file(bpage)); - - if (bpage->access_time == 0) { - /* Make this the time of the first access. */ - bpage->access_time = static_cast(ut_time_ms()); - } -} - -/*********************************************************************//** -Gets the buf_block_t handle of a buffered file block if an uncompressed -page frame exists, or NULL. -@return control block, or NULL */ -UNIV_INLINE -buf_block_t* -buf_page_get_block( -/*===============*/ - buf_page_t* bpage) /*!< in: control block, or NULL */ -{ - if (bpage != NULL) { - ut_ad(buf_page_hash_lock_held_s_or_x(bpage) - || mutex_own(&buf_pool.mutex)); - ut_ad(buf_page_in_file(bpage)); - - if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { - return((buf_block_t*) bpage); - } - } - - return(NULL); -} - #ifdef UNIV_DEBUG /*********************************************************************//** Gets a pointer to the memory frame of a block. @@ -582,17 +136,14 @@ buf_block_get_frame( return NULL; } - switch (buf_block_get_state(block)) { - case BUF_BLOCK_POOL_WATCH: + switch (block->page.state()) { case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: ut_error; break; case BUF_BLOCK_FILE_PAGE: - ut_a(block->page.buf_fix_count > 0); + ut_a(block->page.buf_fix_count()); /* fall through */ - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: goto ok; @@ -603,24 +154,6 @@ ok: } #endif /* UNIV_DEBUG */ -/*********************************************************************** -FIXME_FTS Gets the frame the pointer is pointing to. */ -UNIV_INLINE -buf_frame_t* -buf_frame_align( -/*============*/ - /* out: pointer to frame */ - byte* ptr) /* in: pointer to a frame */ -{ - buf_frame_t* frame; - - ut_ad(ptr); - - frame = (buf_frame_t*) ut_align_down(ptr, srv_page_size); - - return(frame); -} - /**********************************************************************//** Gets the hash value of the page the pointer is pointing to. This can be used in searches in the lock hash table. @@ -632,7 +165,7 @@ buf_block_get_lock_hash_val( const buf_block_t* block) /*!< in: block */ { ut_ad(block); - ut_ad(buf_page_in_file(&block->page)); + ut_ad(block->page.in_file()); ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_X) || rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_S)); @@ -652,7 +185,9 @@ buf_page_alloc_descriptor(void) bpage = (buf_page_t*) ut_zalloc_nokey(sizeof *bpage); ut_ad(bpage); - UNIV_MEM_ALLOC(bpage, sizeof *bpage); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(bpage, sizeof *bpage); +#endif /* HAVE_valgrind_or_MSAN */ return(bpage); } @@ -668,6 +203,13 @@ buf_page_free_descriptor( ut_free(bpage); } +/** Allocate a buffer block. +@return own: the allocated block, in state BUF_BLOCK_MEMORY */ +inline buf_block_t *buf_block_alloc() +{ + return buf_LRU_get_free_block(false); +} + /********************************************************************//** Frees a buffer block which does not contain a file page. */ UNIV_INLINE @@ -677,15 +219,7 @@ buf_block_free( buf_block_t* block) /*!< in, own: block to be freed */ { mutex_enter(&buf_pool.mutex); - - buf_page_mutex_enter(block); - - ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE); - buf_LRU_block_free_non_file_page(block); - - buf_page_mutex_exit(block); - mutex_exit(&buf_pool.mutex); } @@ -700,9 +234,9 @@ buf_block_modify_clock_inc( buf_block_t* block) /*!< in: block */ { /* No latch is acquired for the shared temporary tablespace. */ - ut_ad(fsp_is_system_temporary(block->page.id.space()) + ut_ad(fsp_is_system_temporary(block->page.id().space()) || (mutex_own(&buf_pool.mutex) - && block->page.buf_fix_count == 0) + && !block->page.buf_fix_count()) || rw_lock_own_flagged(&block->lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX)); assert_block_ahi_valid(block); @@ -722,7 +256,7 @@ buf_block_get_modify_clock( { #ifdef UNIV_DEBUG /* No latch is acquired for the shared temporary tablespace. */ - if (!fsp_is_system_temporary(block->page.id.space())) { + if (!fsp_is_system_temporary(block->page.id().space())) { ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) || rw_lock_own(&(block->lock), RW_LOCK_X) || rw_lock_own(&(block->lock), RW_LOCK_SX)); @@ -748,7 +282,7 @@ buf_block_buf_fix_inc_func( /* No debug latch is acquired if block belongs to system temporary. Debug latch is not of much help if access to block is single threaded. */ - if (!fsp_is_system_temporary(block->page.id.space())) { + if (!fsp_is_system_temporary(block->page.id().space())) { ibool ret; ret = rw_lock_s_lock_nowait(block->debug_latch, file, line); ut_a(ret); @@ -772,176 +306,12 @@ buf_block_buf_fix_dec( /* No debug latch is acquired if block belongs to system temporary. Debug latch is not of much help if access to block is single threaded. */ - if (!fsp_is_system_temporary(block->page.id.space())) { + if (!fsp_is_system_temporary(block->page.id().space())) { rw_lock_s_unlock(block->debug_latch); } #endif /* UNIV_DEBUG */ } -/** Returns the control block of a file page, NULL if not found. -@param[in] page_id page id -@return block, NULL if not found */ -inline buf_page_t *buf_page_hash_get_low(page_id_t page_id) -{ - buf_page_t* bpage; - -#ifdef UNIV_DEBUG - rw_lock_t* hash_lock; - - hash_lock = hash_get_lock(buf_pool.page_hash, page_id.fold()); - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X) - || rw_lock_own(hash_lock, RW_LOCK_S)); -#endif /* UNIV_DEBUG */ - - /* Look for the page in the hash table */ - - HASH_SEARCH(hash, buf_pool.page_hash, page_id.fold(), buf_page_t*, - bpage, - ut_ad(bpage->in_page_hash && !bpage->in_zip_hash - && buf_page_in_file(bpage)), - page_id == bpage->id); - if (bpage) { - ut_a(buf_page_in_file(bpage)); - ut_ad(bpage->in_page_hash); - ut_ad(!bpage->in_zip_hash); - } - - return(bpage); -} - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@param[in] watch if true, return watch sentinel also. -@return pointer to the bpage or NULL; if NULL, lock is also NULL or -a watch sentinel. */ -UNIV_INLINE -buf_page_t* -buf_page_hash_get_locked( - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode, - bool watch) -{ - buf_page_t* bpage = NULL; - rw_lock_t* hash_lock; - ulint mode = RW_LOCK_S; - - if (lock != NULL) { - *lock = NULL; - ut_ad(lock_mode == RW_LOCK_X - || lock_mode == RW_LOCK_S); - mode = lock_mode; - } - - hash_lock = hash_get_lock(buf_pool.page_hash, page_id.fold()); - - ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X) - && !rw_lock_own(hash_lock, RW_LOCK_S)); - - if (mode == RW_LOCK_S) { - rw_lock_s_lock(hash_lock); - - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = hash_lock_s_confirm( - hash_lock, buf_pool.page_hash, page_id.fold()); - } else { - rw_lock_x_lock(hash_lock); - /* If not own buf_pool_mutex, page_hash can be changed. */ - hash_lock = hash_lock_x_confirm( - hash_lock, buf_pool.page_hash, page_id.fold()); - } - - bpage = buf_page_hash_get_low(page_id); - - if (!bpage || buf_pool_watch_is_sentinel(bpage)) { - if (!watch) { - bpage = NULL; - } - goto unlock_and_exit; - } - - ut_ad(buf_page_in_file(bpage)); - ut_ad(page_id == bpage->id); - - if (lock == NULL) { - /* The caller wants us to release the page_hash lock */ - goto unlock_and_exit; - } else { - /* To be released by the caller */ - *lock = hash_lock; - goto exit; - } - -unlock_and_exit: - if (mode == RW_LOCK_S) { - rw_lock_s_unlock(hash_lock); - } else { - rw_lock_x_unlock(hash_lock); - } -exit: - return(bpage); -} - -/** Returns the control block of a file page, NULL if not found. -If the block is found and lock is not NULL then the appropriate -page_hash lock is acquired in the specified lock mode. Otherwise, -mode value is ignored. It is up to the caller to release the -lock. If the block is found and the lock is NULL then the page_hash -lock is released by this function. -@param[in] page_id page id -@param[in,out] lock lock of the page hash acquired if bpage is -found, NULL otherwise. If NULL is passed then the hash_lock is released by -this function. -@param[in] lock_mode RW_LOCK_X or RW_LOCK_S. Ignored if -lock == NULL -@return pointer to the block or NULL; if NULL, lock is also NULL. */ -UNIV_INLINE -buf_block_t* -buf_block_hash_get_locked( - const page_id_t page_id, - rw_lock_t** lock, - ulint lock_mode) -{ - buf_page_t* bpage = buf_page_hash_get_locked(page_id, lock, - lock_mode); - buf_block_t* block = buf_page_get_block(bpage); - - if (block != NULL) { - - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(!lock || rw_lock_own(*lock, lock_mode)); - - return(block); - } else if (bpage) { - /* It is not a block. Just a bpage */ - ut_ad(buf_page_in_file(bpage)); - - if (lock) { - if (lock_mode == RW_LOCK_S) { - rw_lock_s_unlock(*lock); - } else { - rw_lock_x_unlock(*lock); - } - } - *lock = NULL; - return(NULL); - } - - ut_ad(!bpage); - ut_ad(lock == NULL ||*lock == NULL); - return(NULL); -} - /********************************************************************//** Releases a compressed-only page acquired with buf_page_get_zip(). */ UNIV_INLINE @@ -951,9 +321,9 @@ buf_page_release_zip( buf_page_t* bpage) /*!< in: buffer block */ { ut_ad(bpage); - ut_a(bpage->buf_fix_count > 0); + ut_a(bpage->buf_fix_count()); - switch (buf_page_get_state(bpage)) { + switch (bpage->state()) { case BUF_BLOCK_FILE_PAGE: #ifdef UNIV_DEBUG { @@ -961,20 +331,17 @@ buf_page_release_zip( temporary. Debug latch is not of much help if access to block is single threaded. */ buf_block_t* block = reinterpret_cast(bpage); - if (!fsp_is_system_temporary(block->page.id.space())) { + if (!fsp_is_system_temporary(block->page.id().space())) { rw_lock_s_unlock(block->debug_latch); } } #endif /* UNIV_DEBUG */ /* Fall through */ case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: reinterpret_cast(bpage)->unfix(); return; - case BUF_BLOCK_POOL_WATCH: case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: case BUF_BLOCK_MEMORY: case BUF_BLOCK_REMOVE_HASH: break; @@ -997,7 +364,7 @@ buf_page_release_latch( /* No debug latch is acquired if block belongs to system temporary. Debug latch is not of much help if access to block is single threaded. */ - if (!fsp_is_system_temporary(block->page.id.space())) { + if (!fsp_is_system_temporary(block->page.id().space())) { rw_lock_s_unlock(block->debug_latch); } #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h index 17fa84a85cc..fca2c61124e 100644 --- a/storage/innobase/include/buf0dblwr.h +++ b/storage/innobase/include/buf0dblwr.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -69,13 +69,8 @@ frees doublewrite buffer. */ void buf_dblwr_free(); -/********************************************************************//** -Updates the doublewrite buffer when an IO request is completed. */ -void -buf_dblwr_update( -/*=============*/ - const buf_page_t* bpage, /*!< in: buffer block descriptor */ - buf_flush_t flush_type);/*!< in: flush type */ +/** Update the doublewrite buffer on write completion. */ +void buf_dblwr_update(const buf_page_t &bpage, bool single_page); /****************************************************************//** Determines if a page number is located inside the doublewrite buffer. @return TRUE if the location is inside the two blocks of the @@ -84,20 +79,6 @@ ibool buf_dblwr_page_inside( /*==================*/ ulint page_no); /*!< in: page number */ -/********************************************************************//** -Posts a buffer page for writing. If the doublewrite memory buffer is -full, calls buf_dblwr_flush_buffered_writes and waits for for free -space to appear. */ -void -buf_dblwr_add_to_batch( -/*====================*/ - buf_page_t* bpage); /*!< in: buffer block to write */ - -/********************************************************************//** -Flush a batch of writes to the datafiles that have already been -written to the dblwr buffer on disk. */ -void -buf_dblwr_sync_datafiles(); /********************************************************************//** Flushes possible buffered writes from the doublewrite memory buffer to disk. @@ -107,20 +88,6 @@ Otherwise a deadlock of threads can occur. */ void buf_dblwr_flush_buffered_writes(); -/********************************************************************//** -Writes a page to the doublewrite buffer on disk, sync it, then write -the page to the datafile and sync the datafile. This function is used -for single page flushes. If all the buffers allocated for single page -flushes in the doublewrite buffer are in use we wait here for one to -become free. We are guaranteed that a slot will become free because any -thread that is using a slot must also release the slot before leaving -this function. */ -void -buf_dblwr_write_single_page( -/*========================*/ - buf_page_t* bpage, /*!< in: buffer block to write */ - bool sync); /*!< in: true if sync IO requested */ - /** Doublewrite control struct */ struct buf_dblwr_t{ ib_mutex_t mutex; /*!< mutex protecting the first_free @@ -140,9 +107,6 @@ struct buf_dblwr_t{ reserved for single page flushes. */ os_event_t s_event;/*!< event where threads wait for a single page flush slot. Protected by mutex. */ - bool* in_use; /*!< flag used to indicate if a slot is - in use. Only used for single page - flushes. */ bool batch_running;/*!< set to TRUE if currently a batch is being written from the doublewrite buffer. */ @@ -150,9 +114,37 @@ struct buf_dblwr_t{ doublewrite buffer, aligned to an address divisible by srv_page_size (which is required by Windows aio) */ - buf_page_t** buf_block_arr;/*!< array to store pointers to - the buffer blocks which have been - cached to write_buf */ + + struct element + { + /** block descriptor */ + buf_page_t *bpage; + /** flush type */ + IORequest::flush_t flush; + /** payload size in bytes */ + size_t size; + }; + + /** buffer blocks to be written via write_buf */ + element *buf_block_arr; + + /** Schedule a page write. If the doublewrite memory buffer is full, + buf_dblwr_flush_buffered_writes() will be invoked to make space. + @param bpage buffer pool page to be written + @param flush type of flush + @param size payload size in bytes */ + void add_to_batch(buf_page_t *bpage, IORequest::flush_t flush, size_t size); + /** Write a page to the doublewrite buffer on disk, sync it, then write + the page to the datafile and sync the datafile. This function is used + for single page flushes. If all the buffers allocated for single page + flushes in the doublewrite buffer are in use we wait here for one to + become free. We are guaranteed that a slot will become free because any + thread that is using a slot must also release the slot before leaving + this function. + @param bpage buffer pool page to be written + @param sync whether synchronous operation is requested + @param size payload size in bytes */ + void write_single_page(buf_page_t *bpage, bool sync, size_t size); }; #endif diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index eb6351fb244..f7f89f1a9e9 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -70,10 +70,14 @@ buf_flush_relocate_on_flush_list( /*=============================*/ buf_page_t* bpage, /*!< in/out: control block being moved */ buf_page_t* dpage); /*!< in/out: destination block */ -/** Update the flush system data structures when a write is completed. -@param[in,out] bpage flushed page -@param[in] dblwr whether the doublewrite buffer was used */ -void buf_flush_write_complete(buf_page_t* bpage, bool dblwr); + +/** Complete write of a file page from buf_pool. +@param bpage written page +@param request write request +@param dblwr whether the doublewrite buffer was used +@param evict whether or not to evict the page from LRU list */ +void buf_page_write_complete(buf_page_t *bpage, const IORequest &request, + bool dblwr, bool evict); /** Assign the full crc32 checksum for non-compressed page. @param[in,out] page page to be updated */ @@ -91,19 +95,9 @@ buf_flush_init_for_writing( void* page_zip_, bool use_full_checksum); -# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG -/** Writes a flushable page asynchronously from the buffer pool to a file. -NOTE: block and LRU list mutexes must be held upon entering this function, and -they will be released by this function after flushing. This is loosely based on -buf_flush_batch() and buf_flush_page(). -@param[in,out] block buffer control block -@return whether the page was flushed and the mutex released */ -bool buf_flush_page_try(buf_block_t* block) - MY_ATTRIBUTE((warn_unused_result)); -# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ /** Do flushing batch of a given type. NOTE: The calling thread is not allowed to own any latches on pages! -@param[in] type flush type +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list @param[in] min_n wished minimum mumber of blocks flushed (it is not guaranteed that the actual number is that big, though) @param[in] lsn_limit in the case BUF_FLUSH_LIST all blocks whose @@ -113,12 +107,8 @@ does not exceed min_n), otherwise ignored passed back to caller. Ignored if NULL @retval true if a batch was queued successfully. @retval false if another batch of same type was already running. */ -bool -buf_flush_do_batch( - buf_flush_t type, - ulint min_n, - lsn_t lsn_limit, - flush_counters_t* n); +bool buf_flush_do_batch(bool lru, ulint min_n, lsn_t lsn_limit, + flush_counters_t *n); /** This utility flushes dirty blocks from the end of the flush list. NOTE: The calling thread is not allowed to own any latches on pages! @@ -144,8 +134,8 @@ is not fast enough to keep pace with the workload. bool buf_flush_single_page_from_LRU(); /** Wait until a flush batch ends. -@param[in] type BUF_FLUSH_LRU or BUF_FLUSH_LIST */ -void buf_flush_wait_batch_end(buf_flush_t type); +@param[in] lru true=buf_pool.LRU; false=buf_pool.flush_list */ +void buf_flush_wait_batch_end(bool lru); /** Wait until a flush batch of the given lsn ends @param[in] new_oldest target oldest_modified_lsn to wait for */ void buf_flush_wait_flushed(lsn_t new_oldest); @@ -162,15 +152,6 @@ buf_flush_note_modification( set of mtr's */ lsn_t end_lsn); /*!< in: end lsn of the last mtr in the set of mtr's */ -/********************************************************************//** -Returns TRUE if the file page block is immediately suitable for replacement, -i.e., transition FILE_PAGE => NOT_USED allowed. -@return TRUE if can replace immediately */ -ibool -buf_flush_ready_for_replace( -/*========================*/ - buf_page_t* bpage); /*!< in: buffer control block, must be - buf_page_in_file(bpage) and in the LRU list */ /** Initialize page_cleaner. */ void buf_flush_page_cleaner_init(); @@ -178,10 +159,10 @@ void buf_flush_page_cleaner_init(); /** Wait for any possible LRU flushes to complete. */ void buf_flush_wait_LRU_batch_end(); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Validate the flush list. */ void buf_flush_validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ /********************************************************************//** Initialize the red-black tree to speed up insertions into the flush_list @@ -197,29 +178,16 @@ void buf_flush_free_flush_rbt(void); /*==========================*/ -/** Write a flushable page asynchronously from the buffer pool to a file. -NOTE: 1. in simulated aio we must call os_aio_simulated_wake_handler_threads -after we have posted a batch of writes! 2. buf_page_get_mutex(bpage) must be -held upon entering this function. The LRU list mutex must be held if flush_type -== BUF_FLUSH_SINGLE_PAGE. Both mutexes will be released by this function if it -returns true. -@param[in] bpage buffer control block -@param[in] flush_type type of flush -@param[in] sync true if sync IO request -@return whether the page was flushed */ -bool buf_flush_page(buf_page_t* bpage, buf_flush_t flush_type, bool sync); - -/** Check if the block is modified and ready for flushing. -@param[in] bpage buffer control block, must be buf_page_in_file() -@param[in] flush_type type of flush -@return true if can flush immediately */ -bool -buf_flush_ready_for_flush( -/*======================*/ - buf_page_t* bpage, /*!< in: buffer control block, must be - buf_page_in_file(bpage) */ - buf_flush_t flush_type)/*!< in: type of flush */ - MY_ATTRIBUTE((warn_unused_result)); +/** Write a flushable page from buf_pool to a file. +buf_pool.mutex must be held. +@param bpage buffer control block +@param flush_type type of flush +@param space tablespace (or nullptr if not known) +@param sync whether this is a synchronous request + (only for flush_type=SINGLE_PAGE) +@return whether the page was flushed and buf_pool.mutex was released */ +bool buf_flush_page(buf_page_t *bpage, IORequest::flush_t flush_type, + fil_space_t *space, bool sync); /** Synchronously flush dirty blocks. NOTE: The calling thread is not allowed to hold any buffer page latches! */ diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic index 4a3ecb57938..5f298c69e6d 100644 --- a/storage/innobase/include/buf0flu.ic +++ b/storage/innobase/include/buf0flu.ic @@ -52,11 +52,10 @@ buf_flush_note_modification( lsn_t end_lsn) /*!< in: end lsn of the mtr that modified this block */ { - mutex_enter(&block->mutex); ut_ad(!srv_read_only_mode - || fsp_is_system_temporary(block->page.id.space())); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(block->page.buf_fix_count > 0); + || fsp_is_system_temporary(block->page.id().space())); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.buf_fix_count()); ut_ad(mach_read_from_8(block->frame + FIL_PAGE_LSN) <= end_lsn); mach_write_to_8(block->frame + FIL_PAGE_LSN, end_lsn); if (UNIV_LIKELY_NULL(block->page.zip.data)) { @@ -64,13 +63,13 @@ buf_flush_note_modification( FIL_PAGE_LSN + block->frame, 8); } - if (block->page.oldest_modification == 0) { + const lsn_t oldest_modification = block->page.oldest_modification(); + + if (!oldest_modification) { buf_flush_insert_into_flush_list(block, start_lsn); } else { - ut_ad(block->page.oldest_modification <= start_lsn); + ut_ad(oldest_modification <= start_lsn); } - mutex_exit(&block->mutex); - srv_stats.buf_pool_write_requests.inc(); } diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 9ed42f4eed0..937cb427a47 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -34,10 +34,6 @@ Created 11/5/1995 Heikki Tuuri struct trx_t; struct fil_space_t; -/** @return whether less than 1/4 of the buffer pool is available */ -bool -buf_LRU_buf_pool_running_out(); - /*####################################################################### These are low-level functions #########################################################################*/ @@ -45,50 +41,30 @@ These are low-level functions /** Minimum LRU list length for which the LRU_old pointer is defined */ #define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */ -#ifdef BTR_CUR_HASH_ADAPT -struct dict_table_t; -/** Try to drop the adaptive hash index for a tablespace. -@param[in,out] table table -@return whether anything was dropped */ -bool buf_LRU_drop_page_hash_for_tablespace(dict_table_t* table) - MY_ATTRIBUTE((warn_unused_result,nonnull)); -#else -# define buf_LRU_drop_page_hash_for_tablespace(table) -#endif /* BTR_CUR_HASH_ADAPT */ - /** Empty the flush list for all pages belonging to a tablespace. @param[in] id tablespace identifier @param[in] flush whether to write the pages to files @param[in] first first page to be flushed or evicted */ void buf_LRU_flush_or_remove_pages(ulint id, bool flush, ulint first = 0); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /********************************************************************//** Insert a compressed block into buf_pool.zip_clean in the LRU order. */ void buf_LRU_insert_zip_clean( /*=====================*/ buf_page_t* bpage); /*!< in: pointer to the block in question */ -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG */ -/******************************************************************//** -Try to free a block. If bpage is a descriptor of a compressed-only -page, the descriptor object will be freed as well. - -NOTE: If this function returns true, it will temporarily -release buf_pool.mutex. Furthermore, the page frame will no longer be -accessible via bpage. - -The caller must hold buf_pool.mutex and must not hold any -buf_page_get_mutex() when calling this function. -@return true if freed, false otherwise. */ -bool -buf_LRU_free_page( -/*==============*/ - buf_page_t* bpage, /*!< in: block to be freed */ - bool zip) /*!< in: true if should remove also the - compressed page of an uncompressed page */ - MY_ATTRIBUTE((nonnull)); +/** Try to free a block. If bpage is a descriptor of a compressed-only +ROW_FORMAT=COMPRESSED page, the buf_page_t object will be freed as well. +The caller must hold buf_pool.mutex. +@param bpage block to be freed +@param zip whether to remove both copies of a ROW_FORMAT=COMPRESSED page +@retval true if freed and buf_pool.mutex may have been temporarily released +@retval false if the page was not freed */ +bool buf_LRU_free_page(buf_page_t *bpage, bool zip) + MY_ATTRIBUTE((nonnull)); /** Try to free a replaceable block. @param[in] scan_all true=scan the whole LRU list, @@ -103,6 +79,7 @@ buf_block_t* buf_LRU_get_free_only(); /** Get a free block from the buf_pool. The block is taken off the free list. If free list is empty, blocks are moved from the end of the LRU list to the free list. + This function is called from a user thread when it needs a clean block to read in a page. Note that we only ever get a block from the free list. Even when we flush a page or find a page in LRU scan @@ -122,8 +99,10 @@ we put it to free list to be used. * scan LRU list even if buf_pool.try_LRU_scan is not set * iteration > 1: * same as iteration 1 but sleep 10ms -@return the free control block, in state BUF_BLOCK_READY_FOR_USE */ -buf_block_t* buf_LRU_get_free_block() + +@param have_mutex whether buf_pool.mutex is already being held +@return the free control block, in state BUF_BLOCK_MEMORY */ +buf_block_t* buf_LRU_get_free_block(bool have_mutex) MY_ATTRIBUTE((malloc,warn_unused_result)); /** @return whether the unzip_LRU list should be used for evicting a victim @@ -142,7 +121,7 @@ void buf_LRU_add_block( /*==============*/ buf_page_t* bpage, /*!< in: control block */ - ibool old); /*!< in: TRUE if should be put to the old + bool old); /*!< in: true if should be put to the old blocks in the LRU list, else put to the start; if the LRU list is very short, added to the start regardless of this parameter */ @@ -154,10 +133,6 @@ buf_unzip_LRU_add_block( buf_block_t* block, /*!< in: control block */ ibool old); /*!< in: TRUE if should be put to the end of the list, else put to the start */ -/******************************************************************//** -Moves a block to the start of the LRU list. */ -void -buf_LRU_make_block_young(buf_page_t* bpage); /** Update buf_pool.LRU_old_ratio. @param[in] old_pct Reserve this percentage of @@ -174,25 +149,21 @@ void buf_LRU_stat_update(); /** Remove one page from LRU list and put it to free list. -@param[in,out] bpage block, must contain a file page and be in - a freeable state; there may or may not be a - hash index to the page -@param[in] old_page_id page number before bpage->id was invalidated */ -void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id) - MY_ATTRIBUTE((nonnull)); +@param bpage file page to be freed +@param id page identifier +@param hash_lock buf_pool.page_hash latch (will be released here) */ +void buf_LRU_free_one_page(buf_page_t *bpage, const page_id_t id, + page_hash_latch *hash_lock) + MY_ATTRIBUTE((nonnull)); -/** Adjust LRU hazard pointers if needed. -@param[in] bpage buffer page descriptor */ -void buf_LRU_adjust_hp(const buf_page_t* bpage); - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /** Validate the LRU list. */ void buf_LRU_validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#endif /* UNIV_DEBUG */ +#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG /** Dump the LRU list to stderr. */ void buf_LRU_print(); -#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ +#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG */ /** @name Heuristics for detecting index scan @{ */ /** The denominator of buf_pool.LRU_old_ratio. */ diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index 611fadae677..55bd2ac3a5a 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -44,16 +44,6 @@ struct buf_dblwr_t; /** A buffer frame. @see page_t */ typedef byte buf_frame_t; -/** Flags for flush types */ -enum buf_flush_t { - BUF_FLUSH_LRU = 0, /*!< flush via the LRU list */ - BUF_FLUSH_LIST, /*!< flush via the flush list - of dirty blocks */ - BUF_FLUSH_SINGLE_PAGE, /*!< flush via the LRU list - but only a single page */ - BUF_FLUSH_N_TYPES /*!< index of last element + 1 */ -}; - /** Flags for io_fix types */ enum buf_io_fix { BUF_IO_NONE = 0, /**< no pending I/O */ @@ -141,11 +131,30 @@ public: ut_ad(page_no <= 0xFFFFFFFFU); } - page_id_t(ulonglong id) : m_id(id) {} + page_id_t(uint64_t id) : m_id(id) {} bool operator==(const page_id_t& rhs) const { return m_id == rhs.m_id; } bool operator!=(const page_id_t& rhs) const { return m_id != rhs.m_id; } - bool operator<(const page_id_t& rhs) const { return m_id < rhs.m_id; } + bool operator>(const page_id_t& rhs) const { return m_id > rhs.m_id; } + bool operator<=(const page_id_t& rhs) const { return m_id <= rhs.m_id; } + bool operator>=(const page_id_t& rhs) const { return m_id >= rhs.m_id; } + page_id_t &operator--() { ut_ad(page_no()); m_id--; return *this; } + page_id_t &operator++() + { + ut_ad(page_no() < 0xFFFFFFFFU); + m_id++; + return *this; + } + page_id_t operator-(uint32_t i) const + { + ut_ad(page_no() >= i); + return page_id_t(m_id - i); + } + page_id_t operator+(uint32_t i) const + { + ut_ad(page_no() < ~i); + return page_id_t(m_id + i); + } /** Retrieve the tablespace id. @return tablespace id */ @@ -167,9 +176,6 @@ public: m_id= (m_id & ~uint64_t{0} << 32) | page_no; } - /** Set the FIL_NULL for the space and page_no */ - void set_corrupt_id() { m_id= ~uint64_t{0}; } - ulonglong raw() { return m_id; } private: /** The page identifier */ @@ -186,12 +192,43 @@ extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX]; #include "ut0mutex.h" #include "sync0rw.h" +#include "rw_lock.h" -typedef ib_bpmutex_t BPageMutex; typedef ib_mutex_t BufPoolMutex; typedef ib_mutex_t FlushListMutex; -typedef BPageMutex BufPoolZipMutex; typedef rw_lock_t BPageLock; + +class page_hash_latch : public rw_lock +{ +public: + /** Wait for a shared lock */ + void read_lock_wait(); + /** Wait for an exclusive lock */ + void write_lock_wait(); + + /** Acquire a shared lock */ + inline void read_lock(); + /** Acquire an exclusive lock */ + inline void write_lock(); + + /** Acquire a lock */ + template void acquire() + { + if (exclusive) + write_lock(); + else + read_lock(); + } + /** Release a lock */ + template void release() + { + if (exclusive) + write_unlock(); + else + read_unlock(); + } +}; + #endif /* !UNIV_INNOCHECKSUM */ #endif /* buf0types.h */ diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index 857ffc15d76..2d1bf5a2d50 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -51,10 +51,6 @@ dfield_set_len( ulint len) /*!< in: length or UNIV_SQL_NULL */ { ut_ad(len != UNIV_SQL_DEFAULT); -#ifdef UNIV_VALGRIND_DEBUG - if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(field->data, len); -#endif /* UNIV_VALGRIND_DEBUG */ - field->ext = 0; field->len = static_cast(len); } @@ -94,9 +90,6 @@ dfield_set_data( const void* data, /*!< in: data */ ulint len) /*!< in: length or UNIV_SQL_NULL */ { -#ifdef UNIV_VALGRIND_DEBUG - if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len); -#endif /* UNIV_VALGRIND_DEBUG */ field->data = (void*) data; field->ext = 0; field->len = static_cast(len); @@ -111,9 +104,7 @@ dfield_write_mbr( dfield_t* field, /*!< in: field */ const double* mbr) /*!< in: data */ { -#ifdef UNIV_VALGRIND_DEBUG - if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len); -#endif /* UNIV_VALGRIND_DEBUG */ + MEM_CHECK_DEFINED(mbr, sizeof *mbr); field->ext = 0; for (unsigned i = 0; i < SPDIMS * 2; i++) { @@ -175,7 +166,7 @@ dfield_dup( mem_heap_t* heap) /*!< in: memory heap where allocated */ { if (!dfield_is_null(field)) { - UNIV_MEM_ASSERT_RW(field->data, field->len); + MEM_CHECK_DEFINED(field->data, field->len); field->data = mem_heap_dup(heap, field->data, field->len); } } @@ -333,8 +324,9 @@ dtuple_create_from_mem( } } #endif - UNIV_MEM_ASSERT_W(tuple->fields, n_t_fields * sizeof *tuple->fields); - UNIV_MEM_INVALID(tuple->fields, n_t_fields * sizeof *tuple->fields); + MEM_CHECK_ADDRESSABLE(tuple->fields, n_t_fields + * sizeof *tuple->fields); + MEM_UNDEFINED(tuple->fields, n_t_fields * sizeof *tuple->fields); return(tuple); } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 867c0c215f3..2a153f448e9 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1197,7 +1197,7 @@ dict_index_get_if_in_cache_low( /*===========================*/ index_id_t index_id) /*!< in: index id */ MY_ATTRIBUTE((warn_unused_result)); -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG +#ifdef UNIV_DEBUG /**********************************************************************//** Returns an index object if it is found in the dictionary cache. @return index, NULL if not found */ @@ -1206,8 +1206,6 @@ dict_index_get_if_in_cache( /*=======================*/ index_id_t index_id) /*!< in: index id */ MY_ATTRIBUTE((warn_unused_result)); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_DEBUG /**********************************************************************//** Checks that a tuple has n_fields_cmp value in a sensible range, so that no comparison can occur with the page number field in a node pointer. @@ -1434,10 +1432,10 @@ public: header and flushed to a file; in recovery this must be derived from the log records */ - hash_table_t* table_hash; /*!< hash table of the tables, based + hash_table_t table_hash; /*!< hash table of the tables, based on name */ /** hash table of persistent table IDs */ - hash_table_t* table_id_hash; + hash_table_t table_id_hash; dict_table_t* sys_tables; /*!< SYS_TABLES table */ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ @@ -1456,7 +1454,7 @@ private: /** the sequence of temporary table IDs */ std::atomic temp_table_id; /** hash table of temporary table IDs */ - hash_table_t* temp_id_hash; + hash_table_t temp_id_hash; public: /** @return a new temporary table ID */ table_id_t get_temporary_table_id() { @@ -1473,7 +1471,7 @@ public: ut_ad(mutex_own(&mutex)); dict_table_t* table; ulint fold = ut_fold_ull(id); - HASH_SEARCH(id_hash, temp_id_hash, fold, dict_table_t*, table, + HASH_SEARCH(id_hash, &temp_id_hash, fold, dict_table_t*, table, ut_ad(table->cached), table->id == id); if (UNIV_LIKELY(table != NULL)) { DBUG_ASSERT(table->is_temporary()); @@ -1492,7 +1490,8 @@ public: ut_ad(mutex_own(&mutex)); dict_table_t* table; ulint fold = ut_fold_ull(id); - HASH_SEARCH(id_hash, table_id_hash, fold, dict_table_t*, table, + HASH_SEARCH(id_hash, &table_id_hash, fold, dict_table_t*, + table, ut_ad(table->cached), table->id == id); DBUG_ASSERT(!table || !table->is_temporary()); return table; @@ -1594,8 +1593,8 @@ public: + (sizeof(dict_col_t) + sizeof(dict_field_t)) * 10 + sizeof(dict_field_t) * 5 /* total number of key fields */ + 200; /* arbitrary, covering names and overhead */ - size += (table_hash->n_cells + table_id_hash->n_cells - + temp_id_hash->n_cells) * sizeof(hash_cell_t); + size += (table_hash.n_cells + table_id_hash.n_cells + + temp_id_hash.n_cells) * sizeof(hash_cell_t); return size; } }; diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index e3b3ffbeb91..694c7081574 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -579,101 +579,103 @@ private: static const unsigned DROPPED = 1023; public: - /** Detach the column from an index. - @param[in] index index to be detached from */ - inline void detach(const dict_index_t& index); + /** Detach a virtual column from an index. + @param index being-freed index */ + inline void detach(const dict_index_t &index); - /** Data for instantly added columns */ - struct def_t { - /** original default value of instantly added column */ - const void* data; - /** len of data, or UNIV_SQL_DEFAULT if unavailable */ - ulint len; - } def_val; + /** Data for instantly added columns */ + struct def_t + { + /** original default value of instantly added column */ + const void *data; + /** len of data, or UNIV_SQL_DEFAULT if unavailable */ + ulint len; + } def_val; - /** Retrieve the column name. - @param[in] table the table of this column */ - const char* name(const dict_table_t& table) const; + /** Retrieve the column name. + @param table the table of this column */ + const char *name(const dict_table_t &table) const; - /** @return whether this is a virtual column */ - bool is_virtual() const { return prtype & DATA_VIRTUAL; } - /** @return whether NULL is an allowed value for this column */ - bool is_nullable() const { return !(prtype & DATA_NOT_NULL); } + /** @return whether this is a virtual column */ + bool is_virtual() const { return prtype & DATA_VIRTUAL; } + /** @return whether NULL is an allowed value for this column */ + bool is_nullable() const { return !(prtype & DATA_NOT_NULL); } - /** @return whether table of this system field is TRX_ID-based */ - bool vers_native() const - { - ut_ad(vers_sys_start() || vers_sys_end()); - ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY); - return mtype == DATA_INT; - } - /** @return whether this user column (not row_start, row_end) - has System Versioning property */ - bool is_versioned() const { return !(~prtype & DATA_VERSIONED); } - /** @return whether this is the system version start */ - bool vers_sys_start() const - { - return (prtype & DATA_VERSIONED) == DATA_VERS_START; - } - /** @return whether this is the system version end */ - bool vers_sys_end() const - { - return (prtype & DATA_VERSIONED) == DATA_VERS_END; - } + /** @return whether table of this system field is TRX_ID-based */ + bool vers_native() const + { + ut_ad(vers_sys_start() || vers_sys_end()); + ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY); + return mtype == DATA_INT; + } + /** @return whether this user column (not row_start, row_end) + has System Versioning property */ + bool is_versioned() const { return !(~prtype & DATA_VERSIONED); } + /** @return whether this is the system version start */ + bool vers_sys_start() const + { + return (prtype & DATA_VERSIONED) == DATA_VERS_START; + } + /** @return whether this is the system version end */ + bool vers_sys_end() const + { + return (prtype & DATA_VERSIONED) == DATA_VERS_END; + } - /** @return whether this is an instantly-added column */ - bool is_added() const - { - DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data); - return def_val.len != UNIV_SQL_DEFAULT; - } - /** Flag the column instantly dropped */ - void set_dropped() { ind = DROPPED; } - /** Flag the column instantly dropped. - @param[in] not_null whether the column was NOT NULL - @param[in] len2 whether the length exceeds 255 bytes - @param[in] fixed_len the fixed length in bytes, or 0 */ - void set_dropped(bool not_null, bool len2, unsigned fixed) - { - DBUG_ASSERT(!len2 || !fixed); - prtype = not_null - ? DATA_NOT_NULL | DATA_BINARY_TYPE - : DATA_BINARY_TYPE; - if (fixed) { - mtype = DATA_FIXBINARY; - len = static_cast(fixed); - } else { - mtype = DATA_BINARY; - len = len2 ? 65535 : 255; - } - mbminlen = mbmaxlen = 0; - ind = DROPPED; - ord_part = 0; - max_prefix = 0; - } - /** @return whether the column was instantly dropped */ - bool is_dropped() const { return ind == DROPPED; } - /** @return whether the column was instantly dropped - @param[in] index the clustered index */ - inline bool is_dropped(const dict_index_t& index) const; + /** @return whether this is an instantly-added column */ + bool is_added() const + { + DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data); + return def_val.len != UNIV_SQL_DEFAULT; + } + /** Flag the column instantly dropped */ + void set_dropped() { ind = DROPPED; } + /** Flag the column instantly dropped. + @param not_null whether the column was NOT NULL + @param len2 whether the length exceeds 255 bytes + @param fixed_len the fixed length in bytes, or 0 */ + void set_dropped(bool not_null, bool len2, unsigned fixed) + { + DBUG_ASSERT(!len2 || !fixed); + prtype= not_null ? DATA_NOT_NULL | DATA_BINARY_TYPE : DATA_BINARY_TYPE; + if (fixed) + { + mtype= DATA_FIXBINARY; + len= static_cast(fixed); + } + else + { + mtype= DATA_BINARY; + len= len2 ? 65535 : 255; + } + mbminlen= mbmaxlen= 0; + ind= DROPPED; + ord_part= 0; + max_prefix= 0; + } + /** @return whether the column was instantly dropped */ + bool is_dropped() const { return ind == DROPPED; } + /** @return whether the column was instantly dropped + @param index the clustered index */ + inline bool is_dropped(const dict_index_t &index) const; - /** Get the default value of an instantly-added column. - @param[out] len value length (in bytes), or UNIV_SQL_NULL - @return default value - @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ - const byte* instant_value(ulint* len) const - { - DBUG_ASSERT(is_added()); - *len = def_val.len; - return static_cast(def_val.data); - } + /** Get the default value of an instantly-added column. + @param[out] len value length (in bytes), or UNIV_SQL_NULL + @return default value + @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ + const byte *instant_value(ulint *len) const + { + DBUG_ASSERT(is_added()); + *len= def_val.len; + return static_cast(def_val.data); + } - /** Remove the 'instant ADD' status of the column */ - void clear_instant() - { - def_val.len = UNIV_SQL_DEFAULT; - def_val.data = NULL; - } + /** Remove the 'instant ADD' status of the column */ + void clear_instant() + { + def_val.len= UNIV_SQL_DEFAULT; + def_val.data= NULL; + } /** @return whether two columns have compatible data type encoding */ bool same_type(const dict_col_t &other) const @@ -719,24 +721,21 @@ public: /** @return whether two collations codes have the same character encoding */ static bool same_encoding(uint16_t a, uint16_t b); - /** Determine if the columns have the same format - except for is_nullable() and is_versioned(). - @param[in] other column to compare to - @return whether the columns have the same format */ - bool same_format(const dict_col_t& other) const - { - return same_type(other) - && len >= other.len - && mbminlen == other.mbminlen - && mbmaxlen == other.mbmaxlen - && !((prtype ^ other.prtype) - & ~(DATA_NOT_NULL | DATA_VERSIONED - | CHAR_COLL_MASK << 16 - | DATA_LONG_TRUE_VARCHAR)); - } + /** Determine if the columns have the same format + except for is_nullable() and is_versioned(). + @param other column to compare to + @return whether the columns have the same format */ + bool same_format(const dict_col_t &other) const + { + return same_type(other) && len >= other.len && + mbminlen == other.mbminlen && mbmaxlen == other.mbmaxlen && + !((prtype ^ other.prtype) & ~(DATA_NOT_NULL | DATA_VERSIONED | + CHAR_COLL_MASK << 16 | + DATA_LONG_TRUE_VARCHAR)); + } /** @return whether the column values are comparable by memcmp() */ - inline bool is_binary() const { return prtype & DATA_BINARY_TYPE; } + bool is_binary() const { return prtype & DATA_BINARY_TYPE; } }; /** Index information put in a list of virtual column structure. Index @@ -774,27 +773,30 @@ struct dict_v_col_t{ std::forward_list > v_indexes; - /** Detach the column from an index. - @param[in] index index to be detached from */ - void detach(const dict_index_t& index) - { - if (!n_v_indexes) return; - auto i = v_indexes.before_begin(); - ut_d(unsigned n = 0); - do { - auto prev = i++; - if (i == v_indexes.end()) { - ut_ad(n == n_v_indexes); - return; - } - ut_ad(++n <= n_v_indexes); - if (i->index == &index) { - v_indexes.erase_after(prev); - n_v_indexes--; - return; - } - } while (i != v_indexes.end()); - } + /** Detach the column from an index. + @param index index to be detached from */ + void detach(const dict_index_t &index) + { + if (!n_v_indexes) return; + auto i= v_indexes.before_begin(); + ut_d(unsigned n= 0); + do { + auto prev = i++; + if (i == v_indexes.end()) + { + ut_ad(n == n_v_indexes); + return; + } + ut_ad(++n <= n_v_indexes); + if (i->index == &index) + { + v_indexes.erase_after(prev); + n_v_indexes--; + return; + } + } + while (i != v_indexes.end()); + } }; /** Data structure for newly added virtual column in a table */ @@ -932,7 +934,7 @@ an uncompressed page should be left as padding to avoid compression failures. This estimate is based on a self-adapting heuristic. */ struct zip_pad_info_t { SysMutex mutex; /*!< mutex protecting the info */ - Atomic_counter + Atomic_relaxed pad; /*!< number of bytes used as pad */ ulint success;/*!< successful compression ops during current round */ @@ -960,7 +962,10 @@ struct dict_index_t { mem_heap_t* heap; /*!< memory heap */ id_name_t name; /*!< index name */ dict_table_t* table; /*!< back pointer to table */ - unsigned page:32;/*!< index tree root page number */ + /** root page number, or FIL_NULL if the index has been detached + from storage (DISCARD TABLESPACE or similar), + or 1 if the index is in table->freed_indexes */ + unsigned page:32; unsigned merge_threshold:6; /*!< In the pessimistic delete, if the page data size drops below this limit in percent, @@ -1105,19 +1110,11 @@ struct dict_index_t { /* @} */ private: /** R-tree split sequence number */ - std::atomic rtr_ssn; + Atomic_relaxed rtr_ssn; public: - - void set_ssn(node_seq_t ssn) - { - rtr_ssn.store(ssn, std::memory_order_relaxed); - } - node_seq_t assign_ssn() - { - node_seq_t ssn= rtr_ssn.fetch_add(1, std::memory_order_relaxed); - return ssn + 1; - } - node_seq_t ssn() const { return rtr_ssn.load(std::memory_order_relaxed); } + void set_ssn(node_seq_t ssn) { rtr_ssn= ssn; } + node_seq_t assign_ssn() { return rtr_ssn.fetch_add(1) + 1; } + node_seq_t ssn() const { return rtr_ssn; } rtr_info_track_t* rtr_track;/*!< tracking all R-Tree search cursors */ @@ -1209,17 +1206,22 @@ public: /** @return whether the index is corrupted */ inline bool is_corrupted() const; - /** Detach the columns from the index that is to be freed. */ - void detach_columns() - { - if (has_virtual()) { - for (unsigned i = 0; i < n_fields; i++) { - fields[i].col->detach(*this); - } - - n_fields = 0; - } - } + /** Detach the virtual columns from the index that is to be removed. + @param whether to reset fields[].col */ + void detach_columns(bool clear= false) + { + if (!has_virtual() || !cached) + return; + for (unsigned i= 0; i < n_fields; i++) + { + dict_col_t* col= fields[i].col; + if (!col || !col->is_virtual()) + continue; + col->detach(*this); + if (clear) + fields[i].col= nullptr; + } + } /** Determine how many fields of a given prefix can be set NULL. @param[in] n_prefix number of fields in the prefix @@ -1280,15 +1282,39 @@ public: bool vers_history_row(const rec_t* rec, bool &history_row); - /** Reconstruct the clustered index fields. */ - inline void reconstruct_fields(); + /** Reconstruct the clustered index fields. */ + inline void reconstruct_fields(); - /** Check if the index contains a column or a prefix of that column. - @param[in] n column number - @param[in] is_virtual whether it is a virtual col - @return whether the index contains the column or its prefix */ - bool contains_col_or_prefix(ulint n, bool is_virtual) const - MY_ATTRIBUTE((warn_unused_result)); + /** Check if the index contains a column or a prefix of that column. + @param[in] n column number + @param[in] is_virtual whether it is a virtual col + @return whether the index contains the column or its prefix */ + bool contains_col_or_prefix(ulint n, bool is_virtual) const + MY_ATTRIBUTE((warn_unused_result)); + +#ifdef BTR_CUR_HASH_ADAPT + /** @return a clone of this */ + dict_index_t* clone() const; + /** Clone this index for lazy dropping of the adaptive hash index. + @return this or a clone */ + dict_index_t* clone_if_needed(); + /** @return number of leaf pages pointed to by the adaptive hash index */ + inline ulint n_ahi_pages() const; + /** @return whether mark_freed() had been invoked */ + bool freed() const { return UNIV_UNLIKELY(page == 1); } + /** Note that the index is waiting for btr_search_lazy_free() */ + void set_freed() { ut_ad(!freed()); page= 1; } +#endif /* BTR_CUR_HASH_ADAPT */ + + /** @return whether it is forbidden to invoke clear_instant_add() */ + bool must_avoid_clear_instant_add() const + { + if (is_instant()) + for (auto i= this; (i= UT_LIST_GET_NEXT(indexes, i)) != nullptr; ) + if (i->to_be_dropped /* || i->online_log*/) + return true; + return false; + } /** This ad-hoc class is used by record_size_info only. */ class record_size_info_t { @@ -1351,13 +1377,12 @@ public: inline record_size_info_t record_size_info() const; }; -/** Detach a column from an index. -@param[in] index index to be detached from */ -inline void dict_col_t::detach(const dict_index_t& index) +/** Detach a virtual column from an index. +@param index being-freed index */ +inline void dict_col_t::detach(const dict_index_t &index) { - if (is_virtual()) { - reinterpret_cast(this)->detach(index); - } + if (is_virtual()) + reinterpret_cast(this)->detach(index); } /** The status of online index creation */ @@ -2062,6 +2087,11 @@ public: /** List of indexes of the table. */ UT_LIST_BASE_NODE_T(dict_index_t) indexes; +#ifdef BTR_CUR_HASH_ADAPT + /** List of detached indexes that are waiting to be freed along with + the last adaptive hash index entry */ + UT_LIST_BASE_NODE_T(dict_index_t) freed_indexes; +#endif /* BTR_CUR_HASH_ADAPT */ /** List of foreign key constraints in the table. These refer to columns in other tables. */ diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic index ff645378175..2fcadc055e1 100644 --- a/storage/innobase/include/dict0priv.ic +++ b/storage/innobase/include/dict0priv.ic @@ -84,7 +84,7 @@ dict_table_check_if_in_cache_low( /* Look for the table name in the hash table */ table_fold = ut_fold_string(table_name); - HASH_SEARCH(name_hash, dict_sys.table_hash, table_fold, + HASH_SEARCH(name_hash, &dict_sys.table_hash, table_fold, dict_table_t*, table, ut_ad(table->cached), !strcmp(table->name.m_name, table_name)); DBUG_RETURN(table); diff --git a/storage/innobase/include/dict0stats.ic b/storage/innobase/include/dict0stats.ic index 3c24e7a8fc3..dbdbceab9ba 100644 --- a/storage/innobase/include/dict0stats.ic +++ b/storage/innobase/include/dict0stats.ic @@ -187,41 +187,40 @@ dict_stats_deinit( table->stat_initialized = FALSE; -#ifdef UNIV_DEBUG_VALGRIND - UNIV_MEM_INVALID(&table->stat_n_rows, - sizeof(table->stat_n_rows)); - UNIV_MEM_INVALID(&table->stat_clustered_index_size, - sizeof(table->stat_clustered_index_size)); - UNIV_MEM_INVALID(&table->stat_sum_of_other_index_sizes, - sizeof(table->stat_sum_of_other_index_sizes)); - UNIV_MEM_INVALID(&table->stat_modified_counter, - sizeof(table->stat_modified_counter)); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&table->stat_n_rows, sizeof table->stat_n_rows); + MEM_UNDEFINED(&table->stat_clustered_index_size, + sizeof table->stat_clustered_index_size); + MEM_UNDEFINED(&table->stat_sum_of_other_index_sizes, + sizeof table->stat_sum_of_other_index_sizes); + MEM_UNDEFINED(&table->stat_modified_counter, + sizeof table->stat_modified_counter); dict_index_t* index; for (index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { - UNIV_MEM_INVALID( + MEM_UNDEFINED( index->stat_n_diff_key_vals, index->n_uniq - * sizeof(index->stat_n_diff_key_vals[0])); - UNIV_MEM_INVALID( + * sizeof index->stat_n_diff_key_vals[0]); + MEM_UNDEFINED( index->stat_n_sample_sizes, index->n_uniq - * sizeof(index->stat_n_sample_sizes[0])); - UNIV_MEM_INVALID( + * sizeof index->stat_n_sample_sizes[0]); + MEM_UNDEFINED( index->stat_n_non_null_key_vals, index->n_uniq - * sizeof(index->stat_n_non_null_key_vals[0])); - UNIV_MEM_INVALID( + * sizeof index->stat_n_non_null_key_vals[0]); + MEM_UNDEFINED( &index->stat_index_size, sizeof(index->stat_index_size)); - UNIV_MEM_INVALID( + MEM_UNDEFINED( &index->stat_n_leaf_pages, sizeof(index->stat_n_leaf_pages)); } -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ rw_lock_x_unlock(&table->stats_latch); } diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index ffe9b5d21dc..e89733fc9ed 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -29,7 +29,7 @@ Created 2013-03-16 Sunny Bains #include "mem0mem.h" #include "dyn0types.h" -#include "intrusive_list.h" +#include "ilist.h" /** Class that manages dynamic buffers. It uses a UT_LIST of @@ -43,9 +43,9 @@ class mtr_buf_t { public: /** SIZE - sizeof(m_node) + sizeof(m_used) */ enum { MAX_DATA_SIZE = DYN_ARRAY_DATA_SIZE - - sizeof(intrusive::list_node<>) + sizeof(uint32_t) }; + - sizeof(ilist_node<>) + sizeof(uint32_t) }; - class block_t : public intrusive::list_node<> { + class block_t : public ilist_node<> { public: block_t() @@ -160,7 +160,7 @@ public: friend class mtr_buf_t; }; - typedef intrusive::list list_t; + typedef sized_ilist list_t; /** Default constructor */ mtr_buf_t() diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 858abaab368..6bc150184ef 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -36,16 +36,62 @@ Created 10/25/1995 Heikki Tuuri #include "hash0hash.h" #include "log0recv.h" #include "dict0types.h" -#include "intrusive_list.h" -#ifdef UNIV_LINUX -# include -#endif +#include "ilist.h" +#include +#include struct unflushed_spaces_tag_t; struct rotation_list_tag_t; // Forward declaration extern my_bool srv_use_doublewrite_buf; + +/** Possible values of innodb_flush_method */ +enum srv_flush_t +{ + /** fsync, the default */ + SRV_FSYNC= 0, + /** open log files in O_DSYNC mode */ + SRV_O_DSYNC, + /** do not call os_file_flush() when writing data files, but do flush + after writing to log files */ + SRV_LITTLESYNC, + /** do not flush after writing */ + SRV_NOSYNC, + /** invoke os_file_set_nocache() on data files. This implies using + non-buffered IO but still using fsync, the reason for which is that + some FS do not flush meta-data when unbuffered IO happens */ + SRV_O_DIRECT, + /** do not use fsync() when using direct IO i.e.: it can be set to + avoid the fsync() call that we make when using SRV_UNIX_O_DIRECT. + However, in this case user/DBA should be sure about the integrity of + the meta-data */ + SRV_O_DIRECT_NO_FSYNC +#ifdef _WIN32 + /** Traditional Windows appoach to open all files without caching, + and do FileFlushBuffers() */ + ,SRV_ALL_O_DIRECT_FSYNC +#endif +}; + +/** innodb_flush_method */ +extern ulong srv_file_flush_method; + +/** Undo tablespaces starts with space_id. */ +extern ulint srv_undo_space_id_start; +/** The number of UNDO tablespaces that are open and ready to use. */ +extern ulint srv_undo_tablespaces_open; + +/** Check whether given space id is undo tablespace id +@param[in] space_id space id to check +@return true if it is undo tablespace else false. */ +inline bool srv_is_undo_tablespace(ulint space_id) +{ + return srv_undo_space_id_start > 0 && + space_id >= srv_undo_space_id_start && + space_id < srv_undo_space_id_start + srv_undo_tablespaces_open; +} + extern struct buf_dblwr_t* buf_dblwr; class page_id_t; @@ -64,12 +110,181 @@ enum fil_type_t { struct fil_node_t; +/** Structure to store first and last value of range */ +struct range_t +{ + uint32_t first; + uint32_t last; +}; + +/** Sort the range based on first value of the range */ +struct range_compare +{ + bool operator() (const range_t lhs, const range_t rhs) const + { + return lhs.first < rhs.first; + } +}; + +using range_set_t= std::set; +/** Range to store the set of ranges of integers */ +class range_set +{ +private: + range_set_t ranges; +public: + /** Merge the current range with previous range. + @param[in] range range to be merged + @param[in] prev_range range to be merged with next */ + void merge_range(range_set_t::iterator range, + range_set_t::iterator prev_range) + { + if (range->first != prev_range->last + 1) + return; + + /* Merge the current range with previous range */ + range_t new_range {prev_range->first, range->last}; + ranges.erase(prev_range); + ranges.erase(range); + ranges.emplace(new_range); + } + + /** Split the range and add two more ranges + @param[in] range range to be split + @param[in] value Value to be removed from range */ + void split_range(range_set_t::iterator range, uint32_t value) + { + range_t split1{range->first, value - 1}; + range_t split2{value + 1, range->last}; + + /* Remove the existing element */ + ranges.erase(range); + + /* Insert the two elements */ + ranges.emplace(split1); + ranges.emplace(split2); + } + + /** Remove the value with the given range + @param[in,out] range range to be changed + @param[in] value value to be removed */ + void remove_within_range(range_set_t::iterator range, uint32_t value) + { + range_t new_range{range->first, range->last}; + if (value == range->first) + { + if (range->first == range->last) + { + ranges.erase(range); + return; + } + else + new_range.first++; + } + else if (value == range->last) + new_range.last--; + else if (range->first < value && range->last > value) + return split_range(range, value); + + ranges.erase(range); + ranges.emplace(new_range); + } + + /** Remove the value from the ranges. + @param[in] value Value to be removed. */ + void remove_value(uint32_t value) + { + if (ranges.empty()) + return; + range_t new_range {value, value}; + range_set_t::iterator range= ranges.lower_bound(new_range); + if (range == ranges.end()) + return remove_within_range(std::prev(range), value); + + if (range->first > value && range != ranges.begin()) + /* Iterate the previous ranges to delete */ + return remove_within_range(std::prev(range), value); + return remove_within_range(range, value); + } + /** Add the value within the existing range + @param[in] range range to be modified + @param[in] value value to be added */ + range_set_t::iterator add_within_range(range_set_t::iterator range, + uint32_t value) + { + if (range->first <= value && range->last >= value) + return range; + + range_t new_range{range->first, range->last}; + if (range->last + 1 == value) + new_range.last++; + else if (range->first - 1 == value) + new_range.first--; + else return ranges.end(); + ranges.erase(range); + return ranges.emplace(new_range).first; + } + /** Add the range in the ranges set + @param[in] new_range range to be added */ + void add_range(range_t new_range) + { + auto r_offset= ranges.lower_bound(new_range); + auto r_begin= ranges.begin(); + auto r_end= ranges.end(); + if (!ranges.size()) + { +new_range: + ranges.emplace(new_range); + return; + } + + if (r_offset == r_end) + { + /* last range */ + if (add_within_range(std::prev(r_offset), new_range.first) == r_end) + goto new_range; + } + else if (r_offset == r_begin) + { + /* First range */ + if (add_within_range(r_offset, new_range.first) == r_end) + goto new_range; + } + else if (r_offset->first - 1 == new_range.first) + { + /* Change starting of the existing range */ + auto r_value= add_within_range(r_offset, new_range.first); + if (r_value != ranges.begin()) + merge_range(r_value, std::prev(r_value)); + } + else + { + /* previous range last_value alone */ + if (add_within_range(std::prev(r_offset), new_range.first) == r_end) + goto new_range; + } + } + + /** Add the value in the ranges + @param[in] value value to be added */ + void add_value(uint32_t value) + { + range_t new_range{value, value}; + add_range(new_range); + } + + ulint size() { return ranges.size(); } + void clear() { ranges.clear(); } + bool empty() const { return ranges.empty(); } + typename range_set_t::iterator begin() { return ranges.begin(); } + typename range_set_t::iterator end() { return ranges.end(); } +}; #endif /** Tablespace or log data space */ #ifndef UNIV_INNOCHECKSUM -struct fil_space_t : intrusive::list_node, - intrusive::list_node +struct fil_space_t : ilist_node, + ilist_node #else struct fil_space_t #endif @@ -137,18 +352,18 @@ struct fil_space_t UT_LIST_NODE_T(fil_space_t) named_spaces; /*!< list of spaces for which FILE_MODIFY records have been issued */ - /** Checks that this tablespace in a list of unflushed tablespaces. - @return true if in a list */ - bool is_in_unflushed_spaces() const; UT_LIST_NODE_T(fil_space_t) space_list; /*!< list of all spaces */ - /** Checks that this tablespace needs key rotation. - @return true if in a rotation list */ - bool is_in_rotation_list() const; /** MariaDB encryption data */ fil_space_crypt_t* crypt_data; + /** Checks that this tablespace in a list of unflushed tablespaces. */ + bool is_in_unflushed_spaces; + + /** Checks that this tablespace needs key rotation. */ + bool is_in_rotation_list; + /** True if the device this filespace is on supports atomic writes */ bool atomic_write_supported; @@ -156,6 +371,16 @@ struct fil_space_t punch hole */ bool punch_hole; + /** mutex to protect freed ranges */ + std::mutex freed_range_mutex; + + /** Variables to store freed ranges. This can be used to write + zeroes/punch the hole in files. Protected by freed_mutex */ + range_set freed_ranges; + + /** Stores last page freed lsn. Protected by freed_mutex */ + lsn_t last_freed_lsn; + ulint magic_n;/*!< FIL_SPACE_MAGIC_N */ /** @return whether the tablespace is about to be dropped */ @@ -249,6 +474,41 @@ struct fil_space_t void release_for_io() { ut_ad(pending_io()); n_pending_ios--; } /** @return whether I/O is pending */ bool pending_io() const { return n_pending_ios; } + + /** @return whether the tablespace file can be closed and reopened */ + bool belongs_in_lru() const + { + switch (purpose) { + case FIL_TYPE_TEMPORARY: + ut_ad(id == SRV_TMP_SPACE_ID); + return false; + case FIL_TYPE_IMPORT: + ut_ad(id != SRV_TMP_SPACE_ID); + return true; + case FIL_TYPE_TABLESPACE: + ut_ad(id != SRV_TMP_SPACE_ID); + return id && !srv_is_undo_tablespace(id); + } + ut_ad(0); + return false; + } + + /** @return last_freed_lsn */ + lsn_t get_last_freed_lsn() { return last_freed_lsn; } + /** Update last_freed_lsn */ + void update_last_freed_lsn(lsn_t lsn) + { + std::lock_guard freed_lock(freed_range_mutex); + last_freed_lsn= lsn; + } + + /** Clear all freed ranges for undo tablespace when InnoDB + encounters TRIM redo log record */ + void clear_freed_ranges() + { + std::lock_guard freed_lock(freed_range_mutex); + freed_ranges.clear(); + } #endif /* !UNIV_INNOCHECKSUM */ /** FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; check fsp0types.h to more info about flags. */ @@ -518,6 +778,38 @@ struct fil_space_t return(ssize == 0 || !is_ibd || srv_page_size != UNIV_PAGE_SIZE_ORIG); } + +#ifndef UNIV_INNOCHECKSUM + /** Add/remove the free page in the freed ranges list. + @param[in] offset page number to be added + @param[in] free true if page to be freed */ + void free_page(uint32_t offset, bool add=true) + { + std::lock_guard freed_lock(freed_range_mutex); + if (add) + return freed_ranges.add_value(offset); + + if (freed_ranges.empty()) + return; + + return freed_ranges.remove_value(offset); + } + + /** Add the range of freed pages */ + void add_free_ranges(range_set ranges) + { + std::lock_guard freed_lock(freed_range_mutex); + freed_ranges= std::move(ranges); + } + + /** Add the set of freed page ranges */ + void add_free_range(const range_t range) + { + std::lock_guard freed_lock(freed_range_mutex); + freed_ranges.add_range(range); + } +#endif /*!UNIV_INNOCHECKSUM */ + }; #ifndef UNIV_INNOCHECKSUM @@ -586,8 +878,21 @@ struct fil_node_t { #endif ); - /** Close the file handle. */ - void close(); + /** Close the file handle. */ + void close(); + /** Same as close() but returns file handle instead of closing it. */ + pfs_os_file_t detach() MY_ATTRIBUTE((warn_unused_result)); + /** Prepare to free a file from fil_system. + @param detach_handle whether to detach instead of closing a handle + @return detached handle or OS_FILE_CLOSED */ + pfs_os_file_t close_to_free(bool detach_handle= false); + + /** Update the data structures on I/O completion */ + inline void complete_io(bool write= false); + +private: + /** Does stuff common for close() and detach() */ + void prepare_to_close_or_detach(); }; /** Value of fil_node_t::magic_n */ @@ -903,12 +1208,18 @@ public: } #endif public: + /** Detach a tablespace from the cache and close the files. + @param space tablespace + @param detach_handle whether to detach or close handles + @return detached handles or empty vector */ + std::vector detach(fil_space_t *space, + bool detach_handle= false); + ib_mutex_t mutex; /*!< The mutex protecting the cache */ fil_space_t* sys_space; /*!< The innodb_system tablespace */ fil_space_t* temp_space; /*!< The innodb_temporary tablespace */ - hash_table_t* spaces; /*!< The hash table of spaces in the - system; they are hashed on the space - id */ + /** Map of fil_space_t::id to fil_space_t* */ + hash_table_t spaces; UT_LIST_BASE_NODE_T(fil_node_t) LRU; /*!< base node for the LRU list of the most recently used open files with no @@ -920,7 +1231,7 @@ public: not put to this list: they are opened after the startup, and kept open until shutdown */ - intrusive::list unflushed_spaces; + sized_ilist unflushed_spaces; /*!< list of those tablespaces whose files contain unflushed writes; those spaces have @@ -941,7 +1252,7 @@ public: record has been written since the latest redo log checkpoint. Protected only by log_sys.mutex. */ - intrusive::list rotation_list; + ilist rotation_list; /*!< list of all file spaces needing key rotation.*/ @@ -979,6 +1290,41 @@ public: /** The tablespace memory cache. */ extern fil_system_t fil_system; +/** Update the data structures on I/O completion */ +inline void fil_node_t::complete_io(bool write) +{ + ut_ad(mutex_own(&fil_system.mutex)); + + if (write) + { + if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) + { + /* We don't need to keep track of unflushed changes as user has + explicitly disabled buffering. */ + ut_ad(!space->is_in_unflushed_spaces); + ut_ad(!needs_flush); + } + else if (!space->is_stopping()) + { + needs_flush= true; + if (!space->is_in_unflushed_spaces) + { + space->is_in_unflushed_spaces= true; + fil_system.unflushed_spaces.push_front(*space); + } + } + } + + switch (n_pending--) { + case 0: + ut_error; + case 1: + if (space->belongs_in_lru()) + /* The node must be put back to the LRU list */ + UT_LIST_ADD_FIRST(fil_system.LRU, this); + } +} + #include "fil0crypt.h" /** Returns the latch of a file space. @@ -1051,14 +1397,9 @@ database server shutdown. This should be called at a server startup after the space objects for the system tablespace have been created. The purpose of this operation is to make sure we never run out of file descriptors if we need to read from the insert buffer. */ -void -fil_open_system_tablespace_files(); -/*==========================================*/ -/*******************************************************************//** -Closes all open files. There must not be any pending i/o's or not flushed -modifications in the files. */ -void -fil_close_all_files(void); +void fil_open_system_tablespace_files(); +/** Close all tablespace files at shutdown */ +void fil_close_all_files(); /*******************************************************************//** Sets the max tablespace id counter if the given number is bigger than the previous value. */ @@ -1182,8 +1523,11 @@ bool fil_table_accessible(const dict_table_t* table) /** Delete a tablespace and associated .ibd file. @param[in] id tablespace identifier @param[in] if_exists whether to ignore missing tablespace +@param[out] leaked_handles return detached handles here @return DB_SUCCESS or error */ -dberr_t fil_delete_tablespace(ulint id, bool if_exists= false); +dberr_t +fil_delete_tablespace(ulint id, bool if_exists= false, + std::vector *detached_handles= nullptr); /** Prepare to truncate an undo tablespace. @param[in] space_id undo tablespace id @@ -1191,15 +1535,10 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists= false); @retval NULL if the tablespace does not exist */ fil_space_t* fil_truncate_prepare(ulint space_id); -/*******************************************************************//** -Closes a single-table tablespace. The tablespace must be cached in the -memory cache. Free all pages used by the tablespace. -@return DB_SUCCESS or error */ -dberr_t -fil_close_tablespace( -/*=================*/ - trx_t* trx, /*!< in/out: Transaction covering the close */ - ulint id); /*!< in: space id */ +/** Close a single-table tablespace on failed IMPORT TABLESPACE. +The tablespace must be cached in the memory cache. +Free all pages used by the tablespace. */ +void fil_close_tablespace(ulint id); /*******************************************************************//** Allocates and builds a file name from a path, a table or tablespace name @@ -1350,6 +1689,14 @@ fil_space_extend( fil_space_t* space, ulint size); +struct fil_io_t +{ + /** error code */ + dberr_t err; + /** file; node->space->release_for_io() must follow fil_io(sync=true) call */ + fil_node_t *node; +}; + /** Reads or writes data. This operation could be asynchronous (aio). @param[in] type IO context @@ -1366,12 +1713,11 @@ fil_space_extend( aligned @param[in] message message for aio handler if non-sync aio used, else ignored -@param[in] ignore whether to ignore out-of-bounds page_id +@param[in] ignore whether to ignore errors @param[in] punch_hole punch the hole to the file for page_compressed tablespace -@return DB_SUCCESS, or DB_TABLESPACE_DELETED -if we are trying to do i/o on a tablespace which does not exist */ -dberr_t +@return status and file descriptor */ +fil_io_t fil_io( const IORequest& type, bool sync, diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 7a945f3a59e..e5bc4c8a6ed 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -487,25 +487,13 @@ fsp_reserve_free_extents( @param[in,out] seg_header file segment header @param[in,out] space tablespace @param[in] offset page number -@param[in] ahi whether we may need to drop the adaptive -hash index @param[in,out] mtr mini-transaction */ void -fseg_free_page_func( +fseg_free_page( fseg_header_t* seg_header, fil_space_t* space, ulint offset, -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr); -#ifdef BTR_CUR_HASH_ADAPT -# define fseg_free_page(header, space, offset, ahi, mtr) \ - fseg_free_page_func(header, space, offset, ahi, mtr) -#else /* BTR_CUR_HASH_ADAPT */ -# define fseg_free_page(header, space, offset, ahi, mtr) \ - fseg_free_page_func(header, space, offset, mtr) -#endif /* BTR_CUR_HASH_ADAPT */ /** Determine whether a page is free. @param[in,out] space tablespace @param[in] page page number @@ -518,45 +506,25 @@ Frees part of a segment. This function can be used to free a segment by repeatedly calling this function in different mini-transactions. Doing the freeing in a single mini-transaction might result in too big a mini-transaction. -@return TRUE if freeing completed */ +@return whether the freeing was completed */ bool -fseg_free_step_func( +fseg_free_step( fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header resides on the first page of the frag list of the segment, this pointer becomes obsolete after the last freeing step */ -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, /*!< in: whether we may need to drop - the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((warn_unused_result)); -#ifdef BTR_CUR_HASH_ADAPT -# define fseg_free_step(header, ahi, mtr) fseg_free_step_func(header, ahi, mtr) -#else /* BTR_CUR_HASH_ADAPT */ -# define fseg_free_step(header, ahi, mtr) fseg_free_step_func(header, mtr) -#endif /* BTR_CUR_HASH_ADAPT */ /**********************************************************************//** Frees part of a segment. Differs from fseg_free_step because this function leaves the header page unfreed. -@return true if freeing completed, except the header page */ +@return whether the freeing was completed, except for the header page */ bool -fseg_free_step_not_header_func( +fseg_free_step_not_header( fseg_header_t* header, /*!< in: segment header which must reside on the first fragment page of the segment */ -#ifdef BTR_CUR_HASH_ADAPT - bool ahi, /*!< in: whether we may need to drop - the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((warn_unused_result)); -#ifdef BTR_CUR_HASH_ADAPT -# define fseg_free_step_not_header(header, ahi, mtr) \ - fseg_free_step_not_header_func(header, ahi, mtr) -#else /* BTR_CUR_HASH_ADAPT */ -# define fseg_free_step_not_header(header, ahi, mtr) \ - fseg_free_step_not_header_func(header, mtr) -#endif /* BTR_CUR_HASH_ADAPT */ /** Reset the page type. Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE. @@ -612,7 +580,7 @@ inline void fsp_init_file_page( buf_block_t* block, mtr_t* mtr) { ut_d(space->modify_check(*mtr)); - ut_ad(space->id == block->page.id.space()); + ut_ad(space->id == block->page.id().space()); fsp_apply_init_file_page(block); mtr->init(block); } diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 0f3a568a048..9e0cab12373 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -24,8 +24,7 @@ Full text search header file Created 2011/09/02 Sunny Bains ***********************************************************************/ -#ifndef fts0fts_h -#define fts0fts_h +#pragma once #include "data0type.h" #include "data0types.h" @@ -986,8 +985,12 @@ fts_trx_t* fts_trx_create( trx_t* trx); +/** Clear all fts resources when there is no internal DOC_ID +and there are no new fts index to add. +@param[in,out] table table where fts is to be freed +@param[in] trx transaction to drop all fts tables */ +void fts_clear_all(dict_table_t *table, trx_t *trx); + /** Sync the table during commit phase @param[in] table table to be synced */ void fts_sync_during_ddl(dict_table_t* table); - -#endif /*!< fts0fts.h */ diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index 6d8617da0c9..09d3a77ba79 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -239,7 +239,7 @@ Do a binary search for a doc id in the array int fts_bsearch( /*========*/ - fts_update_t* array, /*!< in: array to sort */ + doc_id_t* array, /*!< in: array to sort */ int lower, /*!< in: lower bound of array*/ int upper, /*!< in: upper bound of array*/ doc_id_t doc_id) /*!< in: doc id to lookup */ diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index a08a60b9e95..44c3ab77695 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -80,20 +80,6 @@ struct fts_index_cache_t { CHARSET_INFO* charset; /*!< charset */ }; -/** For supporting the tracking of updates on multiple FTS indexes we need -to track which FTS indexes need to be updated. For INSERT and DELETE we -update all fts indexes. */ -struct fts_update_t { - doc_id_t doc_id; /*!< The doc id affected */ - - ib_vector_t* fts_indexes; /*!< The FTS indexes that need to be - updated. A NULL value means all - indexes need to be updated. This - vector is not allocated on the heap - and so must be freed explicitly, - when we are done with it */ -}; - /** Stop word control infotmation. */ struct fts_stopword_t { ulint status; /*!< Status of the stopword tree */ @@ -319,10 +305,9 @@ fts_ranking_doc_id_cmp( const void* p2); /*!< in: id2 */ /******************************************************************//** -Compare two fts_update_t instances doc_ids. */ +Compare two doc_ids. */ UNIV_INLINE -int -fts_update_doc_id_cmp( +int fts_doc_id_cmp( /*==================*/ /*!< out: < 0 if n1 < n2, diff --git a/storage/innobase/include/fts0types.ic b/storage/innobase/include/fts0types.ic index 4974a7a6802..facc1e5c40b 100644 --- a/storage/innobase/include/fts0types.ic +++ b/storage/innobase/include/fts0types.ic @@ -79,19 +79,18 @@ fts_ranking_doc_id_cmp( } /******************************************************************//** -Compare two fts_update_t doc_ids. +Compare two doc_ids. @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ UNIV_INLINE -int -fts_update_doc_id_cmp( +int fts_doc_id_cmp( /*==================*/ const void* p1, /*!< in: id1 */ const void* p2) /*!< in: id2 */ { - const fts_update_t* up1 = (const fts_update_t*) p1; - const fts_update_t* up2 = (const fts_update_t*) p2; + const doc_id_t* up1 = static_cast(p1); + const doc_id_t* up2 = static_cast(p2); - return((int)(up1->doc_id - up2->doc_id)); + return static_cast(*up1 - *up2); } /******************************************************************//** diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 1944309c8ec..561c322521e 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,7 +19,7 @@ this program; if not, write to the Free Software Foundation, Inc., /**************************************************//** @file include/ha0ha.h -The hash table with external chains +The hash table interface for the adaptive hash index Created 8/18/1994 Heikki Tuuri *******************************************************/ @@ -43,160 +43,6 @@ ha_search_and_get_data( /*===================*/ hash_table_t* table, /*!< in: hash table */ ulint fold); /*!< in: folded value of the searched data */ -/*********************************************************//** -Looks for an element when we know the pointer to the data and updates -the pointer to data if found. -@return TRUE if found */ -ibool -ha_search_and_update_if_found_func( -/*===============================*/ - hash_table_t* table, /*!< in/out: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data, /*!< in: pointer to the data */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* new_block,/*!< in: block containing new_data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* new_data);/*!< in: new pointer to the data */ - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** Looks for an element when we know the pointer to the data and -updates the pointer to data if found. -@param table in/out: hash table -@param fold in: folded value of the searched data -@param data in: pointer to the data -@param new_block in: block containing new_data -@param new_data in: new pointer to the data */ -# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ - ha_search_and_update_if_found_func(table,fold,data,new_block,new_data) -#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -/** Looks for an element when we know the pointer to the data and -updates the pointer to data if found. -@param table in/out: hash table -@param fold in: folded value of the searched data -@param data in: pointer to the data -@param new_block ignored: block containing new_data -@param new_data in: new pointer to the data */ -# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ - ha_search_and_update_if_found_func(table,fold,data,new_data) -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -#endif /* BTR_CUR_HASH_ADAPT */ - -/*************************************************************//** -Creates a hash table with at least n array cells. The actual number -of cells is chosen to be a prime number slightly bigger than n. -@return own: created table */ -hash_table_t* -ib_create( -/*======*/ - ulint n, /*!< in: number of array cells */ - latch_id_t id, /*!< in: latch ID */ - ulint n_mutexes,/*!< in: number of mutexes to protect the - hash table: must be a power of 2, or 0 */ - ulint type); /*!< in: type of datastructure for which - the memory heap is going to be used e.g.: - MEM_HEAP_FOR_BTR_SEARCH or - MEM_HEAP_FOR_PAGE_HASH */ - -/** Recreate a hash table with at least n array cells. The actual number -of cells is chosen to be a prime number slightly bigger than n. -The new cells are all cleared. The heaps are recreated. -The sync objects are reused. -@param[in,out] table hash table to be resuzed (to be freed later) -@param[in] n number of array cells -@return resized new table */ -hash_table_t* -ib_recreate( - hash_table_t* table, - ulint n); - -/*************************************************************//** -Empties a hash table and frees the memory heaps. */ -void -ha_clear( -/*=====*/ - hash_table_t* table); /*!< in, own: hash table */ - -#ifdef BTR_CUR_HASH_ADAPT -/*************************************************************//** -Inserts an entry into a hash table. If an entry with the same fold number -is found, its node is updated to point to the new data, and no new node -is inserted. -@return TRUE if succeed, FALSE if no more memory could be allocated */ -ibool -ha_insert_for_fold_func( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of data; if a node with - the same fold value already exists, it is - updated to point to the same data, and no new - node is created! */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* block, /*!< in: buffer block containing the data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* data); /*!< in: data, must not be NULL */ - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** -Inserts an entry into a hash table. If an entry with the same fold number -is found, its node is updated to point to the new data, and no new node -is inserted. -@return TRUE if succeed, FALSE if no more memory could be allocated -@param t in: hash table -@param f in: folded value of data -@param b in: buffer block containing the data -@param d in: data, must not be NULL */ -# define ha_insert_for_fold(t,f,b,d) do { \ - ha_insert_for_fold_func(t,f,b,d); \ - MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \ -} while(0) -#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -/** -Inserts an entry into a hash table. If an entry with the same fold number -is found, its node is updated to point to the new data, and no new node -is inserted. -@return TRUE if succeed, FALSE if no more memory could be allocated -@param t in: hash table -@param f in: folded value of data -@param b ignored: buffer block containing the data -@param d in: data, must not be NULL */ -# define ha_insert_for_fold(t,f,b,d) do { \ - ha_insert_for_fold_func(t,f,d); \ - MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \ -} while (0) -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - -/*********************************************************//** -Looks for an element when we know the pointer to the data and deletes -it from the hash table if found. -@return TRUE if found */ -UNIV_INLINE -ibool -ha_search_and_delete_if_found( -/*==========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data); /*!< in: pointer to the data */ - -/*****************************************************************//** -Removes from the chain determined by fold all nodes whose data pointer -points to the page given. */ -void -ha_remove_all_nodes_to_page( -/*========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: fold value */ - const page_t* page); /*!< in: buffer page */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/*************************************************************//** -Validates a given range of the cells in hash table. -@return TRUE if ok */ -ibool -ha_validate( -/*========*/ - hash_table_t* table, /*!< in: hash table */ - ulint start_index, /*!< in: start index */ - ulint end_index); /*!< in: end index */ -#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ /** The hash table external chain node */ struct ha_node_t { @@ -207,35 +53,8 @@ struct ha_node_t { #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ const rec_t* data; /*!< pointer to the data */ }; -#endif /* BTR_CUR_HASH_ADAPT */ - -#if defined UNIV_DEBUG && defined BTR_CUR_HASH_ADAPT -/********************************************************************//** -Assert that the synchronization object in a hash operation involving -possible change in the hash table is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held in exclusive mode. */ -UNIV_INLINE -void -hash_assert_can_modify( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold value */ -/********************************************************************//** -Assert that the synchronization object in a hash search operation is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held either in x-mode or s-mode. */ -UNIV_INLINE -void -hash_assert_can_search( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold value */ -#else /* UNIV_DEBUG */ -#define hash_assert_can_modify(t, f) -#define hash_assert_can_search(t, f) -#endif /* UNIV_DEBUG */ #include "ha0ha.ic" +#endif /* BTR_CUR_HASH_ADAPT */ #endif diff --git a/storage/innobase/include/ha0ha.ic b/storage/innobase/include/ha0ha.ic index 0612ef1bb25..0b256257214 100644 --- a/storage/innobase/include/ha0ha.ic +++ b/storage/innobase/include/ha0ha.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,14 +19,12 @@ this program; if not, write to the Free Software Foundation, Inc., /********************************************************************//** @file include/ha0ha.ic -The hash table with external chains +The hash table interface for the adaptive hash index Created 8/18/1994 Heikki Tuuri *************************************************************************/ #ifdef BTR_CUR_HASH_ADAPT -#include "ut0rnd.h" -#include "mem0mem.h" #include "btr0types.h" /******************************************************************//** @@ -95,57 +93,9 @@ ha_chain_get_first( hash_table_t* table, /*!< in: hash table */ ulint fold) /*!< in: fold value determining the chain */ { - return((ha_node_t*) - hash_get_nth_cell(table, hash_calc_hash(fold, table))->node); + return static_cast(table->array[table->calc_hash(fold)].node); } -#ifdef UNIV_DEBUG -/********************************************************************//** -Assert that the synchronization object in a hash operation involving -possible change in the hash table is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held in exclusive mode. */ -UNIV_INLINE -void -hash_assert_can_modify( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold value */ -{ - if (table->type == HASH_TABLE_SYNC_MUTEX) { - ut_ad(mutex_own(hash_get_mutex(table, fold))); - } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { -# ifdef UNIV_DEBUG - rw_lock_t* lock = hash_get_lock(table, fold); - ut_ad(rw_lock_own(lock, RW_LOCK_X)); -# endif - } else { - ut_ad(table->type == HASH_TABLE_SYNC_NONE); - } -} - -/********************************************************************//** -Assert that the synchronization object in a hash search operation is held. -Note that in case of mutexes we assert that mutex is owned while in case -of rw-locks we assert that it is held either in x-mode or s-mode. */ -UNIV_INLINE -void -hash_assert_can_search( -/*===================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold value */ -{ - if (table->type == HASH_TABLE_SYNC_MUTEX) { - ut_ad(mutex_own(hash_get_mutex(table, fold))); - } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) { - ut_ad(rw_lock_own_flagged(hash_get_lock(table, fold), - RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); - } else { - ut_ad(table->type == HASH_TABLE_SYNC_NONE); - } -} -#endif /* UNIV_DEBUG */ - /*************************************************************//** Looks for an element in a hash table. @return pointer to the data of the first hash table node in chain @@ -157,7 +107,6 @@ ha_search_and_get_data( hash_table_t* table, /*!< in: hash table */ ulint fold) /*!< in: folded value of the searched data */ { - hash_assert_can_search(table, fold); ut_ad(btr_search_enabled); for (const ha_node_t* node = ha_chain_get_first(table, fold); @@ -186,8 +135,6 @@ ha_search_with_data( { ha_node_t* node; - hash_assert_can_search(table, fold); - ut_ad(btr_search_enabled); node = ha_chain_get_first(table, fold); @@ -204,39 +151,4 @@ ha_search_with_data( return(NULL); } -/***********************************************************//** -Deletes a hash node. */ -void -ha_delete_hash_node( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ha_node_t* del_node); /*!< in: node to be deleted */ - -/*********************************************************//** -Looks for an element when we know the pointer to the data, and deletes -it from the hash table, if found. -@return TRUE if found */ -UNIV_INLINE -ibool -ha_search_and_delete_if_found( -/*==========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data) /*!< in: pointer to the data */ -{ - ha_node_t* node; - - hash_assert_can_modify(table, fold); - ut_ad(btr_search_enabled); - - node = ha_search_with_data(table, fold, data); - - if (node) { - ha_delete_hash_node(table, node); - - return(TRUE); - } - - return(FALSE); -} #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/ha0storage.ic b/storage/innobase/include/ha0storage.ic index 8cc487faf47..df9679cf997 100644 --- a/storage/innobase/include/ha0storage.ic +++ b/storage/innobase/include/ha0storage.ic @@ -32,7 +32,7 @@ Created September 24, 2007 Vasil Dimov struct ha_storage_t { mem_heap_t* heap; /*!< memory heap from which memory is allocated */ - hash_table_t* hash; /*!< hash table used to avoid + hash_table_t hash; /*!< hash table used to avoid duplicates */ }; @@ -77,7 +77,7 @@ ha_storage_create( sizeof(ha_storage_t)); storage->heap = heap; - storage->hash = hash_create(initial_hash_cells); + storage->hash.create(initial_hash_cells); return(storage); } @@ -97,7 +97,7 @@ ha_storage_empty( temp_storage.heap = (*storage)->heap; temp_storage.hash = (*storage)->hash; - hash_table_clear(temp_storage.hash); + temp_storage.hash.clear(); mem_heap_empty(temp_storage.heap); *storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap, @@ -117,9 +117,7 @@ ha_storage_free( /*============*/ ha_storage_t* storage) /*!< in, own: hash storage */ { - /* order is important because the pointer storage->hash is - within the heap */ - hash_table_free(storage->hash); + storage->hash.free(); mem_heap_free(storage->heap); } @@ -138,7 +136,7 @@ ha_storage_get_size( /* this assumes hash->heap and hash->heaps are NULL */ ret += sizeof(hash_table_t); - ret += sizeof(hash_cell_t) * hash_get_n_cells(storage->hash); + ret += sizeof(hash_cell_t) * storage->hash.n_cells; return(ret); } diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index f84540cacc8..ef1174c95dd 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -230,8 +230,8 @@ innobase_casedn_str( #ifdef WITH_WSREP int -wsrep_innobase_kill_one_trx(THD *bf_thd, const trx_t *bf_trx, - trx_t *victim_trx, bool signal); +wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx, + bool signal); ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, ulint str_length, unsigned int buf_length); diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 4f55b051d80..981ff5a0814 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,75 +24,14 @@ The simple hash table utility Created 5/20/1997 Heikki Tuuri *******************************************************/ -#ifndef hash0hash_h -#define hash0hash_h - -#include "mem0mem.h" -#include "sync0rw.h" +#pragma once +#include "ut0rnd.h" struct hash_table_t; -struct hash_cell_t; - -typedef void* hash_node_t; - -/* Fix Bug #13859: symbol collision between imap/mysql */ -#define hash_create hash0_create - -/* Differnt types of hash_table based on the synchronization -method used for it. */ -enum hash_table_sync_t { - HASH_TABLE_SYNC_NONE = 0, /*!< Don't use any internal - synchronization objects for - this hash_table. */ - HASH_TABLE_SYNC_MUTEX, /*!< Use mutexes to control - access to this hash_table. */ - HASH_TABLE_SYNC_RW_LOCK /*!< Use rw_locks to control - access to this hash_table. */ +struct hash_cell_t{ + void* node; /*!< hash chain node, NULL if none */ }; - -/*************************************************************//** -Creates a hash table with >= n array cells. The actual number -of cells is chosen to be a prime number slightly bigger than n. -@return own: created table */ -hash_table_t* -hash_create( -/*========*/ - ulint n); /*!< in: number of array cells */ - -/*************************************************************//** -Creates a sync object array array to protect a hash table. -::sync_obj can be mutexes or rw_locks depening on the type of -hash table. */ -void -hash_create_sync_obj( -/*=================*/ - hash_table_t* table, /*!< in: hash table */ - hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX - or HASH_TABLE_SYNC_RW_LOCK */ - latch_id_t id, /*!< in: mutex/rw_lock ID */ - ulint n_sync_obj);/*!< in: number of sync objects, - must be a power of 2 */ - -/*************************************************************//** -Frees a hash table. */ -void -hash_table_free( -/*============*/ - hash_table_t* table); /*!< in, own: hash table */ -/**************************************************************//** -Calculates the hash value from a folded value. -@return hashed value */ -UNIV_INLINE -ulint -hash_calc_hash( -/*===========*/ - ulint fold, /*!< in: folded value */ - hash_table_t* table); /*!< in: hash table */ -/********************************************************************//** -Assert that the mutex for the table is held */ -#define HASH_ASSERT_OWN(TABLE, FOLD) \ - ut_ad((TABLE)->type != HASH_TABLE_SYNC_MUTEX \ - || (mutex_own(hash_get_mutex((TABLE), FOLD)))); +typedef void* hash_node_t; /*******************************************************************//** Inserts a struct to a hash table. */ @@ -101,12 +40,10 @@ Inserts a struct to a hash table. */ do {\ hash_cell_t* cell3333;\ TYPE* struct3333;\ -\ - HASH_ASSERT_OWN(TABLE, FOLD)\ \ (DATA)->NAME = NULL;\ \ - cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\ + cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \ \ if (cell3333->node == NULL) {\ cell3333->node = DATA;\ @@ -130,11 +67,9 @@ do { \ hash_cell_t* cell3333; \ TYPE* struct3333; \ \ - HASH_ASSERT_OWN(TABLE, FOLD) \ - \ (DATA)->NAME = NULL; \ \ - cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\ + cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \ \ if (cell3333->node == NULL) { \ cell3333->node = DATA; \ @@ -163,9 +98,7 @@ do {\ hash_cell_t* cell3333;\ TYPE* struct3333;\ \ - HASH_ASSERT_OWN(TABLE, FOLD)\ -\ - cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\ + cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \ \ if (cell3333->node == DATA) {\ HASH_ASSERT_VALID(DATA->NAME);\ @@ -189,7 +122,7 @@ do {\ (DATA_NEW)->NAME = (DATA_OLD)->NAME; \ \ hash_cell_t& cell3333 \ - = TABLE->array[hash_calc_hash(FOLD, TABLE)]; \ + = (TABLE)->array[(TABLE)->calc_hash(FOLD)]; \ TYPE** struct3333 = (TYPE**)&cell3333.node; \ while (*struct3333 != DATA_OLD) { \ struct3333 = &((*struct3333)->NAME); \ @@ -199,8 +132,7 @@ do {\ /*******************************************************************//** Gets the first struct in a hash chain, NULL if none. */ -#define HASH_GET_FIRST(TABLE, HASH_VAL)\ - (hash_get_nth_cell(TABLE, HASH_VAL)->node) +#define HASH_GET_FIRST(TABLE, HASH_VAL) (TABLE)->array[HASH_VAL].node /*******************************************************************//** Gets the next struct in a hash chain, NULL if none. */ @@ -211,10 +143,7 @@ Gets the next struct in a hash chain, NULL if none. */ Looks for a struct in a hash table. */ #define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\ {\ -\ - HASH_ASSERT_OWN(TABLE, FOLD)\ -\ - (DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\ + (DATA) = (TYPE) HASH_GET_FIRST(TABLE, (TABLE)->calc_hash(FOLD)); \ HASH_ASSERT_VALID(DATA);\ \ while ((DATA) != NULL) {\ @@ -254,92 +183,6 @@ do { \ } \ } while (0) -/************************************************************//** -Gets the nth cell in a hash table. -@return pointer to cell */ -UNIV_INLINE -hash_cell_t* -hash_get_nth_cell( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint n); /*!< in: cell index */ - -/*************************************************************//** -Clears a hash table so that all the cells become empty. */ -UNIV_INLINE -void -hash_table_clear( -/*=============*/ - hash_table_t* table); /*!< in/out: hash table */ - -/*************************************************************//** -Returns the number of cells in a hash table. -@return number of cells */ -UNIV_INLINE -ulint -hash_get_n_cells( -/*=============*/ - hash_table_t* table); /*!< in: table */ -/*******************************************************************//** -Deletes a struct which is stored in the heap of the hash table, and compacts -the heap. The fold value must be stored in the struct NODE in a field named -'fold'. */ - -#define HASH_DELETE_AND_COMPACT(TYPE, NAME, TABLE, NODE)\ -do {\ - TYPE* node111;\ - TYPE* top_node111;\ - hash_cell_t* cell111;\ - ulint fold111;\ -\ - fold111 = (NODE)->fold;\ -\ - HASH_DELETE(TYPE, NAME, TABLE, fold111, NODE);\ -\ - top_node111 = (TYPE*) mem_heap_get_top(\ - hash_get_heap(TABLE, fold111),\ - sizeof(TYPE));\ -\ - /* If the node to remove is not the top node in the heap, compact the\ - heap of nodes by moving the top node in the place of NODE. */\ -\ - if (NODE != top_node111) {\ -\ - /* Copy the top node in place of NODE */\ -\ - *(NODE) = *top_node111;\ -\ - cell111 = hash_get_nth_cell(TABLE,\ - hash_calc_hash(top_node111->fold, TABLE));\ -\ - /* Look for the pointer to the top node, to update it */\ -\ - if (cell111->node == top_node111) {\ - /* The top node is the first in the chain */\ -\ - cell111->node = NODE;\ - } else {\ - /* We have to look for the predecessor of the top\ - node */\ - node111 = static_cast(cell111->node);\ -\ - while (top_node111 != HASH_GET_NEXT(NAME, node111)) {\ -\ - node111 = static_cast(\ - HASH_GET_NEXT(NAME, node111));\ - }\ -\ - /* Now we have the predecessor node */\ -\ - node111->NAME = NODE;\ - }\ - }\ -\ - /* Free the space occupied by the top node */\ -\ - mem_heap_free_top(hash_get_heap(TABLE, fold111), sizeof(TYPE));\ -} while (0) - /****************************************************************//** Move all hash table entries from OLD_TABLE to NEW_TABLE. */ @@ -348,7 +191,7 @@ do {\ ulint i2222;\ ulint cell_count2222;\ \ - cell_count2222 = hash_get_n_cells(OLD_TABLE);\ + cell_count2222 = (OLD_TABLE)->n_cells; \ \ for (i2222 = 0; i2222 < cell_count2222; i2222++) {\ NODE_TYPE* node2222 = static_cast(\ @@ -367,159 +210,27 @@ do {\ }\ } while (0) -/************************************************************//** -Gets the sync object index for a fold value in a hash table. -@return index */ -UNIV_INLINE -ulint -hash_get_sync_obj_index( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold */ -/************************************************************//** -Gets the nth heap in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_nth_heap( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i); /*!< in: index of the heap */ -/************************************************************//** -Gets the heap for a fold value in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_heap( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold */ -/************************************************************//** -Gets the nth mutex in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_nth_mutex( -/*===============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i); /*!< in: index of the mutex */ -/************************************************************//** -Gets the nth rw_lock in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_nth_lock( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i); /*!< in: index of the rw_lock */ -/************************************************************//** -Gets the mutex for a fold value in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_mutex( -/*===========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold */ -/************************************************************//** -Gets the rw_lock for a fold value in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_lock( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold); /*!< in: fold */ +/** Hash table with singly-linked overflow lists */ +struct hash_table_t +{ + /** number of elements in array (a prime number) */ + ulint n_cells; + /** the hash array */ + hash_cell_t *array; -/** If not appropriate rw_lock for a fold value in a hash table, -relock S-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_s_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold); + /** Create the hash table. + @param n the lower bound of n_cells */ + void create(ulint n) + { + n_cells= ut_find_prime(n); + array= static_cast(ut_zalloc_nokey(n_cells * sizeof *array)); + } -/** If not appropriate rw_lock for a fold value in a hash table, -relock X-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_x_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold); + /** Clear the hash table. */ + void clear() { memset(array, 0, n_cells * sizeof *array); } -/************************************************************//** -Reserves all the locks of a hash table, in an ascending order. */ -void -hash_lock_x_all( -/*============*/ - hash_table_t* table); /*!< in: hash table */ -/************************************************************//** -Releases all the locks of a hash table, in an ascending order. */ -void -hash_unlock_x_all( -/*==============*/ - hash_table_t* table); /*!< in: hash table */ -/************************************************************//** -Releases all but passed in lock of a hash table, */ -void -hash_unlock_x_all_but( -/*==================*/ - hash_table_t* table, /*!< in: hash table */ - rw_lock_t* keep_lock); /*!< in: lock to keep */ + /** Free the hash table. */ + void free() { ut_free(array); array= nullptr; } -struct hash_cell_t{ - void* node; /*!< hash chain node, NULL if none */ + ulint calc_hash(ulint fold) const { return ut_hash_ulint(fold, n_cells); } }; - -/* The hash table structure */ -struct hash_table_t { - enum hash_table_sync_t type; /*magic_n == HASH_TABLE_MAGIC_N); - ut_ad(n < table->n_cells); - - return(table->array + n); -} - -/*************************************************************//** -Clears a hash table so that all the cells become empty. */ -UNIV_INLINE -void -hash_table_clear( -/*=============*/ - hash_table_t* table) /*!< in/out: hash table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - memset(table->array, 0x0, - table->n_cells * sizeof(*table->array)); -} - -/*************************************************************//** -Returns the number of cells in a hash table. -@return number of cells */ -UNIV_INLINE -ulint -hash_get_n_cells( -/*=============*/ - hash_table_t* table) /*!< in: table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - return(table->n_cells); -} - -/**************************************************************//** -Calculates the hash value from a folded value. -@return hashed value */ -UNIV_INLINE -ulint -hash_calc_hash( -/*===========*/ - ulint fold, /*!< in: folded value */ - hash_table_t* table) /*!< in: hash table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - return(ut_hash_ulint(fold, table->n_cells)); -} - -/************************************************************//** -Gets the sync object index for a fold value in a hash table. -@return index */ -UNIV_INLINE -ulint -hash_get_sync_obj_index( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type != HASH_TABLE_SYNC_NONE); - ut_ad(ut_is_2pow(table->n_sync_obj)); - return(ut_2pow_remainder(hash_calc_hash(fold, table), - table->n_sync_obj)); -} - -/************************************************************//** -Gets the nth heap in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_nth_heap( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the heap */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type != HASH_TABLE_SYNC_NONE); - ut_ad(i < table->n_sync_obj); - - return(table->heaps[i]); -} - -/************************************************************//** -Gets the heap for a fold value in a hash table. -@return mem heap */ -UNIV_INLINE -mem_heap_t* -hash_get_heap( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - if (table->heap) { - return(table->heap); - } - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_heap(table, i)); -} - -/************************************************************//** -Gets the nth mutex in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_nth_mutex( -/*===============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the mutex */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); - ut_ad(i < table->n_sync_obj); - - return(table->sync_obj.mutexes + i); -} - -/************************************************************//** -Gets the mutex for a fold value in a hash table. -@return mutex */ -UNIV_INLINE -ib_mutex_t* -hash_get_mutex( -/*===========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_mutex(table, i)); -} - -/************************************************************//** -Gets the nth rw_lock in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_nth_lock( -/*==============*/ - hash_table_t* table, /*!< in: hash table */ - ulint i) /*!< in: index of the rw_lock */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - ut_ad(i < table->n_sync_obj); - - return(table->sync_obj.rw_locks + i); -} - -/************************************************************//** -Gets the rw_lock for a fold value in a hash table. -@return rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_get_lock( -/*==========*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - - i = hash_get_sync_obj_index(table, fold); - - return(hash_get_nth_lock(table, i)); -} - -/** If not appropriate rw_lock for a fold value in a hash table, -relock S-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_s_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold) -{ - ut_ad(rw_lock_own(hash_lock, RW_LOCK_S)); - - rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); - - while (hash_lock_tmp != hash_lock) { - rw_lock_s_unlock(hash_lock); - hash_lock = hash_lock_tmp; - rw_lock_s_lock(hash_lock); - hash_lock_tmp = hash_get_lock(table, fold); - } - - return(hash_lock); -} - -/** If not appropriate rw_lock for a fold value in a hash table, -relock X-lock the another rw_lock until appropriate for a fold value. -@param[in] hash_lock latched rw_lock to be confirmed -@param[in] table hash table -@param[in] fold fold value -@return latched rw_lock */ -UNIV_INLINE -rw_lock_t* -hash_lock_x_confirm( - rw_lock_t* hash_lock, - hash_table_t* table, - ulint fold) -{ - ut_ad(rw_lock_own(hash_lock, RW_LOCK_X)); - - rw_lock_t* hash_lock_tmp = hash_get_lock(table, fold); - - while (hash_lock_tmp != hash_lock) { - rw_lock_x_unlock(hash_lock); - hash_lock = hash_lock_tmp; - rw_lock_x_lock(hash_lock); - hash_lock_tmp = hash_get_lock(table, fold); - } - - return(hash_lock); -} diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index ce0e911dbb4..91bc69ac228 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -457,11 +457,7 @@ struct TTASEventMutex { sync_cell_t* cell; sync_array_t *sync_arr = sync_array_get_and_reserve_cell( - this, - (m_policy.get_id() == LATCH_ID_BUF_BLOCK_MUTEX - || m_policy.get_id() == LATCH_ID_BUF_POOL_ZIP) - ? SYNC_BUF_BLOCK - : SYNC_MUTEX, + this, SYNC_MUTEX, filename, line, &cell); uint32_t oldval = MUTEX_STATE_LOCKED; diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index c05fc1541b7..ab697a730d2 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -541,6 +541,7 @@ lock_has_to_wait( locks are record locks */ /*********************************************************************//** Reports that a transaction id is insensible, i.e., in the future. */ +ATTRIBUTE_COLD void lock_report_trx_id_insanity( /*========================*/ @@ -758,12 +759,12 @@ public: MY_ALIGNED(CACHE_LINE_SIZE) LockMutex mutex; /*!< Mutex protecting the locks */ - hash_table_t* rec_hash; /*!< hash table of the record - locks */ - hash_table_t* prdt_hash; /*!< hash table of the predicate - lock */ - hash_table_t* prdt_page_hash; /*!< hash table of the page - lock */ + /** record locks */ + hash_table_t rec_hash; + /** predicate locks for SPATIAL INDEX */ + hash_table_t prdt_hash; + /** page locks for SPATIAL INDEX */ + hash_table_t prdt_page_hash; MY_ALIGNED(CACHE_LINE_SIZE) LockMutex wait_mutex; /*!< Mutex protecting the diff --git a/storage/innobase/include/lock0lock.ic b/storage/innobase/include/lock0lock.ic index 6c235f23680..6146f835be9 100644 --- a/storage/innobase/include/lock0lock.ic +++ b/storage/innobase/include/lock0lock.ic @@ -53,8 +53,7 @@ lock_rec_hash( ulint space, /*!< in: space */ ulint page_no)/*!< in: page number */ { - return(unsigned(hash_calc_hash(lock_rec_fold(space, page_no), - lock_sys.rec_hash))); + return unsigned(lock_sys.rec_hash.calc_hash(lock_rec_fold(space, page_no))); } /*********************************************************************//** @@ -90,11 +89,11 @@ lock_hash_get( ulint mode) /*!< in: lock mode */ { if (mode & LOCK_PREDICATE) { - return(lock_sys.prdt_hash); + return &lock_sys.prdt_hash; } else if (mode & LOCK_PRDT_PAGE) { - return(lock_sys.prdt_page_hash); + return &lock_sys.prdt_page_hash; } else { - return(lock_sys.rec_hash); + return &lock_sys.rec_hash; } } @@ -123,12 +122,12 @@ lock_rec_create( trx mutex */ { btr_assert_not_corrupted(block, index); + const page_id_t id(block->page.id()); return lock_rec_create_low( #ifdef WITH_WSREP c_lock, thr, #endif - type_mode, - block->page.id.space(), block->page.id.page_no(), + type_mode, id.space(), id.page_no(), block->frame, heap_no, index, trx, caller_owns_trx_mutex); } diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic index 217b61e3625..7468110deeb 100644 --- a/storage/innobase/include/lock0priv.ic +++ b/storage/innobase/include/lock0priv.ic @@ -164,8 +164,8 @@ lock_rec_get_first_on_page( { ut_ad(lock_mutex_own()); - ulint space = block->page.id.space(); - ulint page_no = block->page.id.page_no(); + ulint space = block->page.id().space(); + ulint page_no = block->page.id().page_no(); ulint hash = buf_block_get_lock_hash_val(block); for (lock_t* lock = static_cast( diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index a2c23d0bd89..8a4953d7533 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -44,12 +44,6 @@ Created 12/9/1995 Heikki Tuuri using st_::span; -/* Margin for the free space in the smallest log, before a new query -step which modifies the database, is started */ - -#define LOG_CHECKPOINT_FREE_PER_THREAD (4U << srv_page_size_shift) -#define LOG_CHECKPOINT_EXTRA_FREE (8U << srv_page_size_shift) - static const char LOG_FILE_NAME_PREFIX[] = "ib_logfile"; static const char LOG_FILE_NAME[] = "ib_logfile0"; @@ -139,7 +133,7 @@ log_get_max_modified_age_async(void); /*================================*/ /** Calculate the recommended highest values for lsn - last_checkpoint_lsn -and lsn - buf_get_oldest_modification(). +and lsn - buf_pool.get_oldest_modification(). @param[in] file_size requested innodb_log_file_size @retval true on success @retval false if the smallest log is too small to @@ -175,14 +169,9 @@ bool log_checkpoint(); /** Make a checkpoint */ void log_make_checkpoint(); -/****************************************************************//** -Makes a checkpoint at the latest lsn and writes it to first page of each -data file in the database, so that we know that the file spaces contain -all modifications up to that lsn. This can only be called at database -shutdown. This function also writes all log in log file to the log archive. */ -void -logs_empty_and_mark_files_at_shutdown(void); -/*=======================================*/ +/** Make a checkpoint at the latest lsn on shutdown. */ +void logs_empty_and_mark_files_at_shutdown(); + /** Write checkpoint info to the log header and invoke log_mutex_exit(). @param[in] end_lsn start LSN of the FILE_CHECKPOINT mini-transaction */ void log_write_checkpoint_info(lsn_t end_lsn); @@ -667,13 +656,13 @@ public: lsn_t max_modified_age_async; /*!< when this recommended value for lsn - - buf_pool_get_oldest_modification() + buf_pool.get_oldest_modification() is exceeded, we start an asynchronous preflush of pool pages */ lsn_t max_modified_age_sync; /*!< when this recommended value for lsn - - buf_pool_get_oldest_modification() + buf_pool.get_oldest_modification() is exceeded, we start a synchronous preflush of pool pages */ lsn_t max_checkpoint_age_async; diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 4fea9b8ec68..5e29a334d3a 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -211,7 +211,7 @@ struct recv_sys_t ib_mutex_t mutex; /** whether we are applying redo log records during crash recovery */ bool recovery_on; - /** whether recv_recover_page(), invoked from buf_page_io_complete(), + /** whether recv_recover_page(), invoked from buf_page_read_complete(), should apply log records*/ bool apply_log_recs; @@ -222,9 +222,8 @@ struct recv_sys_t page cleaner threads */ os_event_t flush_end;/*!< event to signal that the page cleaner has finished the request */ - buf_flush_t flush_type;/*!< type of the flush request. - BUF_FLUSH_LRU: flush end of LRU, keeping free blocks. - BUF_FLUSH_LIST: flush all of blocks. */ + /** whether to flush from buf_pool.LRU instead of buf_pool.flush_list */ + bool flush_lru; /** whether recv_apply_hashed_log_recs() is running */ bool apply_batch_on; byte* buf; /*!< buffer for parsing log records */ diff --git a/storage/innobase/include/log0types.h b/storage/innobase/include/log0types.h index 56faa7467cf..337fcd31793 100644 --- a/storage/innobase/include/log0types.h +++ b/storage/innobase/include/log0types.h @@ -41,10 +41,4 @@ typedef ib_uint64_t lsn_t; #define LSN_PF UINT64PF -/** The redo log manager */ -struct RedoLog; - -/** The recovery implementation */ -struct redo_recover_t; - #endif /* log0types_h */ diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index ad4393ba51b..b7fd9c098a6 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -58,7 +58,6 @@ buffer pool; the latter method is used for very big heaps */ /** Different type of heaps in terms of which datastructure is using them */ #define MEM_HEAP_FOR_BTR_SEARCH (MEM_HEAP_BTR_SEARCH | MEM_HEAP_BUFFER) -#define MEM_HEAP_FOR_PAGE_HASH (MEM_HEAP_DYNAMIC) #define MEM_HEAP_FOR_LOCK_HEAP (MEM_HEAP_BUFFER) /** The following start size is used for the first block in the memory heap if diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 2a88c0f1065..c1e7348a548 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -203,7 +203,7 @@ mem_heap_alloc( mem_block_set_free(block, free + MEM_SPACE_NEEDED(n)); buf = buf + REDZONE_SIZE; - UNIV_MEM_ALLOC(buf, n - REDZONE_SIZE); + MEM_UNDEFINED(buf, n - REDZONE_SIZE); return(buf); } @@ -268,7 +268,7 @@ mem_heap_free_heap_top( ulint(old_top - reinterpret_cast(block))); ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); - UNIV_MEM_FREE(old_top, (byte*) block + block->len - old_top); + MEM_NOACCESS(old_top, (byte*) block + block->len - old_top); /* If free == start, we may free the block if it is not the first one */ @@ -342,7 +342,7 @@ mem_heap_free_top( == mem_block_get_start(block))) { mem_heap_block_free(heap, block); } else { - UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); + MEM_NOACCESS((byte*) block + mem_block_get_free(block), n); } } diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h index a8840b187a8..926411a6f97 100644 --- a/storage/innobase/include/mtr0log.h +++ b/storage/innobase/include/mtr0log.h @@ -226,7 +226,7 @@ inline void mtr_t::memset(const buf_block_t &b, ulint ofs, ulint len, byte val) static_assert(MIN_4BYTE > UNIV_PAGE_SIZE_MAX, "consistency"); size_t lenlen= (len < MIN_2BYTE ? 1 + 1 : len < MIN_3BYTE ? 2 + 1 : 3 + 1); - byte *l= log_write(b.page.id, &b.page, lenlen, true, ofs); + byte *l= log_write(b.page.id(), &b.page, lenlen, true, ofs); l= mlog_encode_varint(l, len); *l++= val; m_log.close(l); @@ -263,7 +263,7 @@ inline void mtr_t::memset(const buf_block_t &b, ulint ofs, size_t len, static_assert(MIN_4BYTE > UNIV_PAGE_SIZE_MAX, "consistency"); size_t lenlen= (len < MIN_2BYTE ? 1 : len < MIN_3BYTE ? 2 : 3); - byte *l= log_write(b.page.id, &b.page, lenlen + size, true, ofs); + byte *l= log_write(b.page.id(), &b.page, lenlen + size, true, ofs); l= mlog_encode_varint(l, len); ::memcpy(l, str, size); l+= size; @@ -320,13 +320,14 @@ inline void mtr_t::memcpy_low(const buf_block_t &block, uint16_t offset, return; if (len < mtr_buf_t::MAX_DATA_SIZE - (1 + 3 + 3 + 5 + 5)) { - byte *end= log_write(block.page.id, &block.page, len, true, offset); + byte *end= log_write(block.page.id(), &block.page, len, true, + offset); ::memcpy(end, data, len); m_log.close(end + len); } else { - m_log.close(log_write(block.page.id, &block.page, len, false, + m_log.close(log_write(block.page.id(), &block.page, len, false, offset)); m_log.push(static_cast(data), static_cast(len)); } @@ -363,7 +364,7 @@ inline void mtr_t::memmove(const buf_block_t &b, ulint d, ulint s, ulint len) /* The source offset 0 is not possible. */ s-= 1 << 1; size_t slen= (s < MIN_2BYTE ? 1 : s < MIN_3BYTE ? 2 : 3); - byte *l= log_write(b.page.id, &b.page, lenlen + slen, true, d); + byte *l= log_write(b.page.id(), &b.page, lenlen + slen, true, d); l= mlog_encode_varint(l, len); l= mlog_encode_varint(l, s); m_log.close(l); @@ -386,7 +387,7 @@ inline byte *mtr_t::log_write(const page_id_t id, const buf_page_t *bpage, static_assert(!(type & 15) && type != RESERVED && type != OPTION && type <= FILE_CHECKPOINT, "invalid type"); ut_ad(type >= FILE_CREATE || is_named_space(id.space())); - ut_ad(!bpage || bpage->id == id); + ut_ad(!bpage || bpage->id() == id); constexpr bool have_len= type != INIT_PAGE && type != FREE_PAGE; constexpr bool have_offset= type == WRITE || type == MEMSET || type == MEMMOVE; @@ -510,6 +511,7 @@ inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str, @param[in,out] b buffer page */ inline void mtr_t::init(buf_block_t *b) { + ut_ad(!m_freed_pages); b->page.status= buf_page_t::INIT_ON_FLUSH; if (m_log_mode != MTR_LOG_ALL) @@ -518,16 +520,24 @@ inline void mtr_t::init(buf_block_t *b) return; } - m_log.close(log_write(b->page.id, &b->page)); + m_log.close(log_write(b->page.id(), &b->page)); m_last_offset= FIL_PAGE_TYPE; } /** Free a page. -@param id page identifier */ -inline void mtr_t::free(const page_id_t id) +@param[in] space tablespace contains page to be freed +@param[in] offset page offset to be freed */ +inline void mtr_t::free(fil_space_t &space, uint32_t offset) { + page_id_t freed_page_id(space.id, offset); if (m_log_mode == MTR_LOG_ALL) - m_log.close(log_write(id, nullptr)); + m_log.close(log_write(freed_page_id, nullptr)); + + ut_ad(!m_user_space || m_user_space == &space); + if (&space == fil_system.sys_space) + freed_system_tablespace_page(); + else + m_user_space= &space; } /** Write an EXTENDED log record. @@ -538,7 +548,7 @@ inline void mtr_t::log_write_extended(const buf_block_t &block, byte type) set_modified(block); if (m_log_mode != MTR_LOG_ALL) return; - byte *l= log_write(block.page.id, &block.page, 1, true); + byte *l= log_write(block.page.id(), &block.page, 1, true); *l++= type; m_log.close(l); m_last_offset= FIL_PAGE_TYPE; @@ -566,7 +576,7 @@ inline void mtr_t::page_delete(const buf_block_t &block, ulint prev_rec) if (m_log_mode != MTR_LOG_ALL) return; size_t len= (prev_rec < MIN_2BYTE ? 2 : prev_rec < MIN_3BYTE ? 3 : 4); - byte *l= log_write(block.page.id, &block.page, len, true); + byte *l= log_write(block.page.id(), &block.page, len, true); ut_d(byte *end= l + len); *l++= DELETE_ROW_FORMAT_REDUNDANT; l= mlog_encode_varint(l, prev_rec); @@ -595,7 +605,7 @@ inline void mtr_t::page_delete(const buf_block_t &block, ulint prev_rec, size_t len= prev_rec < MIN_2BYTE ? 2 : prev_rec < MIN_3BYTE ? 3 : 4; len+= hdr_size < MIN_2BYTE ? 1 : 2; len+= data_size < MIN_2BYTE ? 1 : data_size < MIN_3BYTE ? 2 : 3; - byte *l= log_write(block.page.id, &block.page, len, true); + byte *l= log_write(block.page.id(), &block.page, len, true); ut_d(byte *end= l + len); *l++= DELETE_ROW_FORMAT_DYNAMIC; l= mlog_encode_varint(l, prev_rec); @@ -625,7 +635,7 @@ inline void mtr_t::undo_append(const buf_block_t &block, if (m_log_mode != MTR_LOG_ALL) return; const bool small= len + 1 < mtr_buf_t::MAX_DATA_SIZE - (1 + 3 + 3 + 5 + 5); - byte *end= log_write(block.page.id, &block.page, len + 1, small); + byte *end= log_write(block.page.id(), &block.page, len + 1, small); if (UNIV_LIKELY(small)) { *end++= UNDO_APPEND; @@ -650,4 +660,5 @@ inline void mtr_t::trim_pages(const page_id_t id) byte *l= log_write(id, nullptr, 1, true); *l++= TRIM_PAGES; m_log.close(l); + set_trim_pages(); } diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 2664054f5c6..6058d0daaf6 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -55,18 +55,6 @@ savepoint. */ #define mtr_memo_release(m, o, t) \ (m)->memo_release((o), (t)) -#ifdef UNIV_DEBUG -/** Check if memo contains the given item. -@return TRUE if contains */ -#define mtr_memo_contains(m, o, t) \ - (m)->memo_contains((m)->get_memo(), (o), (t)) - -/** Check if memo contains the given page. -@return TRUE if contains */ -#define mtr_memo_contains_page(m, p, t) \ - (m)->memo_contains_page_flagged((p), (t)) -#endif /* UNIV_DEBUG */ - /** Print info of an mtr handle. */ #define mtr_print(m) (m)->print() @@ -84,12 +72,6 @@ savepoint. */ #define mtr_x_lock_index(i, m) (m)->x_lock(&(i)->lock, __FILE__, __LINE__) #define mtr_sx_lock_index(i, m) (m)->sx_lock(&(i)->lock, __FILE__, __LINE__) -#define mtr_memo_contains_flagged(m, p, l) \ - (m)->memo_contains_flagged((p), (l)) - -#define mtr_memo_contains_page_flagged(m, p, l) \ - (m)->memo_contains_page_flagged((p), (l)) - #define mtr_release_block_at_savepoint(m, s, b) \ (m)->release_block_at_savepoint((s), (b)) @@ -330,17 +312,31 @@ public: /** @return true if we are inside the change buffer code */ bool is_inside_ibuf() const { return m_inside_ibuf; } + /** Note that system tablespace page has been freed. */ + void freed_system_tablespace_page() { m_freed_in_system_tablespace= true; } + + /** Note that pages has been trimed */ + void set_trim_pages() { m_trim_pages= true; } + + /** @return true if pages has been trimed */ + bool is_trim_pages() { return m_trim_pages; } + + /** @return whether a page_compressed table was modified */ + bool is_page_compressed() const + { +#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) + return m_user_space && m_user_space->is_compressed(); +#else + return false; +#endif + } #ifdef UNIV_DEBUG - /** Check if memo contains the given item. - @param memo memo stack - @param object object to search - @param type type of object - @return true if contains */ - static bool memo_contains( - const mtr_buf_t* memo, - const void* object, - mtr_memo_type_t type) - MY_ATTRIBUTE((warn_unused_result)); + /** Check if we are holding an rw-latch in this mini-transaction + @param lock latch to search for + @param type held latch type + @return whether (lock,type) is contained */ + bool memo_contains(const rw_lock_t &lock, mtr_memo_type_t type) + MY_ATTRIBUTE((warn_unused_result)); /** Check if memo contains the given item. @param object object to search @@ -370,6 +366,12 @@ public: /** @return the memo stack */ mtr_buf_t* get_memo() { return &m_memo; } + + /** @return true if system tablespace page has been freed */ + bool is_freed_system_tablespace_page() + { + return m_freed_in_system_tablespace; + } #endif /* UNIV_DEBUG */ /** @return true if a record was added to the mini-transaction */ @@ -492,8 +494,9 @@ public: @param[in,out] b buffer page */ void init(buf_block_t *b); /** Free a page. - @param id page identifier */ - inline void free(const page_id_t id); + @param[in] space tablespace contains page to be freed + @param[in] offset page offset to be freed */ + inline void free(fil_space_t &space, uint32_t offset); /** Write log for partly initializing a B-tree or R-tree page. @param block B-tree or R-tree page @param comp false=ROW_FORMAT=REDUNDANT, true=COMPACT or DYNAMIC */ @@ -573,6 +576,15 @@ public: const char *path, const char *new_path= nullptr); + /** Add freed page numbers to freed_pages */ + void add_freed_offset(page_id_t id) + { + ut_ad(m_user_space == NULL || id.space() == m_user_space->id); + if (!m_freed_pages) + m_freed_pages= new range_set(); + m_freed_pages->add_value(id.page_no()); + } + private: /** Log a write of a byte string to a page. @param block buffer page @@ -643,6 +655,12 @@ private: to suppress some read-ahead operations, @see ibuf_inside() */ uint16_t m_inside_ibuf:1; + /** whether the page has been freed in system tablespace */ + uint16_t m_freed_in_system_tablespace:1; + + /** whether the pages has been trimmed */ + uint16_t m_trim_pages:1; + #ifdef UNIV_DEBUG /** Persistent user tablespace associated with the mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ @@ -660,6 +678,9 @@ private: /** LSN at commit time */ lsn_t m_commit_lsn; + + /** set of freed page ids */ + range_set *m_freed_pages= nullptr; }; #include "mtr0mtr.ic" diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index aee390cf8b2..16777da1044 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -28,16 +28,11 @@ Created 11/26/1995 Heikki Tuuri /** Check if a mini-transaction is dirtying a clean page. @return true if the mtr is dirtying a clean page. */ -bool -mtr_t::is_block_dirtied(const buf_block_t* block) +inline bool mtr_t::is_block_dirtied(const buf_block_t *block) { - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); - ut_ad(block->page.buf_fix_count > 0); - - /* It is OK to read oldest_modification because no - other thread can be performing a write of it and it - is only during write that the value is reset to 0. */ - return(block->page.oldest_modification == 0); + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.buf_fix_count()); + return !block->page.oldest_modification(); } /** @@ -170,10 +165,10 @@ mtr_t::release_block_at_savepoint( ut_a(slot->object == block); - reinterpret_cast(block)->unfix(); - buf_page_release_latch(block, slot->type); + reinterpret_cast(block)->unfix(); + slot->object = NULL; } diff --git a/storage/innobase/include/os0api.h b/storage/innobase/include/os0api.h index 3be7c0afaa4..bd9dc5b73a1 100644 --- a/storage/innobase/include/os0api.h +++ b/storage/innobase/include/os0api.h @@ -34,15 +34,6 @@ class buf_page_t; /** File Node */ struct fil_node_t; -/** -Should we punch hole to deallocate unused portion of the page. -@param[in] bpage Page control block -@return true if punch hole should be used, false if not */ -bool -buf_page_should_punch_hole( - const buf_page_t* bpage) - MY_ATTRIBUTE((warn_unused_result)); - /** Calculate the length of trim (punch_hole) operation. @param[in] bpage Page control block diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 543e478f649..08ea482333b 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -189,9 +189,26 @@ static const ulint OS_FILE_ERROR_MAX = 200; #define IORequestWrite IORequest(IORequest::WRITE) /** -The IO Context that is passed down to the low level IO code */ -class IORequest { +The I/O context that is passed down to the low level IO code */ +class IORequest +{ public: + /** Buffer pool flush types */ + enum flush_t + { + /** via buf_pool.LRU */ + LRU= 0, + /** via buf_pool.flush_list */ + FLUSH_LIST, + /** single page of buf_poof.LRU */ + SINGLE_PAGE + }; + + IORequest(ulint type= READ, buf_page_t *bpage= nullptr, + flush_t flush_type= LRU) : + m_bpage(bpage), m_type(static_cast(type)), + m_flush_type(flush_type) {} + /** Flags passed in the request, they can be ORred together. */ enum { READ = 1, @@ -212,25 +229,6 @@ public: PUNCH_HOLE = 64, }; - /** - @param[in] type Request type, can be a value that is - ORed from the above enum - @param[in] bpage Page to be written */ - IORequest(ulint type= READ, buf_page_t *bpage= nullptr) - : m_bpage(bpage), m_type(static_cast(type)) - { - if (bpage && buf_page_should_punch_hole(bpage)) { - set_punch_hole(); - } - - if (!is_punch_hole_supported()) { - clear_punch_hole(); - } - } - - /** Destructor */ - ~IORequest() { } - /** @return true if it is a read request */ bool is_read() const MY_ATTRIBUTE((warn_unused_result)) @@ -342,6 +340,9 @@ public: @return DB_SUCCESS or error code */ dberr_t punch_hole(os_file_t fh, os_offset_t off, ulint len); + /** @return the flush type */ + flush_t flush_type() const { return m_flush_type; } + private: /** Page to be written on write operation. */ buf_page_t* const m_bpage= nullptr; @@ -351,6 +352,9 @@ private: /** Request type bit flags */ uint16_t m_type= READ; + + /** for writes, type of page flush */ + flush_t m_flush_type= LRU; }; /* @} */ diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 7ec5d2eec3d..ad6fac32b69 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -46,7 +46,7 @@ page_update_max_trx_id( mtr_t* mtr) /*!< in/out: mini-transaction */ { ut_ad(block); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(trx_id); ut_ad(page_is_leaf(buf_block_get_frame(block))); @@ -83,8 +83,8 @@ page_set_ssn_id( node_seq_t ssn_id, /*!< in: transaction id */ mtr_t* mtr) /*!< in/out: mini-transaction */ { - ut_ad(mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_SX_FIX | + MTR_MEMO_PAGE_X_FIX)); ut_ad(!page_zip || page_zip == &block->page.zip); constexpr uint16_t field= FIL_RTREE_SPLIT_SEQ_NUM; byte *b= my_assume_aligned<2>(&block->frame[field]); diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index a59d880284a..ede61283f33 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -218,7 +218,7 @@ page_zip_get_trailer_len( ulint uncompressed_size; ut_ad(page_zip_simple_validate(page_zip)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); if (!page_is_leaf(page_zip->data)) { uncompressed_size = PAGE_ZIP_DIR_SLOT_SIZE diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index 63aeaa9251b..651fcb1aa36 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -154,16 +154,6 @@ trx_t* thr_get_trx( /*========*/ que_thr_t* thr); /*!< in: query thread */ -/*******************************************************************//** -Determines if this thread is rolling back an incomplete transaction -in crash recovery. -@return TRUE if thr is rolling back an incomplete transaction in crash -recovery */ -UNIV_INLINE -ibool -thr_is_recv( -/*========*/ - const que_thr_t* thr); /*!< in: query thread */ /***********************************************************************//** Gets the type of a graph node. */ UNIV_INLINE diff --git a/storage/innobase/include/que0que.ic b/storage/innobase/include/que0que.ic index 5b775820df7..1c3ac242bf2 100644 --- a/storage/innobase/include/que0que.ic +++ b/storage/innobase/include/que0que.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,20 +37,6 @@ thr_get_trx( return(thr->graph->trx); } -/*******************************************************************//** -Determines if this thread is rolling back an incomplete transaction -in crash recovery. -@return TRUE if thr is rolling back an incomplete transaction in crash -recovery */ -UNIV_INLINE -ibool -thr_is_recv( -/*========*/ - const que_thr_t* thr) /*!< in: query thread */ -{ - return(trx_is_recv(thr->graph->trx)); -} - /***********************************************************************//** Gets the first thr in a fork. */ UNIV_INLINE diff --git a/storage/innobase/include/read0types.h b/storage/innobase/include/read0types.h index 48575feda10..1428170e704 100644 --- a/storage/innobase/include/read0types.h +++ b/storage/innobase/include/read0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,56 +32,47 @@ Created 2/16/1997 Heikki Tuuri #include -/** View is not visible to purge thread. */ -#define READ_VIEW_STATE_CLOSED 0 - -/** View is being opened, purge thread must wait for state change. */ -#define READ_VIEW_STATE_SNAPSHOT 1 - -/** View is visible to purge thread. */ -#define READ_VIEW_STATE_OPEN 2 - - /** Read view lists the trx ids of those transactions for which a consistent read should not see the modifications to the database. */ -class ReadView +class ReadViewBase { /** - View state. - - It is not defined as enum as it has to be updated using atomic operations. - Possible values are READ_VIEW_STATE_CLOSED, READ_VIEW_STATE_SNAPSHOT and - READ_VIEW_STATE_OPEN. - - Possible state transfers... - - Start view open: - READ_VIEW_STATE_CLOSED -> READ_VIEW_STATE_SNAPSHOT - - Complete view open: - READ_VIEW_STATE_SNAPSHOT -> READ_VIEW_STATE_OPEN - - Close view: - READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_CLOSED + The read should not see any transaction with trx id >= this value. + In other words, this is the "high water mark". */ - std::atomic m_state; + trx_id_t m_low_limit_id; + /** + The read should see all trx ids which are strictly + smaller (<) than this value. In other words, this is the + low water mark". + */ + trx_id_t m_up_limit_id; - /** m_state getter for ReadView owner thread */ - uint32_t state() const - { - return m_state.load(std::memory_order_relaxed); - } + /** Set of RW transactions that was active when this snapshot was taken */ + trx_ids_t m_ids; + /** + The view does not need to see the undo logs for transactions whose + transaction number is strictly smaller (<) than this value: they can be + removed in purge if not needed by other views. + */ + trx_id_t m_low_limit_no; + +protected: + bool empty() { return m_ids.empty(); } + + /** @return the up limit id */ + trx_id_t up_limit_id() const { return m_up_limit_id; } public: - ReadView(): m_state(READ_VIEW_STATE_CLOSED), m_low_limit_id(0) {} + ReadViewBase(): m_low_limit_id(0) {} /** - Copy state from another view. + Append state from another view. This method is used to find min(m_low_limit_no), min(m_low_limit_id) and all transaction ids below min(m_low_limit_id). These values effectively @@ -89,7 +80,7 @@ public: @param other view to copy from */ - void copy(const ReadView &other) + void append(const ReadViewBase &other) { ut_ad(&other != this); if (m_low_limit_no > other.m_low_limit_no) @@ -98,25 +89,24 @@ public: m_low_limit_id= other.m_low_limit_id; trx_ids_t::iterator dst= m_ids.begin(); - for (trx_ids_t::const_iterator src= other.m_ids.begin(); - src != other.m_ids.end(); src++) + for (const trx_id_t id : other.m_ids) { - if (*src >= m_low_limit_id) + if (id >= m_low_limit_id) break; loop: if (dst == m_ids.end()) { - m_ids.push_back(*src); + m_ids.push_back(id); dst= m_ids.end(); continue; } - if (*dst < *src) + if (*dst < id) { dst++; goto loop; } - else if (*dst > *src) - dst= m_ids.insert(dst, *src) + 1; + else if (*dst > id) + dst= m_ids.insert(dst, id) + 1; } m_ids.erase(std::lower_bound(dst, m_ids.end(), m_low_limit_id), m_ids.end()); @@ -126,54 +116,6 @@ loop: } - /** - Opens a read view where exactly the transactions serialized before this - point in time are seen in the view. - - View becomes visible to purge thread. - - @param[in,out] trx transaction - */ - void open(trx_t *trx); - - - /** - Closes the view. - - View becomes not visible to purge thread. - - This method is intended to be called by ReadView owner thread, thus - m_state cannot change. - */ - void close() - { - ut_ad(state() == READ_VIEW_STATE_CLOSED || - state() == READ_VIEW_STATE_OPEN); - m_state.store(READ_VIEW_STATE_CLOSED, std::memory_order_relaxed); - } - - - /** m_state getter for trx_sys::clone_oldest_view() trx_sys::size(). */ - uint32_t get_state() const - { - return m_state.load(std::memory_order_acquire); - } - - - /** - Returns true if view is open. - - This method is intended to be called by ReadView owner thread, thus - m_state cannot change. - */ - bool is_open() const - { - ut_ad(state() == READ_VIEW_STATE_OPEN || - state() == READ_VIEW_STATE_CLOSED); - return state() == READ_VIEW_STATE_OPEN; - } - - /** Creates a snapshot where exactly the transactions serialized before this point in time are seen in the view. @@ -183,10 +125,114 @@ loop: inline void snapshot(trx_t *trx); + /** + Check whether transaction id is valid. + @param[in] id transaction id to check + @param[in] name table name + + @todo changes_visible() was an unfortunate choice for this check. + It should be moved towards the functions that load trx id like + trx_read_trx_id(). No need to issue a warning, error log message should + be enough. Although statement should ideally fail if it sees corrupt + data. + */ + static void check_trx_id_sanity(trx_id_t id, const table_name_t &name); + + + /** + Check whether the changes by id are visible. + @param[in] id transaction id to check against the view + @param[in] name table name + @return whether the view sees the modifications of id. + */ + bool changes_visible(trx_id_t id, const table_name_t &name) const + MY_ATTRIBUTE((warn_unused_result)) + { + if (id >= m_low_limit_id) + { + check_trx_id_sanity(id, name); + return false; + } + return id < m_up_limit_id || + m_ids.empty() || + !std::binary_search(m_ids.begin(), m_ids.end(), id); + } + + + /** + @param id transaction to check + @return true if view sees transaction id + */ + bool sees(trx_id_t id) const { return id < m_up_limit_id; } + + /** @return the low limit no */ + trx_id_t low_limit_no() const { return m_low_limit_no; } + + /** @return the low limit id */ + trx_id_t low_limit_id() const { return m_low_limit_id; } +}; + + +/** A ReadView with extra members required for trx_t::read_view. */ +class ReadView: public ReadViewBase +{ + /** + View state. + + Implemented as atomic to allow mutex-free view close and re-use. + Non-owner thread is allowed to call is_open() alone without mutex + protection as well. E.g. trx_sys.view_count() does this. + + If non-owner thread intends to access other members as well, both + is_open() and other members accesses must be protected by m_mutex. + E.g. copy_to(). + */ + std::atomic m_open; + + /** For synchronisation with purge coordinator. */ + mutable ib_mutex_t m_mutex; + + /** + trx id of creating transaction. + Used exclusively by the read view owner thread. + */ + trx_id_t m_creator_trx_id; + +public: + ReadView(): m_open(false) { mutex_create(LATCH_ID_READ_VIEW, &m_mutex); } + ~ReadView() { mutex_free(&m_mutex); } + + + /** + Opens a read view where exactly the transactions serialized before this + point in time are seen in the view. + + View becomes visible to purge thread. Intended to be called by the ReadView + owner thread. + + @param[in,out] trx transaction + */ + void open(trx_t *trx); + + + /** + Closes the view. + + View becomes not visible to purge thread. Intended to be called by the + ReadView owner thread. + */ + void close() { m_open.store(false, std::memory_order_relaxed); } + + + /** Returns true if view is open. */ + bool is_open() const { return m_open.load(std::memory_order_relaxed); } + + /** Sets the creator transaction id. This should be set only for views created by RW transactions. + Intended to be called by the ReadView owner thread. */ void set_creator_trx_id(trx_id_t id) { @@ -196,97 +242,56 @@ loop: } - /** Check whether transaction id is valid. - @param[in] id transaction id to check - @param[in] name table name */ - static void check_trx_id_sanity( - trx_id_t id, - const table_name_t& name); - - /** Check whether the changes by id are visible. - @param[in] id transaction id to check against the view - @param[in] name table name - @return whether the view sees the modifications of id. */ - bool changes_visible( - trx_id_t id, - const table_name_t& name) const - MY_ATTRIBUTE((warn_unused_result)) - { - if (id < m_up_limit_id || id == m_creator_trx_id) { - - return(true); - } - - check_trx_id_sanity(id, name); - - if (id >= m_low_limit_id) { - - return(false); - - } else if (m_ids.empty()) { - - return(true); - } - - return(!std::binary_search(m_ids.begin(), m_ids.end(), id)); - } - - /** - @param id transaction to check - @return true if view sees transaction id */ - bool sees(trx_id_t id) const - { - return(id < m_up_limit_id); - } - - /** - Write the limits to the file. - @param file file to write to */ - void print_limits(FILE* file) const - { - fprintf(file, - "Trx read view will not see trx with" - " id >= " TRX_ID_FMT ", sees < " TRX_ID_FMT "\n", - m_low_limit_id, m_up_limit_id); - } - - /** - @return the low limit no */ - trx_id_t low_limit_no() const - { - return(m_low_limit_no); - } - - /** - @return the low limit id */ - trx_id_t low_limit_id() const - { - return(m_low_limit_id); - } + /** + Writes the limits to the file. + @param file file to write to + */ + void print_limits(FILE *file) const + { + mutex_enter(&m_mutex); + if (is_open()) + fprintf(file, "Trx read view will not see trx with" + " id >= " TRX_ID_FMT ", sees < " TRX_ID_FMT "\n", + low_limit_id(), up_limit_id()); + mutex_exit(&m_mutex); + } -private: - /** The read should not see any transaction with trx id >= this - value. In other words, this is the "high water mark". */ - trx_id_t m_low_limit_id; + /** + A wrapper around ReadViewBase::changes_visible(). + Intended to be called by the ReadView owner thread. + */ + bool changes_visible(trx_id_t id, const table_name_t &name) const + { return id == m_creator_trx_id || ReadViewBase::changes_visible(id, name); } - /** The read should see all trx ids which are strictly - smaller (<) than this value. In other words, this is the - low water mark". */ - trx_id_t m_up_limit_id; - /** trx id of creating transaction, set to TRX_ID_MAX for free - views. */ - trx_id_t m_creator_trx_id; + /** + A wrapper around ReadViewBase::append(). + Intended to be called by the purge coordinator task. + */ + void append_to(ReadViewBase *to) const + { + mutex_enter(&m_mutex); + if (is_open()) + to->append(*this); + mutex_exit(&m_mutex); + } - /** Set of RW transactions that was active when this snapshot - was taken */ - trx_ids_t m_ids; - - /** The view does not need to see the undo logs for transactions - whose transaction number is strictly smaller (<) than this value: - they can be removed in purge if not needed by other views */ - trx_id_t m_low_limit_no; -}; + /** + Unpoison the memory for innodb_monitor_set_option; + It is operating also on the freed transaction objects. + Declare the contents as initialized for Valgrind; + We checked that it was initialized in trx_pools->mem_free(trx). + */ + void mem_valid() const + { +#ifdef __SANITIZE_ADDRESS__ + MEM_UNDEFINED(&m_mutex, sizeof m_mutex); +#endif +#ifdef HAVE_valgrind + MEM_MAKE_DEFINED(&m_mutex, sizeof m_mutex); +#endif + } +}; #endif diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 197375b6301..c51e831fb0e 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -601,19 +601,17 @@ rec_offs_make_nth_extern( rec_offs* offsets, const ulint n); +MY_ATTRIBUTE((nonnull)) /** Determine the number of allocated elements for an array of offsets. @param[in] offsets offsets after rec_offs_set_n_alloc() @return number of elements */ -inline -ulint -rec_offs_get_n_alloc(const rec_offs* offsets) +inline ulint rec_offs_get_n_alloc(const rec_offs *offsets) { - ulint n_alloc; - ut_ad(offsets); - n_alloc = offsets[0]; - ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets); - return(n_alloc); + ut_ad(offsets); + ulint n_alloc= offsets[0]; + ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); + MEM_CHECK_ADDRESSABLE(offsets, n_alloc * sizeof *offsets); + return n_alloc; } /** Determine the number of fields for which offsets have been initialized. diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 6d0a1771f6d..30c72a7415a 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -703,7 +703,7 @@ rec_offs_set_n_alloc( ulint n_alloc) /*!< in: number of elements */ { ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); + MEM_UNDEFINED(offsets, n_alloc * sizeof *offsets); offsets[0] = static_cast(n_alloc); } diff --git a/storage/innobase/include/rw_lock.h b/storage/innobase/include/rw_lock.h new file mode 100644 index 00000000000..613adfef3f5 --- /dev/null +++ b/storage/innobase/include/rw_lock.h @@ -0,0 +1,106 @@ +/***************************************************************************** + +Copyright (c) 2020, MariaDB Corporation. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +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 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 Street, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +#pragma once +#include +#include "my_dbug.h" + +/** Simple read-write lock based on std::atomic */ +class rw_lock +{ + /** The lock word */ + std::atomic lock; + +protected: + /** Available lock */ + static constexpr uint32_t UNLOCKED= 0; + /** Flag to indicate that write_lock() is being held */ + static constexpr uint32_t WRITER= 1 << 31; + /** Flag to indicate that write_lock_wait() is pending */ + static constexpr uint32_t WRITER_WAITING= 1 << 30; + /** Flag to indicate that write_lock() or write_lock_wait() is pending */ + static constexpr uint32_t WRITER_PENDING= WRITER | WRITER_WAITING; + + /** Yield a read lock request due to a conflict with a write lock. + @return the lock value */ + uint32_t read_lock_yield() + { + uint32_t l= lock.fetch_sub(1, std::memory_order_relaxed); + DBUG_ASSERT(l & ~WRITER_PENDING); + return l; + } + /** Start waiting for an exclusive lock. */ + void write_lock_wait_start() + { lock.fetch_or(WRITER_WAITING, std::memory_order_relaxed); } + /** Wait for an exclusive lock. + @return whether the exclusive lock was acquired */ + bool write_lock_poll() + { + auto l= WRITER_WAITING; + if (lock.compare_exchange_strong(l, WRITER, std::memory_order_acquire, + std::memory_order_relaxed)) + return true; + if (!(l & WRITER_WAITING)) + /* write_lock() must have succeeded for another thread */ + write_lock_wait_start(); + return false; + } + +public: + /** Default constructor */ + rw_lock() : lock(UNLOCKED) {} + + /** Release a shared lock */ + void read_unlock() + { + IF_DBUG_ASSERT(auto l=,) lock.fetch_sub(1, std::memory_order_release); + DBUG_ASSERT(l & ~WRITER_PENDING); /* at least one read lock */ + DBUG_ASSERT(!(l & WRITER)); /* no write lock must have existed */ + } + /** Release an exclusive lock */ + void write_unlock() + { + IF_DBUG_ASSERT(auto l=,) lock.fetch_sub(WRITER, std::memory_order_release); + DBUG_ASSERT(l & WRITER); /* the write lock must have existed */ + } + /** Try to acquire a shared lock. + @return whether the lock was acquired */ + bool read_trylock() + { return !(lock.fetch_add(1, std::memory_order_acquire) & WRITER_PENDING); } + /** Try to acquire an exclusive lock. + @return whether the lock was acquired */ + bool write_trylock() + { + auto l= UNLOCKED; + return lock.compare_exchange_strong(l, WRITER, std::memory_order_acquire, + std::memory_order_relaxed); + } + + /** @return whether an exclusive lock is being held by any thread */ + bool is_write_locked() const + { return !!(lock.load(std::memory_order_relaxed) & WRITER); } + /** @return whether a shared lock is being held by any thread */ + bool is_read_locked() const + { + auto l= lock.load(std::memory_order_relaxed); + return (l & ~WRITER_PENDING) && !(l & WRITER); + } + /** @return whether any lock is being held by any thread */ + bool is_locked() const + { return (lock.load(std::memory_order_relaxed) & ~WRITER_WAITING) != 0; } +}; diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 397787802d4..8e833642ee0 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -2,7 +2,7 @@ Copyright (c) 2010, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -38,6 +38,7 @@ Created 12/15/2009 Jimmy Yang #include #include "my_atomic.h" +#include "my_atomic_wrapper.h" /** Possible status values for "mon_status" in "struct monitor_value" */ enum monitor_running_status { @@ -398,8 +399,6 @@ enum monitor_id_t { MONITOR_MASTER_IDLE_LOOPS, MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND, MONITOR_SRV_LOG_FLUSH_MICROSECOND, - MONITOR_SRV_MEM_VALIDATE_MICROSECOND, - MONITOR_SRV_PURGE_MICROSECOND, MONITOR_SRV_DICT_LRU_MICROSECOND, MONITOR_SRV_DICT_LRU_EVICT_COUNT_ACTIVE, MONITOR_SRV_DICT_LRU_EVICT_COUNT_IDLE, @@ -652,14 +651,14 @@ Use MONITOR_DEC if appropriate mutex protection exists. } \ } -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind_or_MSAN # define MONITOR_CHECK_DEFINED(value) do { \ mon_type_t m = value; \ - UNIV_MEM_ASSERT_RW(&m, sizeof m); \ + MEM_CHECK_DEFINED(&m, sizeof m); \ } while (0) -#else /* UNIV_DEBUG_VALGRIND */ +#else /* HAVE_valgrind_or_MSAN */ # define MONITOR_CHECK_DEFINED(value) (void) 0 -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ #define MONITOR_INC_VALUE(monitor, value) \ MONITOR_CHECK_DEFINED(value); \ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index b0d36d6ad48..d4b6425c44b 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -278,30 +278,11 @@ extern char* srv_undo_dir; /** Number of undo tablespaces to use. */ extern ulong srv_undo_tablespaces; -/** The number of UNDO tablespaces that are open and ready to use. */ -extern ulint srv_undo_tablespaces_open; - /** The number of UNDO tablespaces that are active (hosting some rollback segment). It is quite possible that some of the tablespaces doesn't host any of the rollback-segment based on configuration used. */ extern ulint srv_undo_tablespaces_active; -/** Undo tablespaces starts with space_id. */ -extern ulint srv_undo_space_id_start; - -/** Check whether given space id is undo tablespace id -@param[in] space_id space id to check -@return true if it is undo tablespace else false. */ -inline -bool -srv_is_undo_tablespace(ulint space_id) -{ - return srv_undo_space_id_start > 0 - && space_id >= srv_undo_space_id_start - && space_id < (srv_undo_space_id_start - + srv_undo_tablespaces_open); -} - /** Maximum size of undo tablespace. */ extern unsigned long long srv_max_undo_log_size; @@ -352,8 +333,6 @@ extern const ulint srv_buf_pool_min_size; extern const ulint srv_buf_pool_def_size; /** Requested buffer pool chunk size */ extern ulong srv_buf_pool_chunk_unit; -/** Number of locks to protect buf_pool.page_hash */ -extern ulong srv_n_page_hash_locks; /** Scan depth for LRU flush batch i.e.: number of blocks scanned*/ extern ulong srv_LRU_scan_depth; /** Whether or not to flush neighbors of a block */ @@ -601,37 +580,6 @@ extern PSI_stage_info srv_stage_alter_table_read_pk_internal_sort; extern PSI_stage_info srv_stage_buffer_pool_load; #endif /* HAVE_PSI_STAGE_INTERFACE */ - -/** Alternatives for innodb_flush_method */ -enum srv_flush_t { - SRV_FSYNC = 0, /*!< fsync, the default */ - SRV_O_DSYNC, /*!< open log files in O_DSYNC mode */ - SRV_LITTLESYNC, /*!< do not call os_file_flush() - when writing data files, but do flush - after writing to log files */ - SRV_NOSYNC, /*!< do not flush after writing */ - SRV_O_DIRECT, /*!< invoke os_file_set_nocache() on - data files. This implies using - non-buffered IO but still using fsync, - the reason for which is that some FS - do not flush meta-data when - unbuffered IO happens */ - SRV_O_DIRECT_NO_FSYNC - /*!< do not use fsync() when using - direct IO i.e.: it can be set to avoid - the fsync() call that we make when - using SRV_UNIX_O_DIRECT. However, in - this case user/DBA should be sure about - the integrity of the meta-data */ -#ifdef _WIN32 - ,SRV_ALL_O_DIRECT_FSYNC - /*!< Traditional Windows appoach to open - all files without caching, and do FileFlushBuffers()*/ -#endif -}; -/** innodb_flush_method */ -extern ulong srv_file_flush_method; - /** Alternatives for srv_force_recovery. Non-zero values are intended to help the user get a damaged database up so that he can dump intact tables and rows with SELECT INTO OUTFILE. The database must not otherwise @@ -757,6 +705,16 @@ srv_que_task_enqueue_low( /*=====================*/ que_thr_t* thr); /*!< in: query thread */ +/** +Flag which is set, whenever innodb_purge_threads changes. +It is read and reset in srv_do_purge(). + +Thus it is Atomic_counter, not bool, since unprotected +reads are used. We just need an atomic with relaxed memory +order, to please Thread Sanitizer. +*/ +extern Atomic_counter srv_purge_thread_count_changed; + #ifdef UNIV_DEBUG /** @return whether purge or master task is active */ bool srv_any_background_activity(); @@ -796,7 +754,7 @@ ulint srv_get_task_queue_length(); void srv_purge_shutdown(); /** Init purge tasks*/ -void srv_init_purge_tasks(uint n_max); +void srv_init_purge_tasks(); #ifdef UNIV_DEBUG /** Disables master thread. It's used by: diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index 34ca11a23f0..596f6d4f5ab 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -109,6 +109,8 @@ extern ibool srv_start_raw_disk_in_use; /** Shutdown state */ enum srv_shutdown_t { SRV_SHUTDOWN_NONE = 0, /*!< Database running normally */ + /** Shutdown initiated in srv_shutdown_bg_undo_sources() */ + SRV_SHUTDOWN_INITIATED, SRV_SHUTDOWN_CLEANUP, /*!< Cleaning up in logs_empty_and_mark_files_at_shutdown() */ SRV_SHUTDOWN_FLUSH_PHASE,/*!< At this phase the master and the diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h index 94f49ff628c..4fd03eaea06 100644 --- a/storage/innobase/include/sync0policy.h +++ b/storage/innobase/include/sync0policy.h @@ -286,91 +286,4 @@ private: latch_id_t m_id; }; -/** Track agregate metrics policy, used by the page mutex. There are just -too many of them to count individually. */ -template -class BlockMutexPolicy -{ -public: - /** Called when the mutex is "created". Note: Not from the constructor - but when the mutex is initialised. - @param[in] id Mutex ID */ - void init(const Mutex&, latch_id_t id, const char*, uint32) - UNIV_NOTHROW - { - /* It can be LATCH_ID_BUF_BLOCK_MUTEX or - LATCH_ID_BUF_POOL_ZIP. Unfortunately, they - are mapped to the same mutex type in the - buffer pool code. */ - - m_id = id; - - latch_meta_t& meta = sync_latch_get_meta(m_id); - - ut_ad(meta.get_id() == id); - - m_count = meta.get_counter()->sum_register(); - } - - /** Called when the mutex is destroyed. */ - void destroy() - UNIV_NOTHROW - { - m_count = NULL; - } - - /** Called after a successful mutex acquire. - @param[in] n_spins Number of times the thread did - spins while trying to acquire the mutex - @param[in] n_waits Number of times the thread waited - in some type of OS queue */ - void add( - uint32_t n_spins, - uint32_t n_waits) - UNIV_NOTHROW - { - if (!m_count->m_enabled) { - - return; - } - - m_count->m_spins += n_spins; - m_count->m_waits += n_waits; - - ++m_count->m_calls; - } - - /** Print the information about the latch - @return the string representation */ - std::string print() const - UNIV_NOTHROW; - - /** @return the latch ID */ - latch_id_t get_id() const - { - return(m_id); - } - - - /** - I don't think it makes sense to keep track of the file name - and line number for each block mutex. Too much of overhead. Use the - latch id to figure out the location from the source. - - @return the string representation - */ - std::string to_string() const - { return(sync_mutex_to_string(get_id(), "buf0buf.cc:0")); } - -#ifdef UNIV_DEBUG - MutexDebug context; -#endif - -private: - /** The user visible counters, registered with the meta-data. */ - latch_meta_t::CounterType::Count *m_count; - - /** Latch meta data ID */ - latch_id_t m_id; -}; #endif /* sync0policy_h */ diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index bf47cb8fe88..84f4957c4f6 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -320,8 +320,7 @@ rw_lock_validate( const rw_lock_t* lock); /*!< in: rw-lock */ #endif /* UNIV_DEBUG */ /******************************************************************//** -Low-level function which tries to lock an rw-lock in s-mode. Performs no -spinning. +Low-level function which tries to lock an rw-lock in s-mode. @return TRUE if success */ UNIV_INLINE ibool @@ -568,11 +567,11 @@ struct rw_lock_t : public latch_t #endif /* UNIV_DEBUG */ { - /** Holds the state of the lock. */ - std::atomic lock_word; + /** Holds the state of the lock. */ + Atomic_relaxed lock_word; - /** 1: there are waiters */ - std::atomic waiters; + /** 0=no waiters, 1=waiters for X or SX lock exist */ + Atomic_relaxed waiters; /** number of granted SX locks. */ volatile ulint sx_recursive; diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index 0296ef065ff..169cbdd9aa5 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -77,7 +77,7 @@ rw_lock_get_writer( /*===============*/ const rw_lock_t* lock) /*!< in: rw-lock */ { - auto lock_word = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; ut_ad(lock_word <= X_LOCK_DECR); if (lock_word > X_LOCK_HALF_DECR) { @@ -109,7 +109,7 @@ rw_lock_get_reader_count( /*=====================*/ const rw_lock_t* lock) /*!< in: rw-lock */ { - auto lock_word = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; ut_ad(lock_word <= X_LOCK_DECR); if (lock_word > X_LOCK_HALF_DECR) { @@ -145,7 +145,7 @@ rw_lock_get_x_lock_count( /*=====================*/ const rw_lock_t* lock) /*!< in: rw-lock */ { - auto lock_copy = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_copy = lock->lock_word; ut_ad(lock_copy <= X_LOCK_DECR); if (lock_copy == 0 || lock_copy == -X_LOCK_HALF_DECR) { @@ -178,7 +178,7 @@ rw_lock_get_sx_lock_count( const rw_lock_t* lock) /*!< in: rw-lock */ { #ifdef UNIV_DEBUG - auto lock_copy = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_copy = lock->lock_word; ut_ad(lock_copy <= X_LOCK_DECR); @@ -209,7 +209,7 @@ rw_lock_lock_word_decr( int32_t amount, /*!< in: amount to decrement */ int32_t threshold) /*!< in: threshold of judgement */ { - auto lock_copy = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_copy = lock->lock_word; while (lock_copy > threshold) { if (lock->lock_word.compare_exchange_strong( @@ -220,13 +220,22 @@ rw_lock_lock_word_decr( return(true); } + + /* Note that lock_copy was reloaded above. We will + keep trying if a spurious conflict occurred, typically + caused by concurrent executions of + rw_lock_s_lock(). */ + + /* Note: unlike this implementation, rw_lock::read_lock() + allows concurrent calls without a spin loop */ } + + /* A real conflict was detected. */ return(false); } /******************************************************************//** -Low-level function which tries to lock an rw-lock in s-mode. Performs no -spinning. +Low-level function which tries to lock an rw-lock in s-mode. @return TRUE if success */ UNIV_INLINE ibool @@ -352,26 +361,21 @@ rw_lock_s_unlock_func( #endif /* UNIV_DEBUG */ rw_lock_t* lock) /*!< in/out: rw-lock */ { -#ifdef UNIV_DEBUG - auto dbg_lock_word = lock->lock_word.load(std::memory_order_relaxed); - ut_ad(dbg_lock_word > -X_LOCK_DECR); - ut_ad(dbg_lock_word != 0); - ut_ad(dbg_lock_word < X_LOCK_DECR); -#endif - ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S)); /* Increment lock_word to indicate 1 less reader */ - auto lock_word = lock->lock_word.fetch_add( - 1, std::memory_order_release) + 1; - if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) { + int32_t lock_word = lock->lock_word.fetch_add( + 1, std::memory_order_release); + if (lock_word == -1 || lock_word == -X_LOCK_HALF_DECR - 1) { /* wait_ex waiter exists. It may not be asleep, but we signal anyway. We do not wake other waiters, because they can't exist without wait_ex waiter and wait_ex waiter goes first.*/ os_event_set(lock->wait_ex_event); sync_array_object_signalled(); - + } else { + ut_ad(lock_word > -X_LOCK_DECR); + ut_ad(lock_word < X_LOCK_DECR); } ut_ad(rw_lock_validate(lock)); @@ -389,10 +393,7 @@ rw_lock_x_unlock_func( #endif /* UNIV_DEBUG */ rw_lock_t* lock) /*!< in/out: rw-lock */ { - auto lock_word = lock->lock_word.load(std::memory_order_relaxed); - - ut_ad(lock_word == 0 || lock_word == -X_LOCK_HALF_DECR - || lock_word <= -X_LOCK_DECR); + int32_t lock_word = lock->lock_word; if (lock_word == 0) { /* Last caller in a possible recursive chain. */ @@ -414,21 +415,19 @@ rw_lock_x_unlock_func( We need to signal read/write waiters. We do not need to signal wait_ex waiters, since they cannot exist when there is a writer. */ - if (lock->waiters.load(std::memory_order_relaxed)) { - lock->waiters.store(0, std::memory_order_relaxed); + if (lock->waiters) { + lock->waiters = 0; os_event_set(lock->event); sync_array_object_signalled(); } } else if (lock_word == -X_LOCK_DECR || lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) { /* There are 2 x-locks */ - lock->lock_word.fetch_add(X_LOCK_DECR, - std::memory_order_relaxed); + lock->lock_word.fetch_add(X_LOCK_DECR); } else { /* There are more than 2 x-locks. */ ut_ad(lock_word < -X_LOCK_DECR); - lock->lock_word.fetch_add(1, - std::memory_order_relaxed); + lock->lock_word.fetch_add(1); } ut_ad(rw_lock_validate(lock)); @@ -454,8 +453,7 @@ rw_lock_sx_unlock_func( ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_SX)); if (lock->sx_recursive == 0) { - auto lock_word = - lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; /* Last caller in a possible recursive chain. */ if (lock_word > 0) { lock->writer_thread = 0; @@ -472,8 +470,8 @@ rw_lock_sx_unlock_func( waiters. We do not need to signal wait_ex waiters, since they cannot exist when there is an sx-lock holder. */ - if (lock->waiters.load(std::memory_order_relaxed)) { - lock->waiters.store(0, std::memory_order_relaxed); + if (lock->waiters) { + lock->waiters = 0; os_event_set(lock->event); sync_array_object_signalled(); } @@ -481,8 +479,7 @@ rw_lock_sx_unlock_func( /* still has x-lock */ ut_ad(lock_word == -X_LOCK_HALF_DECR || lock_word <= -(X_LOCK_DECR + X_LOCK_HALF_DECR)); - lock->lock_word.fetch_add(X_LOCK_HALF_DECR, - std::memory_order_relaxed); + lock->lock_word.fetch_add(X_LOCK_HALF_DECR); } } diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index c6f7008e036..c63fedb43ee 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -51,9 +51,7 @@ instrumentation due to their large number of instances. */ #ifdef UNIV_PFS_MUTEX /* Key defines to register InnoDB mutexes with performance schema */ extern mysql_pfs_key_t autoinc_mutex_key; -extern mysql_pfs_key_t buffer_block_mutex_key; extern mysql_pfs_key_t buf_pool_mutex_key; -extern mysql_pfs_key_t buf_pool_zip_mutex_key; extern mysql_pfs_key_t cache_last_read_mutex_key; extern mysql_pfs_key_t dict_foreign_err_mutex_key; extern mysql_pfs_key_t dict_sys_mutex_key; @@ -64,7 +62,6 @@ extern mysql_pfs_key_t fts_delete_mutex_key; extern mysql_pfs_key_t fts_optimize_mutex_key; extern mysql_pfs_key_t fts_doc_id_mutex_key; extern mysql_pfs_key_t fts_pll_tokenize_mutex_key; -extern mysql_pfs_key_t hash_table_mutex_key; extern mysql_pfs_key_t ibuf_bitmap_mutex_key; extern mysql_pfs_key_t ibuf_mutex_key; extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; @@ -108,6 +105,7 @@ extern mysql_pfs_key_t thread_mutex_key; extern mysql_pfs_key_t zip_pad_mutex_key; extern mysql_pfs_key_t row_drop_list_mutex_key; extern mysql_pfs_key_t rw_trx_hash_element_mutex_key; +extern mysql_pfs_key_t read_view_mutex_key; #endif /* UNIV_PFS_MUTEX */ #ifdef UNIV_PFS_RWLOCK @@ -128,7 +126,6 @@ extern mysql_pfs_key_t index_tree_rw_lock_key; extern mysql_pfs_key_t index_online_log_key; extern mysql_pfs_key_t dict_table_stats_key; extern mysql_pfs_key_t trx_sys_rw_lock_key; -extern mysql_pfs_key_t hash_table_locks_key; #endif /* UNIV_PFS_RWLOCK */ /** Prints info of the sync system. diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index 4d2a7c8ff28..0aa1326509e 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -147,7 +147,7 @@ V lock_sys_mutex Mutex protecting lock_sys_t | V -trx_sys.mutex Mutex protecting trx_sys_t +trx_sys.mutex Mutex protecting trx_sys.trx_list | V Threads mutex Background thread scheduling mutex @@ -194,7 +194,6 @@ enum latch_level_t { SYNC_BUF_FLUSH_LIST, - SYNC_BUF_BLOCK, SYNC_BUF_PAGE_HASH, SYNC_BUF_POOL, @@ -221,6 +220,7 @@ enum latch_level_t { SYNC_THREADS, SYNC_TRX, SYNC_RW_TRX_HASH_ELEMENT, + SYNC_READ_VIEW, SYNC_TRX_SYS, SYNC_LOCK_SYS, SYNC_LOCK_WAIT_SYS, @@ -283,9 +283,7 @@ up its meta-data. See sync0debug.c. */ enum latch_id_t { LATCH_ID_NONE = 0, LATCH_ID_AUTOINC, - LATCH_ID_BUF_BLOCK_MUTEX, LATCH_ID_BUF_POOL, - LATCH_ID_BUF_POOL_ZIP, LATCH_ID_CACHE_LAST_READ, LATCH_ID_DICT_FOREIGN_ERR, LATCH_ID_DICT_SYS, @@ -297,7 +295,6 @@ enum latch_id_t { LATCH_ID_FTS_OPTIMIZE, LATCH_ID_FTS_DOC_ID, LATCH_ID_FTS_PLL_TOKENIZE, - LATCH_ID_HASH_TABLE_MUTEX, LATCH_ID_IBUF_BITMAP, LATCH_ID_IBUF, LATCH_ID_IBUF_PESSIMISTIC_INSERT, @@ -368,6 +365,7 @@ enum latch_id_t { LATCH_ID_FIL_CRYPT_DATA_MUTEX, LATCH_ID_FIL_CRYPT_THREADS_MUTEX, LATCH_ID_RW_TRX_HASH_ELEMENT, + LATCH_ID_READ_VIEW, LATCH_ID_TEST_MUTEX, LATCH_ID_MAX = LATCH_ID_TEST_MUTEX }; diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 0c3d4ee5c00..38e9e7207a2 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -128,8 +128,11 @@ class purge_sys_t public: /** latch protecting view, m_enabled */ MY_ALIGNED(CACHE_LINE_SIZE) - rw_lock_t latch; + mutable rw_lock_t latch; private: + /** The purge will not remove undo logs which are >= this view */ + MY_ALIGNED(CACHE_LINE_SIZE) + ReadViewBase view; /** whether purge is enabled; protected by latch and std::atomic */ std::atomic m_enabled; /** number of pending stop() calls without resume() */ @@ -137,9 +140,6 @@ private: public: que_t* query; /*!< The query graph which will do the parallelized purge operation */ - MY_ALIGNED(CACHE_LINE_SIZE) - ReadView view; /*!< The purge will not remove undo logs - which are >= this view (purge view) */ /** Iterator to the undo log records of committed transactions */ struct iterator @@ -246,6 +246,27 @@ public: void stop(); /** Resume purge at UNLOCK TABLES after FLUSH TABLES FOR EXPORT */ void resume(); + /** A wrapper around ReadView::changes_visible(). */ + bool changes_visible(trx_id_t id, const table_name_t &name) const + { + ut_ad(rw_lock_own(&latch, RW_LOCK_S)); + return view.changes_visible(id, name); + } + /** A wrapper around ReadView::low_limit_no(). */ + trx_id_t low_limit_no() const + { +#if 0 /* Unfortunately we don't hold this assertion, see MDEV-22718. */ + ut_ad(rw_lock_own(&latch, RW_LOCK_S)); +#endif + return view.low_limit_no(); + } + /** A wrapper around trx_sys_t::clone_oldest_view(). */ + void clone_oldest_view() + { + rw_lock_x_lock(&latch); + trx_sys.clone_oldest_view(&view); + rw_lock_x_unlock(&latch); + } }; /** The global data structure coordinating a purge */ diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index 89b8bdead53..6a562dcb425 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -34,15 +34,6 @@ Created 3/26/1996 Heikki Tuuri extern bool trx_rollback_is_active; extern const trx_t* trx_roll_crash_recv_trx; -/*******************************************************************//** -Determines if this transaction is rolling back an incomplete transaction -in crash recovery. -@return TRUE if trx is an incomplete transaction that is being rolled -back in crash recovery */ -ibool -trx_is_recv( -/*========*/ - const trx_t* trx); /*!< in: transaction */ /*******************************************************************//** Returns a transaction savepoint taken at this point in time. @return savepoint */ diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 73f05eb5d48..d91e77f9a52 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -41,8 +41,7 @@ Created 3/26/1996 Heikki Tuuri #ifdef WITH_WSREP #include "trx0xa.h" #endif /* WITH_WSREP */ - -typedef UT_LIST_BASE_NODE_T(trx_t) trx_ut_list_t; +#include "ilist.h" /** Checks if a page address is the trx sys header page. @param[in] page_id page id @@ -363,6 +362,13 @@ struct rw_trx_hash_element_t trx_id_t id; /* lf_hash_init() relies on this to be first in the struct */ + + /** + Transaction serialization number. + + Assigned shortly before the transaction is moved to COMMITTED_IN_MEMORY + state. Initially set to TRX_ID_MAX. + */ Atomic_counter no; trx_t *trx; ib_mutex_t mutex; @@ -378,6 +384,10 @@ class rw_trx_hash_t LF_HASH hash; + template + using walk_action= my_bool(rw_trx_hash_element_t *element, T *action); + + /** Constructor callback for lock-free allocator. @@ -480,18 +490,19 @@ class rw_trx_hash_t } - struct eliminate_duplicates_arg + template struct eliminate_duplicates_arg { trx_ids_t ids; - my_hash_walk_action action; - void *argument; - eliminate_duplicates_arg(size_t size, my_hash_walk_action act, void* arg): + walk_action *action; + T *argument; + eliminate_duplicates_arg(size_t size, walk_action *act, T *arg): action(act), argument(arg) { ids.reserve(size); } }; + template static my_bool eliminate_duplicates(rw_trx_hash_element_t *element, - eliminate_duplicates_arg *arg) + eliminate_duplicates_arg *arg) { for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++) { @@ -518,15 +529,16 @@ class rw_trx_hash_t } - struct debug_iterator_arg + template struct debug_iterator_arg { - my_hash_walk_action action; - void *argument; + walk_action *action; + T *argument; }; + template static my_bool debug_iterator(rw_trx_hash_element_t *element, - debug_iterator_arg *arg) + debug_iterator_arg *arg) { mutex_enter(&element->mutex); if (element->trx) @@ -741,23 +753,28 @@ public: @retval 1 iteration was interrupted (action returned 1) */ - int iterate(trx_t *caller_trx, my_hash_walk_action action, void *argument) + template + int iterate(trx_t *caller_trx, walk_action *action, T *argument= nullptr) { LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash); ut_a(pins); #ifdef UNIV_DEBUG - debug_iterator_arg debug_arg= { action, argument }; - action= reinterpret_cast(debug_iterator); - argument= &debug_arg; + debug_iterator_arg debug_arg= { action, argument }; + action= reinterpret_cast(debug_iterator); + argument= reinterpret_cast(&debug_arg); #endif - int res= lf_hash_iterate(&hash, pins, action, argument); + int res= lf_hash_iterate(&hash, pins, + reinterpret_cast(action), + const_cast(static_cast + (argument))); if (!caller_trx) lf_hash_put_pins(pins); return res; } - int iterate(my_hash_walk_action action, void *argument) + template + int iterate(walk_action *action, T *argument= nullptr) { return iterate(current_trx(), action, argument); } @@ -769,21 +786,65 @@ public: @sa iterate() */ - int iterate_no_dups(trx_t *caller_trx, my_hash_walk_action action, - void *argument) + template + int iterate_no_dups(trx_t *caller_trx, walk_action *action, + T *argument= nullptr) { - eliminate_duplicates_arg arg(size() + 32, action, argument); - return iterate(caller_trx, reinterpret_cast - (eliminate_duplicates), &arg); + eliminate_duplicates_arg arg(size() + 32, action, argument); + return iterate(caller_trx, eliminate_duplicates, &arg); } - int iterate_no_dups(my_hash_walk_action action, void *argument) + template + int iterate_no_dups(walk_action *action, T *argument= nullptr) { return iterate_no_dups(current_trx(), action, argument); } }; +class thread_safe_trx_ilist_t +{ +public: + void create() { mutex_create(LATCH_ID_TRX_SYS, &mutex); } + void close() { mutex_free(&mutex); } + + bool empty() const + { + mutex_enter(&mutex); + auto result= trx_list.empty(); + mutex_exit(&mutex); + return result; + } + + void push_front(trx_t &trx) + { + mutex_enter(&mutex); + trx_list.push_front(trx); + mutex_exit(&mutex); + } + + void remove(trx_t &trx) + { + mutex_enter(&mutex); + trx_list.remove(trx); + mutex_exit(&mutex); + } + + template void for_each(Callable &&callback) const + { + mutex_enter(&mutex); + for (const auto &trx : trx_list) + callback(trx); + mutex_exit(&mutex); + } + + void freeze() const { mutex_enter(&mutex); } + void unfreeze() const { mutex_exit(&mutex); } + +private: + alignas(CACHE_LINE_SIZE) mutable TrxSysMutex mutex; + alignas(CACHE_LINE_SIZE) ilist trx_list; +}; /** The transaction system central memory data structure. */ class trx_sys_t @@ -814,11 +875,8 @@ public: */ MY_ALIGNED(CACHE_LINE_SIZE) Atomic_counter rseg_history_len; - /** Mutex protecting trx_list. */ - MY_ALIGNED(CACHE_LINE_SIZE) mutable TrxSysMutex mutex; - /** List of all transactions. */ - MY_ALIGNED(CACHE_LINE_SIZE) trx_ut_list_t trx_list; + thread_safe_trx_ilist_t trx_list; MY_ALIGNED(CACHE_LINE_SIZE) /** Temporary rollback segments */ @@ -874,8 +932,7 @@ public: trx_id_t get_min_trx_id() { trx_id_t id= get_max_trx_id(); - rw_trx_hash.iterate(reinterpret_cast - (get_min_trx_id_callback), &id); + rw_trx_hash.iterate(get_min_trx_id_callback, &id); return id; } @@ -930,8 +987,7 @@ public: */ void assign_new_trx_no(trx_t *trx) { - trx->no= get_new_trx_id_no_refresh(); - trx->rw_trx_hash_element->no= trx->no; + trx->rw_trx_hash_element->no= get_new_trx_id_no_refresh(); refresh_rw_trx_hash_version(); } @@ -955,13 +1011,12 @@ public: @param[in,out] caller_trx used to get access to rw_trx_hash_pins @param[out] ids array to store registered transaction identifiers @param[out] max_trx_id variable to store m_max_trx_id value - @param[out] mix_trx_no variable to store min(trx->no) value + @param[out] mix_trx_no variable to store min(no) value */ void snapshot_ids(trx_t *caller_trx, trx_ids_t *ids, trx_id_t *max_trx_id, trx_id_t *min_trx_no) { - ut_ad(!mutex_own(&mutex)); snapshot_ids_arg arg(ids); while ((arg.m_id= get_rw_trx_hash_version()) != get_max_trx_id()) @@ -970,9 +1025,7 @@ public: ids->clear(); ids->reserve(rw_trx_hash.size() + 32); - rw_trx_hash.iterate(caller_trx, - reinterpret_cast(copy_one_id), - &arg); + rw_trx_hash.iterate(caller_trx, copy_one_id, &arg); *max_trx_id= arg.m_id; *min_trx_no= arg.m_no; @@ -1060,9 +1113,7 @@ public: */ void register_trx(trx_t *trx) { - mutex_enter(&mutex); - UT_LIST_ADD_FIRST(trx_list, trx); - mutex_exit(&mutex); + trx_list.push_front(*trx); } @@ -1073,9 +1124,7 @@ public: */ void deregister_trx(trx_t *trx) { - mutex_enter(&mutex); - UT_LIST_REMOVE(trx_list, trx); - mutex_exit(&mutex); + trx_list.remove(*trx); } @@ -1086,7 +1135,7 @@ public: in. This function is called by purge thread to determine whether it should purge the delete marked record or not. */ - void clone_oldest_view(); + void clone_oldest_view(ReadViewBase *view) const; /** @return the number of active views */ @@ -1094,14 +1143,11 @@ public: { size_t count= 0; - mutex_enter(&mutex); - for (const trx_t *trx= UT_LIST_GET_FIRST(trx_list); trx; - trx= UT_LIST_GET_NEXT(trx_list, trx)) - { - if (trx->read_view.get_state() == READ_VIEW_STATE_OPEN) + trx_list.for_each([&count](const trx_t &trx) { + if (trx.read_view.is_open()) ++count; - } - mutex_exit(&mutex); + }); + return count; } diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index be4504f71d8..034552fc62e 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -35,6 +35,7 @@ Created 3/26/1996 Heikki Tuuri #include "ut0vec.h" #include "fts0fts.h" #include "read0types.h" +#include "ilist.h" #include #include @@ -241,8 +242,7 @@ trx_commit_step( que_thr_t* thr); /*!< in: query thread */ /**********************************************************************//** -Prints info about a transaction. -Caller must hold trx_sys.mutex. */ +Prints info about a transaction. */ void trx_print_low( /*==========*/ @@ -262,7 +262,6 @@ trx_print_low( /**********************************************************************//** Prints info about a transaction. -The caller must hold lock_sys.mutex and trx_sys.mutex. When possible, use trx_print() instead. */ void trx_print_latched( @@ -304,7 +303,7 @@ trx_set_dict_operation( /**********************************************************************//** Determines if a transaction is in the given state. -The caller must hold trx_sys.mutex, or it must be the thread +The caller must hold trx->mutex, or it must be the thread that is serving a running transaction. A running RW transaction must be in trx_sys.rw_trx_hash. @return TRUE if trx->state == state */ @@ -435,32 +434,6 @@ Check transaction state */ ut_error; \ } while (0) -/** Check if transaction is free so that it can be re-initialized. -@param t transaction handle */ -#define assert_trx_is_free(t) do { \ - ut_ad(trx_state_eq((t), TRX_STATE_NOT_STARTED)); \ - ut_ad(!(t)->id); \ - ut_ad(!(t)->has_logged()); \ - ut_ad(!(t)->is_referenced()); \ - ut_ad(!(t)->is_wsrep()); \ - ut_ad(!(t)->read_view.is_open()); \ - ut_ad((t)->lock.wait_thr == NULL); \ - ut_ad(UT_LIST_GET_LEN((t)->lock.trx_locks) == 0); \ - ut_ad((t)->lock.table_locks.empty()); \ - ut_ad(!(t)->autoinc_locks \ - || ib_vector_is_empty((t)->autoinc_locks)); \ - ut_ad(UT_LIST_GET_LEN((t)->lock.evicted_tables) == 0); \ - ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \ -} while(0) - -/** Check if transaction is in-active so that it can be freed and put back to -transaction pool. -@param t transaction handle */ -#define assert_trx_is_inactive(t) do { \ - assert_trx_is_free((t)); \ - ut_ad((t)->dict_operation_lock_mode == 0); \ -} while(0) - #ifdef UNIV_DEBUG /*******************************************************************//** Assert that an autocommit non-locking select cannot be in the @@ -741,7 +714,7 @@ struct trx_rsegs_t { trx_temp_undo_t m_noredo; }; -struct trx_t { +struct trx_t : ilist_node<> { private: /** Count of references. @@ -762,14 +735,6 @@ public: trx_id_t id; /*!< transaction id */ - trx_id_t no; /*!< transaction serialization number: - max trx id shortly before the - transaction is moved to - COMMITTED_IN_MEMORY state. - Protected by trx_sys_t::mutex - when trx is in rw_trx_hash. Initially - set to TRX_ID_MAX. */ - /** State of the trx from the point of view of concurrency control and the valid state transitions. @@ -809,7 +774,7 @@ public: XA (2PC) transactions are always treated as non-autocommit. Transitions to ACTIVE or NOT_STARTED occur when transaction - is not in rw_trx_hash (no trx_sys.mutex needed). + is not in rw_trx_hash. Autocommit non-locking read-only transactions move between states without holding any mutex. They are not in rw_trx_hash. @@ -825,7 +790,7 @@ public: in rw_trx_hash. ACTIVE->PREPARED->COMMITTED is only possible when trx is in rw_trx_hash. - The transition ACTIVE->PREPARED is protected by trx_sys.mutex. + The transition ACTIVE->PREPARED is protected by trx->mutex. ACTIVE->COMMITTED is possible when the transaction is in rw_trx_hash. @@ -945,10 +910,6 @@ public: /*!< how many tables the current SQL statement uses, except those in consistent read */ - /*------------------------------*/ - UT_LIST_NODE_T(trx_t) trx_list; /*!< list of all transactions; - protected by trx_sys.mutex */ - /*------------------------------*/ dberr_t error_state; /*!< 0 if no error, otherwise error number; NOTE That ONLY the thread doing the transaction is allowed to @@ -1150,6 +1111,26 @@ public: } + void assert_freed() const + { + ut_ad(state == TRX_STATE_NOT_STARTED); + ut_ad(!id); + ut_ad(!has_logged()); + ut_ad(!is_referenced()); + ut_ad(!is_wsrep()); +#ifdef WITH_WSREP + ut_ad(!lock.was_chosen_as_wsrep_victim); +#endif + ut_ad(!read_view.is_open()); + ut_ad(!lock.wait_thr); + ut_ad(UT_LIST_GET_LEN(lock.trx_locks) == 0); + ut_ad(lock.table_locks.empty()); + ut_ad(!autoinc_locks || ib_vector_is_empty(autoinc_locks)); + ut_ad(UT_LIST_GET_LEN(lock.evicted_tables) == 0); + ut_ad(dict_operation == TRX_DICT_OP_NONE); + } + + private: /** Assign a rollback segment for modifying temporary tables. @return the assigned rollback segment */ diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic index f51d5368022..9fa4136f743 100644 --- a/storage/innobase/include/trx0trx.ic +++ b/storage/innobase/include/trx0trx.ic @@ -26,7 +26,7 @@ Created 3/26/1996 Heikki Tuuri /**********************************************************************//** Determines if a transaction is in the given state. -The caller must hold trx_sys.mutex, or it must be the thread +The caller must hold trx->mutex, or it must be the thread that is serving a running transaction. A running RW transaction must be in trx_sys.rw_trx_hash. @return TRUE if trx->state == state */ diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 83d6d2c0db2..219783b59e1 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -48,6 +48,8 @@ static const ulint TRX_SYS_SPACE = 0; /** Random value to check for corruption of trx_t */ static const ulint TRX_MAGIC_N = 91118598; +constexpr uint innodb_purge_threads_MAX= 32; + /** Transaction execution states when trx->state == TRX_STATE_ACTIVE */ enum trx_que_t { TRX_QUE_RUNNING, /*!< transaction is running */ diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic index 06e31eb55b3..43af932708e 100644 --- a/storage/innobase/include/trx0undo.ic +++ b/storage/innobase/include/trx0undo.ic @@ -133,7 +133,7 @@ inline uint16_t trx_undo_page_get_end(const buf_block_t *undo_page, uint32_t page_no, uint16_t offset) { - if (page_no == undo_page->page.id.page_no()) + if (page_no == undo_page->page.id().page_no()) if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG + offset + undo_page->frame)) return end; diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 4749ebfbb1c..18c228e56c3 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -170,14 +170,6 @@ using the call command. */ #define UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT */ -#include - -#if defined HAVE_valgrind && defined HAVE_VALGRIND_MEMCHECK_H -# define UNIV_DEBUG_VALGRIND -#elif __has_feature(memory_sanitizer) -# define UNIV_DEBUG_VALGRIND -#endif - #ifdef DBUG_OFF # undef UNIV_DEBUG #elif !defined UNIV_DEBUG @@ -185,14 +177,10 @@ using the call command. */ #endif #if 0 -#define UNIV_DEBUG_VALGRIND /* Enable extra - Valgrind instrumentation */ #define UNIV_DEBUG_PRINT /* Enable the compilation of some debug print functions */ #define UNIV_AHI_DEBUG /* Enable adaptive hash index debugging without UNIV_DEBUG */ -#define UNIV_BUF_DEBUG /* Enable buffer pool - debugging without UNIV_DEBUG */ #define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column debugging without UNIV_DEBUG */ #define UNIV_DEBUG_LOCK_VALIDATE /* Enable @@ -577,56 +565,6 @@ typedef void* os_thread_ret_t; #include "ut0ut.h" #include "sync0types.h" -/* define UNIV macros in terms of my_valgrind.h */ -#define UNIV_MEM_INVALID(addr, size) MEM_UNDEFINED(addr, size) -#define UNIV_MEM_FREE(addr, size) MEM_NOACCESS(addr, size) -#define UNIV_MEM_ALLOC(addr, size) UNIV_MEM_INVALID(addr, size) -#ifdef UNIV_DEBUG_VALGRIND -# include -# define UNIV_MEM_VALID(addr, size) MEM_MAKE_DEFINED(addr, size) -# define UNIV_MEM_DESC(addr, size) VALGRIND_CREATE_BLOCK(addr, size, #addr) -# define UNIV_MEM_UNDESC(b) VALGRIND_DISCARD(b) -# define UNIV_MEM_ASSERT_RW_LOW(addr, size, should_abort) do { \ - const void* _p = (const void*) (ulint) \ - VALGRIND_CHECK_MEM_IS_DEFINED(addr, size); \ - if (UNIV_LIKELY_NULL(_p)) { \ - fprintf(stderr, "%s:%d: %p[%u] undefined at %ld\n", \ - __FILE__, __LINE__, \ - (const void*) (addr), (unsigned) (size), (long) \ - (((const char*) _p) - ((const char*) (addr)))); \ - if (should_abort) { \ - ut_error; \ - } \ - } \ -} while (0) -# define UNIV_MEM_ASSERT_RW(addr, size) \ - UNIV_MEM_ASSERT_RW_LOW(addr, size, false) -# define UNIV_MEM_ASSERT_RW_ABORT(addr, size) \ - UNIV_MEM_ASSERT_RW_LOW(addr, size, true) -# define UNIV_MEM_ASSERT_W(addr, size) do { \ - const void* _p = (const void*) (ulint) \ - VALGRIND_CHECK_MEM_IS_ADDRESSABLE(addr, size); \ - if (UNIV_LIKELY_NULL(_p)) \ - fprintf(stderr, "%s:%d: %p[%u] unwritable at %ld\n", \ - __FILE__, __LINE__, \ - (const void*) (addr), (unsigned) (size), (long) \ - (((const char*) _p) - ((const char*) (addr)))); \ - } while (0) -# define UNIV_MEM_TRASH(addr, c, size) do { \ - ut_d(memset(addr, c, size)); \ - UNIV_MEM_INVALID(addr, size); \ - } while (0) -#else -# define UNIV_MEM_VALID(addr, size) do {} while(0) -# define UNIV_MEM_DESC(addr, size) do {} while(0) -# define UNIV_MEM_UNDESC(b) do {} while(0) -# define UNIV_MEM_ASSERT_RW_LOW(addr, size, should_abort) do {} while(0) -# define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0) -# define UNIV_MEM_ASSERT_RW_ABORT(addr, size) do {} while(0) -# define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) -# define UNIV_MEM_TRASH(addr, c, size) do {} while(0) -#endif - extern ulong srv_page_size_shift; extern ulong srv_page_size; diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index d7d48cd1f28..04ec10cc379 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -40,30 +40,21 @@ Created 2012-03-24 Sunny Bains. # ifdef HAVE_IB_LINUX_FUTEX UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex); -UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex); # endif /* HAVE_IB_LINUX_FUTEX */ UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex); -UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex); - UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex); -UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex); - UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex); -UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex); #ifdef MUTEX_FUTEX /** The default mutex type. */ typedef FutexMutex ib_mutex_t; -typedef BlockFutexMutex ib_bpmutex_t; #define MUTEX_TYPE "Uses futexes" #elif defined(MUTEX_SYS) typedef SysMutex ib_mutex_t; -typedef BlockSysMutex ib_bpmutex_t; #define MUTEX_TYPE "Uses system mutexes" #elif defined(MUTEX_EVENT) typedef SyncArrayMutex ib_mutex_t; -typedef BlockSyncArrayMutex ib_bpmutex_t; #define MUTEX_TYPE "Uses event mutexes" #else #error "ib_mutex_t type is unknown" diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index c35808a56e2..87249062a83 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -148,6 +148,8 @@ InnoDB: /** Maximum number of retries to allocate memory. */ extern const size_t alloc_max_retries; +constexpr uint32_t INVALID_AUTOEVENT_IDX = 0xFFFFFFFFU; + /** Keys for registering allocations with performance schema. Pointers to these variables are supplied to PFS code via the pfs_info[] array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)(). @@ -178,13 +180,13 @@ ut_new_boot(); #ifdef UNIV_PFS_MEMORY -/** Retrieve a memory key (registered with PFS), given a portion of the file -name of the caller. -@param[in] file portion of the filename - basename without an extension -@return registered memory key or PSI_NOT_INSTRUMENTED if not found */ -PSI_memory_key -ut_new_get_key_by_file( - const char* file); +/** +Retrieve a memory key (registered with PFS), +given AUTOEVENT_IDX of the caller + +@param[in] autoevent_idx - AUTOEVENT_IDX value of the caller +@return registered memory key or PSI_NOT_INSTRUMENTED */ +PSI_memory_key ut_new_get_key_by_file(uint32_t autoevent_idx); #endif /* UNIV_PFS_MEMORY */ @@ -293,7 +295,7 @@ public: ) { #ifdef UNIV_PFS_MEMORY - const PSI_memory_key other_key = other.get_mem_key(NULL); + const PSI_memory_key other_key = other.get_mem_key(); m_key = (other_key != mem_key_std) ? other_key @@ -315,7 +317,7 @@ public: #endif /* UNIV_PFS_MEMORY */ } - pointer allocate(size_type n) { return allocate(n, NULL, NULL); } + pointer allocate(size_type n) { return allocate(n, NULL, INVALID_AUTOEVENT_IDX); } /** Allocate a chunk of memory that can hold 'n_elements' objects of type 'T' and trace the allocation. @@ -333,9 +335,9 @@ public: allocate( size_type n_elements, const_pointer, - const char* + uint32_t #ifdef UNIV_PFS_MEMORY - file /*!< file name of the caller */ + autoevent_idx /* AUTOEVENT_IDX of the caller */ #endif , bool set_to_zero = false, @@ -397,7 +399,7 @@ public: #ifdef UNIV_PFS_MEMORY ut_new_pfx_t* pfx = static_cast(ptr); - allocate_trace(total_bytes, file, pfx); + allocate_trace(total_bytes, autoevent_idx, pfx); return(reinterpret_cast(pfx + 1)); #else @@ -479,7 +481,7 @@ public: reallocate( void* ptr, size_type n_elements, - const char* file) + uint32_t autoevent_idx) { if (n_elements == 0) { deallocate(static_cast(ptr)); @@ -487,7 +489,7 @@ public: } if (ptr == NULL) { - return(allocate(n_elements, NULL, file, false, false)); + return(allocate(n_elements, NULL, autoevent_idx, false, false)); } if (n_elements > max_size()) { @@ -530,7 +532,7 @@ public: deallocate_trace(pfx_new); /* pfx_new is set here to describe the new block. */ - allocate_trace(total_bytes, file, pfx_new); + allocate_trace(total_bytes, autoevent_idx, pfx_new); return(reinterpret_cast(pfx_new + 1)); } @@ -546,9 +548,10 @@ public: pointer new_array( size_type n_elements, - const char* file) + uint32_t autoevent_idx + ) { - T* p = allocate(n_elements, NULL, file, false, false); + T* p = allocate(n_elements, NULL, autoevent_idx, false, false); if (p == NULL) { return(NULL); @@ -634,7 +637,7 @@ public: if (pfx != NULL) { #ifdef UNIV_PFS_MEMORY - allocate_trace(n_bytes, NULL, pfx); + allocate_trace(n_bytes, 0, pfx); #endif /* UNIV_PFS_MEMORY */ pfx->m_size = n_bytes; } @@ -687,25 +690,16 @@ public: @return performance schema key */ PSI_memory_key get_mem_key( - const char* file) const + uint32_t autoevent_idx = INVALID_AUTOEVENT_IDX) const { if (m_key != PSI_NOT_INSTRUMENTED) { return(m_key); } - if (file == NULL) { + if (autoevent_idx == INVALID_AUTOEVENT_IDX) { return(mem_key_std); } - - /* e.g. "btr0cur", derived from "/path/to/btr0cur.cc" */ - char keyname[FILENAME_MAX]; - const size_t len = ut_basename_noext(file, keyname, - sizeof(keyname)); - /* If sizeof(keyname) was not enough then the output would - be truncated, assert that this did not happen. */ - ut_a(len < sizeof(keyname)); - - const PSI_memory_key key = ut_new_get_key_by_file(keyname); + const PSI_memory_key key = ut_new_get_key_by_file(autoevent_idx); if (key != PSI_NOT_INSTRUMENTED) { return(key); @@ -747,16 +741,16 @@ private: corresponds to "file", that will be used (see ut_new_boot()) 4. Otherwise, the name associated with mem_key_other will be used. @param[in] size number of bytes that were allocated - @param[in] file file name of the caller or NULL if unknown + @param[in] autoevent_idx autoevent_idx of the caller @param[out] pfx placeholder to store the info which will be needed when freeing the memory */ void allocate_trace( size_t size, - const char* file, + const uint32_t autoevent_idx, ut_new_pfx_t* pfx) { - const PSI_memory_key key = get_mem_key(file); + const PSI_memory_key key = get_mem_key(autoevent_idx); pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner); pfx->m_size = size; @@ -806,6 +800,128 @@ operator!=( #ifdef UNIV_PFS_MEMORY +/* + constexpr trickery ahead. + + Compute AUTOEVENT_IDX at compile time. + (index in the auto_event_names array, corresponding to basename of __FILE__) + + The tricks are necessary to reduce the cost of lookup the + PSI_memory_key for auto event. +*/ + +static constexpr const char* cexpr_basename_helper(const char* s, const char* last_slash) +{ + return + *s == '\0' ? last_slash : + *s == '/' || *s == '\\' ? cexpr_basename_helper(s + 1, s + 1) : + cexpr_basename_helper(s + 1, last_slash); +} + +static constexpr const char* cexpr_basename(const char* filename) +{ + return cexpr_basename_helper(filename, filename); +} + +static constexpr bool cexpr_strequal_ignore_dot(const char* a, const char* b) +{ + return *a == 0 || *a == '.' ? (*b == 0 || *b == '.') + : *a == *b ? cexpr_strequal_ignore_dot(a + 1, b + 1) : false; +} + +constexpr const char* const auto_event_names[] = +{ + "btr0btr", + "btr0buf", + "btr0bulk", + "btr0cur", + "btr0pcur", + "btr0sea", + "buf0buf", + "buf0dblwr", + "buf0dump", + "dict0dict", + "dict0mem", + "dict0stats", + "eval0eval", + "fil0crypt", + "fil0fil", + "fsp0file", + "fts0ast", + "fts0blex", + "fts0config", + "fts0file", + "fts0fts", + "fts0opt", + "fts0pars", + "fts0que", + "fts0sql", + "fts0tlex", + "gis0sea", + "ha_innodb", + "handler0alter", + "hash0hash", + "i_s", + "lexyy", + "lock0lock", + "mem0mem", + "os0event", + "os0file", + "pars0lex", + "rem0rec", + "row0ftsort", + "row0import", + "row0log", + "row0merge", + "row0mysql", + "row0sel", + "srv0start", + "sync0arr", + "sync0debug", + "sync0rw", + "sync0start", + "sync0types", + "trx0i_s", + "trx0i_s", + "trx0roll", + "trx0rseg", + "trx0seg", + "trx0trx", + "trx0undo", + "ut0list", + "ut0mem", + "ut0new", + "ut0pool", + "ut0rbt", + "ut0wqueue", + "xtrabackup", + nullptr +}; + +constexpr uint32_t cexpr_lookup_auto_event_name(const char* name, uint32_t idx = 0) +{ + return !auto_event_names[idx] ? INVALID_AUTOEVENT_IDX : + cexpr_strequal_ignore_dot(name, auto_event_names[idx]) ? idx : + cexpr_lookup_auto_event_name(name, idx + 1); +} + +/* + The AUTOEVENT_IDX macro. + + Note, that there is a static_assert that checks whether + basename of the __FILE is not registered in the auto_event_names array. + If you run into this assert, add the basename to the array. + + Weird looking lambda is used to force the evaluation at the compile time. +*/ +#define AUTOEVENT_IDX []()\ +{\ + constexpr auto idx = cexpr_lookup_auto_event_name(cexpr_basename(__FILE__)); \ + static_assert(idx != INVALID_AUTOEVENT_IDX, "auto_event_names contains no entry for " __FILE__);\ + return idx; \ +}() + + /** Allocate, trace the allocation and construct an object. Use this macro instead of 'new' within InnoDB. For example: instead of @@ -823,7 +939,7 @@ pointer must be passed to UT_DELETE() when no longer needed. object if the passed in pointer is NULL, e.g. if allocate() has failed to allocate memory and has returned NULL. */ \ ::new(ut_allocator(key).allocate( \ - sizeof expr, NULL, __FILE__, false, false)) expr + sizeof expr, NULL, AUTOEVENT_IDX, false, false)) expr /** Allocate, trace the allocation and construct an object. Use this macro instead of 'new' within InnoDB and instead of UT_NEW() @@ -845,6 +961,7 @@ We can't instantiate ut_allocator without having the type of the object, thus we redirect this to a templated function. */ #define UT_DELETE(ptr) ut_delete(ptr) + /** Destroy and account object created by UT_NEW() or UT_NEW_NOKEY(). @param[in,out] ptr pointer to the object */ template @@ -871,7 +988,7 @@ The returned pointer must be passed to UT_DELETE_ARRAY(). @param[in] key performance schema memory tracing key @return pointer to the first allocated object or NULL */ #define UT_NEW_ARRAY(type, n_elements, key) \ - ut_allocator(key).new_array(n_elements, __FILE__) + ut_allocator(key).new_array(n_elements, AUTOEVENT_IDX) /** Allocate and account 'n_elements' objects of type 'type'. Use this macro to allocate memory within InnoDB instead of 'new[]' and @@ -902,7 +1019,7 @@ ut_delete_array( #define ut_malloc(n_bytes, key) static_cast( \ ut_allocator(key).allocate( \ - n_bytes, NULL, __FILE__, false, false)) + n_bytes, NULL, AUTOEVENT_IDX, false, false)) #define ut_malloc_dontdump(n_bytes, key) static_cast( \ ut_allocator(key).allocate_large( \ @@ -910,23 +1027,23 @@ ut_delete_array( #define ut_zalloc(n_bytes, key) static_cast( \ ut_allocator(key).allocate( \ - n_bytes, NULL, __FILE__, true, false)) + n_bytes, NULL, AUTOEVENT_IDX, true, false)) #define ut_malloc_nokey(n_bytes) static_cast( \ ut_allocator(PSI_NOT_INSTRUMENTED).allocate( \ - n_bytes, NULL, __FILE__, false, false)) + n_bytes, NULL, AUTOEVENT_IDX, false, false)) #define ut_zalloc_nokey(n_bytes) static_cast( \ ut_allocator(PSI_NOT_INSTRUMENTED).allocate( \ - n_bytes, NULL, __FILE__, true, false)) + n_bytes, NULL, AUTOEVENT_IDX, true, false)) #define ut_zalloc_nokey_nofatal(n_bytes) static_cast( \ ut_allocator(PSI_NOT_INSTRUMENTED).allocate( \ - n_bytes, NULL, __FILE__, true, false)) + n_bytes, NULL, AUTOEVENT_IDX, true, false)) #define ut_realloc(ptr, n_bytes) static_cast( \ ut_allocator(PSI_NOT_INSTRUMENTED).reallocate( \ - ptr, n_bytes, __FILE__)) + ptr, n_bytes, AUTOEVENT_IDX)) #define ut_free(ptr) ut_allocator(PSI_NOT_INSTRUMENTED).deallocate( \ reinterpret_cast(ptr)) diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index 02a4e16bb70..703a07a23f2 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -86,11 +87,15 @@ struct Pool { for (Element* elem = m_start; elem != m_last; ++elem) { ut_ad(elem->m_pool == this); +#ifdef __SANITIZE_ADDRESS__ /* Unpoison the memory for AddressSanitizer */ MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); +#endif +#ifdef HAVE_valgrind /* Declare the contents as initialized for Valgrind; we checked this in mem_free(). */ - UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); + MEM_MAKE_DEFINED(&elem->m_type, sizeof elem->m_type); +#endif Factory::destroy(&elem->m_type); } @@ -127,13 +132,17 @@ struct Pool { #if defined HAVE_valgrind || defined __SANITIZE_ADDRESS__ if (elem) { +# ifdef __SANITIZE_ADDRESS__ /* Unpoison the memory for AddressSanitizer */ MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); +# endif +# ifdef HAVE_valgrind /* Declare the memory initialized for Valgrind. The trx_t that are released to the pool are actually initialized; we checked that by - UNIV_MEM_ASSERT_RW() in mem_free() below. */ - UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); + MEM_CHECK_DEFINED() in mem_free() below. */ +# endif + MEM_MAKE_DEFINED(&elem->m_type, sizeof elem->m_type); } #endif @@ -149,7 +158,7 @@ struct Pool { byte* p = reinterpret_cast(ptr + 1); elem = reinterpret_cast(p - sizeof(*elem)); - UNIV_MEM_ASSERT_RW(&elem->m_type, sizeof elem->m_type); + MEM_CHECK_DEFINED(&elem->m_type, sizeof elem->m_type); elem->m_pool->m_lock_strategy.enter(); diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 0814b90979d..6b79a445789 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -136,14 +136,6 @@ ulint ut_2_exp( /*=====*/ ulint n); /*!< in: number */ -/*************************************************************//** -Calculates fast the number rounded up to the nearest power of 2. -@return first power of 2 which is >= n */ -ulint -ut_2_power_up( -/*==========*/ - ulint n) /*!< in: number != 0 */ - MY_ATTRIBUTE((const)); /**********************************************************//** Returns the number of milliseconds since some epoch. The @@ -336,48 +328,41 @@ operator<<( It contains a std::ostringstream object. The main purpose of this class is to forward operator<< to the underlying std::ostringstream object. Do not use this class directly, instead use one of the derived classes. */ -class logger { -public: - template - ATTRIBUTE_COLD - logger& operator<<(const T& rhs) - { - m_oss << rhs; - return(*this); - } - - /** Write the given buffer to the internal string stream object. - @param[in] buf the buffer whose contents will be logged. - @param[in] count the length of the buffer buf. - @return the output stream into which buffer was written. */ - ATTRIBUTE_COLD - std::ostream& - write( - const char* buf, - std::streamsize count) - { - return(m_oss.write(buf, count)); - } - - /** Write the given buffer to the internal string stream object. - @param[in] buf the buffer whose contents will be logged. - @param[in] count the length of the buffer buf. - @return the output stream into which buffer was written. */ - ATTRIBUTE_COLD - std::ostream& - write( - const byte* buf, - std::streamsize count) - { - return(m_oss.write(reinterpret_cast(buf), count)); - } - - std::ostringstream m_oss; +class logger +{ protected: - /* This class must not be used directly, hence making the default - constructor protected. */ - ATTRIBUTE_COLD - logger() {} + /* This class must not be used directly */ + ATTRIBUTE_COLD ATTRIBUTE_NOINLINE logger() {} +public: + template ATTRIBUTE_COLD ATTRIBUTE_NOINLINE + logger& operator<<(const T& rhs) + { + m_oss << rhs; + return *this; + } + + /** Handle a fixed character string in the same way as a pointer to + an unknown-length character string, to reduce object code bloat. */ + template logger& operator<<(const char (&rhs)[N]) + { return *this << static_cast(rhs); } + + /** Output an error code name */ + ATTRIBUTE_COLD logger& operator<<(dberr_t err); + + /** Append a string. + @param buf string buffer + @param size buffer size + @return the output stream */ + ATTRIBUTE_COLD __attribute__((noinline)) + std::ostream &write(const char *buf, std::streamsize size) + { + return m_oss.write(buf, size); + } + + std::ostream &write(const byte *buf, std::streamsize size) + { return write(reinterpret_cast(buf), size); } + + std::ostringstream m_oss; }; /** The class info is used to emit informational log messages. It is to be @@ -411,6 +396,14 @@ class error : public logger { public: ATTRIBUTE_COLD ~error(); + /** Indicates that error::~error() was invoked. Can be used to + determine if error messages were logged during innodb code execution. + @return true if there were error messages, false otherwise. */ + static bool was_logged() { return logged; } + +private: + /** true if error::~error() was invoked, false otherwise */ + static bool logged; }; /** The class fatal is used to emit an error message and stop the server diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 938df53ec49..53d79b75a35 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -318,6 +318,7 @@ static FILE* lock_latest_err_file; /*********************************************************************//** Reports that a transaction id is insensible, i.e., in the future. */ +ATTRIBUTE_COLD void lock_report_trx_id_insanity( /*========================*/ @@ -331,7 +332,7 @@ lock_report_trx_id_insanity( ut_ad(!rec_is_metadata(rec, *index)); ib::error() - << "Transaction id " << trx_id + << "Transaction id " << ib::hex(trx_id) << " associated with record" << rec_offsets_print(rec, offsets) << " in index " << index->name << " of table " << index->table->name @@ -350,18 +351,18 @@ lock_check_trx_id_sanity( dict_index_t* index, /*!< in: index */ const rec_offs* offsets) /*!< in: rec_get_offsets(rec, index) */ { - ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_metadata(rec, *index)); + ut_ad(rec_offs_validate(rec, index, offsets)); + ut_ad(!rec_is_metadata(rec, *index)); - trx_id_t max_trx_id = trx_sys.get_max_trx_id(); - ut_ad(max_trx_id || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN); + trx_id_t max_trx_id= trx_sys.get_max_trx_id(); + ut_ad(max_trx_id || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN); - if (max_trx_id && trx_id >= max_trx_id) { - lock_report_trx_id_insanity( - trx_id, rec, index, offsets, max_trx_id); - return false; - } - return(true); + if (UNIV_LIKELY(max_trx_id != 0) && UNIV_UNLIKELY(trx_id >= max_trx_id)) + { + lock_report_trx_id_insanity(trx_id, rec, index, offsets, max_trx_id); + return false; + } + return true; } /*********************************************************************//** @@ -462,9 +463,9 @@ void lock_sys_t::create(ulint n_cells) mutex_create(LATCH_ID_LOCK_SYS_WAIT, &wait_mutex); - rec_hash = hash_create(n_cells); - prdt_hash = hash_create(n_cells); - prdt_page_hash = hash_create(n_cells); + rec_hash.create(n_cells); + prdt_hash.create(n_cells); + prdt_page_hash.create(n_cells); if (!srv_read_only_mode) { lock_latest_err_file = os_file_create_tmpfile(); @@ -497,34 +498,32 @@ void lock_sys_t::resize(ulint n_cells) mutex_enter(&mutex); - hash_table_t* old_hash = rec_hash; - rec_hash = hash_create(n_cells); - HASH_MIGRATE(old_hash, rec_hash, lock_t, hash, + hash_table_t old_hash(rec_hash); + rec_hash.create(n_cells); + HASH_MIGRATE(&old_hash, &rec_hash, lock_t, hash, lock_rec_lock_fold); - hash_table_free(old_hash); + old_hash.free(); old_hash = prdt_hash; - prdt_hash = hash_create(n_cells); - HASH_MIGRATE(old_hash, prdt_hash, lock_t, hash, + prdt_hash.create(n_cells); + HASH_MIGRATE(&old_hash, &prdt_hash, lock_t, hash, lock_rec_lock_fold); - hash_table_free(old_hash); + old_hash.free(); old_hash = prdt_page_hash; - prdt_page_hash = hash_create(n_cells); - HASH_MIGRATE(old_hash, prdt_page_hash, lock_t, hash, + prdt_page_hash.create(n_cells); + HASH_MIGRATE(&old_hash, &prdt_page_hash, lock_t, hash, lock_rec_lock_fold); - hash_table_free(old_hash); + old_hash.free(); /* need to update block->lock_hash_val */ mutex_enter(&buf_pool.mutex); for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU); bpage; bpage = UT_LIST_GET_NEXT(LRU, bpage)) { - if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) { - buf_block_t* block = reinterpret_cast( - bpage); - - block->lock_hash_val = lock_rec_hash( - bpage->id.space(), bpage->id.page_no()); + if (bpage->state() == BUF_BLOCK_FILE_PAGE) { + const page_id_t id(bpage->id()); + reinterpret_cast(bpage)->lock_hash_val + = lock_rec_hash(id.space(), id.page_no()); } } mutex_exit(&buf_pool.mutex); @@ -544,9 +543,9 @@ void lock_sys_t::close() lock_latest_err_file = NULL; } - hash_table_free(rec_hash); - hash_table_free(prdt_hash); - hash_table_free(prdt_page_hash); + rec_hash.free(); + prdt_hash.free(); + prdt_page_hash.free(); mutex_destroy(&mutex); mutex_destroy(&wait_mutex); @@ -734,7 +733,7 @@ lock_rec_has_to_wait( && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { mtr_t mtr; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "BF-BF lock conflict, locking: " << for_locking; lock_rec_print(stderr, lock2, mtr); @@ -746,7 +745,7 @@ lock_rec_has_to_wait( if ((type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - if (for_locking || wsrep_debug) { + if (for_locking || UNIV_UNLIKELY(wsrep_debug)) { /* exclusive lock conflicts are not accepted */ ib::info() @@ -781,7 +780,7 @@ lock_rec_has_to_wait( << ":" << lock2->type_mode << " idx: " << lock2->index->name() << " table: " - << lock2->index->table->name.m_name + << lock2->index->table->name << " n_uniq: " << lock2->index->n_uniq << " n_user: " << lock2->index->n_user_defined_cols @@ -872,7 +871,7 @@ lock_rec_expl_exist_on_page( lock_mutex_enter(); /* Only used in ibuf pages, so rec_hash is good enough */ - lock = lock_rec_get_first_on_page_addr(lock_sys.rec_hash, + lock = lock_rec_get_first_on_page_addr(&lock_sys.rec_hash, space, page_no); lock_mutex_exit(); @@ -990,7 +989,7 @@ lock_rec_has_expl( || (precise_mode & LOCK_MODE_MASK) == LOCK_X); ut_ad(!(precise_mode & LOCK_INSERT_INTENTION)); - for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { @@ -1043,8 +1042,8 @@ lock_rec_other_has_expl_req( return(NULL); } - for (lock_t* lock = lock_rec_get_first(lock_sys.rec_hash, - block, heap_no); + for (lock_t* lock = lock_rec_get_first(&lock_sys.rec_hash, + block, heap_no); lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { @@ -1087,7 +1086,7 @@ wsrep_kill_victim( trx->mysql_thd, lock->trx->mysql_thd))) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: BF victim waiting\n"; } /* cannot release lock, until our lock @@ -1120,7 +1119,7 @@ wsrep_kill_victim( } wsrep_innobase_kill_one_trx(trx->mysql_thd, - trx, lock->trx, TRUE); + lock->trx, true); } } } @@ -1149,7 +1148,7 @@ lock_rec_other_has_conflicting( bool is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM); - for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { @@ -1265,13 +1264,14 @@ lock_number_of_tables_locked( /*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/ #ifdef WITH_WSREP +ATTRIBUTE_COLD static void wsrep_print_wait_locks( /*===================*/ lock_t* c_lock) /* conflicting lock to print */ { - if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) { + if (c_lock->trx->lock.wait_lock != c_lock) { mtr_t mtr; ib::info() << "WSREP: c_lock != wait lock"; ib::info() << " SQL: " @@ -1423,7 +1423,7 @@ lock_rec_create_low( c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { wsrep_print_wait_locks(c_lock); } @@ -1450,7 +1450,7 @@ lock_rec_create_low( trx_mutex_exit(c_lock->trx); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id) << " SQL: " @@ -1468,7 +1468,7 @@ lock_rec_create_low( && innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS && !thd_is_replication_slave_thread(trx->mysql_thd)) { - HASH_PREPEND(lock_t, hash, lock_sys.rec_hash, + HASH_PREPEND(lock_t, hash, &lock_sys.rec_hash, lock_rec_fold(space, page_no), lock); } else { HASH_INSERT(lock_t, hash, lock_hash_get(type_mode), @@ -1538,8 +1538,7 @@ lock_rec_insert_by_trx_age( page_no = in_lock->un_member.rec_lock.page_no; rec_fold = lock_rec_fold(space, page_no); hash = lock_hash_get(in_lock->type_mode); - cell = hash_get_nth_cell(hash, - hash_calc_hash(rec_fold, hash)); + cell = &hash->array[hash->calc_hash(rec_fold)]; node = (lock_t *) cell->node; // If in_lock is not a wait lock, we insert it to the head of the list. @@ -1597,8 +1596,7 @@ lock_queue_validate( page_no = in_lock->un_member.rec_lock.page_no; rec_fold = lock_rec_fold(space, page_no); hash = lock_hash_get(in_lock->type_mode); - cell = hash_get_nth_cell(hash, - hash_calc_hash(rec_fold, hash)); + cell = &hash->array[hash->calc_hash(rec_fold)]; next = (lock_t *) cell->node; while (next != NULL) { // If this is a granted lock, check that there's no wait lock before it. @@ -1628,8 +1626,7 @@ lock_rec_insert_to_head( } hash = lock_hash_get(in_lock->type_mode); - cell = hash_get_nth_cell(hash, - hash_calc_hash(rec_fold, hash)); + cell = &hash->array[hash->calc_hash(rec_fold)]; node = (lock_t *) cell->node; if (node != in_lock) { cell->node = in_lock; @@ -1720,7 +1717,7 @@ lock_rec_enqueue_waiting( transaction as a victim, it is possible that we already have the lock now granted! */ #ifdef WITH_WSREP - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: BF thread got lock granted early, ID " << ib::hex(trx->id) << " query: " << wsrep_thd_query(trx->mysql_thd); } @@ -1745,7 +1742,7 @@ lock_rec_enqueue_waiting( == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS && !prdt && !thd_is_replication_slave_thread(lock->trx->mysql_thd)) { - HASH_DELETE(lock_t, hash, lock_sys.rec_hash, + HASH_DELETE(lock_t, hash, &lock_sys.rec_hash, lock_rec_lock_fold(lock), lock); dberr_t res = lock_rec_insert_by_trx_age(lock); if (res != DB_SUCCESS) { @@ -1928,7 +1925,7 @@ lock_rec_lock( if (lock_table_has(trx, index->table, static_cast(LOCK_MODE_MASK & mode))); - else if (lock_t *lock= lock_rec_get_first_on_page(lock_sys.rec_hash, block)) + else if (lock_t *lock= lock_rec_get_first_on_page(&lock_sys.rec_hash, block)) { trx_mutex_enter(trx); if (lock_rec_get_next_on_page(lock) || @@ -2041,7 +2038,7 @@ lock_rec_has_to_wait_in_queue( #ifdef WITH_WSREP if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { mtr_t mtr; ib::info() << "WSREP: waiting BF trx: " << ib::hex(wait_lock->trx->id) << " query: " << wsrep_thd_query(wait_lock->trx->mysql_thd); @@ -2151,9 +2148,8 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no) { lock_t* lock; lock_t* previous = static_cast( - hash_get_nth_cell(lock_sys.rec_hash, - hash_calc_hash(rec_fold, lock_sys.rec_hash)) - ->node); + lock_sys.rec_hash.array[lock_sys.rec_hash.calc_hash(rec_fold)]. + node); if (previous == NULL) { return; } @@ -2229,7 +2225,7 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock) if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS - || lock_hash != lock_sys.rec_hash + || lock_hash != &lock_sys.rec_hash || thd_is_replication_slave_thread(in_lock->trx->mysql_thd)) { /* Check if waiting locks in the queue can now be granted: grant locks if there are no conflicting locks ahead. Stop at @@ -2327,15 +2323,15 @@ lock_rec_free_all_from_discard_page( ut_ad(lock_mutex_own()); - space = block->page.id.space(); - page_no = block->page.id.page_no(); + space = block->page.id().space(); + page_no = block->page.id().page_no(); lock_rec_free_all_from_discard_page_low( - space, page_no, lock_sys.rec_hash); + space, page_no, &lock_sys.rec_hash); lock_rec_free_all_from_discard_page_low( - space, page_no, lock_sys.prdt_hash); + space, page_no, &lock_sys.prdt_hash); lock_rec_free_all_from_discard_page_low( - space, page_no, lock_sys.prdt_page_hash); + space, page_no, &lock_sys.prdt_page_hash); } /*============= RECORD LOCK MOVING AND INHERITING ===================*/ @@ -2380,12 +2376,12 @@ lock_rec_reset_and_release_wait( ulint heap_no)/*!< in: heap number of record */ { lock_rec_reset_and_release_wait_low( - lock_sys.rec_hash, block, heap_no); + &lock_sys.rec_hash, block, heap_no); lock_rec_reset_and_release_wait_low( - lock_sys.prdt_hash, block, PAGE_HEAP_NO_INFIMUM); + &lock_sys.prdt_hash, block, PAGE_HEAP_NO_INFIMUM); lock_rec_reset_and_release_wait_low( - lock_sys.prdt_page_hash, block, PAGE_HEAP_NO_INFIMUM); + &lock_sys.prdt_page_hash, block, PAGE_HEAP_NO_INFIMUM); } /*************************************************************//** @@ -2418,7 +2414,7 @@ lock_rec_inherit_to_gap( DO want S-locks/X-locks(taken for replace) set by a consistency constraint to be inherited also then. */ - for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { @@ -2454,7 +2450,7 @@ lock_rec_inherit_to_gap_if_gap_lock( lock_mutex_enter(); - for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { @@ -2498,8 +2494,8 @@ lock_rec_move_low( /* If the lock is predicate lock, it resides on INFIMUM record */ ut_ad(lock_rec_get_first( lock_hash, receiver, receiver_heap_no) == NULL - || lock_hash == lock_sys.prdt_hash - || lock_hash == lock_sys.prdt_page_hash); + || lock_hash == &lock_sys.prdt_hash + || lock_hash == &lock_sys.prdt_page_hash); for (lock = lock_rec_get_first(lock_hash, donator, donator_heap_no); @@ -2522,8 +2518,8 @@ lock_rec_move_low( lock->index, lock->trx, FALSE); } - ut_ad(lock_rec_get_first(lock_sys.rec_hash, - donator, donator_heap_no) == NULL); + ut_ad(!lock_rec_get_first(&lock_sys.rec_hash, + donator, donator_heap_no)); } /** Move all the granted locks to the front of the given lock list. @@ -2577,7 +2573,7 @@ lock_rec_move( ulint donator_heap_no)/*!< in: heap_no of the record which gives the locks */ { - lock_rec_move_low(lock_sys.rec_hash, receiver, donator, + lock_rec_move_low(&lock_sys.rec_hash, receiver, donator, receiver_heap_no, donator_heap_no); } @@ -2602,7 +2598,7 @@ lock_move_reorganize_page( lock_mutex_enter(); /* FIXME: This needs to deal with predicate lock too */ - lock = lock_rec_get_first_on_page(lock_sys.rec_hash, block); + lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block); if (lock == NULL) { lock_mutex_exit(); @@ -2735,7 +2731,8 @@ lock_move_rec_list_end( table to the end of the hash chain, and lock_rec_add_to_queue does not reuse locks if there are waiters in the queue. */ - for (lock = lock_rec_get_first_on_page(lock_sys.rec_hash, block); lock; + for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block); + lock; lock = lock_rec_get_next_on_page(lock)) { const rec_t* rec1 = rec; const rec_t* rec2; @@ -2850,7 +2847,8 @@ lock_move_rec_list_start( lock_mutex_enter(); - for (lock = lock_rec_get_first_on_page(lock_sys.rec_hash, block); lock; + for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block); + lock; lock = lock_rec_get_next_on_page(lock)) { const rec_t* rec1; const rec_t* rec2; @@ -2962,7 +2960,8 @@ lock_rtr_move_rec_list( lock_mutex_enter(); - for (lock = lock_rec_get_first_on_page(lock_sys.rec_hash, block); lock; + for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block); + lock; lock = lock_rec_get_next_on_page(lock)) { ulint moved = 0; const rec_t* rec1; @@ -3074,13 +3073,14 @@ lock_update_merge_right( waiting transactions */ lock_rec_reset_and_release_wait_low( - lock_sys.rec_hash, left_block, PAGE_HEAP_NO_SUPREMUM); + &lock_sys.rec_hash, left_block, PAGE_HEAP_NO_SUPREMUM); /* there should exist no page lock on the left page, otherwise, it will be blocked from merge */ - ut_ad(!lock_rec_get_first_on_page_addr(lock_sys.prdt_page_hash, - left_block->page.id.space(), - left_block->page.id.page_no())); + ut_ad(!lock_rec_get_first_on_page_addr( + &lock_sys.prdt_page_hash, + left_block->page.id().space(), + left_block->page.id().page_no())); lock_rec_free_all_from_discard_page(left_block); @@ -3188,7 +3188,7 @@ lock_update_merge_left( releasing waiting transactions */ lock_rec_reset_and_release_wait_low( - lock_sys.rec_hash, left_block, PAGE_HEAP_NO_SUPREMUM); + &lock_sys.rec_hash, left_block, PAGE_HEAP_NO_SUPREMUM); } /* Move the locks from the supremum of right page to the supremum @@ -3200,9 +3200,9 @@ lock_update_merge_left( /* there should exist no page lock on the right page, otherwise, it will be blocked from merge */ ut_ad(!lock_rec_get_first_on_page_addr( - lock_sys.prdt_page_hash, - right_block->page.id.space(), - right_block->page.id.page_no())); + &lock_sys.prdt_page_hash, + right_block->page.id().space(), + right_block->page.id().page_no())); lock_rec_free_all_from_discard_page(right_block); @@ -3253,9 +3253,9 @@ lock_update_discard( lock_mutex_enter(); - if (lock_rec_get_first_on_page(lock_sys.rec_hash, block)) { - ut_ad(!lock_rec_get_first_on_page(lock_sys.prdt_hash, block)); - ut_ad(!lock_rec_get_first_on_page(lock_sys.prdt_page_hash, + if (lock_rec_get_first_on_page(&lock_sys.rec_hash, block)) { + ut_ad(!lock_rec_get_first_on_page(&lock_sys.prdt_hash, block)); + ut_ad(!lock_rec_get_first_on_page(&lock_sys.prdt_page_hash, block)); /* Inherit all the locks on the page to the record and reset all the locks on the page */ @@ -3291,15 +3291,15 @@ lock_update_discard( } lock_rec_free_all_from_discard_page_low( - block->page.id.space(), block->page.id.page_no(), - lock_sys.rec_hash); + block->page.id().space(), block->page.id().page_no(), + &lock_sys.rec_hash); } else { lock_rec_free_all_from_discard_page_low( - block->page.id.space(), block->page.id.page_no(), - lock_sys.prdt_hash); + block->page.id().space(), block->page.id().page_no(), + &lock_sys.prdt_hash); lock_rec_free_all_from_discard_page_low( - block->page.id.space(), block->page.id.page_no(), - lock_sys.prdt_page_hash); + block->page.id().space(), block->page.id().page_no(), + &lock_sys.prdt_page_hash); } lock_mutex_exit(); @@ -3503,7 +3503,7 @@ lock_table_create( if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "table lock BF conflict for " << ib::hex(c_lock->trx->id) << " SQL: " @@ -3519,7 +3519,7 @@ lock_table_create( if (c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { wsrep_print_wait_locks(c_lock); } @@ -3530,7 +3530,7 @@ lock_table_create( c_lock->trx->lock.wait_lock); trx_mutex_enter(trx); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id) << " SQL: " @@ -3803,9 +3803,9 @@ lock_table_other_has_incompatible( #ifdef WITH_WSREP if (lock->trx->is_wsrep()) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: table lock abort for table:" - << table->name.m_name; + << table->name; ib::info() << " SQL: " << wsrep_thd_query(lock->trx->mysql_thd); } @@ -4067,12 +4067,10 @@ run_again: static void lock_grant_and_move_on_rec( - hash_table_t* lock_hash, lock_t* first_lock, ulint heap_no) { lock_t* lock; - lock_t* previous; ulint space; ulint page_no; ulint rec_fold; @@ -4081,8 +4079,9 @@ lock_grant_and_move_on_rec( page_no = first_lock->un_member.rec_lock.page_no; rec_fold = lock_rec_fold(space, page_no); - previous = (lock_t *) hash_get_nth_cell(lock_hash, - hash_calc_hash(rec_fold, lock_hash))->node; + lock_t* previous = static_cast( + lock_sys.rec_hash.array[lock_sys.rec_hash.calc_hash(rec_fold)] + .node); if (previous == NULL) { return; } @@ -4154,7 +4153,7 @@ lock_rec_unlock( lock_mutex_enter(); trx_mutex_enter(trx); - first_lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + first_lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); /* Find the last lock with the same lock_mode and transaction on the record. */ @@ -4203,7 +4202,7 @@ released: } } } else { - lock_grant_and_move_on_rec(lock_sys.rec_hash, first_lock, heap_no); + lock_grant_and_move_on_rec(first_lock, heap_no); } lock_mutex_exit(); @@ -4500,21 +4499,18 @@ http://bugs.mysql.com/36942 */ /*********************************************************************//** Calculates the number of record lock structs in the record lock hash table. @return number of record locks */ -static -ulint -lock_get_n_rec_locks(void) -/*======================*/ +static ulint lock_get_n_rec_locks() { ulint n_locks = 0; ulint i; ut_ad(lock_mutex_own()); - for (i = 0; i < hash_get_n_cells(lock_sys.rec_hash); i++) { + for (i = 0; i < lock_sys.rec_hash.n_cells; i++) { const lock_t* lock; for (lock = static_cast( - HASH_GET_FIRST(lock_sys.rec_hash, i)); + HASH_GET_FIRST(&lock_sys.rec_hash, i)); lock != 0; lock = static_cast( HASH_GET_NEXT(hash, lock))) { @@ -4595,15 +4591,7 @@ lock_trx_print_wait_and_mvcc_state(FILE* file, const trx_t* trx, time_t now) fprintf(file, "---"); trx_print_latched(file, trx, 600); - - /* Note: read_view->get_state() check is race condition. But it - should "kind of work" because read_view is freed only at shutdown. - Worst thing that may happen is that it'll get transferred to - another thread and print wrong values. */ - - if (trx->read_view.get_state() == READ_VIEW_STATE_OPEN) { - trx->read_view.print_limits(file); - } + trx->read_view.print_limits(file); if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) { @@ -4666,15 +4654,14 @@ struct lock_print_info purge_trx(purge_sys.query ? purge_sys.query->trx : NULL) {} - void operator()(const trx_t* trx) const + void operator()(const trx_t &trx) const { - ut_ad(mutex_own(&trx_sys.mutex)); - if (UNIV_UNLIKELY(trx == purge_trx)) + if (UNIV_UNLIKELY(&trx == purge_trx)) return; - lock_trx_print_wait_and_mvcc_state(file, trx, now); + lock_trx_print_wait_and_mvcc_state(file, &trx, now); - if (trx->will_lock && srv_print_innodb_lock_monitor) - lock_trx_print_locks(file, trx); + if (trx.will_lock && srv_print_innodb_lock_monitor) + lock_trx_print_locks(file, &trx); } FILE* const file; @@ -4694,11 +4681,8 @@ lock_print_info_all_transactions( ut_ad(lock_mutex_own()); fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); - const time_t now = time(NULL); - mutex_enter(&trx_sys.mutex); - ut_list_map(trx_sys.trx_list, lock_print_info(file, now)); - mutex_exit(&trx_sys.mutex); + trx_sys.trx_list.for_each(lock_print_info(file, time(nullptr))); lock_mutex_exit(); ut_ad(lock_validate()); @@ -4818,7 +4802,7 @@ lock_rec_queue_validate( if (!page_rec_is_user_rec(rec)) { - for (lock = lock_rec_get_first(lock_sys.rec_hash, + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next_const(heap_no, lock)) { @@ -4903,7 +4887,7 @@ func_exit: mutex_exit(&impl_trx->mutex); } - for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; lock = lock_rec_get_next_const(heap_no, lock)) { @@ -4972,8 +4956,8 @@ lock_rec_validate_page( lock_mutex_enter(); loop: lock = lock_rec_get_first_on_page_addr( - lock_sys.rec_hash, - block->page.id.space(), block->page.id.page_no()); + &lock_sys.rec_hash, + block->page.id().space(), block->page.id().page_no()); if (!lock) { goto function_exit; @@ -5051,7 +5035,7 @@ lock_rec_validate( ut_ad(lock_mutex_own()); for (const lock_t* lock = static_cast( - HASH_GET_FIRST(lock_sys.rec_hash, start)); + HASH_GET_FIRST(&lock_sys.rec_hash, start)); lock != NULL; lock = static_cast(HASH_GET_NEXT(hash, lock))) { @@ -5165,14 +5149,13 @@ lock_validate() lock_mutex_enter(); /* Validate table locks */ - trx_sys.rw_trx_hash.iterate(reinterpret_cast - (lock_validate_table_locks), 0); + trx_sys.rw_trx_hash.iterate(lock_validate_table_locks); /* Iterate over all the record locks and validate the locks. We - don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex. - Release both mutexes during the validation check. */ + don't want to hog the lock_sys_t::mutex. Release it during the + validation check. */ - for (ulint i = 0; i < hash_get_n_cells(lock_sys.rec_hash); i++) { + for (ulint i = 0; i < lock_sys.rec_hash.n_cells; i++) { ib_uint64_t limit = 0; while (const lock_t* lock = lock_rec_validate(i, &limit)) { @@ -5253,7 +5236,7 @@ lock_rec_insert_check_and_lock( BTR_NO_LOCKING_FLAG and skip the locking altogether. */ ut_ad(lock_table_has(trx, index->table, LOCK_IX)); - lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no); + lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); if (lock == NULL) { /* We optimize CPU time usage in the simplest case */ @@ -5460,9 +5443,7 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx, lock_rec_other_trx_holds_expl_arg arg= { page_rec_get_heap_no(rec), block, trx }; trx_sys.rw_trx_hash.iterate(caller_trx, - reinterpret_cast - (lock_rec_other_trx_holds_expl_callback), - &arg); + lock_rec_other_trx_holds_expl_callback, &arg); lock_mutex_exit(); } } @@ -6207,7 +6188,7 @@ static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, ut_ad(lock->trx == element->trx); if (lock_get_type_low(lock) == LOCK_REC) { - ut_ad(!dict_index_is_online_ddl(lock->index) || + ut_ad(lock->index->online_status != ONLINE_INDEX_CREATION || lock->index->is_primary()); ut_ad(lock->index->table != table); } @@ -6241,10 +6222,7 @@ lock_table_has_locks( #ifdef UNIV_DEBUG if (!has_locks) { - trx_sys.rw_trx_hash.iterate( - reinterpret_cast - (lock_table_locks_lookup), - const_cast(table)); + trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup, table); } #endif /* UNIV_DEBUG */ @@ -6492,11 +6470,9 @@ DeadlockChecker::get_first_lock(ulint* heap_no) const const lock_t* lock = m_wait_lock; if (lock_get_type_low(lock) == LOCK_REC) { - hash_table_t* lock_hash; - - lock_hash = lock->type_mode & LOCK_PREDICATE - ? lock_sys.prdt_hash - : lock_sys.rec_hash; + hash_table_t* lock_hash = lock->type_mode & LOCK_PREDICATE + ? &lock_sys.prdt_hash + : &lock_sys.rec_hash; /* We are only interested in records that match the heap_no. */ *heap_no = lock_rec_find_set_bit(lock); diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc index 6458d202bf2..a04fd3fe73c 100644 --- a/storage/innobase/lock/lock0prdt.cc +++ b/storage/innobase/lock/lock0prdt.cc @@ -541,7 +541,7 @@ lock_prdt_insert_check_and_lock( lock_t* lock; /* Only need to check locks on prdt_hash */ - lock = lock_rec_get_first(lock_sys.prdt_hash, block, PRDT_HEAPNO); + lock = lock_rec_get_first(&lock_sys.prdt_hash, block, PRDT_HEAPNO); if (lock == NULL) { lock_mutex_exit(); @@ -628,7 +628,7 @@ lock_prdt_update_parent( /* Get all locks in parent */ for (lock = lock_rec_get_first_on_page_addr( - lock_sys.prdt_hash, space, page_no); + &lock_sys.prdt_hash, space, page_no); lock; lock = lock_rec_get_next_on_page(lock)) { lock_prdt_t* lock_prdt; @@ -815,8 +815,8 @@ lock_prdt_lock( ut_ad(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE)); hash_table_t* hash = type_mode == LOCK_PREDICATE - ? lock_sys.prdt_hash - : lock_sys.prdt_page_hash; + ? &lock_sys.prdt_hash + : &lock_sys.prdt_page_hash; /* Another transaction cannot have an implicit lock on the record, because when we come here, we already have modified the clustered @@ -925,7 +925,7 @@ lock_place_prdt_page_lock( lock_mutex_enter(); const lock_t* lock = lock_rec_get_first_on_page_addr( - lock_sys.prdt_page_hash, space, page_no); + &lock_sys.prdt_page_hash, space, page_no); const ulint mode = LOCK_S | LOCK_PRDT_PAGE; trx_t* trx = thr_get_trx(thr); @@ -981,7 +981,7 @@ lock_test_prdt_page_lock( lock_mutex_enter(); lock = lock_rec_get_first_on_page_addr( - lock_sys.prdt_page_hash, space, page_no); + &lock_sys.prdt_page_hash, space, page_no); lock_mutex_exit(); @@ -999,16 +999,10 @@ lock_prdt_rec_move( const buf_block_t* donator) /*!< in: buffer block containing the donating record */ { - lock_t* lock; - - if (!lock_sys.prdt_hash) { - return; - } - lock_mutex_enter(); - for (lock = lock_rec_get_first(lock_sys.prdt_hash, - donator, PRDT_HEAPNO); + for (lock_t *lock = lock_rec_get_first(&lock_sys.prdt_hash, + donator, PRDT_HEAPNO); lock != NULL; lock = lock_rec_get_next(PRDT_HEAPNO, lock)) { @@ -1041,8 +1035,8 @@ lock_prdt_page_free_from_discard( ut_ad(lock_mutex_own()); - space = block->page.id.space(); - page_no = block->page.id.page_no(); + space = block->page.id().space(); + page_no = block->page.id().page_no(); lock = lock_rec_get_first_on_page_addr(lock_hash, space, page_no); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index fdc47a8d442..84589e7950f 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -91,27 +91,17 @@ should be bigger than LOG_POOL_PREFLUSH_RATIO_SYNC */ the previous */ #define LOG_POOL_PREFLUSH_RATIO_ASYNC 8 -/****************************************************************//** -Returns the oldest modified block lsn in the pool, or log_sys.lsn if none -exists. +/** Return the oldest modified LSN in buf_pool.flush_list, +or the latest LSN if all pages are clean. @return LSN of oldest modification */ -static -lsn_t -log_buf_pool_get_oldest_modification(void) -/*======================================*/ +static lsn_t log_buf_pool_get_oldest_modification() { - lsn_t lsn; + ut_ad(log_mutex_own()); + log_flush_order_mutex_enter(); + lsn_t lsn= buf_pool.get_oldest_modification(); + log_flush_order_mutex_exit(); - ut_ad(log_mutex_own()); - - lsn = buf_pool_get_oldest_modification(); - - if (!lsn) { - - lsn = log_sys.get_lsn(); - } - - return(lsn); + return lsn ? lsn : log_sys.get_lsn(); } /** Extends the log buffer. @@ -419,7 +409,7 @@ log_close(void) goto function_exit; } - oldest_lsn = buf_pool_get_oldest_modification(); + oldest_lsn = log_buf_pool_get_oldest_modification(); if (!oldest_lsn || lsn - oldest_lsn > log_sys.max_modified_age_sync @@ -432,7 +422,7 @@ function_exit: } /** Calculate the recommended highest values for lsn - last_checkpoint_lsn -and lsn - buf_get_oldest_modification(). +and lsn - buf_pool.get_oldest_modification(). @param[in] file_size requested innodb_log_file_size @retval true on success @retval false if the smallest log group is too small to @@ -440,6 +430,12 @@ accommodate the number of OS threads in the database server */ bool log_set_capacity(ulonglong file_size) { + /* Margin for the free space in the smallest log, before a new query + step which modifies the database, is started */ + const size_t LOG_CHECKPOINT_FREE_PER_THREAD = 4U + << srv_page_size_shift; + const size_t LOG_CHECKPOINT_EXTRA_FREE = 8U << srv_page_size_shift; + lsn_t margin; ulint free; @@ -455,14 +451,11 @@ log_set_capacity(ulonglong file_size) free = LOG_CHECKPOINT_FREE_PER_THREAD * (10 + srv_thread_concurrency) + LOG_CHECKPOINT_EXTRA_FREE; if (free >= smallest_capacity / 2) { - ib::error() << "Cannot continue operation. " << LOG_FILE_NAME - << " is too small for innodb_thread_concurrency=" - << srv_thread_concurrency << ". The size of " - << LOG_FILE_NAME - << " should be bigger than 200 kB * " - "innodb_thread_concurrency. " + ib::error() << "Cannot continue operation because log file is " + "too small. Increase innodb_log_file_size " + "or decrease innodb_thread_concurrency. " << INNODB_PARAMETERS_MSG; - return(false); + return false; } margin = smallest_capacity - free; @@ -1051,7 +1044,7 @@ static void log_write(bool rotate_key) } } - if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE)) { + if (UNIV_UNLIKELY(srv_shutdown_state > SRV_SHUTDOWN_INITIATED)) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "InnoDB log write: " LSN_PF, log_sys.write_lsn); @@ -1214,7 +1207,7 @@ static bool log_preflush_pool_modified_pages(lsn_t new_oldest) success = buf_flush_lists(ULINT_MAX, new_oldest, &n_pages); - buf_flush_wait_batch_end(BUF_FLUSH_LIST); + buf_flush_wait_batch_end(false); if (!success) { MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS); @@ -1250,7 +1243,7 @@ void log_write_checkpoint_info(lsn_t end_lsn) ut_ad(end_lsn == 0 || end_lsn >= log_sys.next_checkpoint_lsn); ut_ad(end_lsn <= log_sys.get_lsn()); ut_ad(end_lsn + SIZE_OF_FILE_CHECKPOINT <= log_sys.get_lsn() - || srv_shutdown_state != SRV_SHUTDOWN_NONE); + || srv_shutdown_state > SRV_SHUTDOWN_INITIATED); DBUG_PRINT("ib_log", ("checkpoint " UINT64PF " at " LSN_PF " written", @@ -1364,7 +1357,7 @@ bool log_checkpoint() if (oldest_lsn > log_sys.last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT) { /* Some log has been written since the previous checkpoint. */ - } else if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + } else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { /* MariaDB startup expects the redo log file to be logically empty (not even containing a MLOG_CHECKPOINT record) after a clean shutdown. Perform an extra checkpoint at @@ -1389,7 +1382,7 @@ bool log_checkpoint() lsn_t flush_lsn = oldest_lsn; const lsn_t end_lsn = log_sys.get_lsn(); const bool do_write - = srv_shutdown_state == SRV_SHUTDOWN_NONE + = srv_shutdown_state <= SRV_SHUTDOWN_INITIATED || flush_lsn != end_lsn; if (fil_names_clear(flush_lsn, do_write)) { @@ -1520,14 +1513,9 @@ void log_check_margins() } extern void buf_resize_shutdown(); -/****************************************************************//** -Makes a checkpoint at the latest lsn and writes it to first page of each -data file in the database, so that we know that the file spaces contain -all modifications up to that lsn. This can only be called at database -shutdown. This function also writes log in log file to the log archive. */ -void -logs_empty_and_mark_files_at_shutdown(void) -/*=======================================*/ + +/** Make a checkpoint at the latest lsn on shutdown. */ +void logs_empty_and_mark_files_at_shutdown() { lsn_t lsn; ulint count = 0; @@ -1678,7 +1666,7 @@ wait_suspend_loop: if (!buf_pool.is_initialised()) { ut_ad(!srv_was_started); - } else if (ulint pending_io = buf_pool_check_no_pending_io()) { + } else if (ulint pending_io = buf_pool.io_pending()) { if (srv_print_verbose_log && count > 600) { ib::info() << "Waiting for " << pending_io << " buffer" " page I/Os to complete"; @@ -1709,10 +1697,6 @@ wait_suspend_loop: } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; - - if (fil_system.is_initialised()) { - fil_close_all_files(); - } return; } @@ -1736,8 +1720,6 @@ wait_suspend_loop: goto loop; } - /* Ensure that all buffered changes are written to the - redo log before fil_close_all_files(). */ log_sys.log.flush(); } else { lsn = recv_sys.recovered_lsn; @@ -1772,8 +1754,6 @@ wait_suspend_loop: } } - fil_close_all_files(); - /* Make some checks that the server really is quiet */ ut_ad(!srv_any_background_activity()); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 6f5ef55d958..2a4891f2716 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -165,7 +165,7 @@ public: free + len + 6 >= srv_page_size - FIL_PAGE_DATA_END)) { ib::error() << "Not applying UNDO_APPEND due to corruption on " - << block.page.id; + << block.page.id(); return true; } @@ -224,13 +224,13 @@ public: size_t idlen= mlog_decode_varint_length(*l); ut_ad(idlen <= 5); ut_ad(idlen < rlen); - ut_ad(mlog_decode_varint(l) == block.page.id.space()); + ut_ad(mlog_decode_varint(l) == block.page.id().space()); l+= idlen; rlen-= idlen; idlen= mlog_decode_varint_length(*l); ut_ad(idlen <= 5); ut_ad(idlen <= rlen); - ut_ad(mlog_decode_varint(l) == block.page.id.page_no()); + ut_ad(mlog_decode_varint(l) == block.page.id().page_no()); l+= idlen; rlen-= idlen; last_offset= 0; @@ -244,9 +244,9 @@ public: if (UNIV_LIKELY(rlen == 0)) { memset_aligned(frame, 0, size); - mach_write_to_4(frame + FIL_PAGE_OFFSET, block.page.id.page_no()); + mach_write_to_4(frame + FIL_PAGE_OFFSET, block.page.id().page_no()); memset_aligned<8>(FIL_PAGE_PREV + frame, 0xff, 8); - mach_write_to_4(frame + FIL_PAGE_SPACE_ID, block.page.id.space()); + mach_write_to_4(frame + FIL_PAGE_SPACE_ID, block.page.id().space()); last_offset= FIL_PAGE_TYPE; next_after_applying: if (applied == APPLIED_NO) @@ -269,9 +269,9 @@ public: } ut_ad(mach_read_from_4(frame + FIL_PAGE_OFFSET) == - block.page.id.page_no()); + block.page.id().page_no()); ut_ad(mach_read_from_4(frame + FIL_PAGE_SPACE_ID) == - block.page.id.space()); + block.page.id().space()); ut_ad(last_offset <= 1 || last_offset > 8); ut_ad(last_offset <= size); @@ -279,7 +279,7 @@ public: case OPTION: goto next; case EXTENDED: - if (UNIV_UNLIKELY(block.page.id.page_no() < 3 || + if (UNIV_UNLIKELY(block.page.id().page_no() < 3 || block.page.zip.ssize)) goto record_corrupted; static_assert(INIT_ROW_FORMAT_REDUNDANT == 0, "compatiblity"); @@ -462,7 +462,7 @@ page_corrupted: if (UNIV_UNLIKELY(rlen + last_offset > size)) goto record_corrupted; memcpy(frame + last_offset, l, llen); - if (UNIV_LIKELY(block.page.id.page_no())); + if (UNIV_LIKELY(block.page.id().page_no())); else if (llen == 11 + MY_AES_BLOCK_SIZE && last_offset == FSP_HEADER_OFFSET + MAGIC_SZ + fsp_header_get_encryption_offset(block.zip_size())) @@ -543,11 +543,24 @@ struct file_name_t { /** FSP_SIZE of tablespace */ ulint size; + /** Freed pages of tablespace */ + range_set freed_ranges; + /** Constructor */ file_name_t(std::string name_, bool deleted) : name(std::move(name_)), space(NULL), status(deleted ? DELETED: NORMAL), size(0) {} + + /** Add the freed pages */ + void add_freed_page(uint32_t page_no) { freed_ranges.add_value(page_no); } + + /** Remove the freed pages */ + void remove_freed_page(uint32_t page_no) + { + if (freed_ranges.empty()) return; + freed_ranges.remove_value(page_no); + } }; /** Map of dirty tablespaces during recovery */ @@ -675,7 +688,7 @@ public: break; } ib::error() << "corrupted " - << block->page.id; + << block->page.id(); } } if (recv_no_ibuf_operations) { @@ -685,7 +698,7 @@ public: } mutex_exit(&recv_sys.mutex); block->page.ibuf_exist = ibuf_page_exists( - block->page.id, block->zip_size()); + block->page.id(), block->zip_size()); mtr.commit(); mtr.start(); mutex_enter(&recv_sys.mutex); @@ -966,7 +979,7 @@ DECLARE_THREAD(recv_writer_thread)( /* Flush pages from end of LRU if required */ os_event_reset(recv_sys.flush_end); - recv_sys.flush_type = BUF_FLUSH_LRU; + recv_sys.flush_lru = true; os_event_set(recv_sys.flush_start); os_event_wait(recv_sys.flush_end); @@ -999,7 +1012,7 @@ void recv_sys_t::create() flush_end = os_event_create(0); } - flush_type = BUF_FLUSH_LRU; + flush_lru = true; apply_log_recs = false; apply_batch_on = false; @@ -1035,7 +1048,7 @@ inline void recv_sys_t::clear() for (buf_block_t *block= UT_LIST_GET_LAST(blocks); block; ) { buf_block_t *prev_block= UT_LIST_GET_PREV(unzip_LRU, block); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_MEMORY); + ut_ad(block->page.state() == BUF_BLOCK_MEMORY); UT_LIST_REMOVE(blocks, block); buf_block_free(block); block= prev_block; @@ -1080,8 +1093,8 @@ create_block: ut_calc_align(static_cast(len), ALIGNMENT); static_assert(ut_is_2pow(ALIGNMENT), "ALIGNMENT must be a power of 2"); UT_LIST_ADD_FIRST(blocks, block); - UNIV_MEM_INVALID(block->frame, len); - UNIV_MEM_FREE(block->frame + len, srv_page_size - len); + MEM_UNDEFINED(block->frame, len); + MEM_NOACCESS(block->frame + len, srv_page_size - len); return my_assume_aligned(block->frame); } @@ -1100,7 +1113,7 @@ create_block: block->page.access_time= ((block->page.access_time >> 16) + 1) << 16 | ut_calc_align(static_cast(free_offset), ALIGNMENT); - UNIV_MEM_ALLOC(block->frame + free_offset - len, len); + MEM_UNDEFINED(block->frame + free_offset - len, len); return my_assume_aligned(block->frame + free_offset - len); } @@ -1128,7 +1141,7 @@ inline void recv_sys_t::free(const void *data) continue; buf_block_t *block= &chunk->blocks[offs]; ut_ad(block->frame == data); - ut_ad(buf_block_get_state(block) == BUF_BLOCK_MEMORY); + ut_ad(block->page.state() == BUF_BLOCK_MEMORY); ut_ad(static_cast(block->page.access_time - 1) < srv_page_size); ut_ad(block->page.access_time >= 1U << 16); @@ -1204,7 +1217,7 @@ fail: } }); - if (crc != cksum) { + if (UNIV_UNLIKELY(crc != cksum)) { ib::error() << "Invalid log block checksum." << " block: " << block_number << " checkpoint no: " @@ -1482,7 +1495,7 @@ static dberr_t recv_log_recover_10_4() ulint crc = log_block_calc_checksum_crc32(buf); ulint cksum = log_block_get_checksum(buf); - if (crc != cksum) { + if (UNIV_UNLIKELY(crc != cksum)) { ib::error() << "Invalid log block checksum." << " block: " << log_block_get_hdr_no(buf) @@ -1745,7 +1758,7 @@ inline void recv_sys_t::add(const page_id_t page_id, { /* Use already allocated 'padding' bytes */ append: - UNIV_MEM_ALLOC(end + 1, len); + MEM_UNDEFINED(end + 1, len); /* Append to the preceding record for the page */ tail->append(l, len); return; @@ -1764,6 +1777,36 @@ append: log_phys_t(start_lsn, lsn, l, len)); } +#if 0 /* FIXME: MDEV-22970 Potential corruption */ +/** Store/remove the freed pages in fil_name_t of recv_spaces. +@param[in] page_id freed or init page_id +@param[in] freed TRUE if page is freed */ +static void store_freed_or_init_rec(page_id_t page_id, bool freed) +{ + uint32_t space_id= page_id.space(); + uint32_t page_no= page_id.page_no(); + if (is_predefined_tablespace(space_id)) + { + fil_space_t *space; + if (space_id == TRX_SYS_SPACE) + space= fil_system.sys_space; + else + space= fil_space_get(space_id); + + space->free_page(page_no, freed); + return; + } + + recv_spaces_t::iterator i= recv_spaces.lower_bound(space_id); + if (i != recv_spaces.end() && i->first == space_id) + { + if (freed) + i->second.add_freed_page(page_no); + else + i->second.remove_freed_page(page_no); + } +} +#endif /** Parse and register one mini-transaction in log_t::FORMAT_10_5. @param checkpoint_lsn the log sequence number of the latest checkpoint @@ -1963,6 +2006,9 @@ same_page: case INIT_PAGE: last_offset= FIL_PAGE_TYPE; free_or_init_page: +#if 0 /* FIXME: MDEV-22970 Potential corruption */ + store_freed_or_init_rec(id, (b & 0x70) == FREE_PAGE); +#endif if (UNIV_UNLIKELY(rlen != 0)) goto record_corrupted; break; @@ -2234,18 +2280,18 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, ut_ad(recv_needed_recovery); ut_ad(!init || init->created); ut_ad(!init || init->lsn); - ut_ad(block->page.id == p->first); + ut_ad(block->page.id() == p->first); ut_ad(!p->second.is_being_processed()); - ut_ad(!space || space->id == block->page.id.space()); + ut_ad(!space || space->id == block->page.id().space()); ut_ad(log_sys.is_physical()); if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) { - ib::info() << "Applying log to page " << block->page.id; + ib::info() << "Applying log to page " << block->page.id(); } DBUG_PRINT("ib_log", ("Applying log to page %u:%u", - block->page.id.space(), - block->page.id.page_no())); + block->page.id().space(), + block->page.id().page_no())); p->second.state = page_recv_t::RECV_BEING_PROCESSED; @@ -2277,8 +2323,8 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, /* This record has already been applied. */ DBUG_PRINT("ib_log", ("apply skip %u:%u LSN " LSN_PF " < " LSN_PF, - block->page.id.space(), - block->page.id.page_no(), + block->page.id().space(), + block->page.id().page_no(), l->start_lsn, page_lsn)); continue; } @@ -2286,8 +2332,8 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, if (l->start_lsn < init_lsn) { DBUG_PRINT("ib_log", ("init skip %u:%u LSN " LSN_PF " < " LSN_PF, - block->page.id.space(), - block->page.id.page_no(), + block->page.id().space(), + block->page.id().page_no(), l->start_lsn, init_lsn)); continue; } @@ -2295,13 +2341,13 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) { ib::info() << "apply " << l->start_lsn - << ": " << block->page.id; + << ": " << block->page.id(); } DBUG_PRINT("ib_log", ("apply " LSN_PF ": %u:%u", l->start_lsn, - block->page.id.space(), - block->page.id.page_no())); + block->page.id().space(), + block->page.id().page_no())); log_phys_t::apply_status a= l->apply(*block, p->second.last_offset); @@ -2321,7 +2367,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, if (fil_space_t* s = space ? space - : fil_space_acquire(block->page.id.space())) { + : fil_space_acquire(block->page.id().space())) { switch (a) { case log_phys_t::APPLIED_TO_FSP_HEADER: s->flags = mach_read_from_4( @@ -2448,7 +2494,7 @@ void recv_recover_page(fil_space_t* space, buf_page_t* bpage) mtr.start(); mtr.set_log_mode(MTR_LOG_NONE); - ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); + ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); buf_block_t* block = reinterpret_cast(bpage); /* Move the ownership of the x-latch on the page to @@ -2462,7 +2508,7 @@ void recv_recover_page(fil_space_t* space, buf_page_t* bpage) mutex_enter(&recv_sys.mutex); if (recv_sys.apply_log_recs) { - recv_sys_t::map::iterator p = recv_sys.pages.find(bpage->id); + recv_sys_t::map::iterator p = recv_sys.pages.find(bpage->id()); if (p != recv_sys.pages.end() && !p->second.is_being_processed()) { recv_recover_page(block, mtr, p, space); @@ -2495,7 +2541,7 @@ static void recv_read_in_area(page_id_t page_id) && i->first.space() == page_id.space() && i->first.page_no() < up_limit; i++) { if (i->second.state == page_recv_t::RECV_NOT_PROCESSED - && !buf_page_hash_get(i->first)) { + && !buf_pool.page_hash_contains(i->first)) { i->second.state = page_recv_t::RECV_BEING_READ; *p++ = i->first.page_no(); } @@ -2531,7 +2577,7 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id, { mtr.start(); mtr.set_log_mode(MTR_LOG_NONE); - block= buf_page_create(page_id, space->zip_size(), &mtr); + block= buf_page_create(space, page_id.page_no(), space->zip_size(), &mtr); p= recv_sys.pages.find(page_id); if (p == recv_sys.pages.end()) { @@ -2702,7 +2748,7 @@ void recv_sys_t::apply(bool last_batch) buf_flush_wait_LRU_batch_end(); os_event_reset(flush_end); - flush_type = BUF_FLUSH_LIST; + flush_lru= false; os_event_set(flush_start); os_event_wait(flush_end); @@ -3183,7 +3229,7 @@ func_exit: entire redo log. If rescan is needed or innodb_force_recovery is set, we can ignore missing tablespaces. */ for (const recv_spaces_t::value_type& rs : recv_spaces) { - if (rs.second.status != file_name_t::MISSING) { + if (UNIV_LIKELY(rs.second.status != file_name_t::MISSING)) { continue; } @@ -3240,6 +3286,12 @@ recv_init_crash_recovery_spaces(bool rescan, bool& missing_tablespace) /* The tablespace was found, and there are some redo log records for it. */ fil_names_dirty(rs.second.space); + + /* Add the freed page ranges in the respective + tablespace */ + if (!rs.second.freed_ranges.empty()) + rs.second.space->add_free_ranges( + std::move(rs.second.freed_ranges)); } else if (rs.second.name == "") { ib::error() << "Missing FILE_CREATE, FILE_DELETE" " or FILE_MODIFY before FILE_CHECKPOINT" diff --git a/storage/innobase/mem/mem0mem.cc b/storage/innobase/mem/mem0mem.cc index 261d8062bd6..6d4593e0ab4 100644 --- a/storage/innobase/mem/mem0mem.cc +++ b/storage/innobase/mem/mem0mem.cc @@ -322,8 +322,7 @@ mem_heap_create_block_func( /* Not the first allocation for the heap. This block's total_length field should be set to undefined. */ ut_d(block->total_size = ULINT_UNDEFINED); - UNIV_MEM_INVALID(&block->total_size, - sizeof block->total_size); + MEM_UNDEFINED(&block->total_size, sizeof block->total_size); heap->total_size += len; } @@ -331,7 +330,7 @@ mem_heap_create_block_func( /* Poison all available memory. Individual chunks will be unpoisoned on every mem_heap_alloc() call. */ compile_time_assert(MEM_BLOCK_HEADER_SIZE >= sizeof *block); - UNIV_MEM_FREE(block + 1, len - sizeof *block); + MEM_NOACCESS(block + 1, len - sizeof *block); ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index e77df7c61d5..16a0ecc051c 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -226,11 +226,11 @@ static void memo_slot_release(mtr_memo_slot_t *slot) case MTR_MEMO_PAGE_SX_FIX: case MTR_MEMO_PAGE_X_FIX: buf_block_t *block= reinterpret_cast(slot->object); - block->unfix(); buf_page_release_latch(block, slot->type); + block->unfix(); break; } - slot->object= NULL; + slot->object= nullptr; } /** Release the latches acquired by the mini-transaction. */ @@ -262,8 +262,8 @@ struct ReleaseLatches { case MTR_MEMO_PAGE_SX_FIX: case MTR_MEMO_PAGE_X_FIX: buf_block_t *block= reinterpret_cast(slot->object); - block->unfix(); buf_page_release_latch(block, slot->type); + block->unfix(); break; } slot->object= NULL; @@ -354,7 +354,10 @@ struct mtr_write_log_t { /** Start a mini-transaction. */ void mtr_t::start() { - UNIV_MEM_INVALID(this, sizeof *this); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(this, sizeof *this); + MEM_MAKE_DEFINED(&m_freed_pages, sizeof(m_freed_pages)); +#endif /* HAVE_valgrind_or_MSAN */ ut_d(m_start= true); ut_d(m_commit= false); @@ -372,6 +375,8 @@ void mtr_t::start() ut_d(m_user_space_id= TRX_SYS_SPACE); m_user_space= nullptr; m_commit_lsn= 0; + m_freed_in_system_tablespace= m_trim_pages= false; + ut_ad(!m_freed_pages); } /** Release the resources */ @@ -413,6 +418,32 @@ void mtr_t::commit() to insert into the flush list. */ log_mutex_exit(); + if (m_freed_pages) + { + ut_ad(!m_freed_pages->empty()); + fil_space_t *freed_space= m_user_space; + /* Get the freed tablespace in case of predefined tablespace */ + if (!freed_space) + { + ut_ad(is_freed_system_tablespace_page()); + freed_space= fil_system.sys_space; + } + + ut_ad(memo_contains(freed_space->latch, MTR_MEMO_X_LOCK)); + /* Update the last freed lsn */ + freed_space->update_last_freed_lsn(m_commit_lsn); + + if (!is_trim_pages()) + for (const auto &range : *m_freed_pages) + freed_space->add_free_range(range); + else + freed_space->clear_freed_ranges(); + delete m_freed_pages; + m_freed_pages= nullptr; + /* Reset of m_trim_pages and m_freed_in_system_tablespace + happens in mtr_t::start() */ + } + m_memo.for_each_block_in_reverse(CIterate (ReleaseBlocks(start_lsn, m_commit_lsn))); if (m_made_dirty) @@ -441,6 +472,8 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn) ut_ad(!m_made_dirty); ut_ad(m_memo.size() == 0); ut_ad(!srv_read_only_mode); + ut_ad(!m_freed_pages); + ut_ad(!m_freed_in_system_tablespace); if (checkpoint_lsn) { byte* ptr = m_log.push(SIZE_OF_FILE_CHECKPOINT); @@ -661,34 +694,31 @@ inline lsn_t mtr_t::finish_write(ulint len) } #ifdef UNIV_DEBUG -/** Check if memo contains the given item. -@return true if contains */ -bool -mtr_t::memo_contains( - const mtr_buf_t* memo, - const void* object, - mtr_memo_type_t type) +/** Check if we are holding an rw-latch in this mini-transaction +@param lock latch to search for +@param type held latch type +@return whether (lock,type) is contained */ +bool mtr_t::memo_contains(const rw_lock_t &lock, mtr_memo_type_t type) { - Iterate iteration(Find(object, type)); - if (memo->for_each_block_in_reverse(iteration)) { - return(false); - } + Iterate iteration(Find(&lock, type)); + if (m_memo.for_each_block_in_reverse(iteration)) + return false; - switch (type) { - case MTR_MEMO_X_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_X)); - break; - case MTR_MEMO_SX_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_SX)); - break; - case MTR_MEMO_S_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_S)); - break; - default: - break; - } + switch (type) { + case MTR_MEMO_X_LOCK: + ut_ad(rw_lock_own(const_cast(&lock), RW_LOCK_X)); + break; + case MTR_MEMO_SX_LOCK: + ut_ad(rw_lock_own(const_cast(&lock), RW_LOCK_SX)); + break; + case MTR_MEMO_S_LOCK: + ut_ad(rw_lock_own(const_cast(&lock), RW_LOCK_S)); + break; + default: + break; + } - return(true); + return true; } /** Debug check for flags */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 503f36e033f..12ad59bcff2 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3619,7 +3619,7 @@ fallback: ? 0 : posix_fallocate(file, current_size, size - current_size); } while (err == EINTR - && srv_shutdown_state == SRV_SHUTDOWN_NONE); + && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); switch (err) { case 0: @@ -3653,7 +3653,7 @@ fallback: os_offset_t current_size = os_file_get_size(file); while (current_size < size - && srv_shutdown_state == SRV_SHUTDOWN_NONE) { + && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { ulint n_bytes; if (size - current_size < (os_offset_t) buf_size) { @@ -4010,7 +4010,7 @@ static bool is_linux_native_aio_supported() case -EINVAL: case -ENOSYS: - ib::error() + ib::warn() << "Linux Native AIO not supported. You can either" " move " << (srv_read_only_mode ? log_file_path : "tmpdir") @@ -4020,7 +4020,7 @@ static bool is_linux_native_aio_supported() /* fall through. */ default: - ib::error() + ib::warn() << "Linux Native AIO check on " << (srv_read_only_mode ? log_file_path : "tmpdir") << "returned error[" << -err << "]"; diff --git a/storage/innobase/os/os0proc.cc b/storage/innobase/os/os0proc.cc index 32747aae3ab..819e16f2302 100644 --- a/storage/innobase/os/os0proc.cc +++ b/storage/innobase/os/os0proc.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index fed2f8f4657..92e7ce5e60d 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -1119,7 +1119,7 @@ inline void mtr_t::page_insert(const buf_block_t &block, bool reuse, len+= hdr_l + data_l; const bool small= len < mtr_buf_t::MAX_DATA_SIZE - (1 + 3 + 3 + 5 + 5); - byte *l= log_write(block.page.id, &block.page, len, small); + byte *l= log_write(block.page.id(), &block.page, len, small); if (UNIV_LIKELY(small)) { @@ -1227,7 +1227,7 @@ inline void mtr_t::page_insert(const buf_block_t &block, bool reuse, len+= hdr_l + data_l; const bool small= len < mtr_buf_t::MAX_DATA_SIZE - (1 + 3 + 3 + 5 + 5); - byte *l= log_write(block.page.id, &block.page, len, small); + byte *l= log_write(block.page.id(), &block.page, len, small); if (UNIV_LIKELY(small)) { @@ -1302,7 +1302,7 @@ page_cur_insert_rec_low( /* 1. Get the size of the physical record in the page */ const ulint rec_size= rec_offs_size(offsets); -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind_or_MSAN { const void *rec_start= rec - rec_offs_extra_size(offsets); ulint extra_size= rec_offs_extra_size(offsets) - @@ -1310,11 +1310,11 @@ page_cur_insert_rec_low( ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES); /* All data bytes of the record must be valid. */ - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); /* The variable-length header must be valid. */ - UNIV_MEM_ASSERT_RW(rec_start, extra_size); + MEM_CHECK_DEFINED(rec_start, extra_size); } -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ /* 2. Try to find suitable space from page memory management */ bool reuse= false; @@ -1613,7 +1613,7 @@ static inline void page_zip_dir_add_slot(buf_block_t *block, page_zip_des_t *page_zip= &block->page.zip; ut_ad(page_is_comp(page_zip->data)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); /* Read the old n_dense (n_heap has already been incremented). */ ulint n_dense= page_dir_get_n_heap(page_zip->data) - (PAGE_HEAP_NO_USER_LOW + @@ -1702,16 +1702,16 @@ page_cur_insert_rec_zip( /* 1. Get the size of the physical record in the page */ const ulint rec_size= rec_offs_size(offsets); -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind_or_MSAN { const void *rec_start= rec - rec_offs_extra_size(offsets); ulint extra_size= rec_offs_extra_size(offsets) - REC_N_NEW_EXTRA_BYTES; /* All data bytes of the record must be valid. */ - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); /* The variable-length header must be valid. */ - UNIV_MEM_ASSERT_RW(rec_start, extra_size); + MEM_CHECK_DEFINED(rec_start, extra_size); } -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ const bool reorg_before_insert= page_has_garbage(cursor->block->frame) && rec_size > page_get_max_insert_size(cursor->block->frame, 1) && rec_size <= page_get_max_insert_size_after_reorganize(cursor->block->frame, @@ -1954,8 +1954,8 @@ use_heap: rec_set_bit_field_2(insert_rec, heap_no, REC_NEW_HEAP_NO, REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); - UNIV_MEM_ASSERT_RW(rec_get_start(insert_rec, offsets), - rec_offs_size(offsets)); + MEM_CHECK_DEFINED(rec_get_start(insert_rec, offsets), + rec_offs_size(offsets)); /* 6. Update the last insertion info in page header */ byte *last_insert= my_assume_aligned<4>(PAGE_LAST_INSERT + PAGE_HEADER + @@ -2289,10 +2289,11 @@ bool page_apply_insert_redundant(const buf_block_t &block, bool reuse, byte *page_n_heap= my_assume_aligned<2>(PAGE_N_HEAP + PAGE_HEADER + block.frame); const uint16_t h= mach_read_from_2(page_n_heap); + const page_id_t id(block.page.id()); if (UNIV_UNLIKELY(n_slots < 2 || h < n_slots || h < PAGE_HEAP_NO_USER_LOW || h >= srv_page_size / REC_N_OLD_EXTRA_BYTES || !fil_page_index_page_check(block.frame) || - page_get_page_no(block.frame) != block.page.id.page_no() || + page_get_page_no(block.frame) != id.page_no() || mach_read_from_2(my_assume_aligned<2> (PAGE_OLD_SUPREMUM - REC_NEXT + block.frame)))) @@ -2303,7 +2304,7 @@ corrupted: " due to corruption on " : "Not applying INSERT_HEAP_REDUNDANT" " due to corruption on ") - << block.page.id; + << id; return true; } @@ -2530,11 +2531,12 @@ bool page_apply_insert_dynamic(const buf_block_t &block, bool reuse, byte *page_n_heap= my_assume_aligned<2>(PAGE_N_HEAP + PAGE_HEADER + block.frame); ulint h= mach_read_from_2(page_n_heap); + const page_id_t id(block.page.id()); if (UNIV_UNLIKELY(n_slots < 2 || h < (PAGE_HEAP_NO_USER_LOW | 0x8000) || (h & 0x7fff) >= srv_page_size / REC_N_NEW_EXTRA_BYTES || (h & 0x7fff) < n_slots || !fil_page_index_page_check(block.frame) || - page_get_page_no(block.frame) != block.page.id.page_no() || + page_get_page_no(block.frame) != id.page_no() || mach_read_from_2(my_assume_aligned<2> (PAGE_NEW_SUPREMUM - REC_NEXT + block.frame)) || @@ -2548,7 +2550,7 @@ corrupted: " due to corruption on " : "Not applying INSERT_HEAP_DYNAMIC" " due to corruption on ") - << block.page.id; + << id; return true; } @@ -2746,10 +2748,11 @@ bool page_apply_delete_redundant(const buf_block_t &block, ulint prev) { const uint16_t n_slots= page_dir_get_n_slots(block.frame); ulint n_recs= page_get_n_recs(block.frame); + const page_id_t id(block.page.id()); if (UNIV_UNLIKELY(!n_recs || n_slots < 2 || !fil_page_index_page_check(block.frame) || - page_get_page_no(block.frame) != block.page.id.page_no() || + page_get_page_no(block.frame) != id.page_no() || mach_read_from_2(my_assume_aligned<2> (PAGE_OLD_SUPREMUM - REC_NEXT + block.frame)) || @@ -2757,7 +2760,7 @@ bool page_apply_delete_redundant(const buf_block_t &block, ulint prev) { corrupted: ib::error() << "Not applying DELETE_ROW_FORMAT_REDUNDANT" - " due to corruption on " << block.page.id; + " due to corruption on " << id; return true; } @@ -2841,10 +2844,11 @@ bool page_apply_delete_dynamic(const buf_block_t &block, ulint prev, { const uint16_t n_slots= page_dir_get_n_slots(block.frame); ulint n_recs= page_get_n_recs(block.frame); + const page_id_t id(block.page.id()); if (UNIV_UNLIKELY(!n_recs || n_slots < 2 || !fil_page_index_page_check(block.frame) || - page_get_page_no(block.frame) != block.page.id.page_no() || + page_get_page_no(block.frame) != id.page_no() || mach_read_from_2(my_assume_aligned<2> (PAGE_NEW_SUPREMUM - REC_NEXT + block.frame)) || @@ -2852,7 +2856,7 @@ bool page_apply_delete_dynamic(const buf_block_t &block, ulint prev, { corrupted: ib::error() << "Not applying DELETE_ROW_FORMAT_DYNAMIC" - " due to corruption on " << block.page.id; + " due to corruption on " << id; return true; } diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index fb6fc5858e3..474884d1d4c 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -197,7 +197,7 @@ page_set_max_trx_id( trx_id_t trx_id, /*!< in: transaction id */ mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */ { - ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(!mtr || mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!page_zip || page_zip == &block->page.zip); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); byte *max_trx_id= my_assume_aligned<8>(PAGE_MAX_TRX_ID + @@ -400,7 +400,7 @@ page_create_empty( ut_ad(fil_page_index_page_check(block->frame)); ut_ad(!index->is_dummy); - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id().space() == index->table->space->id); /* Multiple transactions cannot simultaneously operate on the same temp-table in parallel. @@ -411,7 +411,7 @@ page_create_empty( && page_is_leaf(block->frame)) { max_trx_id = page_get_max_trx_id(block->frame); ut_ad(max_trx_id); - } else if (block->page.id.page_no() == index->page) { + } else if (block->page.id().page_no() == index->page) { /* Preserve PAGE_ROOT_AUTO_INC. */ max_trx_id = page_get_max_trx_id(block->frame); } else { @@ -1994,7 +1994,7 @@ bool page_validate(const page_t* page, const dict_index_t* index) const rec_t* rec; const rec_t* old_rec = NULL; const rec_t* first_rec = NULL; - ulint offs; + ulint offs = 0; ulint n_slots; ibool ret = TRUE; ulint i; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index dd34628df08..a89ae5b3a64 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -908,9 +908,9 @@ page_zip_compress_node_ptrs( /* Only leaf nodes may contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); /* Compress the extra bytes. */ c_stream->avail_in = static_cast( @@ -973,8 +973,8 @@ page_zip_compress_sec( - c_stream->next_in); if (UNIV_LIKELY(c_stream->avail_in != 0)) { - UNIV_MEM_ASSERT_RW(c_stream->next_in, - c_stream->avail_in); + MEM_CHECK_DEFINED(c_stream->next_in, + c_stream->avail_in); err = deflate(c_stream, Z_NO_FLUSH); if (UNIV_UNLIKELY(err != Z_OK)) { break; @@ -1016,9 +1016,9 @@ page_zip_compress_clust_ext( int err; ulint i; - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); for (i = 0; i < rec_offs_n_fields(offsets); i++) { ulint len; @@ -1156,9 +1156,9 @@ page_zip_compress_clust( ULINT_UNDEFINED, &heap); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); /* Compress the extra bytes. */ c_stream->avail_in = static_cast( @@ -1205,9 +1205,9 @@ page_zip_compress_clust( == rec_get_nth_field(rec, offsets, trx_id_col + 1, &len)); ut_ad(len == DATA_ROLL_PTR_LEN); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); /* Compress any preceding bytes. */ c_stream->avail_in = static_cast( @@ -1300,7 +1300,7 @@ page_zip_compress( ut_ad(dict_table_is_comp(index->table)); ut_ad(!dict_index_is_ibuf(index)); - UNIV_MEM_ASSERT_RW(page, srv_page_size); + MEM_CHECK_DEFINED(page, srv_page_size); /* Check the data that will be omitted. */ ut_a(!memcmp(page + (PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES), @@ -1388,7 +1388,7 @@ page_zip_compress( << " index " << index->name() << " page " - << block->page.id.page_no() + << block->page.id().page_no() << "(" << (page_is_leaf(page) ? "leaf" : "non-leaf") << ")"; @@ -1463,7 +1463,7 @@ page_zip_compress( trx_id_col = ULINT_UNDEFINED; } - UNIV_MEM_ASSERT_RW(c_stream.next_in, c_stream.avail_in); + MEM_CHECK_DEFINED(c_stream.next_in, c_stream.avail_in); err = deflate(&c_stream, Z_FULL_FLUSH); if (err != Z_OK) { goto zlib_error; @@ -1517,7 +1517,7 @@ page_zip_compress( - (c_stream.next_in - page)); ut_a(c_stream.avail_in <= srv_page_size - PAGE_ZIP_START - PAGE_DIR); - UNIV_MEM_ASSERT_RW(c_stream.next_in, c_stream.avail_in); + MEM_CHECK_DEFINED(c_stream.next_in, c_stream.avail_in); err = deflate(&c_stream, Z_FINISH); if (UNIV_UNLIKELY(err != Z_STREAM_END)) { @@ -1552,9 +1552,11 @@ err_exit: ut_ad(buf + c_stream.total_out == c_stream.next_out); ut_ad((ulint) (storage - c_stream.next_out) >= c_stream.avail_out); +#ifdef HAVE_valgrind /* Valgrind believes that zlib does not initialize some bits in the last 7 or 8 bytes of the stream. Make Valgrind happy. */ - UNIV_MEM_VALID(buf, c_stream.total_out); + MEM_MAKE_DEFINED(buf, c_stream.total_out); +#endif /* HAVE_valgrind */ /* Zero out the area reserved for the modification log. Space for the end marker of the modification log is not @@ -1585,7 +1587,7 @@ err_exit: page_zip_compress_write_log(block, index, mtr); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); #ifdef PAGE_ZIP_COMPRESS_DBG if (logfile) { @@ -1726,8 +1728,9 @@ page_zip_fields_decode( if (!val) { val = ULINT_UNDEFINED; } else if (UNIV_UNLIKELY(val >= n)) { +fail: page_zip_fields_free(index); - index = NULL; + return NULL; } else { index->type = DICT_CLUSTERED; } @@ -1736,8 +1739,7 @@ page_zip_fields_decode( } else { /* Decode the number of nullable fields. */ if (UNIV_UNLIKELY(index->n_nullable > val)) { - page_zip_fields_free(index); - index = NULL; + goto fail; } else { index->n_nullable = static_cast(val) & dict_index_t::MAX_N_FIELDS; @@ -3026,8 +3028,8 @@ page_zip_decompress_low( rec_offs* offsets; ut_ad(page_zip_simple_validate(page_zip)); - UNIV_MEM_ASSERT_W(page, srv_page_size); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_ADDRESSABLE(page, srv_page_size); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); /* The dense directory excludes the infimum and supremum records. */ n_dense = page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW; @@ -3074,7 +3076,9 @@ page_zip_decompress_low( /* Clear the uncompressed page, except the header. */ memset(PAGE_DATA + page, 0x55, srv_page_size - PAGE_DATA); #endif /* UNIV_ZIP_DEBUG */ - UNIV_MEM_INVALID(PAGE_DATA + page, srv_page_size - PAGE_DATA); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(PAGE_DATA + page, srv_page_size - PAGE_DATA); +#endif /* HAVE_valgrind_or_MSAN */ /* Copy the page directory. */ if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs, @@ -3205,7 +3209,7 @@ err_exit: } ut_a(page_is_comp(page)); - UNIV_MEM_ASSERT_RW(page, srv_page_size); + MEM_CHECK_DEFINED(page, srv_page_size); page_zip_fields_free(index); mem_heap_free(heap); @@ -3346,8 +3350,8 @@ page_zip_validate_low( page_t* temp_page = static_cast(aligned_malloc(srv_page_size, srv_page_size)); - UNIV_MEM_ASSERT_RW(page, srv_page_size); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page, srv_page_size); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); temp_page_zip = *page_zip; valid = page_zip_decompress_low(&temp_page_zip, temp_page, TRUE); @@ -3570,9 +3574,9 @@ page_zip_write_rec_ext( page_zip_des_t* const page_zip = &block->page.zip; ut_ad(rec_offs_validate(rec, index, offsets)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); externs -= (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN) * (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW); @@ -3702,10 +3706,10 @@ void page_zip_write_rec(buf_block_t *block, const byte *rec, ut_ad(page_zip_header_cmp(page_zip, page)); ut_ad(page_simple_validate_new((page_t*) page)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); slot = page_zip_dir_find(page_zip, page_offset(rec)); ut_a(slot); @@ -3891,10 +3895,10 @@ page_zip_write_blob_ptr( ut_ad(page_is_leaf(page)); ut_ad(dict_index_is_clust(index)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); blob_no = page_zip_get_n_prev_extern(page_zip, rec, index) + rec_get_n_extern_new(rec, index, n); @@ -3944,8 +3948,8 @@ page_zip_write_node_ptr( ut_ad(!page_is_leaf(page)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(rec, size); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, size); storage = page_zip_dir_start(page_zip) - (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE; @@ -3993,7 +3997,7 @@ page_zip_write_trx_id_and_roll_ptr( ut_ad(page_is_leaf(page)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); constexpr ulint sys_len = DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; const ulint heap_no = rec_get_heap_no_new(rec); @@ -4056,10 +4060,10 @@ write: ut_a(!memcmp(storage - len, field - len, sys_len)); #endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); } /**********************************************************************//** @@ -4093,10 +4097,10 @@ page_zip_clear_rec( heap_no = rec_get_heap_no_new(rec); ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); if (!page_is_leaf(block->frame)) { /* Clear node_ptr. On the compressed page, @@ -4191,7 +4195,7 @@ page_zip_rec_set_owned( ut_ad(page_align(rec) == block->frame); page_zip_des_t *const page_zip= &block->page.zip; byte *slot= page_zip_dir_find(page_zip, page_offset(rec)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); byte b= *slot; if (flag) b|= (PAGE_ZIP_DIR_SLOT_OWNED >> 8); @@ -4223,7 +4227,7 @@ page_zip_dir_insert( ut_ad(page_rec_get_next_const(cursor->rec) == rec); ut_ad(page_zip_simple_validate(page_zip)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); if (page_rec_is_infimum(cursor->rec)) { /* Use the first slot. */ @@ -4306,10 +4310,10 @@ void page_zip_dir_delete(buf_block_t *block, byte *rec, ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_comp(offsets)); - UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets)); - UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), - rec_offs_extra_size(offsets)); + MEM_CHECK_DEFINED(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets)); + MEM_CHECK_DEFINED(rec - rec_offs_extra_size(offsets), + rec_offs_extra_size(offsets)); mach_write_to_2(rec - REC_NEXT, free ? static_cast(free - rec) : 0); @@ -4423,15 +4427,15 @@ page_zip_reorganize( buf_block_t* temp_block; page_t* temp_page; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(block->page.zip.data); ut_ad(page_is_comp(page)); ut_ad(!dict_index_is_ibuf(index)); ut_ad(!index->table->is_temporary()); /* Note that page_zip_validate(page_zip, page, index) may fail here. */ - UNIV_MEM_ASSERT_RW(page, srv_page_size); - UNIV_MEM_ASSERT_RW(buf_block_get_page_zip(block)->data, - page_zip_get_size(buf_block_get_page_zip(block))); + MEM_CHECK_DEFINED(page, srv_page_size); + MEM_CHECK_DEFINED(buf_block_get_page_zip(block)->data, + page_zip_get_size(buf_block_get_page_zip(block))); /* Disable logging */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); @@ -4530,8 +4534,8 @@ page_zip_copy_recs( page_t* page = block->frame; page_zip_des_t* page_zip = &block->page.zip; - ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr->memo_contains_page_flagged(src, MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_ibuf(index)); ut_ad(!index->table->is_temporary()); #ifdef UNIV_ZIP_DEBUG @@ -4547,10 +4551,10 @@ page_zip_copy_recs( ut_a(dict_index_is_clust(index)); } - UNIV_MEM_ASSERT_W(page, srv_page_size); - UNIV_MEM_ASSERT_W(page_zip->data, page_zip_get_size(page_zip)); - UNIV_MEM_ASSERT_RW(src, srv_page_size); - UNIV_MEM_ASSERT_RW(src_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_ADDRESSABLE(page, srv_page_size); + MEM_CHECK_ADDRESSABLE(page_zip->data, page_zip_get_size(page_zip)); + MEM_CHECK_DEFINED(src, srv_page_size); + MEM_CHECK_DEFINED(src_zip->data, page_zip_get_size(page_zip)); /* Copy those B-tree page header fields that are related to the records stored in the page. Also copy the field diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc index 1cc88f4b758..92504546130 100644 --- a/storage/innobase/read/read0read.cc +++ b/storage/innobase/read/read0read.cc @@ -161,16 +161,6 @@ but it will never be dereferenced, because the purge view is older than any active transaction. For details see: row_vers_old_has_index_entry() and row_purge_poss_sec() - -Some additional issues: - -What if trx_sys.view_list == NULL and some transaction T1 and Purge both -try to open read_view at same time. Only one can acquire trx_sys.mutex. -In which order will the views be opened? Should it matter? If no, why? - -The order does not matter. No new transactions can be created and no running -RW transaction can commit or rollback (or free views). AC-NL-RO transactions -will mark their views as closed but not actually free their views. */ @@ -180,7 +170,7 @@ will mark their views as closed but not actually free their views. @param[in,out] trx transaction */ -inline void ReadView::snapshot(trx_t *trx) +inline void ReadViewBase::snapshot(trx_t *trx) { trx_sys.snapshot_ids(trx, &m_ids, &m_low_limit_id, &m_low_limit_no); std::sort(m_ids.begin(), m_ids.end()); @@ -196,74 +186,52 @@ inline void ReadView::snapshot(trx_t *trx) View becomes visible to purge thread. @param[in,out] trx transaction + + Reuses closed view if there were no read-write transactions since (and at) + its creation time. + + Original comment states: there is an inherent race here between purge + and this thread. + + To avoid this race we should've checked trx_sys.get_max_trx_id() and + set m_open atomically under ReadView::m_mutex protection. But we're cutting + edges to achieve greater performance. + + There're at least two types of concurrent threads interested in this + value: purge coordinator thread (see trx_sys_t::clone_oldest_view()) and + InnoDB monitor thread (see lock_trx_print_wait_and_mvcc_state()). + + What bad things can happen because we allow this race? + + Speculative execution may reorder state change before get_max_trx_id(). + In this case purge thread has short gap to clone outdated view. Which is + probably not that bad: it just won't be able to purge things that it was + actually allowed to purge for a short while. + + This thread may as well get suspended after trx_sys.get_max_trx_id() and + before m_open is set. New read-write transaction may get started, committed + and purged meanwhile. It is acceptable as well, since this view doesn't see + it. */ void ReadView::open(trx_t *trx) { ut_ad(this == &trx->read_view); - switch (state()) - { - case READ_VIEW_STATE_OPEN: + if (is_open()) ut_ad(!srv_read_only_mode); - return; - case READ_VIEW_STATE_CLOSED: - if (srv_read_only_mode) - return; - /* - Reuse closed view if there were no read-write transactions since (and at) - its creation time. - - Original comment states: there is an inherent race here between purge - and this thread. - - To avoid this race we should've checked trx_sys.get_max_trx_id() and - set state to READ_VIEW_STATE_OPEN atomically under trx_sys.mutex - protection. But we're cutting edges to achieve great scalability. - - There're at least two types of concurrent threads interested in this - value: purge coordinator thread (see trx_sys_t::clone_oldest_view()) and - InnoDB monitor thread (see lock_trx_print_wait_and_mvcc_state()). - - What bad things can happen because we allow this race? - - Speculative execution may reorder state change before get_max_trx_id(). - In this case purge thread has short gap to clone outdated view. Which is - probably not that bad: it just won't be able to purge things that it was - actually allowed to purge for a short while. - - This thread may as well get suspended after trx_sys.get_max_trx_id() and - before state is set to READ_VIEW_STATE_OPEN. New read-write transaction - may get started, committed and purged meanwhile. It is acceptable as - well, since this view doesn't see it. - */ - if (trx_is_autocommit_non_locking(trx) && m_ids.empty() && - m_low_limit_id == trx_sys.get_max_trx_id()) - goto reopen; - - /* - Can't reuse view, take new snapshot. - - Alas this empty critical section is simplest way to make sure concurrent - purge thread completed snapshot copy. Of course purge thread may come - again and try to copy once again after we release this mutex, but in - this case it is guaranteed to see READ_VIEW_STATE_REGISTERED and thus - it'll skip this view. - - This critical section can be replaced with new state, which purge thread - would set to inform us to wait until it completes snapshot. However it'd - complicate m_state even further. - */ - mutex_enter(&trx_sys.mutex); - mutex_exit(&trx_sys.mutex); - m_state.store(READ_VIEW_STATE_SNAPSHOT, std::memory_order_relaxed); - break; - default: - ut_ad(0); + else if (likely(!srv_read_only_mode)) + { + m_creator_trx_id= trx->id; + if (trx_is_autocommit_non_locking(trx) && empty() && + low_limit_id() == trx_sys.get_max_trx_id()) + m_open.store(true, std::memory_order_relaxed); + else + { + mutex_enter(&m_mutex); + snapshot(trx); + m_open.store(true, std::memory_order_relaxed); + mutex_exit(&m_mutex); + } } - - snapshot(trx); -reopen: - m_creator_trx_id= trx->id; - m_state.store(READ_VIEW_STATE_OPEN, std::memory_order_release); } @@ -274,21 +242,11 @@ reopen: in. This function is called by purge thread to determine whether it should purge the delete marked record or not. */ -void trx_sys_t::clone_oldest_view() +void trx_sys_t::clone_oldest_view(ReadViewBase *view) const { - purge_sys.view.snapshot(0); - mutex_enter(&mutex); + view->snapshot(nullptr); /* Find oldest view. */ - for (const trx_t *trx= UT_LIST_GET_FIRST(trx_list); trx; - trx= UT_LIST_GET_NEXT(trx_list, trx)) - { - uint32_t state; - - while ((state= trx->read_view.get_state()) == READ_VIEW_STATE_SNAPSHOT) - ut_delay(1); - - if (state == READ_VIEW_STATE_OPEN) - purge_sys.view.copy(trx->read_view); - } - mutex_exit(&mutex); + trx_list.for_each([view](const trx_t &trx) { + trx.read_view.append_to(view); + }); } diff --git a/storage/innobase/row/row0ext.cc b/storage/innobase/row/row0ext.cc index 9b07727d058..b7a627603d9 100644 --- a/storage/innobase/row/row0ext.cc +++ b/storage/innobase/row/row0ext.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 9993ab0fa62..4698f25428c 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -849,7 +849,8 @@ loop: num_doc_processed++; - if (fts_enable_diag_print && num_doc_processed % 10000 == 1) { + if (UNIV_UNLIKELY(fts_enable_diag_print) + && num_doc_processed % 10000 == 1) { ib::info() << "Number of documents processed: " << num_doc_processed; #ifdef FTS_INTERNAL_DIAG_PRINT @@ -887,7 +888,7 @@ loop: goto func_exit; } - UNIV_MEM_INVALID(block[t_ctx.buf_used], srv_sort_buf_size); + MEM_UNDEFINED(block[t_ctx.buf_used], srv_sort_buf_size); buf[t_ctx.buf_used] = row_merge_buf_empty(buf[t_ctx.buf_used]); mycount[t_ctx.buf_used] += t_ctx.rows_added[t_ctx.buf_used]; t_ctx.rows_added[t_ctx.buf_used] = 0; @@ -981,12 +982,14 @@ exit: goto func_exit; } - UNIV_MEM_INVALID(block[i], srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(block[i], srv_sort_buf_size); if (crypt_block[i]) { - UNIV_MEM_INVALID(crypt_block[i], - srv_sort_buf_size); + MEM_UNDEFINED(crypt_block[i], + srv_sort_buf_size); } +#endif /* HAVE_valgrind_or_MSAN */ } buf[i] = row_merge_buf_empty(buf[i]); @@ -994,7 +997,7 @@ exit: } } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { DEBUG_FTS_SORT_PRINT(" InnoDB_FTS: start merge sort\n"); } @@ -1025,7 +1028,7 @@ exit: } func_exit: - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { DEBUG_FTS_SORT_PRINT(" InnoDB_FTS: complete merge sort\n"); } @@ -1185,11 +1188,9 @@ row_merge_write_fts_word( error = row_merge_write_fts_node(ins_ctx, &word->text, fts_node); - if (error != DB_SUCCESS) { - ib::error() << "Failed to write word " - << word->text.f_str << " to FTS auxiliary" - " index table, error (" << ut_strerr(error) - << ")"; + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "Failed to write word to FTS auxiliary" + " index table, error " << error; ret = error; } @@ -1497,10 +1498,11 @@ row_fts_build_sel_tree( sel_tree[i + start] = int(i); } - for (i = treelevel; --i; ) { + i = treelevel; + do { row_fts_build_sel_tree_level( - sel_tree, i, mrec, offsets, index); - } + sel_tree, --i, mrec, offsets, index); + } while (i > 0); return(treelevel); } @@ -1602,7 +1604,7 @@ row_fts_merge_insert( count_diag += psort_info[i].merge_file[id]->n_rec; } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "InnoDB_FTS: to insert " << count_diag << " records"; } @@ -1771,7 +1773,7 @@ exit: mem_heap_free(heap); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "InnoDB_FTS: inserted " << count << " records"; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 880b64616e8..9612d95690b 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -26,6 +26,9 @@ Created 2012-02-08 by Sunny Bains. #include "row0import.h" #include "btr0pcur.h" +#ifdef BTR_CUR_HASH_ADAPT +# include "btr0sea.h" +#endif #include "que0que.h" #include "dict0boot.h" #include "dict0load.h" @@ -280,7 +283,7 @@ public: } if (!rec_offs_any_extern(offsets) - && m_cur.block->page.id.page_no() != index->page + && m_cur.block->page.id().page_no() != index->page && ((page_get_data_size(m_cur.block->frame) - rec_offs_size(offsets) < BTR_CUR_PAGE_COMPRESS_LIMIT(index)) @@ -694,14 +697,14 @@ dberr_t FetchIndexRootPages::operator()(buf_block_t* block) UNIV_NOTHROW ulint page_type = fil_page_get_type(page); if (page_type == FIL_PAGE_TYPE_XDES) { - return set_current_xdes(block->page.id.page_no(), page); + return set_current_xdes(block->page.id().page_no(), page); } else if (fil_page_index_page_check(page) - && !is_free(block->page.id.page_no()) + && !is_free(block->page.id().page_no()) && !page_has_siblings(page)) { index_id_t id = btr_page_get_index_id(page); - m_indexes.push_back(Index(id, block->page.id.page_no())); + m_indexes.push_back(Index(id, block->page.id().page_no())); if (m_indexes.size() == 1) { /* Check that the tablespace flags match the table flags. */ @@ -1569,7 +1572,7 @@ IndexPurge::next() UNIV_NOTHROW return status that will be checked in all callers! */ switch (next_page) { default: - if (next_page != block->page.id.page_no()) { + if (next_page != block->page.id().page_no()) { break; } /* MDEV-20931 FIXME: Check that @@ -1599,7 +1602,7 @@ IndexPurge::next() UNIV_NOTHROW != page_is_comp(block->frame) || btr_page_get_prev( next_block->frame) - != block->page.id.page_no())) { + != block->page.id().page_no())) { return DB_CORRUPTION; } @@ -1888,14 +1891,15 @@ PageConverter::update_index_page( { index_id_t id; buf_frame_t* page = block->frame; + const page_id_t page_id(block->page.id()); - if (is_free(block->page.id.page_no())) { + if (is_free(page_id.page_no())) { return(DB_SUCCESS); } else if ((id = btr_page_get_index_id(page)) != m_index->m_id) { row_index_t* index = find_index(id); - if (index == 0) { + if (UNIV_UNLIKELY(!index)) { ib::error() << "Page for tablespace " << m_space << " is index page with id " << id << " but that index is not found from" @@ -1915,10 +1919,12 @@ PageConverter::update_index_page( return(DB_SUCCESS); } - if (m_index && block->page.id.page_no() == m_index->m_page_no) { + + + if (m_index && page_id.page_no() == m_index->m_page_no) { byte *b = FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + FSEG_HDR_SPACE + page; - mach_write_to_4(b, block->page.id.space()); + mach_write_to_4(b, page_id.space()); memcpy(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP + FSEG_HDR_SPACE + page, b, 4); @@ -1947,7 +1953,7 @@ PageConverter::update_index_page( } if (m_index->m_srv_index->is_clust()) { - if (block->page.id.page_no() == m_index->m_srv_index->page) { + if (page_id.page_no() == m_index->m_srv_index->page) { dict_index_t* index = const_cast( m_index->m_srv_index); /* Preserve the PAGE_ROOT_AUTO_INC. */ @@ -2065,7 +2071,7 @@ PageConverter::update_page(buf_block_t* block, uint16_t& page_type) switch (page_type = fil_page_get_type(get_frame(block))) { case FIL_PAGE_TYPE_FSP_HDR: - ut_a(block->page.id.page_no() == 0); + ut_a(block->page.id().page_no() == 0); /* Work directly on the uncompressed page headers. */ return(update_header(block)); @@ -2094,7 +2100,7 @@ PageConverter::update_page(buf_block_t* block, uint16_t& page_type) case FIL_PAGE_TYPE_XDES: err = set_current_xdes( - block->page.id.page_no(), get_frame(block)); + block->page.id().page_no(), get_frame(block)); /* fall through */ case FIL_PAGE_INODE: case FIL_PAGE_TYPE_TRX_SYS: @@ -2128,7 +2134,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW /* If we already had an old page with matching number in the buffer pool, evict it now, because we no longer evict the pages on DISCARD TABLESPACE. */ - buf_page_get_gen(block->page.id, get_zip_size(), + buf_page_get_gen(block->page.id(), get_zip_size(), RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL, __FILE__, __LINE__, NULL, NULL); @@ -2159,54 +2165,6 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW return DB_SUCCESS; } -/*****************************************************************//** -Clean up after import tablespace failure, this function will acquire -the dictionary latches on behalf of the transaction if the transaction -hasn't already acquired them. */ -static MY_ATTRIBUTE((nonnull)) -void -row_import_discard_changes( -/*=======================*/ - row_prebuilt_t* prebuilt, /*!< in/out: prebuilt from handler */ - trx_t* trx, /*!< in/out: transaction for import */ - dberr_t err) /*!< in: error code */ -{ - dict_table_t* table = prebuilt->table; - - ut_a(err != DB_SUCCESS); - - prebuilt->trx->error_info = NULL; - - ib::info() << "Discarding tablespace of table " - << prebuilt->table->name - << ": " << ut_strerr(err); - - if (trx->dict_operation_lock_mode != RW_X_LATCH) { - ut_a(trx->dict_operation_lock_mode == 0); - row_mysql_lock_data_dictionary(trx); - } - - ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); - - /* Since we update the index root page numbers on disk after - we've done a successful import. The table will not be loadable. - However, we need to ensure that the in memory root page numbers - are reset to "NULL". */ - - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != 0; - index = UT_LIST_GET_NEXT(indexes, index)) { - - index->page = FIL_NULL; - } - - table->file_unreadable = true; - if (table->space) { - fil_close_tablespace(trx, table->space_id); - table->space = NULL; - } -} - /*****************************************************************//** Clean up after import tablespace. */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -2220,7 +2178,27 @@ row_import_cleanup( ut_a(prebuilt->trx != trx); if (err != DB_SUCCESS) { - row_import_discard_changes(prebuilt, trx, err); + dict_table_t* table = prebuilt->table; + table->file_unreadable = true; + if (table->space) { + fil_close_tablespace(table->space_id); + table->space = NULL; + } + + prebuilt->trx->error_info = NULL; + + ib::info() << "Discarding tablespace of table " + << table->name << ": " << err; + + if (!trx->dict_operation_lock_mode) { + row_mysql_lock_data_dictionary(trx); + } + + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index; + index = UT_LIST_GET_NEXT(indexes, index)) { + index->page = FIL_NULL; + } } ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); @@ -3468,14 +3446,15 @@ fil_iterate( bool updated = false; os_offset_t page_off = offset; ulint n_pages_read = n_bytes / size; - block->page.id.set_page_no(ulint(page_off / size)); + /* This block is not attached to buf_pool */ + block->page.id_.set_page_no(ulint(page_off / size)); for (ulint i = 0; i < n_pages_read; - block->page.id.set_page_no(block->page.id.page_no() + 1), + ++block->page.id_, ++i, page_off += size, block->frame += size) { byte* src = readptr + i * size; const ulint page_no = page_get_page_no(src); - if (!page_no && block->page.id.page_no()) { + if (!page_no && block->page.id().page_no()) { if (!buf_is_zeroes(span(src, size))) { goto page_corrupted; @@ -3485,7 +3464,7 @@ fil_iterate( continue; } - if (page_no != block->page.id.page_no()) { + if (page_no != block->page.id().page_no()) { page_corrupted: ib::warn() << callback.filename() << ": Page " << (offset / size) @@ -3495,7 +3474,7 @@ page_corrupted: goto func_exit; } - if (block->page.id.page_no() == 0) { + if (block->page.id().page_no() == 0) { actual_space_id = mach_read_from_4( src + FIL_PAGE_SPACE_ID); } @@ -3523,7 +3502,7 @@ page_corrupted: if (!encrypted) { } else if (!key_version) { not_encrypted: - if (block->page.id.page_no() == 0 + if (block->page.id().page_no() == 0 && block->page.zip.data) { block->page.zip.data = src; frame_changed = true; @@ -3586,7 +3565,7 @@ not_encrypted: if ((err = callback(block)) != DB_SUCCESS) { goto func_exit; } else if (!updated) { - updated = buf_block_get_state(block) + updated = block->page.state() == BUF_BLOCK_FILE_PAGE; } @@ -3621,7 +3600,7 @@ not_encrypted: /* When tablespace is encrypted or compressed its first page (i.e. page 0) is not encrypted or compressed and there is no need to copy frame. */ - if (encrypted && block->page.id.page_no() != 0) { + if (encrypted && block->page.id().page_no() != 0) { byte *local_frame = callback.get_frame(block); ut_ad((writeptr + (i * size)) != local_frame); memcpy((writeptr + (i * size)), local_frame, size); @@ -3658,8 +3637,8 @@ not_encrypted: byte* tmp = fil_encrypt_buf( iter.crypt_data, - block->page.id.space(), - block->page.id.page_no(), + block->page.id().space(), + block->page.id().page_no(), src, block->zip_size(), dest, full_crc32); @@ -3786,10 +3765,7 @@ fil_tablespace_iterate( buf_block_t* block = reinterpret_cast (ut_zalloc_nokey(sizeof *block)); block->frame = page; - block->page.id = page_id_t(0, 0); - block->page.io_fix = BUF_IO_NONE; - block->page.buf_fix_count = 1; - block->page.state = BUF_BLOCK_FILE_PAGE; + block->page.init(BUF_BLOCK_FILE_PAGE, page_id_t(~0ULL), 1); /* Read the first page and determine the page and zip size. */ @@ -3804,7 +3780,7 @@ fil_tablespace_iterate( } if (err == DB_SUCCESS) { - block->page.id = page_id_t(callback.get_space_id(), 0); + block->page.id_ = page_id_t(callback.get_space_id(), 0); if (ulint zip_size = callback.get_zip_size()) { page_zip_set_size(&block->page.zip, zip_size); /* ROW_FORMAT=COMPRESSED is not optimised for block IO @@ -4048,15 +4024,12 @@ row_import_for_mysql( index entries that point to cached garbage pages in the buffer pool, because PageConverter::operator() only evicted those pages that were replaced by the imported pages. We must - discard all remaining adaptive hash index entries, because the + detach any remaining adaptive hash index entries, because the adaptive hash index must be a subset of the table contents; false positives are not tolerated. */ - while (buf_LRU_drop_page_hash_for_tablespace(table)) { - if (trx_is_interrupted(trx) - || srv_shutdown_state != SRV_SHUTDOWN_NONE) { - err = DB_INTERRUPTED; - break; - } + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index; + index = UT_LIST_GET_NEXT(indexes, index)) { + index = index->clone_if_needed(); } #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index e5b697dbe31..5f3cdb4356e 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -58,35 +58,22 @@ check. If you make a change in this module make sure that no codepath is introduced where a call to log_free_check() is bypassed. */ -/***********************************************************//** -Creates an entry template for each index of a table. */ -static -void -ins_node_create_entry_list( -/*=======================*/ - ins_node_t* node) /*!< in: row insert node */ +/** Create an row template for each index of a table. */ +static void ins_node_create_entry_list(ins_node_t *node) { - dict_index_t* index; - dtuple_t* entry; + node->entry_list.reserve(UT_LIST_GET_LEN(node->table->indexes)); - ut_ad(node->entry_sys_heap); - - /* We will include all indexes (include those corrupted - secondary indexes) in the entry list. Filtration of - these corrupted index will be done in row_ins() */ - - node->entry_list.reserve(UT_LIST_GET_LEN(node->table->indexes)); - - for (index = dict_table_get_first_index(node->table); - index != 0; - index = dict_table_get_next_index(index)) { - - entry = row_build_index_entry_low( - node->row, NULL, index, node->entry_sys_heap, - ROW_BUILD_FOR_INSERT); - - node->entry_list.push_back(entry); - } + for (dict_index_t *index= dict_table_get_first_index(node->table); index; + index= dict_table_get_next_index(index)) + { + /* Corrupted or incomplete secondary indexes will be filtered out in + row_ins(). */ + dtuple_t *entry= index->online_status >= ONLINE_INDEX_ABORTED + ? dtuple_create(node->entry_sys_heap, 0) + : row_build_index_entry_low(node->row, NULL, index, node->entry_sys_heap, + ROW_BUILD_FOR_INSERT); + node->entry_list.push_back(entry); + } } /*****************************************************************//** @@ -252,7 +239,7 @@ row_ins_sec_index_entry_by_modify( } } else { ut_a(mode == BTR_MODIFY_TREE); - if (buf_LRU_buf_pool_running_out()) { + if (buf_pool.running_out()) { return(DB_LOCK_TABLE_FULL); } @@ -342,10 +329,8 @@ row_ins_clust_index_entry_by_modify( break; } } else { - if (buf_LRU_buf_pool_running_out()) { - - return(DB_LOCK_TABLE_FULL); - + if (buf_pool.running_out()) { + return DB_LOCK_TABLE_FULL; } big_rec_t* big_rec = NULL; @@ -1255,8 +1240,10 @@ row_ins_foreign_check_on_constraint( update->info_bits = 0; update->n_fields = foreign->n_fields; - UNIV_MEM_INVALID(update->fields, - update->n_fields * sizeof *update->fields); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(update->fields, + update->n_fields * sizeof *update->fields); +#endif /* HAVE_valgrind_or_MSAN */ bool affects_fulltext = false; @@ -2731,8 +2718,7 @@ do_insert: entry, &insert_rec, &big_rec, n_ext, thr, &mtr); } else { - if (buf_LRU_buf_pool_running_out()) { - + if (buf_pool.running_out()) { err = DB_LOCK_TABLE_FULL; goto err_exit; } @@ -3089,8 +3075,7 @@ row_ins_sec_index_entry_low( } } else { ut_ad(mode == BTR_MODIFY_TREE); - if (buf_LRU_buf_pool_running_out()) { - + if (buf_pool.running_out()) { err = DB_LOCK_TABLE_FULL; goto func_exit; } diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index a654f221f38..78f605c373d 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -375,7 +375,9 @@ row_log_online_op( goto err_exit; } - UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); +#endif /* HAVE_valgrind_or_MSAN */ ut_ad(log->tail.bytes < srv_sort_buf_size); avail_size = srv_sort_buf_size - log->tail.bytes; @@ -425,7 +427,7 @@ row_log_online_op( log->tail.buf, avail_size); } - UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size); + MEM_CHECK_DEFINED(buf, srv_sort_buf_size); if (row_log_tmpfile(log) == OS_FILE_CLOSED) { log->error = DB_OUT_OF_MEMORY; @@ -460,8 +462,10 @@ write_failed: index->type |= DICT_CORRUPT; } - UNIV_MEM_INVALID(log->tail.block, srv_sort_buf_size); - UNIV_MEM_INVALID(buf, srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.block, srv_sort_buf_size); + MEM_UNDEFINED(buf, srv_sort_buf_size); +#endif /* HAVE_valgrind_or_MSAN */ memcpy(log->tail.block, log->tail.buf + avail_size, mrec_size - avail_size); @@ -471,7 +475,9 @@ write_failed: ut_ad(b == log->tail.block + log->tail.bytes); } - UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); +#endif /* HAVE_valgrind_or_MSAN */ err_exit: mutex_exit(&log->mutex); } @@ -503,7 +509,9 @@ row_log_table_open( { mutex_enter(&log->mutex); - UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); +#endif /* HAVE_valgrind_or_MSAN */ if (log->error != DB_SUCCESS) { err_exit: @@ -563,7 +571,7 @@ row_log_table_close_func( memcpy(buf + log->tail.bytes, log->tail.buf, avail); } - UNIV_MEM_ASSERT_RW(buf, srv_sort_buf_size); + MEM_CHECK_DEFINED(buf, srv_sort_buf_size); if (row_log_tmpfile(log) == OS_FILE_CLOSED) { log->error = DB_OUT_OF_MEMORY; @@ -595,8 +603,10 @@ row_log_table_close_func( write_failed: log->error = DB_ONLINE_LOG_TOO_BIG; } - UNIV_MEM_INVALID(log->tail.block, srv_sort_buf_size); - UNIV_MEM_INVALID(buf, srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.block, srv_sort_buf_size); + MEM_UNDEFINED(buf, srv_sort_buf_size); +#endif /* HAVE_valgrind_or_MSAN */ memcpy(log->tail.block, log->tail.buf + avail, size - avail); log->tail.bytes = size - avail; } else { @@ -605,7 +615,9 @@ write_failed: } log->tail.total += size; - UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); +#endif /* HAVE_valgrind_or_MSAN */ err_exit: mutex_exit(&log->mutex); @@ -1178,19 +1190,15 @@ row_log_table_get_pk_col( return(DB_INVALID_NULL); } - ulint new_i = dict_col_get_clust_pos(ifield->col, index); - - if (UNIV_UNLIKELY(new_i >= log->defaults->n_fields)) { - ut_ad(0); - return DB_INVALID_NULL; - } + unsigned col_no= ifield->col->ind; + ut_ad(col_no < log->defaults->n_fields); field = static_cast( - log->defaults->fields[new_i].data); + log->defaults->fields[col_no].data); if (!field) { return(DB_INVALID_NULL); } - len = log->defaults->fields[new_i].len; + len = log->defaults->fields[col_no].len; } if (rec_offs_nth_extern(offsets, i)) { @@ -1672,10 +1680,12 @@ blob_done: const dfield_t& default_field = log->defaults->fields[col_no]; - Field* field = log->old_table->field[col_no]; + + Field* field = log->old_table->field[col->ind]; field->set_warning(Sql_condition::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1, ulong(log->n_rows)); + WARN_DATA_TRUNCATED, 1, + ulong(log->n_rows)); if (!log->allow_not_null) { /* We got a NULL value for a NOT NULL column. */ @@ -2779,7 +2789,9 @@ row_log_table_apply_ops( ut_ad(new_trx_id_col > 0); ut_ad(new_trx_id_col != ULINT_UNDEFINED); - UNIV_MEM_INVALID(&mrec_end, sizeof mrec_end); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&mrec_end, sizeof mrec_end); +#endif /* HAVE_valgrind_or_MSAN */ offsets = static_cast(ut_malloc_nokey(i * sizeof *offsets)); rec_offs_set_n_alloc(offsets, i); @@ -3691,7 +3703,9 @@ row_log_apply_ops( ut_ad(!index->is_committed()); ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X)); ut_ad(index->online_log); - UNIV_MEM_INVALID(&mrec_end, sizeof mrec_end); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&mrec_end, sizeof mrec_end); +#endif /* HAVE_valgrind_or_MSAN */ offsets = static_cast(ut_malloc_nokey(i * sizeof *offsets)); rec_offs_set_n_alloc(offsets, i); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 0508b92e6d0..d1074f74725 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -46,6 +46,9 @@ Completed by Sunny Bains and Marko Makela #include "row0vers.h" #include "handler0alter.h" #include "btr0bulk.h" +#ifdef BTR_CUR_ADAPT +# include "btr0sea.h" +#endif /* BTR_CUR_ADAPT */ #include "ut0stage.h" #include "fil0crypt.h" @@ -197,7 +200,6 @@ public: &ins_cur, 0, __FILE__, __LINE__, &mtr); - error = btr_cur_pessimistic_insert( flag, &ins_cur, &ins_offsets, &row_heap, dtuple, &rec, @@ -1019,11 +1021,11 @@ row_merge_buf_write( ut_a(b < &block[srv_sort_buf_size]); ut_a(b == &block[0] + buf->total_size); *b++ = 0; -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind_or_MSAN /* The rest of the block is uninitialized. Initialize it to avoid bogus warnings. */ memset(b, 0xff, &block[srv_sort_buf_size] - b); -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* HAVE_valgrind_or_MSAN */ DBUG_LOG("ib_merge_sort", "write " << reinterpret_cast(b) << ',' << of->fd << ',' << of->offset << " EOF"); @@ -1416,7 +1418,9 @@ row_merge_write_rec( return(NULL); } - UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&block[0], srv_sort_buf_size); +#endif /* HAVE_valgrind_or_MSAN */ /* Copy the rest. */ b = &block[0]; @@ -1457,20 +1461,19 @@ row_merge_write_eof( ",fd=" << fd << ',' << *foffs); *b++ = 0; - UNIV_MEM_ASSERT_RW(&block[0], b - &block[0]); - UNIV_MEM_ASSERT_W(&block[0], srv_sort_buf_size); + MEM_CHECK_DEFINED(&block[0], b - &block[0]); + MEM_CHECK_ADDRESSABLE(&block[0], srv_sort_buf_size); -#ifdef UNIV_DEBUG_VALGRIND - /* The rest of the block is uninitialized. Initialize it - to avoid bogus warnings. */ - memset(b, 0xff, ulint(&block[srv_sort_buf_size] - b)); -#endif /* UNIV_DEBUG_VALGRIND */ + /* The rest of the block is uninitialized. Silence warnings. */ + MEM_MAKE_DEFINED(b, &block[srv_sort_buf_size] - b); if (!row_merge_write(fd, (*foffs)++, block, crypt_block, space)) { DBUG_RETURN(NULL); } - UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&block[0], srv_sort_buf_size); +#endif DBUG_RETURN(&block[0]); } @@ -1957,8 +1960,7 @@ row_merge_read_clustered_index( goto scan_next; } - if (clust_index->lock.waiters.load( - std::memory_order_relaxed)) { + if (clust_index->lock.waiters) { /* There are waiters on the clustered index tree lock, likely the purge thread. Store and restore the cursor @@ -1973,7 +1975,7 @@ row_merge_read_clustered_index( this is the only page in the index tree. */ ut_ad(btr_pcur_is_on_user_rec(&pcur) || btr_pcur_get_block( - &pcur)->page.id.page_no() + &pcur)->page.id().page_no() == clust_index->page); btr_pcur_store_position(&pcur, &mtr); @@ -2659,8 +2661,10 @@ write_buffers: break; } - UNIV_MEM_INVALID( +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED( &block[0], srv_sort_buf_size); +#endif /* HAVE_valgrind_or_MSAN */ } } merge_buf[i] = row_merge_buf_empty(buf); @@ -3136,10 +3140,10 @@ row_merge( ulint n_run = 0; /*!< num of runs generated from this merge */ - UNIV_MEM_ASSERT_W(&block[0], 3 * srv_sort_buf_size); + MEM_CHECK_ADDRESSABLE(&block[0], 3 * srv_sort_buf_size); if (crypt_block) { - UNIV_MEM_ASSERT_W(&crypt_block[0], 3 * srv_sort_buf_size); + MEM_CHECK_ADDRESSABLE(&crypt_block[0], 3 * srv_sort_buf_size); } ut_ad(ihalf < file->offset); @@ -3160,7 +3164,9 @@ row_merge( foffs0 = 0; foffs1 = ihalf; - UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(run_offset, *num_run * sizeof *run_offset); +#endif /* HAVE_valgrind_or_MSAN */ for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { @@ -3241,7 +3247,9 @@ row_merge( *tmpfd = file->fd; *file = of; - UNIV_MEM_INVALID(&block[0], 3 * srv_sort_buf_size); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&block[0], 3 * srv_sort_buf_size); +#endif /* HAVE_valgrind_or_MSAN */ return(DB_SUCCESS); } @@ -3355,7 +3363,7 @@ row_merge_sort( break; } - UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset); + MEM_CHECK_DEFINED(run_offset, num_runs * sizeof *run_offset); } while (num_runs > 1); ut_free(run_offset); @@ -3872,6 +3880,9 @@ row_merge_drop_indexes( we should exclude FTS entries from prebuilt->ins_node->entry_list in ins_node_create_entry_list(). */ +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!index->search_info->ref_count); +#endif /* BTR_CUR_HASH_ADAPT */ dict_index_remove_from_cache( table, index); index = prev; @@ -3912,6 +3923,7 @@ row_merge_drop_indexes( ut_error; } + fts_clear_all(table, trx); return; } @@ -3964,6 +3976,7 @@ row_merge_drop_indexes( } } + fts_clear_all(table, trx); table->drop_aborted = FALSE; ut_d(dict_table_check_for_dup_indexes(table, CHECK_ALL_COMPLETE)); } @@ -4714,7 +4727,8 @@ row_merge_build_indexes( goto func_exit; } - if (indexes[i]->type & DICT_FTS && fts_enable_diag_print) { + if (indexes[i]->type & DICT_FTS + && UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "Finished building full-text index " << indexes[i]->name; } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 9e945da79d8..20f06fc5444 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -97,7 +97,7 @@ static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list; static ib_mutex_t row_drop_list_mutex; /** Flag: has row_mysql_drop_list been initialized? */ -static ibool row_mysql_drop_list_inited = FALSE; +static bool row_mysql_drop_list_inited; /*******************************************************************//** Determine if the given name is a name reserved for MySQL system tables. @@ -294,9 +294,7 @@ row_mysql_store_geometry( { /* MySQL might assume the field is set to zero except the length and the pointer fields */ - UNIV_MEM_ASSERT_RW(src, src_len); - UNIV_MEM_ASSERT_W(dest, dest_len); - UNIV_MEM_INVALID(dest, dest_len); + MEM_CHECK_DEFINED(src, src_len); memset(dest, '\0', dest_len); @@ -786,8 +784,7 @@ handle_new_error: " foreign constraints and try again"; goto rollback_to_savept; default: - ib::fatal() << "Unknown error code " << err << ": " - << ut_strerr(err); + ib::fatal() << "Unknown error " << err; } if (trx->error_state != DB_SUCCESS) { @@ -2563,6 +2560,9 @@ row_create_index_for_mysql( UT_BITS_IN_BYTES(unsigned(index->n_nullable))); err = dict_create_index_tree_in_mem(index, trx); +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!index->search_info->ref_count); +#endif /* BTR_CUR_HASH_ADAPT */ if (err != DB_SUCCESS) { dict_index_remove_from_cache(table, index); @@ -2658,15 +2658,33 @@ next: ut_a(!table->can_be_evicted); + bool skip = false; + if (!table->to_be_dropped) { +skip: dict_table_close(table, FALSE, FALSE); mutex_enter(&row_drop_list_mutex); UT_LIST_REMOVE(row_mysql_drop_list, drop); - UT_LIST_ADD_LAST(row_mysql_drop_list, drop); + if (!skip) { + UT_LIST_ADD_LAST(row_mysql_drop_list, drop); + } else { + ut_free(drop); + } goto next; } + if (!srv_fast_shutdown && !trx_sys.any_active_transactions()) { + lock_mutex_enter(); + skip = UT_LIST_GET_LEN(table->locks) != 0; + lock_mutex_exit(); + if (skip) { + /* We cannot drop tables that are locked by XA + PREPARE transactions. */ + goto skip; + } + } + char* name = mem_strdup(table->name.m_name); dict_table_close(table, FALSE, FALSE); @@ -3233,10 +3251,10 @@ row_drop_ancillary_fts_tables( dberr_t err = fts_drop_tables(trx, table); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << " Unable to remove ancillary FTS" " tables for table " - << table->name << " : " << ut_strerr(err); + << table->name << " : " << err; return(err); } @@ -3354,6 +3372,8 @@ row_drop_table_for_mysql( DBUG_RETURN(DB_TABLE_NOT_FOUND); } + std::vector detached_handles; + const bool is_temp_name = strstr(table->name.m_name, "/" TEMP_FILE_PREFIX); @@ -3400,35 +3420,6 @@ row_drop_table_for_mysql( ut_ad(!(table->stats_bg_flag & BG_STAT_IN_PROGRESS)); if (!table->no_rollback()) { if (table->space != fil_system.sys_space) { -#ifdef BTR_CUR_HASH_ADAPT - /* On DISCARD TABLESPACE, we would not drop the - adaptive hash index entries. If the tablespace is - missing here, delete-marking the record in SYS_INDEXES - would not free any pages in the buffer pool. Thus, - dict_index_remove_from_cache() would hang due to - adaptive hash index entries existing in the buffer - pool. To prevent this hang, and also to guarantee - that btr_search_drop_page_hash_when_freed() will avoid - calling btr_search_drop_page_hash_index() while we - hold the InnoDB dictionary lock, we will drop any - adaptive hash index entries upfront. */ - const bool immune = is_temp_name - || create_failed - || sqlcom == SQLCOM_CREATE_TABLE - || strstr(table->name.m_name, "/FTS"); - - while (buf_LRU_drop_page_hash_for_tablespace(table)) { - if ((!immune && trx_is_interrupted(trx)) - || srv_shutdown_state - != SRV_SHUTDOWN_NONE) { - err = DB_INTERRUPTED; - table->to_be_dropped = false; - dict_table_close(table, true, false); - goto funct_exit; - } - } -#endif /* BTR_CUR_HASH_ADAPT */ - /* Delete the link file if used. */ if (DICT_TF_HAS_DATA_DIR(table->flags)) { RemoteDatafile::delete_link_file(name); @@ -3445,15 +3436,15 @@ row_drop_table_for_mysql( btr_defragment_remove_table(table); } - /* Remove stats for this table and all of its indexes from the - persistent storage if it exists and if there are stats for this - table in there. This function creates its own trx and commits - it. */ - char errstr[1024]; - err = dict_stats_drop_table(name, errstr, sizeof(errstr)); - - if (err != DB_SUCCESS) { - ib::warn() << errstr; + if (UNIV_LIKELY(!strstr(name, "/" TEMP_FILE_PREFIX_INNODB))) { + /* Remove any persistent statistics for this table, + in a separate transaction. */ + char errstr[1024]; + err = dict_stats_drop_table(name, errstr, + sizeof errstr); + if (err != DB_SUCCESS) { + ib::warn() << errstr; + } } } @@ -3766,7 +3757,8 @@ do_drop: ut_ad(!filepath); if (space->id != TRX_SYS_SPACE) { - err = fil_delete_tablespace(space->id); + err = fil_delete_tablespace(space->id, false, + &detached_handles); } break; @@ -3846,6 +3838,11 @@ funct_exit_all_freed: row_mysql_unlock_data_dictionary(trx); } + for (const auto& handle : detached_handles) { + ut_ad(handle != OS_FILE_CLOSED); + os_file_close(handle); + } + trx->op_info = ""; srv_wake_master_thread(); @@ -4051,10 +4048,10 @@ loop: table_name, trx, SQLCOM_DROP_DB); trx_commit_for_mysql(trx); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "DROP DATABASE " << ut_get_name(trx, name) << " failed" - " with error (" << ut_strerr(err) << ") for" + " with error (" << err << ") for" " table " << ut_get_name(trx, table_name); ut_free(table_name); break; @@ -4849,19 +4846,22 @@ row_mysql_init(void) row_mysql_drop_list, &row_mysql_drop_t::row_mysql_drop_list); - row_mysql_drop_list_inited = TRUE; + row_mysql_drop_list_inited = true; } -/*********************************************************************//** -Close this module */ -void -row_mysql_close(void) -/*================*/ +void row_mysql_close() { - ut_a(UT_LIST_GET_LEN(row_mysql_drop_list) == 0); + ut_ad(!UT_LIST_GET_LEN(row_mysql_drop_list) || + srv_force_recovery >= SRV_FORCE_NO_BACKGROUND); + if (row_mysql_drop_list_inited) + { + row_mysql_drop_list_inited= false; + mutex_free(&row_drop_list_mutex); - if (row_mysql_drop_list_inited) { - mutex_free(&row_drop_list_mutex); - row_mysql_drop_list_inited = FALSE; - } + while (row_mysql_drop_t *drop= UT_LIST_GET_FIRST(row_mysql_drop_list)) + { + UT_LIST_REMOVE(row_mysql_drop_list, drop); + ut_free(drop); + } + } } diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 9f1a7bc702e..aec4fa32ad7 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -46,7 +46,6 @@ Created 3/14/1997 Heikki Tuuri #include "handler.h" #include "ha_innodb.h" #include "fil0fil.h" -#include "debug_sync.h" /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -492,7 +491,7 @@ row_purge_remove_sec_if_poss_leaf( const buf_block_t* block = btr_cur_get_block( btr_cur); - if (block->page.id.page_no() + if (block->page.id().page_no() != index->page && page_get_n_recs(block->frame) < 2 && !lock_test_prdt_page_lock( @@ -501,8 +500,8 @@ row_purge_remove_sec_if_poss_leaf( ? thr_get_trx( btr_cur->rtr_info->thr) : NULL, - block->page.id.space(), - block->page.id.page_no())) { + block->page.id().space(), + block->page.id().page_no())) { /* this is the last record on page, and it has a "page" lock on it, which mean search is still depending @@ -510,7 +509,7 @@ row_purge_remove_sec_if_poss_leaf( DBUG_LOG("purge", "skip purging last" " record on page " - << block->page.id); + << block->page.id()); btr_pcur_close(&pcur); mtr.commit(); @@ -957,7 +956,7 @@ already_locked: if (!mysqld_server_started) { node->close_table(); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return(false); } os_thread_sleep(1000000); @@ -1111,7 +1110,7 @@ row_purge( node, undo_rec, thr, updated_extern); if (purged - || srv_shutdown_state != SRV_SHUTDOWN_NONE) { + || srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 08572b2a3a1..aec5377ce14 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -435,7 +435,6 @@ row_build_low( ut_ad(rec != NULL); ut_ad(heap != NULL); ut_ad(dict_index_is_clust(index)); - ut_ad(!mutex_own(&trx_sys.mutex)); ut_ad(!col_map || col_table); if (!offsets) { diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 7bcbbe8dcea..8b46364c744 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -974,9 +974,11 @@ row_sel_get_clust_rec( switch (err) { case DB_SUCCESS: case DB_SUCCESS_LOCKED_REC: - /* Declare the variable uninitialized in Valgrind. +#ifdef HAVE_valgrind_or_MSAN + /* Declare the variable uninitialized. It should be set to DB_SUCCESS at func_exit. */ - UNIV_MEM_INVALID(&err, sizeof err); + MEM_UNDEFINED(&err, sizeof err); +#endif /* HAVE_valgrind_or_MSAN */ break; default: goto err_exit; @@ -1241,11 +1243,9 @@ sel_set_rec_lock( trx = thr_get_trx(thr); - if (UT_LIST_GET_LEN(trx->lock.trx_locks) > 10000) { - if (buf_LRU_buf_pool_running_out()) { - - return(DB_LOCK_TABLE_FULL); - } + if (UT_LIST_GET_LEN(trx->lock.trx_locks) > 10000 + && buf_pool.running_out()) { + return DB_LOCK_TABLE_FULL; } if (dict_index_is_clust(index)) { @@ -1280,10 +1280,6 @@ void row_sel_open_pcur( /*==============*/ plan_t* plan, /*!< in: table plan */ -#ifdef BTR_CUR_HASH_ADAPT - rw_lock_t* ahi_latch, - /*!< in: the adaptive hash index latch */ -#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { dict_index_t* index; @@ -1327,7 +1323,7 @@ row_sel_open_pcur( btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, BTR_SEARCH_LEAF, &plan->pcur, - ahi_latch, mtr); + NULL, mtr); } else { /* Open the cursor to the start or the end of the index (FALSE: no init) */ @@ -1472,16 +1468,12 @@ row_sel_try_search_shortcut( ut_ad(plan->unique_search); ut_ad(!plan->must_get_clust); - rw_lock_t* ahi_latch = btr_get_search_latch(index); - rw_lock_s_lock(ahi_latch); - - row_sel_open_pcur(plan, ahi_latch, mtr); + row_sel_open_pcur(plan, mtr); const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { retry: - rw_lock_s_unlock(ahi_latch); return(SEL_RETRY); } @@ -1493,7 +1485,6 @@ retry: if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) { exhausted: - rw_lock_s_unlock(ahi_latch); return(SEL_EXHAUSTED); } @@ -1539,7 +1530,6 @@ exhausted: ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF); plan->n_rows_fetched++; - rw_lock_s_unlock(ahi_latch); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1661,11 +1651,7 @@ table_loop: if (!plan->pcur_is_open) { /* Evaluate the expressions to build the search tuple and open the cursor */ - row_sel_open_pcur(plan, -#ifdef BTR_CUR_HASH_ADAPT - NULL, -#endif /* BTR_CUR_HASH_ADAPT */ - &mtr); + row_sel_open_pcur(plan, &mtr); cursor_just_opened = TRUE; @@ -2698,9 +2684,11 @@ row_sel_field_store_in_mysql_format_func( #endif /* UNIV_DEBUG */ ut_ad(len != UNIV_SQL_NULL); - UNIV_MEM_ASSERT_RW(data, len); - UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len); - UNIV_MEM_INVALID(dest, templ->mysql_col_len); + MEM_CHECK_DEFINED(data, len); + MEM_CHECK_ADDRESSABLE(dest, templ->mysql_col_len); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(dest, templ->mysql_col_len); +#endif /* HAVE_valgrind_or_MSAN */ byte* pad = dest + len; @@ -2948,9 +2936,9 @@ row_sel_store_mysql_field( NULL value is set to the default value. */ ut_ad(templ->mysql_null_bit_mask); - UNIV_MEM_ASSERT_RW(prebuilt->default_rec - + templ->mysql_col_offset, - templ->mysql_col_len); + MEM_CHECK_DEFINED(prebuilt->default_rec + + templ->mysql_col_offset, + templ->mysql_col_len); #if defined __GNUC__ && !defined __clang__ && __GNUC__ < 6 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" /* GCC 5 may need this here */ @@ -3326,7 +3314,7 @@ Row_sel_get_clust_rec_for_mysql::operator()( same as btr_pcur_get_block(prebuilt->pcur), and is it not unsafe to use RW_NO_LATCH here? */ buf_block_t* block = buf_page_get_gen( - btr_pcur_get_block(prebuilt->pcur)->page.id, + btr_pcur_get_block(prebuilt->pcur)->page.id(), btr_pcur_get_block(prebuilt->pcur)->zip_size(), RW_NO_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); @@ -3617,7 +3605,7 @@ row_sel_copy_cached_field_for_mysql( buf += templ->mysql_col_offset; cache += templ->mysql_col_offset; - UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len); + MEM_CHECK_ADDRESSABLE(buf, templ->mysql_col_len); if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR && (templ->type != DATA_INT)) { @@ -3627,7 +3615,9 @@ row_sel_copy_cached_field_for_mysql( row_mysql_read_true_varchar( &len, cache, templ->mysql_length_bytes); len += templ->mysql_length_bytes; - UNIV_MEM_INVALID(buf, templ->mysql_col_len); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(buf, templ->mysql_col_len); +#endif /* HAVE_valgrind_or_MSAN */ } else { len = templ->mysql_col_len; } @@ -3693,7 +3683,7 @@ row_sel_dequeue_cached_row_for_mysql( ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); - UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len); + MEM_CHECK_ADDRESSABLE(buf, prebuilt->mysql_row_len); cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first]; @@ -3703,7 +3693,9 @@ row_sel_dequeue_cached_row_for_mysql( /* The record is long. Copy it field by field, in case there are some long VARCHAR column of which only a small length is being used. */ - UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(buf, prebuilt->mysql_prefix_len); +#endif /* HAVE_valgrind_or_MSAN */ /* First copy the NULL bits. */ memcpy(buf, cached_rec, prebuilt->null_bitmap_len); @@ -3787,8 +3779,10 @@ row_sel_fetch_last_buf( } ut_ad(prebuilt->fetch_cache_first == 0); - UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached], - prebuilt->mysql_row_len); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(prebuilt->fetch_cache[prebuilt->n_fetch_cached], + prebuilt->mysql_row_len); +#endif /* HAVE_valgrind_or_MSAN */ return(prebuilt->fetch_cache[prebuilt->n_fetch_cached]); } @@ -3839,7 +3833,7 @@ row_sel_try_search_shortcut_for_mysql( ut_ad(dict_index_is_clust(index)); ut_ad(!prebuilt->templ_contains_blob); - rw_lock_t* ahi_latch = btr_get_search_latch(index); + rw_lock_t* ahi_latch = btr_search_sys.get_latch(*index); rw_lock_s_lock(ahi_latch); btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, pcur, ahi_latch, mtr); @@ -4793,12 +4787,12 @@ wrong_offs: << static_cast(rec) << ", buf block fix count " << btr_pcur_get_block(pcur)->page - .buf_fix_count; + .buf_fix_count(); ib::error() << "Index corruption: rec offs " << page_offset(rec) << " next offs " - << next_offs << ", page no " - << btr_pcur_get_block(pcur)->page.id.page_no() + << next_offs + << btr_pcur_get_block(pcur)->page.id() << ", index " << index->name << " of table " << index->table->name << ". Run CHECK TABLE. You may need to" @@ -4814,8 +4808,8 @@ wrong_offs: ib::info() << "Index corruption: rec offs " << page_offset(rec) << " next offs " - << next_offs << ", page no " - << btr_pcur_get_block(pcur)->page.id.page_no() + << next_offs + << btr_pcur_get_block(pcur)->page.id() << ", index " << index->name << " of table " << index->table->name << ". We try to skip the rest of the page."; @@ -4842,8 +4836,8 @@ wrong_offs: ib::error() << "Index corruption: rec offs " << page_offset(rec) << " next offs " - << next_offs << ", page no " - << btr_pcur_get_block(pcur)->page.id.page_no() + << next_offs + << btr_pcur_get_block(pcur)->page.id() << ", index " << index->name << " of table " << index->table->name << ". We try to skip the record."; diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 3df17365560..39f7ddbd79a 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -216,8 +216,7 @@ static bool row_undo_mod_must_purge(undo_node_t* node, mtr_t* mtr) mtr->s_lock(&purge_sys.latch, __FILE__, __LINE__); - if (!purge_sys.view.changes_visible(node->new_trx_id, - node->table->name)) { + if (!purge_sys.changes_visible(node->new_trx_id, node->table->name)) { return false; } @@ -422,8 +421,8 @@ row_undo_mod_clust( } rec_t* rec = btr_pcur_get_rec(pcur); mtr.s_lock(&purge_sys.latch, __FILE__, __LINE__); - if (!purge_sys.view.changes_visible(node->new_trx_id, - node->table->name)) { + if (!purge_sys.changes_visible(node->new_trx_id, + node->table->name)) { goto mtr_commit_exit; } @@ -965,7 +964,7 @@ row_undo_mod_upd_del_sec( does not exist. However, this situation may only occur during the rollback of incomplete transactions. */ - ut_a(thr_is_recv(thr)); + ut_a(thr_get_trx(thr) == trx_roll_crash_recv_trx); } else { err = row_undo_mod_del_mark_or_remove_sec( node, thr, index, entry); diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 8fca99a44b8..20bf53e3f91 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -348,7 +348,7 @@ static bool row_undo_rec_get(undo_node_t* node) trx->pages_undone++; } - undo->top_page_no = prev_page->page.id.page_no(); + undo->top_page_no = prev_page->page.id().page_no(); undo->top_offset = page_offset(prev_rec); undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); ut_ad(!undo->empty()); @@ -478,7 +478,7 @@ row_undo_step( if (UNIV_UNLIKELY(trx_get_dict_operation(trx) == TRX_DICT_OP_NONE && !srv_undo_sources - && !srv_is_being_started) + && srv_shutdown_state != SRV_SHUTDOWN_NONE) && (srv_fast_shutdown == 3 || trx == trx_roll_crash_recv_trx)) { /* Shutdown has been initiated. */ trx->error_state = DB_INTERRUPTED; @@ -499,15 +499,8 @@ row_undo_step( trx->error_state = err; - if (err != DB_SUCCESS) { - /* SQL error detected */ - - if (err == DB_OUT_OF_FILE_SPACE) { - ib::fatal() << "Out of tablespace during rollback." - " Consider increasing your tablespace."; - } - - ib::fatal() << "Error (" << ut_strerr(err) << ") in rollback."; + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::fatal() << "Error (" << err << ") in rollback."; } return(thr); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 06c18e15ef3..969d0017eeb 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1542,7 +1542,9 @@ row_upd_changes_ord_field_binary_func( /* Silence a compiler warning without silencing a Valgrind error. */ dfield_len = 0; - UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len); +#ifdef HAVE_valgrind_or_MSAN + MEM_UNDEFINED(&dfield_len, sizeof dfield_len); +#endif /* HAVE_valgrind_or_MSAN */ /* See if the column is stored externally. */ buf = row_ext_lookup(ext, col_no, &dfield_len); @@ -1557,7 +1559,8 @@ row_upd_changes_ord_field_binary_func( when the server had crashed before storing the field. */ ut_ad(thr->graph->trx->is_recovered); - ut_ad(trx_is_recv(thr->graph->trx)); + ut_ad(thr->graph->trx + == trx_roll_crash_recv_trx); return(TRUE); } @@ -2155,7 +2158,7 @@ row_upd_sec_index_entry( err = DB_SUCCESS; break; case DB_LOCK_WAIT: - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK lock wait" << " index " << index->name << " table " << index->table->name @@ -2163,7 +2166,7 @@ row_upd_sec_index_entry( } break; case DB_DEADLOCK: - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name @@ -2171,7 +2174,7 @@ row_upd_sec_index_entry( } break; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name << " query " << wsrep_thd_query(trx->mysql_thd); @@ -2481,14 +2484,14 @@ check_fk: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; } goto err_exit; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name; goto err_exit; @@ -2572,8 +2575,7 @@ row_upd_clust_rec( mtr_commit(mtr); - if (buf_LRU_buf_pool_running_out()) { - + if (buf_pool.running_out()) { err = DB_LOCK_TABLE_FULL; goto func_exit; } @@ -2707,14 +2709,14 @@ row_upd_del_mark_clust_rec( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; } break; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name; diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index a0d0d5d1ad4..d84747c9007 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -396,7 +396,6 @@ row_vers_impl_x_locked( dict_index_t* clust_index; ut_ad(!lock_mutex_own()); - ut_ad(!mutex_own(&trx_sys.mutex)); mtr_start(&mtr); @@ -459,8 +458,6 @@ row_vers_build_clust_v_col( ut_ad(dict_index_has_virtual(index)); ut_ad(index->table == clust_index->table); - DEBUG_SYNC(current_thd, "ib_clust_v_col_before_row_allocated"); - innobase_allocate_row_for_vcol(thd, index, &local_heap, &maria_table, @@ -876,8 +873,8 @@ row_vers_old_has_index_entry( mem_heap_t* v_heap = NULL; dtuple_t* cur_vrow = NULL; - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); clust_index = dict_table_get_first_index(index->table); comp = page_rec_is_comp(rec); @@ -1129,9 +1126,9 @@ row_vers_build_for_consistent_read( byte* buf; dberr_t err; - ut_ad(dict_index_is_clust(index)); - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(index->is_primary()); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(!rw_lock_own(&(purge_sys.latch), RW_LOCK_S)); ut_ad(rec_offs_validate(rec, index, *offsets)); @@ -1242,9 +1239,9 @@ row_vers_build_for_semi_consistent_read( byte* buf; trx_id_t rec_trx_id = 0; - ut_ad(dict_index_is_clust(index)); - ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_S_FIX)); + ut_ad(index->is_primary()); + ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(!rw_lock_own(&(purge_sys.latch), RW_LOCK_S)); ut_ad(rec_offs_validate(rec, index, *offsets)); diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 2f358901f2e..07e0299dc98 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -120,7 +120,7 @@ srv_conc_enter_innodb_with_atomics( ulint sleep_in_us; #ifdef WITH_WSREP if (trx->is_wsrep() && wsrep_thd_is_aborting(trx->mysql_thd)) { - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "srv_conc_enter due to MUST_ABORT"; } @@ -308,14 +308,14 @@ wsrep_srv_conc_cancel_wait( srv_conc_enter_innodb_with_atomics(). No need to cancel here, thr will wake up after os_sleep and let to enter innodb */ - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: conc slot cancel, no atomics"; } #else // JAN: TODO: MySQL 5.7 //os_fast_mutex_lock(&srv_conc_mutex); if (trx->wsrep_event) { - if (wsrep_get_debug()) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: conc slot cancel"; } os_event_set(trx->wsrep_event); diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 017c5da0353..ef16c453657 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -1194,16 +1194,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_SRV_LOG_FLUSH_MICROSECOND}, - {"innodb_mem_validate_usec", "server", - "Time (in microseconds) spent to do memory validation", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_SRV_MEM_VALIDATE_MICROSECOND}, - - {"innodb_master_purge_usec", "server", - "Time (in microseconds) spent by master thread to purge records", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_SRV_PURGE_MICROSECOND}, - {"innodb_dict_lru_usec", "server", "Time (in microseconds) spent to process DICT LRU list", MONITOR_NONE, @@ -2002,7 +1992,7 @@ srv_mon_process_existing_counter( break; case MONITOR_OVLD_BUF_OLDEST_LSN: - value = (mon_type_t) buf_pool_get_oldest_modification(); + value = (mon_type_t) buf_pool.get_oldest_modification(); break; case MONITOR_OVLD_LSN_CHECKPOINT: diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 726fe613f46..8b8765b2748 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -72,6 +72,7 @@ Created 10/8/1995 Heikki Tuuri #include "fil0fil.h" #include "fil0crypt.h" #include "fil0pagecompress.h" +#include "trx0types.h" #include @@ -206,9 +207,6 @@ const ulint srv_buf_pool_min_size = 5 * 1024 * 1024; const ulint srv_buf_pool_def_size = 128 * 1024 * 1024; /** Requested buffer pool chunk size */ ulong srv_buf_pool_chunk_unit; -/** innodb_page_hash_locks (a debug-only parameter); -number of locks to protect buf_pool.page_hash */ -ulong srv_n_page_hash_locks = 16; /** innodb_lru_scan_depth; number of blocks scanned in LRU flush batch */ ulong srv_LRU_scan_depth; /** innodb_flush_neighbors; whether or not to flush neighbors of a block */ @@ -458,9 +456,6 @@ current_time % 60 == 0 and no tasks will be performed when current_time % 5 != 0. */ # define SRV_MASTER_CHECKPOINT_INTERVAL (7) -#ifdef MEM_PERIODIC_CHECK -# define SRV_MASTER_MEM_VALIDATE_INTERVAL (13) -#endif /* MEM_PERIODIC_CHECK */ # define SRV_MASTER_DICT_LRU_INTERVAL (47) /** Simulate compression failures. */ @@ -967,29 +962,15 @@ srv_printf_innodb_monitor( ibuf_print(file); #ifdef BTR_CUR_HASH_ADAPT - for (ulint i = 0; i < btr_ahi_parts; ++i) { - const hash_table_t* table = btr_search_sys->hash_tables[i]; - - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - /* this is only used for buf_pool.page_hash */ - ut_ad(!table->heaps); - /* this is used for the adaptive hash index */ - ut_ad(table->heap); - - const mem_heap_t* heap = table->heap; - /* The heap may change during the following call, - so the data displayed may be garbage. We intentionally - avoid acquiring btr_search_latches[] so that the - diagnostic output will not stop here even in case another - thread hangs while holding btr_search_latches[]. - - This should be safe from crashes, because - table->heap will be pointing to the same object - for the full lifetime of the server. Even during - btr_search_disable() the heap will stay valid. */ + for (ulint i = 0; i < btr_ahi_parts && btr_search_enabled; ++i) { + const auto part= &btr_search_sys.parts[i]; + rw_lock_s_lock(&part->latch); + ut_ad(part->heap->type == MEM_HEAP_FOR_BTR_SEARCH); fprintf(file, "Hash table size " ULINTPF ", node heap has " ULINTPF " buffer(s)\n", - table->n_cells, heap->base.count - !heap->free_block); + part->table.n_cells, + part->heap->base.count - !part->heap->free_block); + rw_lock_s_unlock(&part->latch); } fprintf(file, @@ -1128,21 +1109,16 @@ srv_export_innodb_status(void) #ifdef BTR_CUR_HASH_ADAPT ulint mem_adaptive_hash = 0; - ut_ad(btr_search_sys->hash_tables); for (ulong i = 0; i < btr_ahi_parts; i++) { - rw_lock_s_lock(btr_search_latches[i]); - hash_table_t* ht = btr_search_sys->hash_tables[i]; + const auto part= &btr_search_sys.parts[i]; + rw_lock_s_lock(&part->latch); + if (part->heap) { + ut_ad(part->heap->type == MEM_HEAP_FOR_BTR_SEARCH); - ut_ad(ht); - ut_ad(ht->heap); - /* Multiple mutexes/heaps are currently never used for adaptive - hash index tables. */ - ut_ad(!ht->n_sync_obj); - ut_ad(!ht->heaps); - - mem_adaptive_hash += mem_heap_get_size(ht->heap) - + ht->n_cells * sizeof(hash_cell_t); - rw_lock_s_unlock(btr_search_latches[i]); + mem_adaptive_hash += mem_heap_get_size(part->heap) + + part->table.n_cells * sizeof(hash_cell_t); + } + rw_lock_s_unlock(&part->latch); } export_vars.innodb_mem_adaptive_hash = mem_adaptive_hash; #endif @@ -1815,7 +1791,7 @@ srv_master_do_active_tasks(void) ut_d(srv_master_do_disabled_loop()); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1833,7 +1809,7 @@ srv_master_do_active_tasks(void) /* Now see if various tasks that are performed at defined intervals need to be performed. */ - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1858,7 +1834,7 @@ srv_master_do_active_tasks(void) early and often to avoid those situations. */ DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1901,7 +1877,7 @@ srv_master_do_idle_tasks(void) ut_d(srv_master_do_disabled_loop()); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1910,7 +1886,7 @@ srv_master_do_idle_tasks(void) srv_main_thread_op_info = "checking free log space"; log_free_check(); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1938,7 +1914,7 @@ srv_master_do_idle_tasks(void) early and often to avoid those situations. */ DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -1991,7 +1967,7 @@ void srv_master_callback(void*) { static ulint old_activity_count; - ut_a(srv_shutdown_state == SRV_SHUTDOWN_NONE); + ut_a(srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); srv_main_thread_op_info = ""; MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP); @@ -2007,33 +1983,33 @@ void srv_master_callback(void*) /** @return whether purge should exit due to shutdown */ static bool srv_purge_should_exit() { - ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE - || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP); + ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP); - if (srv_undo_sources) { - return(false); - } - if (srv_fast_shutdown) { - return(true); - } - /* Slow shutdown was requested. */ - uint32_t history_size = trx_sys.rseg_history_len; - if (history_size) { + if (srv_undo_sources) + return false; + + if (srv_fast_shutdown) + return true; + + /* Slow shutdown was requested. */ + if (const uint32_t history_size= trx_sys.rseg_history_len) + { + static time_t progress_time; + time_t now= time(NULL); + if (now - progress_time >= 15) + { + progress_time= now; #if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY - static time_t progress_time; - time_t now = time(NULL); - if (now - progress_time >= 15) { - progress_time = now; - service_manager_extend_timeout( - INNODB_EXTEND_TIMEOUT_INTERVAL, - "InnoDB: to purge %u transactions", - history_size); - } + service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, + "InnoDB: to purge %u transactions", + history_size); + ib::info() << "to purge " << history_size << " transactions"; #endif - return false; - } + } + return false; + } - return !trx_sys.any_active_transactions(); + return !trx_sys.any_active_transactions(); } /*********************************************************************//** @@ -2060,6 +2036,15 @@ static bool srv_task_execute() return false; } +std::mutex purge_thread_count_mtx; +void srv_update_purge_thread_count(uint n) +{ + std::lock_guard lk(purge_thread_count_mtx); + srv_n_purge_threads = n; + srv_purge_thread_count_changed = 1; +} + +Atomic_counter srv_purge_thread_count_changed; /** Do the actual purge operation. @param[in,out] n_total_purged total number of purged pages @@ -2072,7 +2057,7 @@ static uint32_t srv_do_purge(ulint* n_total_purged) static ulint n_use_threads = 0; static uint32_t rseg_history_len = 0; ulint old_activity_count = srv_get_activity_count(); - const ulint n_threads = srv_n_purge_threads; + static ulint n_threads = srv_n_purge_threads; ut_a(n_threads > 0); ut_ad(!srv_read_only_mode); @@ -2088,7 +2073,20 @@ static uint32_t srv_do_purge(ulint* n_total_purged) } do { - if (trx_sys.rseg_history_len > rseg_history_len + if (UNIV_UNLIKELY(srv_purge_thread_count_changed)) { + /* Read the fresh value of srv_n_purge_threads, reset + the changed flag. Both variables are protected by + purge_thread_count_mtx. + + This code does not run concurrently, it is executed + by a single purge_coordinator thread, and no races + involving srv_purge_thread_count_changed are possible. + */ + + std::lock_guard lk(purge_thread_count_mtx); + n_threads = n_use_threads = srv_n_purge_threads; + srv_purge_thread_count_changed = 0; + } else if (trx_sys.rseg_history_len > rseg_history_len || (srv_max_purge_lag > 0 && rseg_history_len > srv_max_purge_lag)) { @@ -2136,23 +2134,17 @@ static uint32_t srv_do_purge(ulint* n_total_purged) static std::queue purge_thds; static std::mutex purge_thd_mutex; - -static void purge_create_background_thds(int n) -{ - THD *thd= current_thd; - std::unique_lock lk(purge_thd_mutex); - while (n--) - purge_thds.push(innobase_create_background_thd("InnoDB purge worker")); - set_current_thd(thd); -} - extern void* thd_attach_thd(THD*); extern void thd_detach_thd(void *); THD* acquire_thd(void **ctx) { std::unique_lock lk(purge_thd_mutex); - ut_a(!purge_thds.empty()); + if (purge_thds.empty()) { + THD* thd = current_thd; + purge_thds.push(innobase_create_background_thd("InnoDB purge worker")); + set_current_thd(thd); + } THD* thd = purge_thds.front(); purge_thds.pop(); lk.unlock(); @@ -2173,7 +2165,6 @@ void release_thd(THD *thd, void *ctx) } - /* Called by timer when purge coordinator decides to delay processing of purge records. @@ -2252,10 +2243,8 @@ static void purge_coordinator_callback(void*) purge_state.m_running= 0; } -void srv_init_purge_tasks(uint n_tasks) +void srv_init_purge_tasks() { - purge_task_group.set_max_tasks(n_tasks - 1); - purge_create_background_thds(n_tasks); purge_coordinator_timer= srv_thread_pool->create_timer (purge_coordinator_timer_callback, nullptr); } @@ -2311,10 +2300,11 @@ ulint srv_get_task_queue_length() void srv_purge_shutdown() { if (purge_sys.enabled()) { + srv_update_purge_thread_count(innodb_purge_threads_MAX); while(!srv_purge_should_exit()) { ut_a(!purge_sys.paused()); srv_wake_purge_thread_if_not_active(); - os_thread_sleep(100); + os_thread_sleep(1000); } purge_sys.coordinator_shutdown(); srv_shutdown_purge_tasks(); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index c234a3c8782..5dbf01c6b49 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -269,7 +269,7 @@ static dberr_t create_log_file(lsn_t lsn, std::string& logfile0) } DBUG_PRINT("ib_log", ("After innodb_log_abort_6")); - ut_ad(!buf_pool_check_no_pending_io()); + DBUG_ASSERT(!buf_pool.any_io_pending()); DBUG_EXECUTE_IF("innodb_log_abort_7", return DB_ERROR;); DBUG_PRINT("ib_log", ("After innodb_log_abort_7")); @@ -947,12 +947,14 @@ srv_init_abort_low( #endif /* UNIV_DEBUG */ dberr_t err) { + ut_ad(srv_is_being_started); + if (create_new_db) { ib::error() << "Database creation was aborted" #ifdef UNIV_DEBUG " at " << innobase_basename(file) << "[" << line << "]" #endif /* UNIV_DEBUG */ - " with error " << ut_strerr(err) << ". You may need" + " with error " << err << ". You may need" " to delete the ibdata1 file before trying to start" " up again."; } else { @@ -960,7 +962,7 @@ srv_init_abort_low( #ifdef UNIV_DEBUG " at " << innobase_basename(file) << "[" << line << "]" #endif /* UNIV_DEBUG */ - " with error " << ut_strerr(err); + " with error " << err; } srv_shutdown_bg_undo_sources(); @@ -977,14 +979,13 @@ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists) DBUG_ENTER("srv_prepare_to_delete_redo_log_file"); lsn_t flushed_lsn; - ulint pending_io = 0; ulint count = 0; if (log_sys.log.subformat != 2) { srv_log_file_size = 0; } - do { + for (;;) { /* Clean the buffer pool. */ buf_flush_sync(); @@ -1041,9 +1042,7 @@ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists) /* Check if the buffer pools are clean. If not retry till it is clean. */ - pending_io = buf_pool_check_no_pending_io(); - - if (pending_io > 0) { + if (ulint pending_io = buf_pool.io_pending()) { count++; /* Print a message every 60 seconds if we are waiting to clean the buffer pools */ @@ -1053,10 +1052,13 @@ static lsn_t srv_prepare_to_delete_redo_log_file(bool old_exists) << "page I/Os to complete"; count = 0; } - } - os_thread_sleep(100000); - } while (buf_pool_check_no_pending_io()); + os_thread_sleep(100000); + continue; + } + + break; + } DBUG_RETURN(flushed_lsn); } @@ -1160,11 +1162,6 @@ dberr_t srv_start(bool create_new_db) ib::info() << "!!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!"; #endif -#ifdef _WIN32 - ib::info() << "Mutexes and rw_locks use Windows interlocked functions"; -#else - ib::info() << "Mutexes and rw_locks use GCC atomic builtins"; -#endif ib::info() << MUTEX_TYPE; ib::info() << "Compressed tables use zlib " ZLIB_VERSION @@ -1680,7 +1677,7 @@ file_checked: ut_ad(recv_no_log_write); buf_flush_sync(); err = fil_write_flushed_lsn(log_get_lsn()); - ut_ad(!buf_pool_check_no_pending_io()); + DBUG_ASSERT(!buf_pool.any_io_pending()); log_sys.log.close_file(); if (err == DB_SUCCESS) { bool trunc = srv_operation @@ -1724,7 +1721,7 @@ file_checked: threads until creating a log checkpoint at the end of create_log_file(). */ ut_d(recv_no_log_write = true); - ut_ad(!buf_pool_check_no_pending_io()); + DBUG_ASSERT(!buf_pool.any_io_pending()); DBUG_EXECUTE_IF("innodb_log_abort_3", return(srv_init_abort(DB_ERROR));); @@ -1967,8 +1964,7 @@ skip_monitors: if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) { - - srv_init_purge_tasks(srv_n_purge_threads); + srv_init_purge_tasks(); purge_sys.coordinator_startup(); srv_wake_purge_thread_if_not_active(); srv_start_state_set(SRV_START_STATE_PURGE); @@ -2046,6 +2042,7 @@ void srv_shutdown_bg_undo_sources() { if (srv_undo_sources) { ut_ad(!srv_read_only_mode); + srv_shutdown_state = SRV_SHUTDOWN_INITIATED; fts_optimize_shutdown(); dict_stats_shutdown(); while (row_get_background_drop_list_len_low()) { @@ -2070,8 +2067,14 @@ void innodb_preshutdown() if (srv_read_only_mode) return; if (!srv_fast_shutdown && srv_operation == SRV_OPERATION_NORMAL) + { + /* Because a slow shutdown must empty the change buffer, we had + better prevent any further changes from being buffered. */ + innodb_change_buffering= 0; + while (trx_sys.any_active_transactions()) os_thread_sleep(1000); + } srv_shutdown_bg_undo_sources(); srv_purge_shutdown(); } @@ -2087,7 +2090,6 @@ void innodb_shutdown() case SRV_OPERATION_RESTORE: case SRV_OPERATION_RESTORE_DELTA: case SRV_OPERATION_RESTORE_EXPORT: - fil_close_all_files(); break; case SRV_OPERATION_NORMAL: /* Shut down the persistent files. */ @@ -2100,6 +2102,8 @@ void innodb_shutdown() } } + os_aio_free(); + fil_close_all_files(); /* Exit any remaining threads. */ srv_shutdown_all_bg_threads(); @@ -2123,9 +2127,6 @@ void innodb_shutdown() || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); ut_ad(lock_sys.is_initialised() || !srv_was_started); ut_ad(log_sys.is_initialised() || !srv_was_started); -#ifdef BTR_CUR_HASH_ADAPT - ut_ad(btr_search_sys || !srv_was_started); -#endif /* BTR_CUR_HASH_ADAPT */ ut_ad(ibuf.index || !srv_was_started); dict_stats_deinit(); @@ -2144,7 +2145,7 @@ void innodb_shutdown() #ifdef BTR_CUR_HASH_ADAPT if (dict_sys.is_initialised()) { - btr_search_disable(true); + btr_search_disable(); } #endif /* BTR_CUR_HASH_ADAPT */ ibuf_close(); @@ -2163,7 +2164,6 @@ void innodb_shutdown() } dict_sys.close(); - os_aio_free(); btr_search_sys_free(); row_mysql_close(); srv_free(); diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index 4f2f384a5ef..a0203ca6bde 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -77,7 +77,6 @@ infinite wait The error_monitor thread scans the global wait array to signal any waiting threads who have missed the signal. */ typedef TTASEventMutex WaitMutex; -typedef TTASEventMutex BlockWaitMutex; /** The latch types that use the sync array. */ union sync_object_t { @@ -87,9 +86,6 @@ union sync_object_t { /** Mutex instance */ WaitMutex* mutex; - - /** Block mutex instance */ - BlockWaitMutex* bpmutex; }; /** A cell where an individual thread may wait suspended until a resource @@ -294,22 +290,12 @@ sync_cell_get_event( /*================*/ sync_cell_t* cell) /*!< in: non-empty sync array cell */ { - ulint type = cell->request_type; - - if (type == SYNC_MUTEX) { - + switch(cell->request_type) { + case SYNC_MUTEX: return(cell->latch.mutex->event()); - - } else if (type == SYNC_BUF_BLOCK) { - - return(cell->latch.bpmutex->event()); - - } else if (type == RW_LOCK_X_WAIT) { - + case RW_LOCK_X_WAIT: return(cell->latch.lock->wait_ex_event); - - } else { /* RW_LOCK_S and RW_LOCK_X wait on the same event */ - + default: return(cell->latch.lock->event); } } @@ -362,8 +348,6 @@ sync_array_reserve_cell( if (cell->request_type == SYNC_MUTEX) { cell->latch.mutex = reinterpret_cast(object); - } else if (cell->request_type == SYNC_BUF_BLOCK) { - cell->latch.bpmutex = reinterpret_cast(object); } else { cell->latch.lock = reinterpret_cast(object); } @@ -499,65 +483,13 @@ sync_array_cell_print( innobase_basename(cell->file), (ulong) cell->line, difftime(time(NULL), cell->reservation_time)); - if (type == SYNC_MUTEX) { - WaitMutex* mutex = cell->latch.mutex; - const WaitMutex::MutexPolicy& policy = mutex->policy(); -#ifdef UNIV_DEBUG - const char* name = policy.context.get_enter_filename(); - if (name == NULL) { - /* The mutex might have been released. */ - name = "NULL"; - } -#endif /* UNIV_DEBUG */ - - if (mutex) { - fprintf(file, - "Mutex at %p, %s, lock var %x\n" -#ifdef UNIV_DEBUG - "Last time reserved in file %s line %u" -#endif /* UNIV_DEBUG */ - "\n", - (void*) mutex, - policy.to_string().c_str(), - mutex->state() -#ifdef UNIV_DEBUG - ,name, - policy.context.get_enter_line() -#endif /* UNIV_DEBUG */ - ); - } - } else if (type == SYNC_BUF_BLOCK) { - BlockWaitMutex* mutex = cell->latch.bpmutex; - - const BlockWaitMutex::MutexPolicy& policy = - mutex->policy(); -#ifdef UNIV_DEBUG - const char* name = policy.context.get_enter_filename(); - if (name == NULL) { - /* The mutex might have been released. */ - name = "NULL"; - } -#endif /* UNIV_DEBUG */ - - fprintf(file, - "Mutex at %p, %s, lock var %lu\n" -#ifdef UNIV_DEBUG - "Last time reserved in file %s line %lu" -#endif /* UNIV_DEBUG */ - "\n", - (void*) mutex, - policy.to_string().c_str(), - (ulong) mutex->state() -#ifdef UNIV_DEBUG - ,name, - (ulong) policy.context.get_enter_line() -#endif /* UNIV_DEBUG */ - ); - } else if (type == RW_LOCK_X - || type == RW_LOCK_X_WAIT - || type == RW_LOCK_SX - || type == RW_LOCK_S) { - + switch (type) { + default: + ut_error; + case RW_LOCK_X: + case RW_LOCK_X_WAIT: + case RW_LOCK_SX: + case RW_LOCK_S: fputs(type == RW_LOCK_X ? "X-lock on" : type == RW_LOCK_X_WAIT ? "X-lock (wait_ex) on" : type == RW_LOCK_SX ? "SX-lock on" @@ -595,8 +527,8 @@ sync_array_cell_print( #endif "\n", rw_lock_get_reader_count(rwlock), - rwlock->waiters.load(std::memory_order_relaxed), - rwlock->lock_word.load(std::memory_order_relaxed), + uint32_t{rwlock->waiters}, + int32_t{rwlock->lock_word}, innobase_basename(rwlock->last_x_file_name), rwlock->last_x_line #if 0 /* JAN: TODO: FIX LATER */ @@ -606,9 +538,35 @@ sync_array_cell_print( #endif ); } + break; + case SYNC_MUTEX: + WaitMutex* mutex = cell->latch.mutex; + const WaitMutex::MutexPolicy& policy = mutex->policy(); +#ifdef UNIV_DEBUG + const char* name = policy.context.get_enter_filename(); + if (name == NULL) { + /* The mutex might have been released. */ + name = "NULL"; + } +#endif /* UNIV_DEBUG */ - } else { - ut_error; + if (mutex) { + fprintf(file, + "Mutex at %p, %s, lock var %x\n" +#ifdef UNIV_DEBUG + "Last time reserved in file %s line %u" +#endif /* UNIV_DEBUG */ + "\n", + (void*) mutex, + policy.to_string().c_str(), + mutex->state() +#ifdef UNIV_DEBUG + ,name, + policy.context.get_enter_line() +#endif /* UNIV_DEBUG */ + ); + } + break; } if (!cell->waiting) { @@ -781,52 +739,6 @@ sync_array_detect_deadlock( return(false); } - case SYNC_BUF_BLOCK: { - - BlockWaitMutex* mutex = cell->latch.bpmutex; - - const BlockWaitMutex::MutexPolicy& policy = - mutex->policy(); - - if (mutex->state() != MUTEX_STATE_UNLOCKED) { - thread = policy.context.get_thread_id(); - - /* Note that mutex->thread_id above may be - also OS_THREAD_ID_UNDEFINED, because the - thread which held the mutex maybe has not - yet updated the value, or it has already - released the mutex: in this case no deadlock - can occur, as the wait array cannot contain - a thread with ID_UNDEFINED value. */ - ret = sync_array_deadlock_step( - arr, start, thread, 0, depth); - - if (ret) { - const char* name; - - name = policy.context.get_enter_filename(); - - if (name == NULL) { - /* The mutex might have been - released. */ - name = "NULL"; - } - - ib::info() - << "Mutex " << mutex << " owned by" - " thread " << os_thread_pf(thread) - << " file " << name << " line " - << policy.context.get_enter_line(); - - - return(true); - } - } - - /* No deadlock */ - return(false); - } - case RW_LOCK_X: case RW_LOCK_X_WAIT: @@ -979,9 +891,9 @@ sync_array_print_long_waits_low( return(false); } -#ifdef UNIV_DEBUG_VALGRIND +#ifdef HAVE_valgrind /* Increase the timeouts if running under valgrind because it executes - extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that + extremely slowly. HAVE_valgrind does not necessary mean that we are running under valgrind but we have no better way to tell. See Bug#58432 innodb.innodb_bug56143 fails under valgrind for an example */ @@ -1384,10 +1296,10 @@ sync_arr_fill_sys_semphore_waits_table( //fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE]->set_notnull(); OK(fields[SYS_SEMAPHORE_WAITS_READERS]->store(rw_lock_get_reader_count(rwlock), true)); OK(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG]->store( - rwlock->waiters.load(std::memory_order_relaxed), + rwlock->waiters, true)); OK(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD]->store( - rwlock->lock_word.load(std::memory_order_relaxed), + rwlock->lock_word, true)); OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name))); OK(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE]->store(rwlock->last_x_line, true)); diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index 837d0846699..08f8baab101 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -456,7 +456,6 @@ LatchDebug::LatchDebug() LEVEL_MAP_INSERT(SYNC_ANY_LATCH); LEVEL_MAP_INSERT(SYNC_DOUBLEWRITE); LEVEL_MAP_INSERT(SYNC_BUF_FLUSH_LIST); - LEVEL_MAP_INSERT(SYNC_BUF_BLOCK); LEVEL_MAP_INSERT(SYNC_BUF_PAGE_HASH); LEVEL_MAP_INSERT(SYNC_BUF_POOL); LEVEL_MAP_INSERT(SYNC_POOL); @@ -478,6 +477,7 @@ LatchDebug::LatchDebug() LEVEL_MAP_INSERT(SYNC_THREADS); LEVEL_MAP_INSERT(SYNC_TRX); LEVEL_MAP_INSERT(SYNC_RW_TRX_HASH_ELEMENT); + LEVEL_MAP_INSERT(SYNC_READ_VIEW); LEVEL_MAP_INSERT(SYNC_TRX_SYS); LEVEL_MAP_INSERT(SYNC_LOCK_SYS); LEVEL_MAP_INSERT(SYNC_LOCK_WAIT_SYS); @@ -759,6 +759,7 @@ LatchDebug::check_order( case SYNC_LOCK_SYS: case SYNC_LOCK_WAIT_SYS: case SYNC_RW_TRX_HASH_ELEMENT: + case SYNC_READ_VIEW: case SYNC_TRX_SYS: case SYNC_IBUF_BITMAP_MUTEX: case SYNC_REDO_RSEG: @@ -776,7 +777,7 @@ LatchDebug::check_order( case SYNC_POOL: case SYNC_POOL_MANAGER: case SYNC_RECV_WRITER: - + case SYNC_BUF_PAGE_HASH: basic_check(latches, level, level); break; @@ -824,26 +825,6 @@ LatchDebug::check_order( basic_check(latches, level, level - 1); break; - case SYNC_BUF_PAGE_HASH: - - /* Multiple page_hash locks are only allowed during - buf_pool.validate() and that is where buf_pool mutex is already - held. */ - - /* Fall through */ - - case SYNC_BUF_BLOCK: - - /* Either the thread must own the (buffer pool) buf_pool.mutex - or it is allowed to latch only ONE of (buffer block) - block->mutex or buf_pool.zip_mutex. */ - - if (less(latches, level) != NULL) { - basic_check(latches, level, level - 1); - ut_a(find(latches, SYNC_BUF_POOL) != 0); - } - break; - case SYNC_REC_LOCK: if (find(latches, SYNC_LOCK_SYS) != 0) { @@ -1278,17 +1259,8 @@ sync_latch_meta_init() LATCH_ADD_MUTEX(AUTOINC, SYNC_DICT_AUTOINC_MUTEX, autoinc_mutex_key); -#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC - LATCH_ADD_MUTEX(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK, PFS_NOT_INSTRUMENTED); -#else - LATCH_ADD_MUTEX(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK, - buffer_block_mutex_key); -#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */ - LATCH_ADD_MUTEX(BUF_POOL, SYNC_BUF_POOL, buf_pool_mutex_key); - LATCH_ADD_MUTEX(BUF_POOL_ZIP, SYNC_BUF_BLOCK, buf_pool_zip_mutex_key); - LATCH_ADD_MUTEX(CACHE_LAST_READ, SYNC_TRX_I_S_LAST_READ, cache_last_read_mutex_key); @@ -1314,9 +1286,6 @@ sync_latch_meta_init() LATCH_ADD_MUTEX(FTS_PLL_TOKENIZE, SYNC_FTS_TOKENIZE, fts_pll_tokenize_mutex_key); - LATCH_ADD_MUTEX(HASH_TABLE_MUTEX, SYNC_BUF_PAGE_HASH, - hash_table_mutex_key); - LATCH_ADD_MUTEX(IBUF_BITMAP, SYNC_IBUF_BITMAP_MUTEX, ibuf_bitmap_mutex_key); @@ -1476,9 +1445,6 @@ sync_latch_meta_init() LATCH_ADD_RWLOCK(DICT_TABLE_STATS, SYNC_INDEX_TREE, dict_table_stats_key); - LATCH_ADD_RWLOCK(HASH_TABLE_RW_LOCK, SYNC_BUF_PAGE_HASH, - hash_table_locks_key); - LATCH_ADD_MUTEX(SYNC_DEBUG_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); @@ -1499,6 +1465,7 @@ sync_latch_meta_init() PFS_NOT_INSTRUMENTED); LATCH_ADD_MUTEX(RW_TRX_HASH_ELEMENT, SYNC_RW_TRX_HASH_ELEMENT, rw_trx_hash_element_mutex_key); + LATCH_ADD_MUTEX(READ_VIEW, SYNC_READ_VIEW, read_view_mutex_key); latch_id_t id = LATCH_ID_NONE; diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index 6f22d640298..638896a9a86 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -202,11 +202,8 @@ rw_lock_create_func( new(lock) rw_lock_t(); #endif /* UNIV_DEBUG */ - /* If this is the very first time a synchronization object is - created, then the following call initializes the sync system. */ - - lock->lock_word.store(X_LOCK_DECR, std::memory_order_relaxed); - lock->waiters.store(0, std::memory_order_relaxed); + lock->lock_word = X_LOCK_DECR; + lock->waiters = 0; lock->sx_recursive = 0; lock->writer_thread= 0; @@ -252,7 +249,7 @@ rw_lock_free_func( rw_lock_t* lock) /*!< in/out: rw-lock */ { ut_ad(rw_lock_validate(lock)); - ut_a(lock->lock_word.load(std::memory_order_relaxed) == X_LOCK_DECR); + ut_a(lock->lock_word == X_LOCK_DECR); mutex_enter(&rw_lock_list_mutex); @@ -289,12 +286,15 @@ rw_lock_s_lock_spin( ut_ad(rw_lock_validate(lock)); + rw_lock_stats.rw_s_spin_wait_count.inc(); + lock_loop: /* Spin waiting for the writer field to become free */ HMT_low(); + ulint j = i; while (i < srv_n_spin_wait_rounds && - lock->lock_word.load(std::memory_order_relaxed) <= 0) { + lock->lock_word <= 0) { ut_delay(srv_spin_wait_delay); i++; } @@ -304,7 +304,7 @@ lock_loop: os_thread_yield(); } - ++spin_count; + spin_count += lint(i - j); /* We try once again to obtain the lock */ if (rw_lock_s_lock_low(lock, pass, file_name, line)) { @@ -412,10 +412,10 @@ rw_lock_x_lock_wait_func( sync_array_t* sync_arr; int64_t count_os_wait = 0; - ut_ad(lock->lock_word.load(std::memory_order_relaxed) <= threshold); + ut_ad(lock->lock_word <= threshold); HMT_low(); - while (lock->lock_word.load(std::memory_order_relaxed) < threshold) { + while (lock->lock_word < threshold) { ut_delay(srv_spin_wait_delay); if (i < srv_n_spin_wait_rounds) { @@ -424,7 +424,7 @@ rw_lock_x_lock_wait_func( } /* If there is still a reader, then go to sleep.*/ - ++n_spins; + n_spins += i; sync_cell_t* cell; @@ -434,8 +434,7 @@ rw_lock_x_lock_wait_func( i = 0; /* Check lock_word to ensure wake-up isn't missed.*/ - if (lock->lock_word.load(std::memory_order_relaxed) < threshold) { - + if (lock->lock_word < threshold) { ++count_os_wait; /* Add debug info as it is needed to detect possible @@ -524,17 +523,15 @@ rw_lock_x_lock_low( file_name, line); } else { - auto lock_word = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; /* At least one X lock by this thread already exists. Add another. */ if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) { - lock->lock_word.fetch_sub(X_LOCK_DECR, - std::memory_order_relaxed); + lock->lock_word.fetch_sub(X_LOCK_DECR); } else { ut_ad(lock_word <= -X_LOCK_DECR); - lock->lock_word.fetch_sub(1, - std::memory_order_relaxed); + lock->lock_word.fetch_sub(1); } } @@ -657,6 +654,12 @@ rw_lock_x_lock_func( ut_ad(rw_lock_validate(lock)); ut_ad(!rw_lock_own(lock, RW_LOCK_S)); + if (rw_lock_x_lock_low(lock, pass, file_name, line)) { + /* Locking succeeded */ + return; + } + rw_lock_stats.rw_x_spin_wait_count.inc(); + lock_loop: if (rw_lock_x_lock_low(lock, pass, file_name, line)) { @@ -676,14 +679,15 @@ lock_loop: /* Spin waiting for the lock_word to become free */ HMT_low(); + ulint j = i; while (i < srv_n_spin_wait_rounds - && lock->lock_word.load(std::memory_order_relaxed) <= X_LOCK_HALF_DECR) { + && lock->lock_word <= X_LOCK_HALF_DECR) { ut_delay(srv_spin_wait_delay); i++; } HMT_medium(); - spin_count += lint(i); + spin_count += lint(i - j); if (i >= srv_n_spin_wait_rounds) { @@ -751,11 +755,17 @@ rw_lock_sx_lock_func( sync_array_t* sync_arr; lint spin_count = 0; int64_t count_os_wait = 0; - lint spin_wait_count = 0; ut_ad(rw_lock_validate(lock)); ut_ad(!rw_lock_own(lock, RW_LOCK_S)); + if (rw_lock_sx_lock_low(lock, pass, file_name, line)) { + /* Locking succeeded */ + return; + } + + rw_lock_stats.rw_sx_spin_wait_count.inc(); + lock_loop: if (rw_lock_sx_lock_low(lock, pass, file_name, line)) { @@ -767,23 +777,21 @@ lock_loop: } rw_lock_stats.rw_sx_spin_round_count.add(spin_count); - rw_lock_stats.rw_sx_spin_wait_count.add(spin_wait_count); /* Locking succeeded */ return; } else { - ++spin_wait_count; - /* Spin waiting for the lock_word to become free */ + ulint j = i; while (i < srv_n_spin_wait_rounds - && lock->lock_word.load(std::memory_order_relaxed) <= X_LOCK_HALF_DECR) { + && lock->lock_word <= X_LOCK_HALF_DECR) { ut_delay(srv_spin_wait_delay); i++; } - spin_count += lint(i); + spin_count += lint(i - j); if (i >= srv_n_spin_wait_rounds) { @@ -815,7 +823,6 @@ lock_loop: } rw_lock_stats.rw_sx_spin_round_count.add(spin_count); - rw_lock_stats.rw_sx_spin_wait_count.add(spin_wait_count); /* Locking succeeded */ return; @@ -841,13 +848,11 @@ rw_lock_validate( /*=============*/ const rw_lock_t* lock) /*!< in: rw-lock */ { - int32_t lock_word; - ut_ad(lock); - lock_word = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; - ut_ad(lock->waiters.load(std::memory_order_relaxed) < 2); + ut_ad(lock->waiters < 2); ut_ad(lock_word > -(2 * X_LOCK_DECR)); ut_ad(lock_word <= X_LOCK_DECR); @@ -910,7 +915,7 @@ rw_lock_add_debug_info( rw_lock_debug_mutex_exit(); if (pass == 0 && lock_type != RW_LOCK_X_WAIT) { - auto lock_word = lock->lock_word.load(std::memory_order_relaxed); + int32_t lock_word = lock->lock_word; /* Recursive x while holding SX (lock_type == RW_LOCK_X && lock_word == -X_LOCK_HALF_DECR) @@ -1096,11 +1101,11 @@ rw_lock_list_print_info( count++; - if (lock->lock_word.load(std::memory_order_relaxed) != X_LOCK_DECR) { + if (lock->lock_word != X_LOCK_DECR) { fprintf(file, "RW-LOCK: %p ", (void*) lock); - if (int32_t waiters= lock->waiters.load(std::memory_order_relaxed)) { + if (int32_t waiters= lock->waiters) { fprintf(file, " (%d waiters)\n", waiters); } else { putc('\n', file); diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 0f028d6400d..8b81d8a5ff8 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -38,9 +38,7 @@ Created 9/5/1995 Heikki Tuuri #ifdef UNIV_PFS_MUTEX /* Key to register autoinc_mutex with performance schema */ mysql_pfs_key_t autoinc_mutex_key; -mysql_pfs_key_t buffer_block_mutex_key; mysql_pfs_key_t buf_pool_mutex_key; -mysql_pfs_key_t buf_pool_zip_mutex_key; mysql_pfs_key_t cache_last_read_mutex_key; mysql_pfs_key_t dict_foreign_err_mutex_key; mysql_pfs_key_t dict_sys_mutex_key; @@ -51,7 +49,6 @@ mysql_pfs_key_t fts_delete_mutex_key; mysql_pfs_key_t fts_optimize_mutex_key; mysql_pfs_key_t fts_doc_id_mutex_key; mysql_pfs_key_t fts_pll_tokenize_mutex_key; -mysql_pfs_key_t hash_table_mutex_key; mysql_pfs_key_t ibuf_bitmap_mutex_key; mysql_pfs_key_t ibuf_mutex_key; mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; @@ -95,6 +92,7 @@ mysql_pfs_key_t thread_mutex_key; mysql_pfs_key_t zip_pad_mutex_key; mysql_pfs_key_t row_drop_list_mutex_key; mysql_pfs_key_t rw_trx_hash_element_mutex_key; +mysql_pfs_key_t read_view_mutex_key; #endif /* UNIV_PFS_MUTEX */ #ifdef UNIV_PFS_RWLOCK mysql_pfs_key_t btr_search_latch_key; @@ -104,7 +102,6 @@ mysql_pfs_key_t buf_block_debug_latch_key; # endif /* UNIV_DEBUG */ mysql_pfs_key_t dict_operation_lock_key; mysql_pfs_key_t dict_table_stats_key; -mysql_pfs_key_t hash_table_locks_key; mysql_pfs_key_t index_tree_rw_lock_key; mysql_pfs_key_t index_online_log_key; mysql_pfs_key_t fil_space_latch_key; diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 2aaba63885c..8e46057f654 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -152,7 +152,7 @@ struct trx_i_s_cache_t { i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */ /** the hash table size is LOCKS_HASH_CELLS_NUM * sizeof(void*) bytes */ #define LOCKS_HASH_CELLS_NUM 10000 - hash_table_t* locks_hash; /*!< hash table used to eliminate + hash_table_t locks_hash; /*!< hash table used to eliminate duplicate entries in the innodb_locks table */ /** Initial size of the cache storage */ @@ -162,7 +162,7 @@ struct trx_i_s_cache_t { ha_storage_t* storage; /*!< storage for external volatile data that may become unavailable when we release - lock_sys.mutex or trx_sys.mutex */ + lock_sys.mutex */ ulint mem_allocd; /*!< the amount of memory allocated with mem_alloc*() */ bool is_truncated; /*!< this is true if the memory @@ -180,12 +180,12 @@ code in handler/i_s.cc. */ trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static; /** @return the heap number of a record lock -@retval 0 for table locks */ -static uint16_t wait_lock_get_heap_no(const lock_t* lock) +@retval 0xFFFF for table locks */ +static uint16_t wait_lock_get_heap_no(const lock_t *lock) { - return lock_get_type(lock) == LOCK_REC - ? static_cast(lock_rec_find_set_bit(lock)) - : uint16_t{0}; + return lock_get_type(lock) == LOCK_REC + ? static_cast(lock_rec_find_set_bit(lock)) + : uint16_t{0xFFFF}; } /*******************************************************************//** @@ -820,7 +820,7 @@ fold_lock( /*======*/ const lock_t* lock, /*!< in: lock object to fold */ ulint heap_no)/*!< in: lock's record number - or ULINT_UNDEFINED if the lock + or 0xFFFF if the lock is a table lock */ { #ifdef TEST_LOCK_FOLD_ALWAYS_DIFFERENT @@ -832,7 +832,7 @@ fold_lock( switch (lock_get_type(lock)) { case LOCK_REC: - ut_a(heap_no != ULINT_UNDEFINED); + ut_a(heap_no != 0xFFFF); ret = ut_fold_ulint_pair((ulint) lock->trx->id, lock->un_member.rec_lock.space); @@ -847,7 +847,7 @@ fold_lock( /* this check is actually not necessary for continuing correct operation, but something must have gone wrong if it fails. */ - ut_a(heap_no == ULINT_UNDEFINED); + ut_a(heap_no == 0xFFFF); ret = (ulint) lock_get_table_id(lock); @@ -870,7 +870,7 @@ locks_row_eq_lock( const i_s_locks_row_t* row, /*!< in: innodb_locks row */ const lock_t* lock, /*!< in: lock object */ ulint heap_no)/*!< in: lock's record number - or ULINT_UNDEFINED if the lock + or 0xFFFF if the lock is a table lock */ { ut_ad(i_s_locks_row_validate(row)); @@ -879,7 +879,7 @@ locks_row_eq_lock( #else switch (lock_get_type(lock)) { case LOCK_REC: - ut_a(heap_no != ULINT_UNDEFINED); + ut_a(heap_no != 0xFFFF); return(row->lock_trx_id == lock->trx->id && row->lock_space == lock->un_member.rec_lock.space @@ -890,7 +890,7 @@ locks_row_eq_lock( /* this check is actually not necessary for continuing correct operation, but something must have gone wrong if it fails. */ - ut_a(heap_no == ULINT_UNDEFINED); + ut_a(heap_no == 0xFFFF); return(row->lock_trx_id == lock->trx->id && row->lock_table_id == lock_get_table_id(lock)); @@ -914,7 +914,7 @@ search_innodb_locks( trx_i_s_cache_t* cache, /*!< in: cache */ const lock_t* lock, /*!< in: lock to search for */ uint16_t heap_no)/*!< in: lock's record number - or ULINT_UNDEFINED if the lock + or 0xFFFF if the lock is a table lock */ { i_s_hash_chain_t* hash_chain; @@ -923,7 +923,7 @@ search_innodb_locks( /* hash_chain->"next" */ next, /* the hash table */ - cache->locks_hash, + &cache->locks_hash, /* fold */ fold_lock(lock, heap_no), /* the type of the next variable */ @@ -999,7 +999,7 @@ add_lock_to_cache( /* hash_chain->"next" */ next, /* the hash table */ - cache->locks_hash, + &cache->locks_hash, /* fold */ fold_lock(lock, heap_no), /* add this data to the hash */ @@ -1174,7 +1174,7 @@ trx_i_s_cache_clear( cache->innodb_locks.rows_used = 0; cache->innodb_lock_waits.rows_used = 0; - hash_table_clear(cache->locks_hash); + cache->locks_hash.clear(); ha_storage_empty(&cache->storage); } @@ -1220,19 +1220,13 @@ static void fetch_data_into_cache(trx_i_s_cache_t *cache) trx_i_s_cache_clear(cache); /* Capture the state of transactions */ - mutex_enter(&trx_sys.mutex); - for (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys.trx_list); - trx != NULL; - trx= UT_LIST_GET_NEXT(trx_list, trx)) - { - if (trx_is_started(trx) && trx != purge_sys.query->trx) + trx_sys.trx_list.for_each([cache](const trx_t &trx) { + if (!cache->is_truncated && trx_is_started(&trx) && + &trx != purge_sys.query->trx) { - fetch_data_into_cache_low(cache, trx); - if (cache->is_truncated) - break; - } - } - mutex_exit(&trx_sys.mutex); + fetch_data_into_cache_low(cache, &trx); + } + }); cache->is_truncated= false; } @@ -1304,7 +1298,7 @@ trx_i_s_cache_init( table_cache_init(&cache->innodb_lock_waits, sizeof(i_s_lock_waits_row_t)); - cache->locks_hash = hash_create(LOCKS_HASH_CELLS_NUM); + cache->locks_hash.create(LOCKS_HASH_CELLS_NUM); cache->storage = ha_storage_create(CACHE_STORAGE_INITIAL_SIZE, CACHE_STORAGE_HASH_CELLS); @@ -1324,7 +1318,7 @@ trx_i_s_cache_free( rw_lock_free(&cache->rw_lock); mutex_free(&cache->last_read_mutex); - hash_table_free(cache->locks_hash); + cache->locks_hash.free(); ha_storage_free(cache->storage); table_cache_free(&cache->innodb_trx); table_cache_free(&cache->innodb_locks); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index f0b4d6f91b5..6747ada6de4 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -149,7 +149,7 @@ purge_graph_build() NULL, NULL, QUE_FORK_PURGE, heap); fork->trx = trx; - for (ulint i = 0; i < srv_n_purge_threads; ++i) { + for (auto i = innodb_purge_threads_MAX; i; i--) { que_thr_t* thr = que_thr_create(fork, heap, NULL); thr->child = new(mem_heap_alloc(heap, sizeof(purge_node_t))) purge_node_t(thr); @@ -210,7 +210,7 @@ void trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) { DBUG_PRINT("trx", ("commit(" TRX_ID_FMT "," TRX_ID_FMT ")", - trx->id, trx->no)); + trx->id, trx_id_t{trx->rw_trx_hash_element->no})); ut_ad(undo == trx->rsegs.m_redo.undo || undo == trx->rsegs.m_redo.old_insert); trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; @@ -301,7 +301,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) + TRX_UNDO_HISTORY_NODE), mtr); mtr->write<8,mtr_t::MAYBE_NOP>(*undo_page, - undo_header + TRX_UNDO_TRX_NO, trx->no); + undo_header + TRX_UNDO_TRX_NO, + trx->rw_trx_hash_element->no); /* This is needed for upgrading old undo log pages from before MariaDB 10.3.1. */ if (UNIV_UNLIKELY(!mach_read_from_2(undo_header @@ -313,7 +314,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) if (rseg->last_page_no == FIL_NULL) { rseg->last_page_no = undo->hdr_page_no; rseg->last_offset = undo->hdr_offset; - rseg->set_last_trx_no(trx->no, undo == trx->rsegs.m_redo.undo); + rseg->set_last_trx_no(trx->rw_trx_hash_element->no, + undo == trx->rsegs.m_redo.undo); rseg->needs_purge = true; } @@ -369,7 +371,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) while (!fseg_free_step_not_header( TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER - + block->frame, false, &mtr)) { + + block->frame, &mtr)) { mutex_exit(&rseg->mutex); mtr.commit(); @@ -405,7 +407,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) fsp0fsp.cc. */ } while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER - + block->frame, false, &mtr)); + + block->frame, &mtr)); byte* hist = TRX_RSEG + TRX_RSEG_HISTORY_SIZE + rseg_hdr->frame; ut_ad(mach_read_from_4(hist) >= seg_size); @@ -555,9 +557,9 @@ static void trx_purge_truncate_history() purge_sys_t::iterator& head = purge_sys.head.commit ? purge_sys.head : purge_sys.tail; - if (head.trx_no() >= purge_sys.view.low_limit_no()) { + if (head.trx_no() >= purge_sys.low_limit_no()) { /* This is sometimes necessary. TODO: find out why. */ - head.reset_trx_no(purge_sys.view.low_limit_no()); + head.reset_trx_no(purge_sys.low_limit_no()); head.undo_no = 0; } @@ -694,6 +696,10 @@ not_free: const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; mtr.start(); mtr_x_lock_space(purge_sys.truncate.current, &mtr); + /* Associate the undo tablespace with mtr. + During mtr::commit(), InnoDB can use the undo + tablespace object to clear all freed ranges */ + mtr.set_named_space(purge_sys.truncate.current); mtr.trim_pages(page_id_t(space.id, size)); fsp_header_init(purge_sys.truncate.current, size, &mtr); mutex_enter(&fil_system.mutex); @@ -716,7 +722,7 @@ not_free: rseg->id, sys_header, &mtr); ut_ad(rblock); rseg->page_no = rblock - ? rblock->page.id.page_no() : FIL_NULL; + ? rblock->page.id().page_no() : FIL_NULL; ut_ad(old_page == rseg->page_no); /* Before re-initialization ensure that we @@ -925,7 +931,7 @@ trx_purge_read_undo_rec() offset = page_offset(undo_rec); undo_no = trx_undo_rec_get_undo_no(undo_rec); - page_no = undo_page->page.id.page_no(); + page_no = undo_page->page.id().page_no(); } else { offset = 0; undo_no = 0; @@ -978,7 +984,7 @@ trx_purge_get_next_rec( mtr_t mtr; ut_ad(purge_sys.next_stored); - ut_ad(purge_sys.tail.trx_no() < purge_sys.view.low_limit_no()); + ut_ad(purge_sys.tail.trx_no() < purge_sys.low_limit_no()); const ulint space = purge_sys.rseg->space->id; const uint32_t page_no = purge_sys.page_no; @@ -1027,7 +1033,7 @@ trx_purge_get_next_rec( page_id_t(space, page_no), &mtr); } else { purge_sys.offset = page_offset(rec2); - purge_sys.page_no = rec2_page->page.id.page_no(); + purge_sys.page_no = rec2_page->page.id().page_no(); purge_sys.tail.undo_no = trx_undo_rec_get_undo_no(rec2); if (undo_page != rec2_page) { @@ -1068,7 +1074,7 @@ trx_purge_fetch_next_rec( } } - if (purge_sys.tail.trx_no() >= purge_sys.view.low_limit_no()) { + if (purge_sys.tail.trx_no() >= purge_sys.low_limit_no()) { return(NULL); } @@ -1213,9 +1219,7 @@ trx_purge_dml_delay(void) thread. */ ulint delay = 0; /* in microseconds; default: no delay */ - /* If purge lag is set (ie. > 0) then calculate the new DML delay. - Note: we do a dirty read of the trx_sys_t data structure here, - without holding trx_sys.mutex. */ + /* If purge lag is set then calculate the new DML delay. */ if (srv_max_purge_lag > 0) { double ratio = static_cast(trx_sys.rseg_history_len) / @@ -1273,9 +1277,7 @@ ulint trx_purge(ulint n_tasks, bool truncate) srv_dml_needed_delay = trx_purge_dml_delay(); - rw_lock_x_lock(&purge_sys.latch); - trx_sys.clone_oldest_view(); - rw_lock_x_unlock(&purge_sys.latch); + purge_sys.clone_oldest_view(); #ifdef UNIV_DEBUG if (srv_purge_view_update_only_debug) { diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index cf18c249a3b..040618015d4 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1891,7 +1891,8 @@ dberr_t trx_undo_report_rename(trx_t* trx, const dict_table_t* table) ut_ad(undo); for (ut_d(int loop_count = 0);;) { ut_ad(loop_count++ < 2); - ut_ad(undo->last_page_no == block->page.id.page_no()); + ut_ad(undo->last_page_no + == block->page.id().page_no()); if (uint16_t offset = trx_undo_page_report_rename( trx, table, block, &mtr)) { @@ -1915,10 +1916,9 @@ dberr_t trx_undo_report_rename(trx_t* trx, const dict_table_t* table) } } } - - mtr.commit(); } + mtr.commit(); return err; } @@ -2048,7 +2048,7 @@ trx_undo_report_row_operation( undo->withdraw_clock = buf_pool.withdraw_clock(); mtr_commit(&mtr); - undo->top_page_no = undo_block->page.id.page_no(); + undo->top_page_no = undo_block->page.id().page_no(); undo->top_offset = offset; undo->top_undo_no = trx->undo_no++; undo->guess_block = undo_block; @@ -2080,7 +2080,7 @@ trx_undo_report_row_operation( return(DB_SUCCESS); } - ut_ad(undo_block->page.id.page_no() == undo->last_page_no); + ut_ad(undo_block->page.id().page_no() == undo->last_page_no); /* We have to extend the undo log by one page */ @@ -2174,11 +2174,9 @@ trx_undo_get_undo_rec( const table_name_t& name, trx_undo_rec_t** undo_rec) { - bool missing_history; - rw_lock_s_lock(&purge_sys.latch); - missing_history = purge_sys.view.changes_visible(trx_id, name); + bool missing_history = purge_sys.changes_visible(trx_id, name); if (!missing_history) { *undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap); } @@ -2247,9 +2245,9 @@ trx_undo_prev_version_build( ut_ad(!index->table->is_temporary()); ut_ad(!rw_lock_own(&purge_sys.latch, RW_LOCK_S)); - ut_ad(mtr_memo_contains_page_flagged(index_mtr, index_rec, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX)); + ut_ad(index_mtr->memo_contains_page_flagged(index_rec, + MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_a(index->is_primary()); @@ -2344,7 +2342,7 @@ trx_undo_prev_version_build( rw_lock_s_lock(&purge_sys.latch); - missing_extern = purge_sys.view.changes_visible( + missing_extern = purge_sys.changes_visible( trx_id, index->table->name); rw_lock_s_unlock(&purge_sys.latch); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index c20cf4842a0..85daf649c6a 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -199,7 +199,7 @@ trx_rollback_for_mysql_low( @return error code or DB_SUCCESS */ dberr_t trx_rollback_for_mysql(trx_t* trx) { - /* We are reading trx->state without holding trx_sys.mutex + /* We are reading trx->state without holding trx->mutex here, because the rollback should be invoked for a running active MySQL transaction (or recovered prepared transaction) that is associated with the current thread. */ @@ -209,7 +209,8 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) trx->will_lock = 0; ut_ad(trx->mysql_thd); #ifdef WITH_WSREP - trx->wsrep = false; + trx->wsrep= false; + trx->lock.was_chosen_as_wsrep_victim= false; #endif return(DB_SUCCESS); @@ -285,7 +286,7 @@ trx_rollback_last_sql_stat_for_mysql( { dberr_t err; - /* We are reading trx->state without holding trx_sys.mutex + /* We are reading trx->state without holding trx->mutex here, because the statement rollback should be invoked for a running active MySQL transaction that is associated with the current thread. */ @@ -459,7 +460,7 @@ trx_rollback_to_savepoint_for_mysql( { trx_named_savept_t* savep; - /* We are reading trx->state without holding trx_sys.mutex + /* We are reading trx->state without holding trx->mutex here, because the savepoint rollback should be invoked for a running active MySQL transaction that is associated with the current thread. */ @@ -568,19 +569,6 @@ trx_release_savepoint_for_mysql( return(savep != NULL ? DB_SUCCESS : DB_NO_SAVEPOINT); } -/*******************************************************************//** -Determines if this transaction is rolling back an incomplete transaction -in crash recovery. -@return TRUE if trx is an incomplete transaction that is being rolled -back in crash recovery */ -ibool -trx_is_recv( -/*========*/ - const trx_t* trx) /*!< in: transaction */ -{ - return(trx == trx_roll_crash_recv_trx); -} - /*******************************************************************//** Returns a transaction savepoint taken at this point in time. @return savepoint */ @@ -716,8 +704,7 @@ void trx_roll_report_progress() rows they modified. Numbers must be accurate, because only this thread is allowed to touch recovered transactions. */ trx_sys.rw_trx_hash.iterate_no_dups( - reinterpret_cast - (trx_roll_count_callback), &arg); + trx_roll_count_callback, &arg); if (arg.n_rows > 0) { service_manager_extend_timeout( @@ -775,8 +762,7 @@ void trx_rollback_recovered(bool all) other thread is allowed to modify or remove these transactions from rw_trx_hash. */ - trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast - (trx_rollback_recovered_callback), + trx_sys.rw_trx_hash.iterate_no_dups(trx_rollback_recovered_callback, &trx_list); while (!trx_list.empty()) diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 25dfaded978..28268ed6bf0 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -312,7 +312,7 @@ trx_rseg_header_create( { buf_block_t* block; - ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); + ut_ad(mtr->memo_contains(space->latch, MTR_MEMO_X_LOCK)); ut_ad(!sys_header == (space == fil_system.temp_space)); /* Allocate a new file segment for the rollback segment */ @@ -350,7 +350,7 @@ trx_rseg_header_create( *sys_header, TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO + rseg_id * TRX_SYS_RSEG_SLOT_SIZE - + sys_header->frame, block->page.id.page_no()); + + sys_header->frame, block->page.id().page_no()); } return block; @@ -671,8 +671,6 @@ trx_rseg_create(ulint space_id) mtr.start(); - /* To obey the latching order, acquire the file space - x-latch before the trx_sys.mutex. */ fil_space_t* space = mtr_x_lock_space(space_id, &mtr); ut_ad(space->purpose == FIL_TYPE_TABLESPACE); @@ -685,7 +683,8 @@ trx_rseg_create(ulint space_id) ut_ad(trx_sysf_rseg_get_space(sys_header, rseg_id) == space_id); rseg = trx_rseg_mem_create(rseg_id, space, - rblock->page.id.page_no()); + rblock->page.id(). + page_no()); ut_ad(rseg->id == rseg_id); ut_ad(rseg->is_persistent()); ut_ad(!trx_sys.rseg_array[rseg->id]); @@ -712,7 +711,7 @@ trx_temp_rseg_create() buf_block_t* rblock = trx_rseg_header_create( fil_system.temp_space, i, NULL, &mtr); trx_rseg_t* rseg = trx_rseg_mem_create( - i, fil_system.temp_space, rblock->page.id.page_no()); + i, fil_system.temp_space, rblock->page.id().page_no()); ut_ad(!rseg->is_persistent()); ut_ad(!trx_sys.temp_rsegs[i]); trx_sys.temp_rsegs[i] = rseg; diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index aa2fe4bff45..52b344498b1 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -48,7 +48,7 @@ trx_sys_t trx_sys; @param[in] id transaction id to check @param[in] name table name */ void -ReadView::check_trx_id_sanity( +ReadViewBase::check_trx_id_sanity( trx_id_t id, const table_name_t& name) { @@ -163,7 +163,7 @@ trx_sysf_create( mtr); buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER); - ut_a(block->page.id.page_no() == TRX_SYS_PAGE_NO); + ut_a(block->page.id().page_no() == TRX_SYS_PAGE_NO); mtr->write<2>(*block, FIL_PAGE_TYPE + block->frame, FIL_PAGE_TYPE_TRX_SYS); @@ -195,7 +195,7 @@ trx_sysf_create( slot_no, block, mtr); ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID); - ut_a(rblock->page.id.page_no() == FSP_FIRST_RSEG_PAGE_NO); + ut_a(rblock->page.id().page_no() == FSP_FIRST_RSEG_PAGE_NO); } /** Create the instance */ @@ -205,8 +205,7 @@ trx_sys_t::create() ut_ad(this == &trx_sys); ut_ad(!is_initialised()); m_initialised = true; - mutex_create(LATCH_ID_TRX_SYS, &mutex); - UT_LIST_INIT(trx_list, &trx_t::trx_list); + trx_list.create(); rseg_history_len= 0; rw_trx_hash.init(); @@ -320,8 +319,8 @@ trx_sys_t::close() } } - ut_a(UT_LIST_GET_LEN(trx_list) == 0); - mutex_free(&mutex); + ut_a(trx_list.empty()); + trx_list.close(); m_initialised = false; } @@ -330,15 +329,11 @@ ulint trx_sys_t::any_active_transactions() { uint32_t total_trx= 0; - mutex_enter(&mutex); - for (trx_t* trx= UT_LIST_GET_FIRST(trx_sys.trx_list); - trx != NULL; - trx= UT_LIST_GET_NEXT(trx_list, trx)) - { - if (trx->state == TRX_STATE_COMMITTED_IN_MEMORY || - (trx->state == TRX_STATE_ACTIVE && trx->id)) + trx_sys.trx_list.for_each([&total_trx](const trx_t &trx) { + if (trx.state == TRX_STATE_COMMITTED_IN_MEMORY || + (trx.state == TRX_STATE_ACTIVE && trx.id)) total_trx++; - } - mutex_exit(&mutex); + }); + return total_trx; } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index f9c8ede1f1b..eaf127b5a43 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -104,8 +104,6 @@ trx_init( /*=====*/ trx_t* trx) { - trx->no = TRX_ID_MAX; - trx->state = TRX_STATE_NOT_STARTED; trx->is_recovered = false; @@ -351,14 +349,13 @@ trx_t *trx_create() { trx_t* trx = trx_pools->get(); - assert_trx_is_free(trx); + trx->assert_freed(); mem_heap_t* heap; ib_alloc_t* alloc; /* We just got trx from pool, it should be non locking */ ut_ad(trx->will_lock == 0); - ut_ad(trx->state == TRX_STATE_NOT_STARTED); ut_ad(!trx->rw_trx_hash_pins); DBUG_LOG("trx", "Create: " << trx); @@ -381,7 +378,7 @@ trx_t *trx_create() ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); #ifdef WITH_WSREP - trx->wsrep_event = NULL; + trx->wsrep_event= NULL; #endif /* WITH_WSREP */ trx_sys.register_trx(trx); @@ -401,9 +398,8 @@ void trx_free(trx_t*& trx) ut_ad(!trx->internal); ut_ad(!trx->mysql_log_file_name); - if (trx->declared_to_be_inside_innodb) { - - ib::error() << "Freeing a trx (" << trx << ", " + if (UNIV_UNLIKELY(trx->declared_to_be_inside_innodb)) { + ib::error() << "Freeing a trx (" << trx_get_id_for_print(trx) << ") which is declared" " to be processing inside InnoDB"; @@ -430,11 +426,11 @@ void trx_free(trx_t*& trx) } trx->dict_operation = TRX_DICT_OP_NONE; - assert_trx_is_inactive(trx); + ut_ad(!trx->dict_operation_lock_mode); trx_sys.deregister_trx(trx); - assert_trx_is_free(trx); + trx->assert_freed(); trx_sys.rw_trx_hash.put_pins(trx); trx->mysql_thd = 0; @@ -454,12 +450,31 @@ void trx_free(trx_t*& trx) ut_ad(trx->will_lock == 0); trx_pools->mem_free(trx); + trx->read_view.mem_valid(); +#ifdef __SANITIZE_ADDRESS__ /* Unpoison the memory for innodb_monitor_set_option; it is operating also on the freed transaction objects. */ MEM_UNDEFINED(&trx->mutex, sizeof trx->mutex); - /* Declare the contents as initialized for Valgrind; - we checked that it was initialized in trx_pools->mem_free(trx). */ - UNIV_MEM_VALID(&trx->mutex, sizeof trx->mutex); + /* For innobase_kill_connection() */ +# ifdef WITH_WSREP + MEM_UNDEFINED(&trx->wsrep, sizeof trx->wsrep); +# endif + MEM_UNDEFINED(&trx->state, sizeof trx->state); + MEM_UNDEFINED(&trx->mysql_thd, sizeof trx->mysql_thd); +#endif +#ifdef HAVE_valgrind_or_MSAN + /* Unpoison the memory for innodb_monitor_set_option; + it is operating also on the freed transaction objects. + We checked that these were initialized in + trx_pools->mem_free(trx). */ + MEM_MAKE_DEFINED(&trx->mutex, sizeof trx->mutex); + /* For innobase_kill_connection() */ +# ifdef WITH_WSREP + MEM_MAKE_DEFINED(&trx->wsrep, sizeof trx->wsrep); +# endif + MEM_MAKE_DEFINED(&trx->state, sizeof trx->state); + MEM_MAKE_DEFINED(&trx->mysql_thd, sizeof trx->mysql_thd); +#endif trx = NULL; } @@ -651,7 +666,7 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg, trx_state_t state; /* This is single-threaded startup code, we do not need the - protection of trx->mutex or trx_sys.mutex here. + protection of trx->mutex here. */ switch (undo->state) { @@ -678,7 +693,6 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg, trx->state= state; ut_d(trx->start_file= __FILE__); ut_d(trx->start_line= __LINE__); - ut_ad(trx->no == TRX_ID_MAX); if (is_old_insert) trx->rsegs.m_redo.old_insert= undo; @@ -805,7 +819,7 @@ trx_lists_init_at_db_start() ib::info() << "Trx id counter is " << trx_sys.get_max_trx_id(); } - trx_sys.clone_oldest_view(); + purge_sys.clone_oldest_view(); } /** Assign a persistent rollback segment in a round-robin fashion, @@ -826,14 +840,9 @@ static trx_rseg_t* trx_assign_rseg_low() /* Choose a rollback segment evenly distributed between 0 and innodb_undo_logs-1 in a round-robin fashion, skipping those - undo tablespaces that are scheduled for truncation. - - Because rseg_slot is not protected by atomics or any mutex, race - conditions are possible, meaning that multiple transactions - that start modifications concurrently will write their undo - log to the same rollback segment. */ - static ulong rseg_slot; - ulint slot = rseg_slot++ % TRX_SYS_N_RSEGS; + undo tablespaces that are scheduled for truncation. */ + static Atomic_counter rseg_slot; + unsigned slot = rseg_slot++ % TRX_SYS_N_RSEGS; ut_d(if (trx_rseg_n_slots_debug) slot = 0); trx_rseg_t* rseg; @@ -912,11 +921,8 @@ trx_t::assign_temp_rseg() compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS)); /* Choose a temporary rollback segment between 0 and 127 - in a round-robin fashion. Because rseg_slot is not protected by - atomics or any mutex, race conditions are possible, meaning that - multiple transactions that start modifications concurrently - will write their undo log to the same rollback segment. */ - static ulong rseg_slot; + in a round-robin fashion. */ + static Atomic_counter rseg_slot; trx_rseg_t* rseg = trx_sys.temp_rsegs[ rseg_slot++ & (TRX_SYS_N_RSEGS - 1)]; ut_ad(!rseg->is_persistent()); @@ -967,18 +973,13 @@ trx_start_low( trx->xid->null(); #endif /* WITH_WSREP */ - /* The initial value for trx->no: TRX_ID_MAX is used in - read_view_open_now: */ - - trx->no = TRX_ID_MAX; - ut_a(ib_vector_is_empty(trx->autoinc_locks)); ut_a(trx->lock.table_locks.empty()); - /* No other thread can access this trx object through rw_trx_hash, thus - we don't need trx_sys.mutex protection for that purpose. Still this - trx can be found through trx_sys.trx_list, which means state - change must be protected by e.g. trx->mutex. + /* No other thread can access this trx object through rw_trx_hash, + still it can be found through trx_sys.trx_list. Sometimes it's + possible to indirectly protect trx_t::state by freezing + trx_sys.trx_list. For now we update it without mutex protection, because original code did it this way. It has to be reviewed and fixed properly. */ @@ -1048,7 +1049,8 @@ trx_serialise(trx_t* trx) already in the rollback segment. User threads only produce events when a rollback segment is empty. */ if (rseg->last_page_no == FIL_NULL) { - purge_sys.purge_queue.push(TrxUndoRsegs(trx->no, *rseg)); + purge_sys.purge_queue.push(TrxUndoRsegs(trx->rw_trx_hash_element->no, + *rseg)); mutex_exit(&purge_sys.pq_mutex); } } @@ -1342,9 +1344,9 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) /* This state change is not protected by any mutex, therefore there is an inherent race here around state transition during printouts. We ignore this race for the sake of efficiency. - However, the trx_sys_t::mutex will protect the trx_t instance - and it cannot be removed from the trx_list and freed - without first acquiring the trx_sys_t::mutex. */ + However, the freezing of trx_sys.trx_list will protect the trx_t + instance and it cannot be removed from the trx_list and freed + without first unfreezing trx_list. */ ut_ad(trx_state_eq(this, TRX_STATE_ACTIVE)); MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT); @@ -1479,13 +1481,6 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) if (fts_trx) trx_finalize_for_fts(this, undo_no != 0); - trx_mutex_enter(this); - dict_operation= TRX_DICT_OP_NONE; - lock.was_chosen_as_deadlock_victim= false; - - DBUG_LOG("trx", "Commit in memory: " << this); - state= TRX_STATE_NOT_STARTED; - #ifdef WITH_WSREP /* Serialization history has been written and the transaction is committed in memory, which makes this commit ordered. Release commit @@ -1495,9 +1490,15 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) wsrep= false; wsrep_commit_ordered(mysql_thd); } + lock.was_chosen_as_wsrep_victim= false; #endif /* WITH_WSREP */ + trx_mutex_enter(this); + dict_operation= TRX_DICT_OP_NONE; - assert_trx_is_free(this); + DBUG_LOG("trx", "Commit in memory: " << this); + state= TRX_STATE_NOT_STARTED; + + assert_freed(); trx_init(this); trx_mutex_exit(this); @@ -1583,7 +1584,7 @@ trx_commit_or_rollback_prepare( /*===========================*/ trx_t* trx) /*!< in/out: transaction */ { - /* We are reading trx->state without holding trx_sys.mutex + /* We are reading trx->state without holding trx->mutex here, because the commit or rollback should be invoked for a running (or recovered prepared) transaction that is associated with the current thread. */ @@ -1790,9 +1791,6 @@ trx_print_low( fprintf(f, "TRANSACTION " TRX_ID_FMT, trx_get_id_for_print(trx)); - /* trx->state cannot change from or to NOT_STARTED while we - are holding the trx_sys.mutex. It may change from ACTIVE to - PREPARED or COMMITTED. */ switch (trx->state) { case TRX_STATE_NOT_STARTED: fputs(", not started", f); @@ -2146,8 +2144,7 @@ int trx_recover_for_mysql(XID *xid_list, uint len) ut_ad(len); /* Fill xid_list with PREPARED transactions. */ - trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast - (trx_recover_for_mysql_callback), &arg); + trx_sys.rw_trx_hash.iterate_no_dups(trx_recover_for_mysql_callback, &arg); if (arg.count) { ib::info() << arg.count @@ -2157,8 +2154,7 @@ int trx_recover_for_mysql(XID *xid_list, uint len) transactions twice, by first calling tc_log->open() and then ha_recover() directly. */ if (arg.count <= len) - trx_sys.rw_trx_hash.iterate(reinterpret_cast - (trx_recover_reset_callback), NULL); + trx_sys.rw_trx_hash.iterate(trx_recover_reset_callback); } return int(std::min(arg.count, len)); } @@ -2212,8 +2208,7 @@ trx_t* trx_get_trx_by_xid(const XID* xid) trx_get_trx_by_xid_callback_arg arg= { xid, 0 }; if (xid) - trx_sys.rw_trx_hash.iterate(reinterpret_cast - (trx_get_trx_by_xid_callback), &arg); + trx_sys.rw_trx_hash.iterate(trx_get_trx_by_xid_callback, &arg); return arg.trx; } @@ -2367,13 +2362,6 @@ trx_set_rw_mode( return; } - /* Function is promoting existing trx from ro mode to rw mode. - In this process it has acquired trx_sys.mutex as it plan to - move trx from ro list to rw list. If in future, some other thread - looks at this trx object while it is being promoted then ensure - that both threads are synced by acquring trx->mutex to avoid decision - based on in-consistent view formed during promotion. */ - trx->rsegs.m_redo.rseg = trx_assign_rseg_low(); ut_ad(trx->rsegs.m_redo.rseg != 0); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index aa8c644a896..9ec219870c4 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -74,9 +74,9 @@ can still remove old versions from the bottom of the stack. */ ------------------------------------------------------------------- latches? ------- -The contention of the trx_sys.mutex should be minimized. When a transaction -does its first insert or modify in an index, an undo log is assigned for it. -Then we must have an x-latch to the rollback segment header. +When a transaction does its first insert or modify in the clustered index, an +undo log is assigned for it. Then we must have an x-latch to the rollback +segment header. When the transaction performs modifications or rolls back, its undo log is protected by undo page latches. Only the thread that is associated with the transaction may hold multiple @@ -117,7 +117,7 @@ static uint16_t trx_undo_page_get_start(const buf_block_t *block, uint32_t page_no, uint16_t offset) { - return page_no == block->page.id.page_no() + return page_no == block->page.id().page_no() ? mach_read_from_2(offset + TRX_UNDO_LOG_START + block->frame) : TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE; } @@ -171,10 +171,10 @@ trx_undo_get_prev_rec_from_prev_page(buf_block_t *&block, uint16_t rec, block->frame).page; if (prev_page_no == FIL_NULL) - return NULL; + return nullptr; - block = buf_page_get(page_id_t(block->page.id.space(), prev_page_no), - 0, shared ? RW_S_LATCH : RW_X_LATCH, mtr); + block= buf_page_get(page_id_t(block->page.id().space(), prev_page_no), + 0, shared ? RW_S_LATCH : RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); return trx_undo_page_get_last_rec(block, page_no, offset); @@ -233,7 +233,7 @@ static trx_undo_rec_t* trx_undo_get_next_rec_from_next_page(buf_block_t *&block, uint32_t page_no, uint16_t offset, ulint mode, mtr_t *mtr) { - if (page_no == block->page.id.page_no() && + if (page_no == block->page.id().page_no() && mach_read_from_2(block->frame + offset + TRX_UNDO_NEXT_LOG)) return NULL; @@ -242,7 +242,7 @@ trx_undo_get_next_rec_from_next_page(buf_block_t *&block, uint32_t page_no, if (next == FIL_NULL) return NULL; - block= buf_page_get(page_id_t(block->page.id.space(), next), 0, mode, mtr); + block= buf_page_get(page_id_t(block->page.id().space(), next), 0, mode, mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); return trx_undo_page_get_first_rec(block, page_no, offset); @@ -414,7 +414,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id, *id = slot_no; mtr->write<4>(*rseg_hdr, TRX_RSEG + TRX_RSEG_UNDO_SLOTS + slot_no * TRX_RSEG_SLOT_SIZE + rseg_hdr->frame, - block->page.id.page_no()); + block->page.id().page_no()); MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED); @@ -580,7 +580,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr) ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1); buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE); - undo->last_page_no = new_block->page.id.page_no(); + undo->last_page_no = new_block->page.id().page_no(); mtr->undo_create(*new_block); trx_undo_page_init(*new_block); @@ -628,7 +628,8 @@ trx_undo_free_page( fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + header_block->frame, - rseg->space, page_no, false, mtr); + rseg->space, page_no, mtr); + buf_page_free(page_id_t(space, page_no), mtr, __FILE__, __LINE__); const fil_addr_t last_addr = flst_get_last( TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_block->frame); @@ -766,7 +767,7 @@ done: goto done; } - if (undo_page->page.id.page_no() == hdr_page_no) { + if (undo_page->page.id().page_no() == hdr_page_no) { uint16_t end = mach_read_from_2(hdr_offset + TRX_UNDO_NEXT_LOG + undo_page->frame); if (end == 0) { @@ -779,7 +780,7 @@ done: + TRX_UNDO_LOG_START, end); } else { trx_undo_free_page(rseg, true, hdr_page_no, - undo_page->page.id.page_no(), &mtr); + undo_page->page.id().page_no(), &mtr); } mtr_commit(&mtr); @@ -813,7 +814,7 @@ static void trx_undo_seg_free(const trx_undo_t* undo, bool noredo) fseg_header_t* file_seg = TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + block->frame; - finished = fseg_free_step(file_seg, false, &mtr); + finished = fseg_free_step(file_seg, &mtr); if (finished) { /* Update the rseg header */ @@ -1043,7 +1044,7 @@ trx_undo_create(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, uint16_t offset = trx_undo_header_create(block, trx->id, mtr); *undo = trx_undo_mem_create(rseg, id, trx->id, trx->xid, - block->page.id.page_no(), offset); + block->page.id().page_no(), offset); if (*undo == NULL) { *err = DB_OUT_OF_MEMORY; /* FIXME: this will not free the undo block to the file */ diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index 52b69e899b0..dabf92e875b 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -84,9 +84,10 @@ mysys/my_perf.c, contributed by Facebook under the following license. #include #include "ut0crc32.h" +#include "my_valgrind.h" #ifdef _MSC_VER -#include +# include #endif /* CRC32 hardware implementation. */ @@ -97,157 +98,79 @@ unsigned int crc32c_vpmsum(unsigned int crc, const unsigned char *p, unsigned lo ut_crc32_func_t ut_crc32_low= crc32c_vpmsum; const char* ut_crc32_implementation = "Using POWER8 crc32 instructions"; #else -# if defined(__GNUC__) && defined(__linux__) && defined(HAVE_ARMV8_CRC) +# if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) extern "C" { uint32_t crc32c_aarch64(uint32_t crc, const unsigned char *buffer, uint64_t len); -/* For runtime check */ -unsigned int crc32c_aarch64_available(void); }; +# elif defined(_MSC_VER) +# define TRY_SSE4_2 +# elif defined (__GNUC__) +# ifdef __x86_64__ +# define TRY_SSE4_2 +# elif defined(__i386__) && (__GNUC__ > 4 || defined __clang__) +# define TRY_SSE4_2 +# endif # endif - -# if (defined(__GNUC__) && defined(__x86_64__)) || defined(_MSC_VER) -/********************************************************************//** -Fetches CPU info */ -static -void -ut_cpuid( -/*=====*/ - uint32_t vend[3], /*!< out: CPU vendor */ - uint32_t* model, /*!< out: CPU model */ - uint32_t* family, /*!< out: CPU family */ - uint32_t* stepping, /*!< out: CPU stepping */ - uint32_t* features_ecx, /*!< out: CPU features ecx */ - uint32_t* features_edx) /*!< out: CPU features edx */ +# ifdef TRY_SSE4_2 +/** return whether SSE4.2 instructions are available */ +static inline bool has_sse4_2() { - uint32_t sig; + /* We assume that the CPUID instruction and its parameter 1 are available. + We do not support any precursors of the Intel 80486. */ # ifdef _MSC_VER - int data[4]; - __cpuid(data, 0); - /* ebx */ - vend[0] = data[1]; - /* edx */ - vend[1] = data[3]; - /* ecx */ - vend[2] = data[2]; - - __cpuid(data, 1); - /* eax */ - sig = data[0]; - /* ecx */ - *features_ecx = data[2]; - /* edx */ - *features_edx = data[3]; + int data[4]; + __cpuid(data, 1); + return !!(data[2] & 1 << 20); # else - asm("cpuid" : "=b" (vend[0]), "=c" (vend[2]), "=d" (vend[1]) : "a" (0)); - asm("cpuid" : "=a" (sig), "=c" (*features_ecx), "=d" (*features_edx) - : "a" (1) - : "ebx"); + uint32_t eax, ecx; + asm("cpuid" : "=a"(eax), "=c"(ecx) : "a"(1) : "ebx", "edx"); + return !!(ecx & 1 << 20); # endif - - *model = ((sig >> 4) & 0xF); - *family = ((sig >> 8) & 0xF); - *stepping = (sig & 0xF); - - if (memcmp(vend, "GenuineIntel", 12) == 0 - || (memcmp(vend, "AuthenticAMD", 12) == 0 && *family == 0xF)) { - - *model += (((sig >> 16) & 0xF) << 4); - *family += ((sig >> 20) & 0xFF); - } } -/** Calculate CRC32 over 8-bit data using a hardware/CPU instruction. -@param[in,out] crc crc32 checksum so far when this function is called, -when the function ends it will contain the new checksum -@param[in,out] data data to be checksummed, the pointer will be advanced -with 1 byte -@param[in,out] len remaining bytes, it will be decremented with 1 */ -inline -void -ut_crc32_8_hw( - uint32_t* crc, - const byte** data, - ulint* len) +/** Append 8 bits (1 byte) to a CRC-32C checksum. +@param crc CRC-32C checksum so far +@param data data to be checksummed +@return the updated CRC-32C */ +static inline ulint ut_crc32c_8(ulint crc, byte data) { # ifdef _MSC_VER - *crc = _mm_crc32_u8(*crc, (*data)[0]); + return _mm_crc32_u8(static_cast(crc), data); # elif __has_feature(memory_sanitizer) - *crc = __builtin_ia32_crc32qi(*crc, (*data)[0]); + return __builtin_ia32_crc32qi(static_cast(crc), data); # else - asm("crc32b %1, %0" - /* output operands */ - : "+r" (*crc) - /* input operands */ - : "rm" ((*data)[0])); + asm("crc32b %1, %0" : "+r" (crc) : "rm" (data)); + return crc; # endif - - (*data)++; - (*len)--; } -/** Calculate CRC32 over a 64-bit integer using a hardware/CPU instruction. -@param[in] crc crc32 checksum so far -@param[in] data data to be checksummed -@return resulting checksum of crc + crc(data) */ -inline -uint32_t -ut_crc32_64_low_hw( - uint32_t crc, - uint64_t data) +/** Append 64 bits (8 aligned bytes) to a CRC-32C checksum +@param[in] crc CRC-32C checksum so far +@param[in] data 8 bytes of aligned data +@return the updated CRC-32C */ +static inline ulint ut_crc32c_64(ulint crc, uint64_t data) { - uint64_t crc_64bit = crc; # ifdef _MSC_VER # ifdef _M_X64 - crc_64bit = _mm_crc32_u64(crc_64bit, data); + return _mm_crc32_u64(crc, data); # elif defined(_M_IX86) - crc = _mm_crc32_u32(crc, static_cast(data)); - crc_64bit = _mm_crc32_u32(crc, static_cast(data >> 32)); + crc= _mm_crc32_u32(crc, static_cast(data)); + crc= _mm_crc32_u32(crc, static_cast(data >> 32)); + return crc; # else -# error Not Supported processors type. +# error Unsupported processor type # endif # elif __has_feature(memory_sanitizer) - crc_64bit = __builtin_ia32_crc32di(crc_64bit, data); + return __builtin_ia32_crc32di(crc, data); +# elif defined __x86_64__ + asm("crc32q %1, %0" : "+r" (crc) : "rm" (data)); + return crc; # else - asm("crc32q %1, %0" - /* output operands */ - : "+r" (crc_64bit) - /* input operands */ - : "rm" (data)); + asm("crc32l %1, %0" : "+r" (crc) : "rm" (static_cast(data))); + asm("crc32l %1, %0" : "+r" (crc) : "rm" (static_cast(data >> 32))); + return crc; # endif - - return(static_cast(crc_64bit)); -} - -/** Calculate CRC32 over 64-bit byte string using a hardware/CPU instruction. -@param[in,out] crc crc32 checksum so far when this function is called, -when the function ends it will contain the new checksum -@param[in,out] data data to be checksummed, the pointer will be advanced -with 8 bytes -@param[in,out] len remaining bytes, it will be decremented with 8 */ -inline -void -ut_crc32_64_hw( - uint32_t* crc, - const byte** data, - ulint* len) -{ - uint64_t data_int = *reinterpret_cast(*data); - -# ifdef WORDS_BIGENDIAN - /* Currently we only support x86_64 (little endian) CPUs. In case - some big endian CPU supports a CRC32 instruction, then maybe we will - need a byte order swap here. */ -# error Dont know how to handle big endian CPUs - /* - data_int = ut_crc32_swap_byteorder(data_int); - */ -# endif /* WORDS_BIGENDIAN */ - - *crc = ut_crc32_64_low_hw(*crc, data_int); - - *data += 8; - *len -= 8; } /** Calculate CRC-32C using dedicated IA-32 or AMD64 instructions @@ -257,84 +180,50 @@ ut_crc32_64_hw( @return CRC-32C (polynomial 0x11EDC6F41) */ uint32_t ut_crc32_hw(uint32_t crc, const byte *buf, size_t len) { - crc = ~crc; + ulint c= static_cast(~crc); - /* Calculate byte-by-byte up to an 8-byte aligned address. After - this consume the input 8-bytes at a time. */ - while (len > 0 && (reinterpret_cast(buf) & 7) != 0) { - ut_crc32_8_hw(&crc, &buf, &len); - } + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast(buf) & 7) != 0) + { + c= ut_crc32c_8(c, *buf++); + len--; + } - /* Perf testing - ./unittest/gunit/innodb/merge_innodb_tests-t --gtest_filter=ut0crc32.perf - on CPU "Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz" - with different N in "while (len >= N) {" shows: - N=16 - 2.867254 sec - 2.866860 sec - 2.867973 sec + const uint64_t* b64= reinterpret_cast(buf); - N=32 - 2.715725 sec - 2.713008 sec - 2.712520 sec - (5.36% speedup over N=16) + for (; len >= 128; len-= 128) + { + /* This call is repeated 16 times. 16 * 8 = 128. */ + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + c= ut_crc32c_64(c, *b64++); + } - N=64 - 2.634140 sec - 2.636558 sec - 2.636488 sec - (2.88% speedup over N=32) + for (; len >= 8; len-= 8) + c= ut_crc32c_64(c, *b64++); - N=128 - 2.599534 sec - 2.599919 sec - 2.598035 sec - (1.39% speedup over N=64) + buf= reinterpret_cast(b64); - N=256 - 2.576993 sec - 2.576748 sec - 2.575700 sec - (0.87% speedup over N=128) + while (len--) + c= ut_crc32c_8(c, *buf++); - N=512 - 2.693928 sec - 2.691663 sec - 2.692142 sec - (4.51% slowdown over N=256) - */ - while (len >= 128) { - /* This call is repeated 16 times. 16 * 8 = 128. */ - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - ut_crc32_64_hw(&crc, &buf, &len); - } - - while (len >= 8) { - ut_crc32_64_hw(&crc, &buf, &len); - } - - while (len > 0) { - ut_crc32_8_hw(&crc, &buf, &len); - } - - return(~crc); + return ~static_cast(c); } -# endif /* defined(__GNUC__) && defined(__x86_64__) || (_WIN64) */ +# endif /* (defined(__GNUC__) && defined(__i386__)) || _MSC_VER */ /* CRC32 software implementation. */ @@ -373,91 +262,44 @@ ut_crc32_slice8_table_init() } } -/** Calculate CRC32 over 8-bit data using a software implementation. -@param[in,out] crc crc32 checksum so far when this function is called, -when the function ends it will contain the new checksum -@param[in,out] data data to be checksummed, the pointer will be advanced -with 1 byte -@param[in,out] len remaining bytes, it will be decremented with 1 */ -inline -void -ut_crc32_8_sw( - uint32_t* crc, - const byte** data, - ulint* len) +/** Append 8 bits (1 byte) to a CRC-32C checksum. +@param crc CRC-32C checksum so far +@param data data to be checksummed +@return the updated CRC-32C */ +static inline uint32_t ut_crc32c_8_sw(uint32_t crc, byte data) { - const uint8_t i = (*crc ^ (*data)[0]) & 0xFF; + const uint8_t i= (crc ^ data) & 0xFF; - *crc = (*crc >> 8) ^ ut_crc32_slice8_table[0][i]; - - (*data)++; - (*len)--; + return (crc >> 8) ^ ut_crc32_slice8_table[0][i]; } -/** Swap the byte order of an 8 byte integer. -@param[in] i 8-byte integer -@return 8-byte integer */ +/** Append 64 bits (8 aligned bytes) to a CRC-32C checksum +@param[in] crc CRC-32C checksum so far +@param[in] data 8 bytes of aligned data +@return the updated CRC-32C */ +static inline uint32_t ut_crc32c_64_sw(uint32_t crc, uint64_t data) +{ # ifdef WORDS_BIGENDIAN -inline uint64_t ut_crc32_swap_byteorder(uint64_t i) -{ - return i << 56 | - (i & 0x000000000000FF00ULL) << 40 | - (i & 0x0000000000FF0000ULL) << 24 | - (i & 0x00000000FF000000ULL) << 8 | - (i & 0x000000FF00000000ULL) >> 8 | - (i & 0x0000FF0000000000ULL) >> 24 | - (i & 0x00FF000000000000ULL) >> 40 | - i >> 56; -} + data= data << 56 | + (data & 0x000000000000FF00ULL) << 40 | + (data & 0x0000000000FF0000ULL) << 24 | + (data & 0x00000000FF000000ULL) << 8 | + (data & 0x000000FF00000000ULL) >> 8 | + (data & 0x0000FF0000000000ULL) >> 24 | + (data & 0x00FF000000000000ULL) >> 40 | + data >> 56; # endif /* WORDS_BIGENDIAN */ -/** Calculate CRC32 over a 64-bit integer using a software implementation. -@param[in] crc crc32 checksum so far -@param[in] data data to be checksummed -@return resulting checksum of crc + crc(data) */ -inline -uint32_t -ut_crc32_64_low_sw( - uint32_t crc, - uint64_t data) -{ - const uint64_t i = crc ^ data; - - return( - ut_crc32_slice8_table[7][(i ) & 0xFF] ^ - ut_crc32_slice8_table[6][(i >> 8) & 0xFF] ^ - ut_crc32_slice8_table[5][(i >> 16) & 0xFF] ^ - ut_crc32_slice8_table[4][(i >> 24) & 0xFF] ^ - ut_crc32_slice8_table[3][(i >> 32) & 0xFF] ^ - ut_crc32_slice8_table[2][(i >> 40) & 0xFF] ^ - ut_crc32_slice8_table[1][(i >> 48) & 0xFF] ^ - ut_crc32_slice8_table[0][(i >> 56)] - ); -} - -/** Calculate CRC32 over 64-bit byte string using a software implementation. -@param[in,out] crc crc32 checksum so far when this function is called, -when the function ends it will contain the new checksum -@param[in,out] data data to be checksummed, the pointer will be advanced -with 8 bytes -@param[in,out] len remaining bytes, it will be decremented with 8 */ -inline -void -ut_crc32_64_sw( - uint32_t* crc, - const byte** data, - ulint* len) -{ - uint64_t data_int = *reinterpret_cast(*data); - -# ifdef WORDS_BIGENDIAN - data_int = ut_crc32_swap_byteorder(data_int); -# endif /* WORDS_BIGENDIAN */ - - *crc = ut_crc32_64_low_sw(*crc, data_int); - - *data += 8; - *len -= 8; + data^= crc; + return + ut_crc32_slice8_table[7][(data ) & 0xFF] ^ + ut_crc32_slice8_table[6][(data >> 8) & 0xFF] ^ + ut_crc32_slice8_table[5][(data >> 16) & 0xFF] ^ + ut_crc32_slice8_table[4][(data >> 24) & 0xFF] ^ + ut_crc32_slice8_table[3][(data >> 32) & 0xFF] ^ + ut_crc32_slice8_table[2][(data >> 40) & 0xFF] ^ + ut_crc32_slice8_table[1][(data >> 48) & 0xFF] ^ + ut_crc32_slice8_table[0][(data >> 56)]; } /** Calculate CRC-32C using a look-up table. @@ -467,43 +309,27 @@ ut_crc32_64_sw( @return CRC-32C (polynomial 0x11EDC6F41) */ uint32_t ut_crc32_sw(uint32_t crc, const byte *buf, size_t len) { - crc = ~crc; + crc= ~crc; - /* Calculate byte-by-byte up to an 8-byte aligned address. After - this consume the input 8-bytes at a time. */ - while (len > 0 && (reinterpret_cast(buf) & 7) != 0) { - ut_crc32_8_sw(&crc, &buf, &len); - } + /* Calculate byte-by-byte up to an 8-byte aligned address. After + this consume the input 8-bytes at a time. */ + while (len > 0 && (reinterpret_cast(buf) & 7) != 0) + { + crc= ut_crc32c_8_sw(crc, *buf++); + len--; + } - while (len >= 128) { - /* This call is repeated 16 times. 16 * 8 = 128. */ - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - ut_crc32_64_sw(&crc, &buf, &len); - } + const uint64_t* b64= reinterpret_cast(buf); - while (len >= 8) { - ut_crc32_64_sw(&crc, &buf, &len); - } + for (; len >= 8; len-= 8) + crc= ut_crc32c_64_sw(crc, *b64++); - while (len > 0) { - ut_crc32_8_sw(&crc, &buf, &len); - } + buf= reinterpret_cast(b64); - return(~crc); + while (len--) + crc= ut_crc32c_8_sw(crc, *buf++); + + return ~crc; } ut_crc32_func_t ut_crc32_low= ut_crc32_sw; @@ -513,37 +339,24 @@ const char *ut_crc32_implementation= "Using generic crc32 instructions"; /********************************************************************//** Initializes the data structures used by ut_crc32*(). Does not do any allocations, would not hurt if called twice, but would be pointless. */ -void -ut_crc32_init() +void ut_crc32_init() { -#ifdef HAVE_CRC32_VPMSUM -#else - ut_crc32_slice8_table_init(); - -# if (defined(__GNUC__) && defined(__x86_64__)) || defined(_MSC_VER) - uint32_t vend[3]; - uint32_t model; - uint32_t family; - uint32_t stepping; - uint32_t features_ecx; - uint32_t features_edx; - - ut_cpuid(vend, &model, &family, &stepping, - &features_ecx, &features_edx); - - if (features_ecx & 1 << 20) { - ut_crc32_low = ut_crc32_hw; - ut_crc32_implementation = "Using SSE2 crc32 instructions"; - } +#ifndef HAVE_CRC32_VPMSUM +# if defined(__GNUC__) && defined(HAVE_ARMV8_CRC) + if (crc32_aarch64_available()) + { + ut_crc32_low= crc32c_aarch64; + ut_crc32_implementation= "Using ARMv8 crc32 instructions"; + return; + } +# elif defined(TRY_SSE4_2) + if (has_sse4_2()) + { + ut_crc32_low= ut_crc32_hw; + ut_crc32_implementation= "Using SSE4.2 crc32 instructions"; + return; + } # endif - - -# if defined(__GNUC__) && defined(__linux__) && defined(HAVE_ARMV8_CRC) - if (crc32c_aarch64_available()) { - ut_crc32_low = crc32c_aarch64; - ut_crc32_implementation = "Using Armv8 crc32 instructions"; - - } -# endif -#endif + ut_crc32_slice8_table_init(); +#endif /* !HAVE_CRC32_VPMSUM */ } diff --git a/storage/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc index d1d9e8452f1..c4cf8364806 100644 --- a/storage/innobase/ut/ut0new.cc +++ b/storage/innobase/ut/ut0new.cc @@ -25,7 +25,7 @@ Created May 26, 2014 Vasil Dimov *******************************************************/ #include "univ.i" - +#include /** Maximum number of retries to allocate memory. */ const size_t alloc_max_retries = 60; @@ -59,163 +59,50 @@ the list below: Keep this list alphabetically sorted. */ static PSI_memory_info pfs_info[] = { #ifdef BTR_CUR_HASH_ADAPT - {&mem_key_ahi, "adaptive hash index", 0}, + {&mem_key_ahi, "adaptive hash index", 0}, #endif /* BTR_CUR_HASH_ADAPT */ - {&mem_key_buf_buf_pool, "buf_buf_pool", 0}, - {&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0}, - {&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0}, - {&mem_key_dict_stats_n_diff_on_level, "dict_stats_n_diff_on_level", 0}, - {&mem_key_other, "other", 0}, - {&mem_key_row_log_buf, "row_log_buf", 0}, - {&mem_key_row_merge_sort, "row_merge_sort", 0}, - {&mem_key_std, "std", 0}, + {&mem_key_buf_buf_pool, "buf_buf_pool", 0}, + {&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0}, + {&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0}, + {&mem_key_dict_stats_n_diff_on_level, "dict_stats_n_diff_on_level", 0}, + {&mem_key_other, "other", 0}, + {&mem_key_row_log_buf, "row_log_buf", 0}, + {&mem_key_row_merge_sort, "row_merge_sort", 0}, + {&mem_key_std, "std", 0}, }; -/** Map used for default performance schema keys, based on file name of the -caller. The key is the file name of the caller and the value is a pointer -to a PSI_memory_key variable to be passed to performance schema methods. -We use ut_strcmp_functor because by default std::map will compare the pointers -themselves (cont char*) and not do strcmp(). */ -typedef std::map - mem_keys_auto_t; - -/** Map of filename/pfskey, used for tracing allocations that have not -provided a manually created pfs key. This map is only ever modified (bulk -insert) at startup in a single-threaded environment by ut_new_boot(). -Later it is only read (only std::map::find() is called) from multithreaded -environment, thus it is not protected by any latch. */ -static mem_keys_auto_t mem_keys_auto; - -#endif /* UNIV_PFS_MEMORY */ +static const int NKEYS = static_castUT_ARR_SIZE(auto_event_names)-1; +static PSI_memory_key auto_event_keys[NKEYS]; /** Setup the internal objects needed for UT_NEW() to operate. This must be called before the first call to UT_NEW(). */ -void -ut_new_boot() +void ut_new_boot() { -#ifdef UNIV_PFS_MEMORY - static const char* auto_event_names[] = { - /* Keep this list alphabetically sorted. */ - "btr0btr", - "btr0bulk", - "btr0cur", - "btr0pcur", - "btr0sea", - "buf0buf", - "buf0dblwr", - "buf0dump", - "buf0flu", - "buf0lru", - "dict0dict", - "dict0mem", - "dict0stats", - "dict0stats_bg", - "eval0eval", - "fil0fil", - "fsp0file", - "fsp0space", - "fsp0sysspace", - "fts0ast", - "fts0config", - "fts0fts", - "fts0opt", - "fts0pars", - "fts0que", - "fts0sql", - "gis0sea", - "ha0ha", - "ha_innodb", - "handler0alter", - "hash0hash", - "i_s", - "ibuf0ibuf", - "lexyy", - "lock0lock", - "log0log", - "log0recv", - "mem0mem", - "os0event", - "os0file", - "page0cur", - "page0zip", - "pars0lex", - "read0read", - "rem0rec", - "row0ftsort", - "row0import", - "row0log", - "row0merge", - "row0mysql", - "row0sel", - "srv0conc", - "srv0srv", - "srv0start", - "sync0arr", - "sync0debug", - "sync0rw", - "sync0types", - "trx0i_s", - "trx0purge", - "trx0roll", - "trx0rseg", - "trx0sys", - "trx0trx", - "trx0undo", - "ut0list", - "ut0mem", - "ut0mutex", - "ut0pool", - "ut0rbt", - "ut0wqueue", - }; - static const size_t n_auto = UT_ARR_SIZE(auto_event_names); - static PSI_memory_key auto_event_keys[n_auto]; - static PSI_memory_info pfs_info_auto[n_auto]; + PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, static_cast + UT_ARR_SIZE(pfs_info)); - for (size_t i = 0; i < n_auto; i++) { + PSI_memory_info pfs_info_auto[NKEYS]; + for (int i= 0; i < NKEYS; i++) + { + pfs_info_auto[i]= {&auto_event_keys[i], auto_event_names[i], 0}; + } - const std::pair ret - MY_ATTRIBUTE((unused)) - = mem_keys_auto.insert( - mem_keys_auto_t::value_type(auto_event_names[i], - &auto_event_keys[i])); - - /* ret.second is true if new element has been inserted */ - ut_a(ret.second); - - /* e.g. "btr0btr" */ - pfs_info_auto[i].m_name = auto_event_names[i]; - - /* a pointer to the pfs key */ - pfs_info_auto[i].m_key = &auto_event_keys[i]; - - pfs_info_auto[i].m_flags = 0; - } - - PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, static_cast( - UT_ARR_SIZE(pfs_info))); - PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto, - static_cast(n_auto)); -#endif /* UNIV_PFS_MEMORY */ + PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto,NKEYS); } -#ifdef UNIV_PFS_MEMORY +/** Retrieve a memory key (registered with PFS), corresponding to source file . -/** Retrieve a memory key (registered with PFS), given a portion of the file -name of the caller. -@param[in] file portion of the filename - basename without an extension -@return registered memory key or PSI_NOT_INSTRUMENTED if not found */ -PSI_memory_key -ut_new_get_key_by_file( - const char* file) +@param[in] autoevent_idx - offset to the auto_event_names corresponding to the +file name of the caller. + +@return registered memory key or PSI_NOT_INSTRUMENTED +*/ +PSI_memory_key ut_new_get_key_by_file(uint32_t autoevent_idx) { - mem_keys_auto_t::const_iterator el = mem_keys_auto.find(file); - - if (el != mem_keys_auto.end()) { - return(*(el->second)); - } - - return(PSI_NOT_INSTRUMENTED); + ut_ad(autoevent_idx < NKEYS); + return auto_event_keys[autoevent_idx]; } -#endif /* UNIV_PFS_MEMORY */ +#else /* UNIV_PFS_MEMORY */ +void ut_new_boot(){} +#endif diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 5c19fcb6825..bf35e7857c5 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -148,8 +148,6 @@ ut_print_buf( const byte* data; ulint i; - UNIV_MEM_ASSERT_RW(buf, len); - fprintf(file, " len " ULINTPF "; hex ", len); for (data = (const byte*) buf, i = 0; i < len; i++) { @@ -184,8 +182,6 @@ ut_print_buf_hex( '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; - UNIV_MEM_ASSERT_RW(buf, len); - o << "(0x"; for (data = static_cast(buf), i = 0; i < len; i++) { @@ -208,8 +204,6 @@ ut_print_buf( const byte* data; ulint i; - UNIV_MEM_ASSERT_RW(buf, len); - for (data = static_cast(buf), i = 0; i < len; i++) { int c = static_cast(*data++); o << (isprint(c) ? static_cast(c) : ' '); @@ -218,27 +212,6 @@ ut_print_buf( ut_print_buf_hex(o, buf, len); } -/*************************************************************//** -Calculates fast the number rounded up to the nearest power of 2. -@return first power of 2 which is >= n */ -ulint -ut_2_power_up( -/*==========*/ - ulint n) /*!< in: number != 0 */ -{ - ulint res; - - res = 1; - - ut_ad(n > 0); - - while (res < n) { - res = res * 2; - } - - return(res); -} - /** Get a fixed-length string, quoted as an SQL identifier. If the string contains a slash '/', the string will be output as two identifiers separated by a period (.), @@ -566,6 +539,12 @@ ut_basename_noext( namespace ib { +ATTRIBUTE_COLD logger& logger::operator<<(dberr_t err) +{ + m_oss << ut_strerr(err); + return *this; +} + info::~info() { sql_print_information("InnoDB: %s", m_oss.str().c_str()); @@ -576,9 +555,13 @@ warn::~warn() sql_print_warning("InnoDB: %s", m_oss.str().c_str()); } +/** true if error::~error() was invoked, false otherwise */ +bool error::logged; + error::~error() { sql_print_error("InnoDB: %s", m_oss.str().c_str()); + logged = true; } #ifdef _MSC_VER diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index 7e84bf67860..34af45d07fa 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (C) 2007 MySQL AB +# Copyright (C) 2009,2020 MariaDB Corporation Ab # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -55,20 +56,20 @@ MYSQL_ADD_PLUGIN(aria ${ARIA_SOURCES} STORAGE_ENGINE MANDATORY LINK_LIBRARIES myisam mysys mysys_ssl RECOMPILE_FOR_EMBEDDED) -MYSQL_ADD_EXECUTABLE(aria_ftdump maria_ftdump.c COMPONENT Server) +MYSQL_ADD_EXECUTABLE(aria_ftdump aria_ftdump.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_ftdump aria) -MYSQL_ADD_EXECUTABLE(aria_chk maria_chk.c COMPONENT Server) +MYSQL_ADD_EXECUTABLE(aria_chk aria_chk.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_chk aria) -MYSQL_ADD_EXECUTABLE(aria_read_log maria_read_log.c COMPONENT Server) +MYSQL_ADD_EXECUTABLE(aria_read_log aria_read_log.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_read_log aria) -MYSQL_ADD_EXECUTABLE(aria_dump_log maria_dump_log.c unittest/ma_loghandler_examples.c COMPONENT Server) +MYSQL_ADD_EXECUTABLE(aria_dump_log aria_dump_log.c unittest/ma_loghandler_examples.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_dump_log aria) SET_TARGET_PROPERTIES(aria_dump_log PROPERTIES COMPILE_FLAGS "-DMARIA_DUMP_LOG") -MYSQL_ADD_EXECUTABLE(aria_pack maria_pack.c COMPONENT Server) +MYSQL_ADD_EXECUTABLE(aria_pack aria_pack.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_pack aria) IF(WITH_UNIT_TESTS) @@ -104,65 +105,24 @@ OPTION(USE_ARIA_FOR_TMP_TABLES "Use Aria for temporary tables" ON) # S3 # INCLUDE (CheckIncludeFiles) -INCLUDE (CheckCSourceRuns) -SET(CURL_SSL_TEST_SOURCE "\n - #include \n - #include \n - #include \n - int main(void)\n - {\n - curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);\n -\n - if (data->ssl_version)\n - {\n - if (strncmp(data->ssl_version, \"OpenSSL\", 7) != 0)\n - {\n - return EXIT_SUCCESS;\n - }\n - if (data->ssl_version[8] == '0')\n - {\n - return EXIT_FAILURE;\n - }\n - if ((data->ssl_version[8] == '1') && (data->ssl_version[10] == '0'))\n - {\n - return EXIT_FAILURE;\n - }\n - }\n - return EXIT_SUCCESS;\n - }") - -SET(S3_SOURCES ha_s3.cc s3_func.c +SET(S3_SOURCES s3_func.c libmarias3/src/debug.c libmarias3/src/error.c libmarias3/src/marias3.c libmarias3/src/request.c libmarias3/src/response.c libmarias3/src/sha256.c - libmarias3/src/sha256-internal.c) + libmarias3/src/sha256-internal.c libmarias3/src/xml.c) IF(NOT PLUGIN_S3 STREQUAL NO) - FIND_PACKAGE(LibXml2) FIND_PACKAGE(CURL) ENDIF() -IF (LIBXML2_FOUND AND CURL_FOUND) - MYSQL_ADD_PLUGIN(s3 ${S3_SOURCES} STORAGE_ENGINE STATIC_ONLY - LINK_LIBRARIES aria myisam mysys mysys_ssl xml2 curl - NOT_EMBEDDED) +IF (CURL_FOUND) + MYSQL_ADD_PLUGIN(s3 ha_s3.cc ${S3_SOURCES} COMPONENT s3-engine + LINK_LIBRARIES curl STORAGE_ENGINE NOT_EMBEDDED CONFIG s3.cnf) ENDIF() IF(TARGET s3) - SET(CMAKE_REQUIRED_LIBRARIES curl) - CHECK_C_SOURCE_RUNS("${CURL_SSL_TEST_SOURCE}" FOUND_SAFE_CURL_SSL) - UNSET(CMAKE_REQUIRED_LIBRARIES) - MYSQL_ADD_EXECUTABLE(aria_s3_copy aria_s3_copy.cc COMPONENT Server) - TARGET_LINK_LIBRARIES(aria_s3_copy s3) - - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libmarias3 ${LIBXML2_INCLUDE_DIR}) + MYSQL_ADD_EXECUTABLE(aria_s3_copy aria_s3_copy.cc ${S3_SOURCES} COMPONENT s3-engine) + TARGET_LINK_LIBRARIES(aria_s3_copy aria myisam mysys mysys_ssl curl) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libmarias3) ADD_DEFINITIONS(-DWITH_S3_STORAGE_ENGINE) - IF (FOUND_SAFE_CURL_SSL) - MESSAGE(STATUS "Found thread safe curl ssl") - ELSE () - MESSAGE(STATUS "Found thread unsafe curl ssl, locks added") - ADD_DEFINITIONS(-DHAVE_CURL_OPENSSL_UNSAFE) - ENDIF () - - TARGET_LINK_LIBRARIES(aria s3) ENDIF() diff --git a/storage/maria/maria_chk.c b/storage/maria/aria_chk.c similarity index 99% rename from storage/maria/maria_chk.c rename to storage/maria/aria_chk.c index 5f3eef088f6..f46fe7490d8 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/aria_chk.c @@ -140,16 +140,20 @@ int main(int argc, char **argv) HA_ERR_FIRST+ array_elements(handler_error_messages)-1); maria_block_size= 0; /* Use block size from control file */ - if (!opt_ignore_control_file && - (ma_control_file_open(FALSE, opt_require_control_file || - !(check_param.testflag & T_SILENT), - TRUE) && - (opt_require_control_file || - (opt_transaction_logging && (check_param.testflag & T_REP_ANY))))) + if (!opt_ignore_control_file) { - error= 1; - goto end; + if ((ma_control_file_open(FALSE, opt_require_control_file || + !(check_param.testflag & T_SILENT), + TRUE) && + (opt_require_control_file || + (opt_transaction_logging && (check_param.testflag & T_REP_ANY))))) + { + error= 1; + goto end; + } } + else + opt_warning_for_wrong_transid= 0; /* If we are doing a repair, user may want to store this repair into the log @@ -1769,21 +1773,26 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) type=share->columndef[field].base_type; else type=(enum en_fieldtype) share->columndef[field].type; - end=strmov(buff,field_pack[type]); + end= strmov(buff, field_pack[type]); + if (end != buff) + { + *(end++)=','; + *(end++)=' '; + } if (share->options & HA_OPTION_COMPRESS_RECORD) { if (share->columndef[field].pack_type & PACK_TYPE_SELECTED) - end=strmov(end,", not_always"); + end=strmov(end,"not_always, "); if (share->columndef[field].pack_type & PACK_TYPE_SPACE_FIELDS) - end=strmov(end,", no empty"); + end=strmov(end,"no empty, "); if (share->columndef[field].pack_type & PACK_TYPE_ZERO_FILL) { - sprintf(end,", zerofill(%d)",share->columndef[field].space_length_bits); + sprintf(end,"zerofill(%d), ",share->columndef[field].space_length_bits); end=strend(end); } } - if (buff[0] == ',') - strmov(buff,buff+2); + if (end != buff) + end[-2]= 0; int10_to_str((long) share->columndef[field].length,length,10); null_bit[0]=null_pos[0]=0; if (share->columndef[field].null_bit) diff --git a/storage/maria/maria_dump_log.c b/storage/maria/aria_dump_log.c similarity index 100% rename from storage/maria/maria_dump_log.c rename to storage/maria/aria_dump_log.c diff --git a/storage/maria/maria_ftdump.c b/storage/maria/aria_ftdump.c similarity index 100% rename from storage/maria/maria_ftdump.c rename to storage/maria/aria_ftdump.c diff --git a/storage/maria/maria_pack.c b/storage/maria/aria_pack.c similarity index 100% rename from storage/maria/maria_pack.c rename to storage/maria/aria_pack.c diff --git a/storage/maria/maria_read_log.c b/storage/maria/aria_read_log.c similarity index 80% rename from storage/maria/maria_read_log.c rename to storage/maria/aria_read_log.c index b0bf9c01b84..a3a6d4375c1 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/aria_read_log.c @@ -1,5 +1,6 @@ /* Copyright (C) 2007 MySQL AB Copyright (C) 2010 Monty Program Ab + Copyright (C) 2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,15 +30,51 @@ const char *default_dbug_option= "d:t:O,\\aria_read_log.trace"; const char *default_dbug_option= "d:t:o,/tmp/aria_read_log.trace"; #endif #endif /* DBUG_OFF */ -static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent; -static my_bool opt_check; +static my_bool opt_display_only, opt_apply, opt_silent, opt_apply_undo; +static my_bool opt_check, opt_start_from_checkpoint; static my_bool opt_print_aria_log_control; static const char *opt_tmpdir; static ulong opt_translog_buffer_size; static ulonglong opt_page_buffer_size; -static ulonglong opt_start_from_lsn, opt_end_lsn, opt_start_from_checkpoint; +static ulonglong opt_start_from_lsn, opt_lsn_redo_end, opt_lsn_undo_end; +static char *start_from_lsn_buf, *lsn_redo_end_buf, *lsn_undo_end_buf; static MY_TMPDIR maria_chk_tmpdir; +/* + Get lsn from file number and offset + Format supported: + ulonglong + uint,0xhex +*/ + +static ulonglong get_lsn(const char *lsn_str) +{ + ulong file; + ulong pos; + if (sscanf(lsn_str, " %lu,0x%lx", &file, &pos) == 2) + return MAKE_LSN(file, pos); + if (sscanf(lsn_str, " %lu", &pos) == 1) + return (ulonglong) pos; + return ~(ulonglong) 0; /* Error */ +} + +static my_bool get_lsn_arg(const char *lsn_string, ulonglong *lsn, + const char *name) +{ + ulonglong value; + value= get_lsn(lsn_string); + if (value != ~(ulonglong) 0) + { + *lsn= value; + return 0; + } + fprintf(stderr, + "Wrong value '%s' for option %s. Value should be in format: " + "number,0xhexnumber\n", + lsn_string, name); + return 1; +} + int main(int argc, char **argv) { @@ -136,17 +173,12 @@ int main(int argc, char **argv) LSN_IN_PARTS(lsn)); } - if (opt_end_lsn != LSN_IMPOSSIBLE) - { - /* We can't apply undo if we use end_lsn */ - opt_apply_undo= 0; - } - fprintf(stdout, "TRACE of the last aria_read_log\n"); - if (maria_apply_log(lsn, opt_end_lsn, opt_apply ? MARIA_LOG_APPLY : + if (maria_apply_log(lsn, opt_lsn_redo_end, opt_lsn_undo_end, + opt_apply ? MARIA_LOG_APPLY : (opt_check ? MARIA_LOG_CHECK : MARIA_LOG_DISPLAY_HEADER), opt_silent ? NULL : stdout, - opt_apply_undo, FALSE, FALSE, &warnings_count)) + FALSE, FALSE, &warnings_count)) goto err; if (warnings_count == 0) fprintf(stdout, "%s: SUCCESS\n", my_progname_short); @@ -204,9 +236,16 @@ static struct my_option my_long_options[] = {"display-only", 'd', "display brief info read from records' header", &opt_display_only, &opt_display_only, 0, GET_BOOL, NO_ARG,0, 0, 0, 0, 0, 0}, - { "end-lsn", 'e', "Stop applying at this lsn. If end-lsn is used, UNDO:s " - "will not be applied", &opt_end_lsn, &opt_end_lsn, - 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, + { "end-lsn", 'e', "Alias for lsn-redo-end", + &lsn_redo_end_buf, &lsn_redo_end_buf, 0, GET_STR, REQUIRED_ARG, 0, 0, + 0, 0, 0, 0 }, + { "lsn-redo-end", 'e', "Stop applying at this lsn during redo. If " + "this option is used UNDO:s will not be applied unless --lsn-undo-end is " + "given", &lsn_redo_end_buf, + &lsn_redo_end_buf, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "lsn-undo-end", 'E', "Stop applying undo after this lsn has been applied", + &lsn_undo_end_buf, &lsn_undo_end_buf, 0, GET_STR, REQUIRED_ARG, 0, 0, + 0, 0, 0, 0 }, {"aria-log-dir-path", 'h', "Path to the directory where to store transactional log", (uchar **) &maria_data_root, (uchar **) &maria_data_root, 0, @@ -246,7 +285,9 @@ static struct my_option my_long_options[] = GET_ULONG, REQUIRED_ARG, (long) TRANSLOG_PAGECACHE_SIZE, 1024L*1024L, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, - {"undo", 'u', "Apply UNDO records to tables. (disable with --disable-undo)", + {"undo", 'u', + "Apply UNDO records to tables. (disable with --disable-undo). " + "Will be automatically set if lsn-undo-end is used", (uchar **) &opt_apply_undo, (uchar **) &opt_apply_undo, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"verbose", 'v', "Print more information during apply/undo phase", @@ -257,10 +298,9 @@ static struct my_option my_long_options[] = { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - static void print_version(void) { - printf("%s Ver 1.4 for %s on %s\n", + printf("%s Ver 1.5 for %s on %s\n", my_progname_short, SYSTEM_TYPE, MACHINE_TYPE); } @@ -268,7 +308,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright (C) 2007 MySQL AB, 2009-2011 Monty Program Ab"); + puts("Copyright (C) 2007 MySQL AB, 2009-2011 Monty Program Ab, 2020 MariaDB Corporation"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); puts("and you are welcome to modify and redistribute it under the GPL license\n"); @@ -284,7 +324,7 @@ static void usage(void) my_progname_short); printf("or\n"); printf("Usage: %s OPTIONS -h `aria_log_directory` " - "--print-aria-log-control\n\n", + "--print-log-control-file\n\n", my_progname_short); my_print_help(my_long_options); @@ -312,6 +352,9 @@ get_one_option(const struct my_option *opt, case 'V': print_version(); exit(0); + case 'E': + opt_apply_undo= TRUE; + break; case 'T': { char *pos; @@ -341,13 +384,34 @@ get_one_option(const struct my_option *opt, static void get_options(int *argc,char ***argv) { int ho_error; - my_bool need_help= 0; + my_bool need_help= 0, need_abort= 0; if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); + if (start_from_lsn_buf) + { + if (get_lsn_arg(start_from_lsn_buf, &opt_start_from_lsn, + "start-from-lsn")) + need_abort= 1; + } + if (lsn_redo_end_buf) + { + if (get_lsn_arg(lsn_redo_end_buf, &opt_lsn_redo_end, + "lsn-redo-end")) + need_abort= 1; + } + if (lsn_undo_end_buf) + { + if (get_lsn_arg(lsn_undo_end_buf, &opt_lsn_undo_end, + "lsn-undo-end")) + need_abort= 1; + } + if (!opt_apply) opt_apply_undo= FALSE; + if (!opt_apply_undo) + opt_lsn_undo_end= LSN_MAX; if (*argc > 0) { @@ -356,21 +420,20 @@ static void get_options(int *argc,char ***argv) } if ((opt_display_only + opt_apply + opt_print_aria_log_control) != 1) { - need_help= 1; + need_abort= 1; fprintf(stderr, "You must use one and only one of the options 'display-only', \n" "'print-log-control-file' and 'apply'\n"); } - if (need_help) + if (need_help || need_abort) { fflush(stderr); - need_help =1; - usage(); + if (need_help) + usage(); exit(1); } if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir)) exit(1); maria_tmpdir= &maria_chk_tmpdir; } - diff --git a/storage/maria/aria_s3_copy.cc b/storage/maria/aria_s3_copy.cc index 981aa052415..2eac95ab9de 100644 --- a/storage/maria/aria_s3_copy.cc +++ b/storage/maria/aria_s3_copy.cc @@ -155,7 +155,7 @@ extern "C" my_bool get_one_option(const struct my_option *opt } -static void get_options(register int *argc,register char ***argv) +static void get_options(int *argc, char ***argv) { int ho_error; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index c15469ecb75..c257a2094f1 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1,6 +1,6 @@ /* Copyright (C) 2004-2008 MySQL AB & MySQL Finland AB & TCX DataKonsult AB Copyright (C) 2008-2009 Sun Microsystems, Inc. - Copyright (c) 2009, 2017, MariaDB Corporation. + Copyright (c) 2009, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,12 +50,12 @@ C_MODE_END Note that in future versions, only *transactional* Maria tables can rollback, so this flag should be up or down conditionally. */ -#ifdef MARIA_CANNOT_ROLLBACK -#define CANNOT_ROLLBACK_FLAG HA_NO_TRANSACTIONS -#define trans_register_ha(A, B, C) do { /* nothing */ } while(0) +#ifdef ARIA_HAS_TRANSACTIONS +#define TRANSACTION_STATE #else -#define CANNOT_ROLLBACK_FLAG 0 +#define TRANSACTION_STATE HA_NO_TRANSACTIONS #endif + #define THD_TRN (TRN*) thd_get_ha_data(thd, maria_hton) ulong pagecache_division_limit, pagecache_age_threshold, pagecache_file_hash_size; @@ -72,7 +72,7 @@ const char *zerofill_error_msg= corrupted. */ ulonglong maria_recover_options= HA_RECOVER_NONE; -handlerton *maria_hton; +handlerton __attribute__((visibility("default"))) *maria_hton; /* bits in maria_recover_options */ const char *maria_recover_names[]= @@ -210,7 +210,7 @@ static MYSQL_SYSVAR_ENUM(group_commit, maria_group_commit, static MYSQL_SYSVAR_ULONG(group_commit_interval, maria_group_commit_interval, PLUGIN_VAR_RQCMDARG, - "Interval between commite in microseconds (1/1000000c)." + "Interval between commits in microseconds (1/1000000 sec)." " 0 stands for no waiting" " for other threads to come and do a commit in \"hard\" mode and no" " sync()/commit at all in \"soft\" mode. Option has only an effect" @@ -959,17 +959,17 @@ static int maria_create_trn_for_mysql(MARIA_HA *info) if (!trn) /* no transaction yet - open it now */ { - trn= trnman_new_trn(& thd->transaction.wt); + trn= trnman_new_trn(& thd->transaction->wt); if (unlikely(!trn)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); thd_set_ha_data(thd, maria_hton, trn); if (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) - trans_register_ha(thd, TRUE, maria_hton); + trans_register_ha(thd, TRUE, maria_hton, trn->trid); } _ma_set_trn_for_table(info, trn); if (!trnman_increment_locked_tables(trn)) { - trans_register_ha(thd, FALSE, maria_hton); + trans_register_ha(thd, FALSE, maria_hton, trn->trid); trnman_new_statement(trn); } #ifdef EXTRA_DEBUG @@ -1020,7 +1020,7 @@ handler(hton, table_arg), file(0), int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | - HA_FILE_BASED | HA_CAN_GEOMETRY | CANNOT_ROLLBACK_FLAG | + HA_FILE_BASED | HA_CAN_GEOMETRY | TRANSACTION_STATE | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_CAN_REPAIR | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_EXPORT | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | @@ -1185,8 +1185,11 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) client doing INSERT DELAYED knows the specificities; but we then should make sure to regularly commit in the delayed_insert thread). */ - int_table_flags|= HA_CAN_INSERT_DELAYED; + int_table_flags|= HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS; } + else + int_table_flags|= HA_CRASH_SAFE; + if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) int_table_flags |= HA_HAS_NEW_CHECKSUM; @@ -1477,6 +1480,13 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt) } break; } + /* + Commit is needed in the case of tables are locked to ensure that repair + is registered in the recovery log + */ + if (implicit_commit(thd, TRUE)) + error= HA_ADMIN_COMMIT_ERROR; + if (!error && start_records != file->state->records && !(check_opt->flags & T_VERY_SILENT)) { @@ -2678,6 +2688,16 @@ int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size) } +bool ha_maria::auto_repair(int error) const +{ + /* Always auto-repair moved tables (error == HA_ERR_OLD_FILE) */ + return ((MY_TEST(maria_recover_options & HA_RECOVER_ANY) && + error == HA_ERR_CRASHED_ON_USAGE) || + error == HA_ERR_OLD_FILE); + +} + + int ha_maria::delete_all_rows() { THD *thd= table->in_use; @@ -2738,6 +2758,7 @@ void ha_maria::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share) int ha_maria::external_lock(THD *thd, int lock_type) { + int result= 0, result2; DBUG_ENTER("ha_maria::external_lock"); file->external_ref= (void*) table; // For ma_killed() /* @@ -2765,7 +2786,7 @@ int ha_maria::external_lock(THD *thd, int lock_type) trnman_increment_locked_tables(file->trn); } - if (!thd->transaction.on) + if (!thd->transaction->on) { /* No need to log REDOs/UNDOs. If this is an internal temporary table @@ -2778,7 +2799,19 @@ int ha_maria::external_lock(THD *thd, int lock_type) */ DBUG_PRINT("info", ("Disabling logging for table")); _ma_tmp_disable_logging_for_table(file, TRUE); + file->autocommit= 0; } + else + file->autocommit= !(thd->variables.option_bits & + (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); +#ifndef ARIA_HAS_TRANSACTIONS + /* + Until Aria has full transactions support, including MVCC support for + delete and update and purging of old states, we have to commit for + every statement. + */ + file->autocommit=1; +#endif } else { @@ -2820,27 +2853,27 @@ int ha_maria::external_lock(THD *thd, int lock_type) */ DBUG_ASSERT(!thd->get_stmt_da()->is_sent() || thd->killed); - /* autocommit ? rollback a transaction */ -#ifdef MARIA_CANNOT_ROLLBACK - if (ma_commit(trn)) - DBUG_RETURN(1); - thd_set_ha_data(thd, maria_hton, 0); -#else - if (!(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + /* + If autocommit, commit transaction. This can happen when open and + lock tables as part of creating triggers, in which case commit + is not called. + Until ARIA_HAS_TRANSACTIONS is not defined, always commit. + */ + if (file->autocommit) { - trnman_rollback_trn(trn); - DBUG_PRINT("info", ("THD_TRN set to 0x0")); + if (ma_commit(trn)) + result= HA_ERR_INTERNAL_ERROR; thd_set_ha_data(thd, maria_hton, 0); } -#endif } trnman_set_flags(trn, trnman_get_flags(trn) & ~ TRN_STATE_INFO_LOGGED); } } } /* if transactional table */ - int result = maria_lock_database(file, !table->s->tmp_table ? - lock_type : ((lock_type == F_UNLCK) ? - F_UNLCK : F_EXTRA_LCK)); + if ((result2= maria_lock_database(file, !table->s->tmp_table ? + lock_type : ((lock_type == F_UNLCK) ? + F_UNLCK : F_EXTRA_LCK)))) + result= result2; if (!file->s->base.born_transactional) file->state= &file->s->state.state; // Restore state if clone @@ -2976,7 +3009,7 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) tables may be under LOCK TABLES, and so they will start the next statement assuming they have a trn (see ha_maria::start_stmt()). */ - trn= trnman_new_trn(& thd->transaction.wt); + trn= trnman_new_trn(& thd->transaction->wt); thd_set_ha_data(thd, maria_hton, trn); if (unlikely(trn == NULL)) { @@ -3325,6 +3358,14 @@ ha_rows ha_maria::records_in_range(uint inx, const key_range *min_key, } +FT_INFO *ha_maria::ft_init_ext(uint flags, uint inx, String * key) +{ + return maria_ft_init_search(flags, file, inx, + (uchar *) key->ptr(), key->length(), + key->charset(), table->record[0]); +} + + int ha_maria::ft_read(uchar * buf) { int error; @@ -3394,22 +3435,49 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)), { TRN *trn= THD_TRN; int res; - MARIA_HA *used_instances= (MARIA_HA*) trn->used_instances; + MARIA_HA *used_instances; DBUG_ENTER("maria_commit"); - DBUG_ASSERT(trnman_has_locked_tables(trn) == 0); - trnman_reset_locked_tables(trn, 0); - trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED); + /* No commit inside lock_tables() */ + if ((!trn || + thd->locked_tables_mode == LTM_LOCK_TABLES || + thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) + DBUG_RETURN(0); /* statement or transaction ? */ if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all) DBUG_RETURN(0); // end of statement + + used_instances= (MARIA_HA*) trn->used_instances; + trnman_reset_locked_tables(trn, 0); + trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED); + trn->used_instances= 0; res= ma_commit(trn); reset_thd_trn(thd, used_instances); + thd_set_ha_data(thd, maria_hton, 0); DBUG_RETURN(res); } +#ifdef MARIA_CANNOT_ROLLBACK +static int maria_rollback(handlerton *hton, THD *thd, bool all) +{ + TRN *trn= THD_TRN; + DBUG_ENTER("maria_rollback"); + if (!trn) + DBUG_RETURN(0); + if (trn->undo_lsn) + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_DATA_WAS_COMMITED_UNDER_ROLLBACK, + ER_THD(thd, ER_DATA_WAS_COMMITED_UNDER_ROLLBACK), + "Aria"); + if (all) + DBUG_RETURN(maria_commit(hton, thd, all)); + /* Statement rollbacks are ignored. Commit will happen in external_lock */ + DBUG_RETURN(0); +} + +#else static int maria_rollback(handlerton *hton __attribute__ ((unused)), THD *thd, bool all) @@ -3430,7 +3498,7 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)), DBUG_RETURN(trnman_rollback_trn(trn) ? HA_ERR_OUT_OF_MEM : 0); // end of transaction } - +#endif /* MARIA_CANNOT_ROLLBACK */ /** @@ -3674,16 +3742,15 @@ static int ha_maria_init(void *p) maria_hton->commit= maria_commit; maria_hton->rollback= maria_rollback; maria_hton->checkpoint_state= maria_checkpoint_state; -#ifdef MARIA_CANNOT_ROLLBACK - maria_hton->commit= 0; -#endif maria_hton->flush_logs= maria_flush_logs; maria_hton->show_status= maria_show_status; maria_hton->prepare_for_backup= maria_prepare_for_backup; maria_hton->end_backup= maria_end_backup; /* TODO: decide if we support Maria being used for log tables */ - maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES; + maria_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | + HTON_NO_ROLLBACK | + HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL); bzero(maria_log_pagecache, sizeof(*maria_log_pagecache)); maria_tmpdir= &mysql_tmpdir_list; /* For REDO */ diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index d7ed43f2ca1..bff7ace8813 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -1,6 +1,7 @@ #ifndef HA_MARIA_INCLUDED #define HA_MARIA_INCLUDED -/* Copyright (C) 2006,2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2006, 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + Copyright (c) 2009, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +22,7 @@ /* class for the maria handler */ -#include +#include "maria_def.h" #include "handler.h" #include "table.h" @@ -38,9 +39,11 @@ C_MODE_END extern TYPELIB maria_recover_typelib; extern ulonglong maria_recover_options; -class ha_maria :public handler +class __attribute__((visibility("default"))) ha_maria :public handler { +public: MARIA_HA *file; +private: ulonglong int_table_flags; MARIA_RECORD_POS remember_pos; char *data_file_name, *index_file_name; @@ -95,12 +98,7 @@ public: ft_handler->please->reinit_search(ft_handler); return 0; } - FT_INFO *ft_init_ext(uint flags, uint inx, String * key) - { - return maria_ft_init_search(flags, file, inx, - (uchar *) key->ptr(), key->length(), - key->charset(), table->record[0]); - } + FT_INFO *ft_init_ext(uint flags, uint inx, String * key); int ft_read(uchar * buf); int index_init(uint idx, bool sorted); int index_end(); @@ -144,14 +142,7 @@ public: bool check_and_repair(THD * thd); bool is_crashed() const; bool is_changed() const; - bool auto_repair(int error) const - { - /* Always auto-repair moved tables (error == HA_ERR_OLD_FILE) */ - return ((MY_TEST(maria_recover_options & HA_RECOVER_ANY) && - error == HA_ERR_CRASHED_ON_USAGE) || - error == HA_ERR_OLD_FILE); - - } + bool auto_repair(int error) const; int optimize(THD * thd, HA_CHECK_OPT * check_opt); int assign_to_keycache(THD * thd, HA_CHECK_OPT * check_opt); int preload_keys(THD * thd, HA_CHECK_OPT * check_opt); diff --git a/storage/maria/ha_s3.cc b/storage/maria/ha_s3.cc index dc267d31405..1aae5a5b81f 100644 --- a/storage/maria/ha_s3.cc +++ b/storage/maria/ha_s3.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 MariaDB Corppration AB +/* Copyright (C) 2019, 2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -770,6 +770,7 @@ static int s3_discover_table_existance(handlerton *hton, const char *db, res= s3_frm_exists(s3_client, &s3_info); s3_deinit(s3_client); + DBUG_PRINT("exit", ("exists: %d", res == 0)); DBUG_RETURN(res == 0); // Return 1 if exists } @@ -1007,9 +1008,24 @@ static int ha_s3_init(void *p) s3_init_library(); if (s3_debug) ms3_debug(); + + struct s3_func s3f_real = + { + ms3_set_option, s3_free, ms3_deinit, s3_unique_file_number, + read_index_header, s3_check_frm_version, s3_info_copy, + set_database_and_table_from_path, s3_open_connection + }; + s3f= s3f_real; + return res ? HA_ERR_INITIALIZATION : 0; } +static int ha_s3_deinit(void*) +{ + bzero(&s3f, sizeof(s3f)); + return 0; +} + static SHOW_VAR status_variables[]= { {"pagecache_blocks_not_flushed", (char*) &s3_pagecache.global_blocks_changed, SHOW_LONG}, @@ -1056,7 +1072,7 @@ maria_declare_plugin(s3) "ALTER TABLE table_name ENGINE=s3", PLUGIN_LICENSE_GPL, ha_s3_init, /* Plugin Init */ - NULL, /* Plugin Deinit */ + ha_s3_deinit, /* Plugin Deinit */ 0x0100, /* 1.0 */ status_variables, /* status variables */ system_variables, /* system variables */ diff --git a/storage/maria/ha_s3.h b/storage/maria/ha_s3.h index 57fdeb03e6b..0777debc8d8 100644 --- a/storage/maria/ha_s3.h +++ b/storage/maria/ha_s3.h @@ -30,52 +30,53 @@ public: ha_s3(handlerton *hton, TABLE_SHARE * table_arg); ~ha_s3() {} - int create(const char *name, TABLE *table_arg, HA_CREATE_INFO *ha_create_info); - int open(const char *name, int mode, uint open_flags); - int write_row(const uchar *buf); - int update_row(const uchar * old_data, const uchar * new_data) + int create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *ha_create_info) final; + int open(const char *name, int mode, uint open_flags) final; + int write_row(const uchar *buf) final; + int update_row(const uchar * old_data, const uchar * new_data) final { DBUG_ENTER("update_row"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int delete_row(const uchar * buf) + int delete_row(const uchar * buf) final { DBUG_ENTER("delete_row"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int check(THD * thd, HA_CHECK_OPT * check_opt) + int check(THD * thd, HA_CHECK_OPT * check_opt) final { DBUG_ENTER("delete_row"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int analyze(THD * thd, HA_CHECK_OPT * check_opt) + int analyze(THD * thd, HA_CHECK_OPT * check_opt) final { DBUG_ENTER("analyze"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int repair(THD * thd, HA_CHECK_OPT * check_opt) + int repair(THD * thd, HA_CHECK_OPT * check_opt) final { DBUG_ENTER("repair"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int preload_keys(THD * thd, HA_CHECK_OPT * check_opt) + int preload_keys(THD * thd, HA_CHECK_OPT * check_opt) final { DBUG_ENTER("preload_keys"); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - int external_lock(THD * thd, int lock_type); + int external_lock(THD * thd, int lock_type) final; /* drop_table() is only used for internal temporary tables, not applicable for s3 */ - void drop_table(const char *name) + void drop_table(const char *name) final { } - int delete_table(const char *name); - int rename_table(const char *from, const char *to); + int delete_table(const char *name) final; + int rename_table(const char *from, const char *to) final; int discover_check_version() override; int rebind(); - S3_INFO *s3_open_args() { return open_args; } - void register_handler(MARIA_HA *file); + S3_INFO *s3_open_args() final { return open_args; } + void register_handler(MARIA_HA *file) final; }; #endif /* HA_S3_INCLUDED */ diff --git a/storage/maria/libmarias3 b/storage/maria/libmarias3 index fe0869eb40b..d172e86c162 160000 --- a/storage/maria/libmarias3 +++ b/storage/maria/libmarias3 @@ -1 +1 @@ -Subproject commit fe0869eb40b13c361454c44cebe6f889b52535cb +Subproject commit d172e86c16224b4e0229ca6f102e662a2315aeff diff --git a/storage/maria/ma_backup.c b/storage/maria/ma_backup.c index 83b521b1cad..1ce6d43a9de 100644 --- a/storage/maria/ma_backup.c +++ b/storage/maria/ma_backup.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 MariaDB corporation +/* Copyright (C) 2018, 2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,8 +20,6 @@ #include "ma_checkpoint.h" #include -static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); - /** @brief Get capabilites for an Aria table @@ -32,6 +30,7 @@ static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); @return X errno */ +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)__attribute__((visibility("default"))) ; int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap) { MARIA_SHARE share; @@ -102,20 +101,13 @@ int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap) err: my_free(disc_cache); DBUG_RETURN(error); -} /* maria_get_capabilities */ +} /* aria_get_capabilities */ +/**************************************************************************** +** store MARIA_BASE_INFO +****************************************************************************/ -/* - This is a copy of my_base_info_read from ma_open(). - The base information will never change (something may be added - last, but not relevant for maria_get_capabilities), so it's safe to - copy it here. - - The copy is done to avoid linking in the fill Aria library just - because maria_backup uses maria_get_capabilities() -*/ - -static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) +uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) { bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE; base->keystart= mi_sizekorr(ptr); ptr+= 8; diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 391ffb4b2e6..bf0f97984a7 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -519,9 +519,10 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) #ifdef EXTRA_DEBUG_BITMAP { char tmp[MAX_BITMAP_INFO_LENGTH]; - _ma_get_bitmap_description(bitmap, bitmap->map, bitmap->page, tmp); + size_t len; + len= _ma_get_bitmap_description(bitmap, bitmap->map, bitmap->page, tmp); (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY, - (uchar*) tmp, strlen(tmp)); + (uchar*) tmp, len); } #endif @@ -957,13 +958,13 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, Return content of bitmap as a printable string */ -void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, - uchar *bitmap_data, - pgcache_page_no_t page, - char *out) +size_t _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, + uchar *bitmap_data, + pgcache_page_no_t page, + char *out) { uchar *pos, *end; - uint count=0, dot_printed= 0, len; + size_t count=0, dot_printed= 0, len; char buff[80], last[80]; page++; @@ -980,7 +981,7 @@ void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, if (memcmp(buff, last, count)) { memcpy(last, buff, count); - len= sprintf(out, "%8lu: ", (ulong) page - count); + len= sprintf(out, "%8lu: ", (ulong) (page - count)); memcpy(out+len, buff, count); out+= len + count + 1; out[-1]= '\n'; @@ -996,10 +997,11 @@ void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, page++; } } - len= sprintf(out, "%8lu: ", (ulong) page - count); + len= sprintf(out, "%8lu: ", (ulong) (page - count)); memcpy(out+len, buff, count); out[len + count]= '\n'; out[len + count + 1]= 0; + return len + count + 1; } @@ -1288,6 +1290,7 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, uint byte= 6 * (last_insert_page / 16); first_pattern= last_insert_page % 16; data= bitmap->map+byte; + first_found= 0; /* Don't update full_head_size */ DBUG_ASSERT(data <= end); } else diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index a03a4656a3e..067dbaa8233 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -3682,6 +3682,15 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info) _ma_bitmap_unlock(share); if (share->now_transactional) { + /* + Write clr to mark end of aborted row insert. + The above delete_head_or_tail() calls will only log redo, not undo. + The undo just before the row insert is stored in row->orig_undo_lsn. + + When applying undo's, we can skip all undo records between current + lsn and row->orig_undo_lsn as logically things are as before the + attempted insert. + */ if (_ma_write_clr(info, info->cur_row.orig_undo_lsn, LOGREC_UNDO_ROW_INSERT, share->calc_checksum != 0, diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 0382eb44006..42546ebdd3f 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -245,10 +245,10 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file, void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, pgcache_page_no_t page); #endif -void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, - uchar *bitmap_data, - pgcache_page_no_t page, - char *out); +size_t _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, + uchar *bitmap_data, + pgcache_page_no_t page, + char *out); uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint page_type, @@ -306,7 +306,7 @@ my_bool write_hook_for_file_id(enum translog_record_type type, my_bool write_hook_for_commit(enum translog_record_type type, TRN *trn, MARIA_HA *tbl_info, LSN *lsn, void *hook_arg); -void _ma_block_get_status(void *param, my_bool concurrent_insert); +my_bool _ma_block_get_status(void *param, my_bool concurrent_insert); my_bool _ma_block_start_trans(void* param); my_bool _ma_block_start_trans_no_versioning(void *param); void _ma_block_update_status(void *param); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 6f202e2a406..6840dcb76cb 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -590,8 +590,8 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) { _ma_check_print_error(param,"Found %s keys of %s",llstr(keys,buff), llstr(share->state.state.records,buff2)); - if (!(param->testflag & T_INFO)) - DBUG_RETURN(-1); + if (!(param->testflag & (T_INFO | T_EXTEND))) + DBUG_RETURN(-1); result= -1; continue; } @@ -1119,8 +1119,8 @@ static uint isam_key_length(MARIA_HA *info, register MARIA_KEYDEF *keyinfo) -static void record_pos_to_txt(MARIA_HA *info, my_off_t recpos, - char *buff) +static char * record_pos_to_txt(MARIA_HA *info, my_off_t recpos, + char *buff) { if (info->s->data_file_type != BLOCK_RECORD) llstr(recpos, buff); @@ -1132,6 +1132,7 @@ static void record_pos_to_txt(MARIA_HA *info, my_off_t recpos, *(end++)= ':'; longlong10_to_str(row, end, 10); } + return buff; } @@ -1195,11 +1196,14 @@ static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend, _ma_search(info, &key, SEARCH_SAME, share->state.key_root[keynr]); if (search_result) { - record_pos_to_txt(info, start_recpos, llbuff); _ma_check_print_error(param, "Record at: %14s " "Can't find key for index: %2d", - llbuff, keynr+1); + record_pos_to_txt(info, start_recpos, + llbuff), + keynr+1); + if (param->testflag & T_VERBOSE) + _ma_print_key(stdout, &key); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) return -1; } @@ -1541,6 +1545,7 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend, my_errno, llstr(block_info.filepos, llbuff)); DBUG_RETURN(1); } + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ if (_ma_pack_rec_unpack(info, &info->bit_buff, record, info->rec_buff, block_info.rec_len)) { @@ -2367,7 +2372,7 @@ static int initialize_variables_for_repair(HA_CHECK *param, /* Repair code relies on share->state.state so we have to update it here */ if (share->lock.update_status) - (*share->lock.update_status)(info); + (*share->lock.update_status)(info->lock.status_param); bzero((char*) sort_info, sizeof(*sort_info)); bzero((char*) sort_param, sizeof(*sort_param)); @@ -2731,8 +2736,11 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, "Duplicate key %2d for record at %10s against " "new record at %10s", info->errkey+1, - llstr(sort_param.current_filepos, llbuff), - llstr(info->dup_key_pos,llbuff2)); + record_pos_to_txt(info, + sort_param.current_filepos, + llbuff), + record_pos_to_txt(info, + info->dup_key_pos, llbuff2)); if (param->testflag & T_VERBOSE) { MARIA_KEY tmp_key; @@ -4895,10 +4903,12 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) { if (param->testflag & T_VERBOSE) { - record_pos_to_txt(info, info->cur_row.lastpos, llbuff); _ma_check_print_info(param, "Found record with wrong checksum at %s", - llbuff); + record_pos_to_txt(info, + info->cur_row.lastpos, + llbuff)); + } continue; } @@ -5318,10 +5328,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) llstr(sort_param->pos,llbuff)); continue; } -#ifdef HAVE_valgrind - bzero(sort_param->rec_buff + block_info.rec_len, - share->base.extra_rec_buff_size); -#endif + sort_param->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ if (_ma_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record, sort_param->rec_buff, block_info.rec_len)) { @@ -5517,6 +5524,7 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a) char llbuff[22],llbuff2[22]; MARIA_SORT_INFO *sort_info=sort_param->sort_info; HA_CHECK *param= sort_info->param; + MARIA_HA *info= sort_info->info; int cmp; if (sort_info->key_block->inited) @@ -5559,11 +5567,14 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a) "Duplicate key %2u for record at %10s against " "record at %10s", sort_param->key + 1, - llstr(sort_info->info->cur_row.lastpos, llbuff), - llstr(get_record_for_key(sort_param->keyinfo, - sort_info->key_block-> - lastkey), - llbuff2)); + record_pos_to_txt(info, + sort_info->info->cur_row.lastpos, + llbuff), + record_pos_to_txt(info, + get_record_for_key(sort_param-> + keyinfo, + sort_info->key_block->lastkey), + llbuff2)); param->testflag|=T_RETRY_WITHOUT_QUICK; if (sort_info->param->testflag & T_VERBOSE) _ma_print_keydata(stdout,sort_param->seg, a, USE_WHOLE_KEY); diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index 4b043f0795e..3af808478e4 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -1218,10 +1218,9 @@ err: MARIA_SHARE *share= distinct_shares[i]; if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME) { + share->in_checkpoint&= ~MARIA_CHECKPOINT_SHOULD_FREE_ME; /* maria_close() left us to free the share */ - mysql_mutex_destroy(&share->intern_lock); - ma_crypt_free(share); - my_free(share); + free_maria_share(share); } else { diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index c1747148b9f..d2bbdd6f60a 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -1,4 +1,5 @@ /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + Copyright (c) 2010, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +30,6 @@ int maria_close(register MARIA_HA *info) { int error=0,flag; - my_bool share_can_be_freed= FALSE; MARIA_SHARE *share= info->s; my_bool internal_table= share->internal_table; DBUG_ENTER("maria_close"); @@ -95,12 +95,16 @@ int maria_close(register MARIA_HA *info) if (flag) { - /* Last close of file; Flush everything */ + /* Last close of file */ - /* Check that we don't have any dangling pointers from the transaction */ - DBUG_ASSERT(share->in_trans == 0); + /* + Check that we don't have any dangling open files + We may still have some open transactions. In this case the share + will be kept around until the transaction has closed + */ DBUG_ASSERT(share->open_list == 0); + /* Flush everything */ if (share->kfile.file >= 0) { my_bool save_global_changed= share->global_changed; @@ -199,8 +203,6 @@ int maria_close(register MARIA_HA *info) /* we cannot my_free() the share, Checkpoint would see a bad pointer */ share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME; } - else - share_can_be_freed= TRUE; if (share->state_history) { @@ -232,23 +234,12 @@ int maria_close(register MARIA_HA *info) if (!internal_table) { mysql_mutex_unlock(&THR_LOCK_maria); - mysql_mutex_unlock(&share->intern_lock); mysql_mutex_unlock(&share->close_lock); } - if (share_can_be_freed) - { - ma_crypt_free(share); - my_free(share->s3_path); - (void) mysql_mutex_destroy(&share->intern_lock); - (void) mysql_mutex_destroy(&share->close_lock); - (void) mysql_cond_destroy(&share->key_del_cond); - my_free(share); - /* - If share cannot be freed, it's because checkpoint has previously - recorded to include this share in the checkpoint and so is soon going to - look at some of its content (share->in_checkpoint/id/last_version). - */ - } + + /* free_maria_share will free share->internal_lock */ + free_maria_share(share); + my_free(info->ftparser_param); if (info->dfile.file >= 0 && ! info->s3) { @@ -263,7 +254,7 @@ int maria_close(register MARIA_HA *info) delete_dynamic(&info->pinned_pages); #ifdef WITH_S3_STORAGE_ENGINE if (info->s3) - ms3_deinit(info->s3); + s3f.deinit(info->s3); #endif /* WITH_S3_STORAGE_ENGINE */ my_free(info); @@ -274,3 +265,35 @@ int maria_close(register MARIA_HA *info) } DBUG_RETURN(0); } /* maria_close */ + + +/** + Free Aria table share + + Note that share will not be freed a long as there are active checkpoints + or transactions pointing at the shared object +*/ + +void free_maria_share(MARIA_SHARE *share) +{ + if (!share->internal_table) + mysql_mutex_assert_owner(&share->intern_lock); + + if (!share->reopen && !share->in_trans && + !(share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)) + { + /* No one can access this share anymore, time to delete it ! */ + if (!share->internal_table) + mysql_mutex_unlock(&share->intern_lock); + ma_crypt_free(share); + my_free(share->s3_path); + (void) mysql_mutex_destroy(&share->intern_lock); + (void) mysql_mutex_destroy(&share->close_lock); + (void) mysql_cond_destroy(&share->key_del_cond); + my_free(share); + return; + } + if (!share->internal_table) + mysql_mutex_unlock(&share->intern_lock); + return; +} diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 0f6b8b7200b..65b8b0922aa 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -721,7 +721,7 @@ my_bool print_aria_log_control() { recovery_fails= (buffer + new_cf_create_time_size + CF_RECOV_FAIL_OFFSET)[0]; - printf("recovery_failuers: %u\n", recovery_fails); + printf("recovery_failures: %u\n", recovery_fails); } DBUG_RETURN(0); diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h index 232f13f734e..40428f665f4 100644 --- a/storage/maria/ma_control_file.h +++ b/storage/maria/ma_control_file.h @@ -21,6 +21,8 @@ #ifndef _ma_control_file_h #define _ma_control_file_h +C_MODE_START + #define CONTROL_FILE_BASE_NAME "aria_log_control" /* Major version for control file. Should only be changed when doing @@ -63,7 +65,7 @@ typedef enum enum_control_file_error { CONTROL_FILE_UNKNOWN_ERROR /* any other error */ } CONTROL_FILE_ERROR; -C_MODE_START + CONTROL_FILE_ERROR ma_control_file_open(my_bool create_if_missing, my_bool print_error, my_bool wait_for_lock); diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 89e7e7d1551..0ec0e58f8a8 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -1909,7 +1909,7 @@ static void translog_put_sector_protection(uchar *page, static uint32 translog_crc(uchar *area, uint length) { DBUG_ENTER("translog_crc"); - DBUG_RETURN(crc32(0L, (unsigned char*) area, length)); + DBUG_RETURN(my_checksum(0L, area, length)); } diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 4cda524715b..e7d6f97d57c 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -1,5 +1,5 @@ /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - Copyright (c) 2009, 2019, MariaDB Corporation. + Copyright (c) 2009, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,7 +39,6 @@ static my_bool maria_scan_init_dummy(MARIA_HA *info); static void maria_scan_end_dummy(MARIA_HA *info); static my_bool maria_once_init_dummy(MARIA_SHARE *, File); static my_bool maria_once_end_dummy(MARIA_SHARE *); -static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \ @@ -90,7 +89,6 @@ MARIA_HA *_ma_test_if_reopen(const char *filename) 0 Error */ - static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, File data_file, uint internal_table, @@ -152,7 +150,8 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, info.last_loop= share->state.update_count; #endif info.errkey= -1; - info.page_changed=1; + info.page_changed= 1; + info.autocommit= 1; info.keyread_buff= info.buff + share->base.max_key_block_length; info.lock_type= F_UNLCK; @@ -318,7 +317,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, else { strmake(name_buff, name, sizeof(name_buff)-1); /* test_if_reopen() */ - if (!(s3_client= s3_open_connection(s3))) + if (!(s3_client= s3f.open_connection(s3))) { internal_table= 1; /* Avoid unlock on error */ goto err; @@ -371,7 +370,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, else { errpos= 1; - if (set_database_and_table_from_path(s3, name_buff)) + if (s3f.set_database_and_table_from_path(s3, name_buff)) { my_printf_error(HA_ERR_NO_SUCH_TABLE, "Can't find database and path from %s", MYF(0), @@ -379,17 +378,17 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, my_errno= HA_ERR_NO_SUCH_TABLE; goto err; } - if (!(share_s3= share->s3_path= s3_info_copy(s3))) + if (!(share_s3= share->s3_path= s3f.info_copy(s3))) goto err; /* EiOM */ /* Check if table has changed in S3 */ - if (s3_check_frm_version(s3_client, share_s3) == 1) + if (s3f.check_frm_version(s3_client, share_s3) == 1) { my_errno= HA_ERR_TABLE_DEF_CHANGED; goto err; } - if (read_index_header(s3_client, share_s3, &index_header)) + if (s3f.read_index_header(s3_client, share_s3, &index_header)) goto err; if (index_header.length < head_length) { @@ -398,7 +397,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, } memcpy(share->state.header.file_version, index_header.str, head_length); - kfile= s3_unique_file_number(); + kfile= s3f.unique_file_number(); } #endif /* WITH_S3_STORAGE_ENGINE */ @@ -972,7 +971,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, } #ifdef WITH_S3_STORAGE_ENGINE else - data_file= info.dfile.file= s3_unique_file_number(); + data_file= info.dfile.file= s3f.unique_file_number(); #endif /* WITH_S3_STORAGE_ENGINE */ } errpos= 5; @@ -1149,7 +1148,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, if (s3_client) { size_t block_size= share->base.s3_block_size; - ms3_set_option(s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size); + s3f.set_option(s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size); } #endif /* WITH_S3_STORAGE_ENGINE */ } @@ -1162,7 +1161,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, #ifdef WITH_S3_STORAGE_ENGINE if (index_header.alloc_ptr) - s3_free(&index_header); + s3f.free(&index_header); #endif /* WITH_S3_STORAGE_ENGINE */ if (!(m_info= maria_clone_internal(share, mode, data_file, @@ -1224,9 +1223,9 @@ err: } #ifdef WITH_S3_STORAGE_ENGINE if (s3_client) - ms3_deinit(s3_client); + s3f.deinit(s3_client); if (index_header.alloc_ptr) - s3_free(&index_header); + s3f.free(&index_header); #endif /* WITH_S3_STORAGE_ENGINE */ if (!internal_table) mysql_mutex_unlock(&THR_LOCK_maria); @@ -1725,7 +1724,7 @@ uint _ma_state_info_read_dsk(File file __attribute__((unused)), /**************************************************************************** -** store and read of MARIA_BASE_INFO +** store MARIA_BASE_INFO ****************************************************************************/ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) @@ -1775,49 +1774,6 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) } -static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) -{ - bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE; - base->keystart= mi_sizekorr(ptr); ptr+= 8; - base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8; - base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8; - base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8; - base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8; - base->mean_row_length= mi_uint4korr(ptr); ptr+= 4; - base->reclength= mi_uint4korr(ptr); ptr+= 4; - base->pack_reclength= mi_uint4korr(ptr); ptr+= 4; - base->min_pack_length= mi_uint4korr(ptr); ptr+= 4; - base->max_pack_length= mi_uint4korr(ptr); ptr+= 4; - base->min_block_length= mi_uint4korr(ptr); ptr+= 4; - base->fields= mi_uint2korr(ptr); ptr+= 2; - base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2; - base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2; - base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2; - base->pack_fields= mi_uint2korr(ptr); ptr+= 2; - base->extra_options= mi_uint2korr(ptr); ptr+= 2; - base->null_bytes= mi_uint2korr(ptr); ptr+= 2; - base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2; - base->field_offsets= mi_uint2korr(ptr); ptr+= 2; - base->language= mi_uint2korr(ptr); ptr+= 2; - base->block_size= mi_uint2korr(ptr); ptr+= 2; - - base->rec_reflength= *ptr++; - base->key_reflength= *ptr++; - base->keys= *ptr++; - base->auto_key= *ptr++; - base->born_transactional= *ptr++; - base->compression_algorithm= *ptr++; - base->pack_bytes= mi_uint2korr(ptr); ptr+= 2; - base->blobs= mi_uint2korr(ptr); ptr+= 2; - base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2; - base->max_key_length= mi_uint2korr(ptr); ptr+= 2; - base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2; - base->extra_alloc_procent= *ptr++; - base->s3_block_size= mi_uint3korr(ptr); ptr+= 3; - ptr+= 13; - return ptr; -} - /*-------------------------------------------------------------------------- maria_keydef ---------------------------------------------------------------------------*/ diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index dd4ac28bbac..5eec3faa88f 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -757,6 +757,8 @@ int _ma_read_pack_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos) block_info.rec_len - block_info.offset, MYF(MY_NABP))) goto panic; info->update|= HA_STATE_AKTIV; + + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ DBUG_RETURN(_ma_pack_rec_unpack(info,&info->bit_buff, buf, info->rec_buff, block_info.rec_len)); panic: @@ -1397,8 +1399,9 @@ int _ma_read_rnd_pack_record(MARIA_HA *info, info->cur_row.nextpos= block_info.filepos+block_info.rec_len; info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - DBUG_RETURN (_ma_pack_rec_unpack(info, &info->bit_buff, buf, - info->rec_buff, block_info.rec_len)); + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ + DBUG_RETURN(_ma_pack_rec_unpack(info, &info->bit_buff, buf, + info->rec_buff, block_info.rec_len)); err: DBUG_RETURN(my_errno); } diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index cf1414f991a..0a55018db0f 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -130,8 +130,7 @@ my_bool my_disable_flush_pagecache_blocks= 0; #define COND_FOR_REQUESTED 0 /* queue of thread waiting for read operation */ #define COND_FOR_SAVED 1 /* queue of thread waiting for flush */ #define COND_FOR_WRLOCK 2 /* queue of write lock */ -#define COND_FOR_BIG_BLOCK 3 /* queue of waiting fo big block read */ -#define COND_SIZE 4 /* number of COND_* queues */ +#define COND_SIZE 3 /* number of COND_* queues */ typedef mysql_cond_t KEYCACHE_CONDVAR; @@ -178,7 +177,9 @@ struct st_pagecache_hash_link #define PCBLOCK_CHANGED 32 /* block buffer contains a dirty page */ #define PCBLOCK_DIRECT_W 64 /* possible direct write to the block */ #define PCBLOCK_DEL_WRITE 128 /* should be written on delete */ -#define PCBLOCK_BIG_READ 256 /* the first block of the big read in progress */ +#define PCBLOCK_BIG_READ 256 /* the first block of the big read in progress + or not first block which other thread wait + to be read in big read operation */ /* page status, returned by find_block */ #define PAGE_READ 0 @@ -1373,8 +1374,8 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, } } while (thread != last_thread); - DBUG_PRINT("XXX", ("hash_link (link block): %p, hash_link: %p -> %p", - hash_link, hash_link->block, block)); + DBUG_PRINT("hash", ("hash_link (link block): %p, hash_link: %p -> %p", + hash_link, hash_link->block, block)); hash_link->block= block; /* Ensure that no other thread tries to use this block */ block->status|= PCBLOCK_REASSIGNED; @@ -1662,8 +1663,8 @@ static inline void link_hash(PAGECACHE_HASH_LINK **start, static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link) { DBUG_ENTER("unlink_hash"); - DBUG_PRINT("enter", ("hash_link: %p fd: %u pos: %lu requests: %u", - hash_link, (uint) hash_link->file.file, + DBUG_PRINT("enter", ("hash_link: %p block: %p fd: %u pos: %lu requests: %u", + hash_link, hash_link->block, (uint) hash_link->file.file, (ulong) hash_link->pageno, hash_link->requests)); DBUG_ASSERT(hash_link->requests == 0); @@ -1672,8 +1673,6 @@ static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link) if ((*hash_link->prev= hash_link->next)) hash_link->next->prev= hash_link->prev; - DBUG_PRINT("XXX", ("hash_link (unlink): %p, hash_link: %p -> NULL", - hash_link, hash_link->block)); hash_link->block= NULL; if (pagecache->waiting_for_hash_link.last_thread) { @@ -2048,11 +2047,11 @@ restart: /* This is a request for a new page or for a page not to be removed */ if (! block) { - DBUG_PRINT("XXX", ("request for a new page")); + DBUG_PRINT("info", ("request for a new page")); /* No block is assigned for the page yet */ if (pagecache->blocks_unused) { - DBUG_PRINT("XXX", ("there is never used blocks")); + DBUG_PRINT("info", ("there is never used blocks")); if (pagecache->free_block_list) { /* There is a block in the free list. */ @@ -2086,11 +2085,13 @@ restart: block->last_hit_time= 0; block->rec_lsn= LSN_MAX; link_to_file_list(pagecache, block, file, 0); - DBUG_PRINT("XXX", ("block (no block assigned): %p, hash_link: %p -> %p", - block, block->hash_link, hash_link)); + DBUG_PRINT("hash", + ("block (no block assigned): %p hash_link: %p -> %p", + block, block->hash_link, hash_link)); block->hash_link= hash_link; - DBUG_PRINT("XXX", ("hash_link (no block assignment): %p, hash_link: %p -> %p", - hash_link, hash_link->block, block)); + DBUG_PRINT("hash", + ("hash_link (no block assignment): %p hash_link: %p -> %p", + hash_link, hash_link->block, block)); hash_link->block= block; page_status= PAGE_TO_BE_READ; DBUG_PRINT("info", ("page to be read set for page %p (%u)", @@ -2101,7 +2102,7 @@ restart: } else { - DBUG_PRINT("XXX", ("there is NOT never used blocks")); + DBUG_PRINT("info", ("there is NOT never used blocks")); /* There are no never used blocks, use a block from the LRU chain */ /* @@ -2114,7 +2115,7 @@ restart: if (! pagecache->used_last) { struct st_my_thread_var *thread; - DBUG_PRINT("XXX", ("there is NOT UNUSED blocks")); + DBUG_PRINT("info", ("there is NOT UNUSED blocks")); /* Wait until a new block is added to the LRU chain; several threads might wait here for the same page, @@ -2153,7 +2154,7 @@ restart: } else { - DBUG_PRINT("XXX", ("take a block from LRU")); + DBUG_PRINT("info", ("take a block from LRU")); /* Take the first block from the LRU chain unlinking it from the chain @@ -2175,8 +2176,8 @@ restart: } if (reg_req) reg_requests(pagecache, block, 1); - DBUG_PRINT("XXX", ("hash_link (LRU): %p, hash_link: %p -> %p", - hash_link, hash_link->block, block)); + DBUG_PRINT("hash", ("hash_link (LRU): %p, hash_link: %p -> %p", + hash_link, hash_link->block, block)); hash_link->block= block; DBUG_ASSERT(block->requests == 1); } @@ -2247,8 +2248,8 @@ restart: link_to_file_list(pagecache, block, file, (my_bool)(block->hash_link ? 1 : 0)); - DBUG_PRINT("XXX", ("block (LRU): %p, hash_link: %p -> %p", - block, block->hash_link, hash_link)); + DBUG_PRINT("hash", ("block (LRU): %p, hash_link: %p -> %p", + block, block->hash_link, hash_link)); block->hash_link= hash_link; PCBLOCK_INFO(block); block->hits_left= init_hits_left; @@ -2770,7 +2771,7 @@ retry: */ #ifdef WITH_S3_STORAGE_ENGINE -static my_bool read_big_block(PAGECACHE *pagecache, +static void read_big_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) { int page_st; @@ -2809,25 +2810,26 @@ static my_bool read_big_block(PAGECACHE *pagecache, if (block_to_read->status & PCBLOCK_ERROR) { /* We get first block with an error so all operation failed */ - block->status|= PCBLOCK_ERROR; - block->error= block_to_read->error; - DBUG_RETURN(FALSE); // no retry + goto error; } - // only primary request here, PAGE_WAIT_TO_BE_READ is impossible - DBUG_ASSERT(page_st != PAGE_WAIT_TO_BE_READ); if (block_to_read->status & PCBLOCK_BIG_READ) { + /* + Other thread is reading the big block so we will wait when it will + have read our block for us + */ struct st_my_thread_var *thread; + DBUG_ASSERT(page_st == PAGE_WAIT_TO_BE_READ); DBUG_ASSERT(page_st != PAGE_TO_BE_READ); + block->status|= PCBLOCK_BIG_READ; // will be read by other thread /* Block read failed because somebody else is reading the first block (and all other blocks part of this one). Wait until block is available. */ - unreg_request(pagecache, block, 1); thread= my_thread_var; /* Put the request into a queue and wait until it can be processed */ - wqueue_add_to_queue(&block->wqueue[COND_FOR_BIG_BLOCK], thread); + wqueue_add_to_queue(&block_to_read->wqueue[COND_FOR_REQUESTED], thread); do { DBUG_PRINT("wait", @@ -2837,7 +2839,21 @@ static my_bool read_big_block(PAGECACHE *pagecache, &pagecache->cache_lock); } while (thread->next); - DBUG_RETURN(TRUE); + // page should be read by other thread + DBUG_ASSERT(block->status & PCBLOCK_READ || + block->status & PCBLOCK_ERROR); + DBUG_ASSERT(block->status & PCBLOCK_BIG_READ); + block->status&= ~PCBLOCK_BIG_READ; + // all is read => lets finish nice + DBUG_ASSERT(block_to_read != block); + remove_reader(block_to_read); + unreg_request(pagecache, block_to_read, 1); + DBUG_VOID_RETURN; + } + else + { + // only primary request here, PAGE_WAIT_TO_BE_READ is impossible + DBUG_ASSERT(page_st != PAGE_WAIT_TO_BE_READ); } } else @@ -2863,18 +2879,9 @@ static my_bool read_big_block(PAGECACHE *pagecache, { pagecache_pthread_mutex_lock(&pagecache->cache_lock); block_to_read->status|= PCBLOCK_ERROR; - block->status|= PCBLOCK_ERROR; - block_to_read->error= block->error= (int16) my_errno; + block_to_read->error= (int16) my_errno; pagecache->big_block_free(&data); - if (block_to_read != block) - { - remove_reader(block_to_read); - unreg_request(pagecache, block_to_read, 1); - } - /* Signal that all pending requests for this page now can be processed */ - if (block->wqueue[COND_FOR_REQUESTED].last_thread) - wqueue_release_queue(&block->wqueue[COND_FOR_REQUESTED]); - DBUG_RETURN(FALSE); // no retry + goto error; } /* @@ -2892,7 +2899,12 @@ static my_bool read_big_block(PAGECACHE *pagecache, block_to_read->status|= PCBLOCK_READ; } else + { DBUG_ASSERT(block_to_read->status & PCBLOCK_READ); + } + /* Signal that all pending requests for this page now can be processed */ + if (block_to_read->wqueue[COND_FOR_REQUESTED].last_thread) + wqueue_release_queue(&block_to_read->wqueue[COND_FOR_REQUESTED]); /* Copy the rest of the pages */ for (offset= pagecache->block_size, page= page_to_read + 1; @@ -2914,18 +2926,27 @@ static my_bool read_big_block(PAGECACHE *pagecache, TRUE /*register*/, TRUE /*fast*/, &page_st); if (!bl) { - // we run out of easy avaliable pages in the cache - break; + /* + We can not get this page easy. + Maybe we will be lucky with other pages, + also among other pages can be page which waited by other thread + */ + continue; } DBUG_ASSERT(bl == bl->hash_link->block); if ((bl->status & PCBLOCK_ERROR) == 0 && - page_st == PAGE_TO_BE_READ) + (page_st == PAGE_TO_BE_READ || // page should be read + (page_st == PAGE_WAIT_TO_BE_READ && + (bl->status & PCBLOCK_BIG_READ)))) // or page waited by other thread { memcpy(bl->buffer, data.str + offset, pagecache->block_size); bl->status|= PCBLOCK_READ; } remove_reader(bl); unreg_request(pagecache, bl, 1); + /* Signal that all pending requests for this page now can be processed */ + if (bl->wqueue[COND_FOR_REQUESTED].last_thread) + wqueue_release_queue(&bl->wqueue[COND_FOR_REQUESTED]); } } if (page < our_page) @@ -2940,17 +2961,66 @@ static my_bool read_big_block(PAGECACHE *pagecache, pagecache->big_block_free(&data); block_to_read->status&= ~PCBLOCK_BIG_READ; + +end: if (block_to_read != block) { remove_reader(block_to_read); unreg_request(pagecache, block_to_read, 1); } - if (block->wqueue[COND_FOR_BIG_BLOCK].last_thread) - wqueue_release_queue(&block->wqueue[COND_FOR_BIG_BLOCK]); + /* Signal that all pending requests for this page now can be processed */ if (block->wqueue[COND_FOR_REQUESTED].last_thread) wqueue_release_queue(&block->wqueue[COND_FOR_REQUESTED]); + DBUG_VOID_RETURN; - DBUG_RETURN(FALSE); +error: + /* + Read failed. Mark all readers waiting for the a block covered by the + big block that the read failed + */ + for (offset= pagecache->block_size, page= page_to_read + 1; + offset < data.length; + offset+= pagecache->block_size, page++) + { + DBUG_ASSERT(offset + pagecache->block_size <= data.length); + if (page == our_page) + { + DBUG_ASSERT(!(block->status & PCBLOCK_READ)); + block->status|= PCBLOCK_ERROR; + block->error= (int16) my_errno; + } + else + { + PAGECACHE_BLOCK_LINK *bl; + bl= find_block(pagecache, &block->hash_link->file, page, 1, + FALSE, TRUE /* copy under protection (?)*/, + TRUE /*register*/, TRUE /*fast*/, &page_st); + if (!bl) + { + /* + We can not get this page easy. + Maybe we will be lucky with other pages, + also among other pages can be page which waited by other thread + */ + continue; + } + DBUG_ASSERT(bl == bl->hash_link->block); + if ((bl->status & PCBLOCK_ERROR) == 0 && + (page_st == PAGE_TO_BE_READ || // page should be read + (page_st == PAGE_WAIT_TO_BE_READ && + (bl->status & PCBLOCK_BIG_READ)))) // or page waited by other thread + { + bl->status|= PCBLOCK_ERROR; + bl->error= (int16) my_errno; + } + remove_reader(bl); + unreg_request(pagecache, bl, 1); + /* Signal that all pending requests for this page now can be processed */ + if (bl->wqueue[COND_FOR_REQUESTED].last_thread) + wqueue_release_queue(&bl->wqueue[COND_FOR_REQUESTED]); + } + } + goto end; } #endif /* WITH_S3_STORAGE_ENGINE */ @@ -3706,13 +3776,8 @@ restart: /* It is big read and this thread should read */ DBUG_ASSERT(page_st == PAGE_TO_BE_READ); - if (read_big_block(pagecache, block)) - { - /* block is unregistered in read_big_block */ - pagecache_pthread_mutex_unlock(&pagecache->cache_lock); - DBUG_PRINT("restart", ("big block fail, restarting...")); - goto restart; - } + read_big_block(pagecache, block); + if (!((new_pin == PAGECACHE_PIN_LEFT_UNPINNED) || (new_pin == PAGECACHE_PIN))) { @@ -4176,6 +4241,7 @@ restart: unreg_request(pagecache, block, 1); dec_counter_for_resize_op(pagecache); pagecache_pthread_mutex_unlock(&pagecache->cache_lock); + dec_counter_for_resize_op(pagecache); DBUG_PRINT("info", ("restarting...")); goto restart; } @@ -4602,8 +4668,8 @@ static my_bool free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, block->type= PAGECACHE_EMPTY_PAGE; #endif block->rec_lsn= LSN_MAX; - DBUG_PRINT("XXX", ("block (Free): %p, hash_link: %p -> NULL", - block, block->hash_link)); + DBUG_PRINT("hash", ("block (Free): %p, hash_link: %p -> NULL", + block, block->hash_link)); block->hash_link= NULL; if (block->temperature == PCBLOCK_WARM) pagecache->warm_blocks--; diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 1096444aa33..dbd86fc0def 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -1,4 +1,5 @@ /* Copyright (C) 2006 MySQL AB + Copyright (c) 2011, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -238,7 +239,7 @@ extern PAGECACHE dflt_pagecache_var, *dflt_pagecache; extern size_t init_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, uint block_size, uint changed_blocks_hash_size, - myf my_read_flags); + myf my_read_flags)__attribute__((visibility("default"))) ; extern size_t resize_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, uint changed_blocks_hash_size); @@ -318,7 +319,7 @@ extern int flush_pagecache_blocks_with_filter(PAGECACHE *keycache, PAGECACHE_FILE *file, enum flush_type type, PAGECACHE_FLUSH_FILTER filter, - void *filter_arg); + void *filter_arg)__attribute__((visibility("default"))) ; extern my_bool pagecache_delete(PAGECACHE *pagecache, PAGECACHE_FILE *file, pgcache_page_no_t pageno, @@ -334,7 +335,7 @@ extern my_bool pagecache_delete_pages(PAGECACHE *pagecache, uint page_count, enum pagecache_page_lock lock, my_bool flush); -extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup); +extern void end_pagecache(PAGECACHE *keycache, my_bool cleanup)__attribute__((visibility("default"))) ; extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, LEX_STRING *str, LSN *min_lsn); @@ -354,8 +355,6 @@ extern my_bool multi_pagecache_set(const uchar *key, uint length, PAGECACHE *pagecache); extern void multi_pagecache_change(PAGECACHE *old_data, PAGECACHE *new_data); -extern int reset_pagecache_counters(const char *name, - PAGECACHE *pagecache); #ifndef DBUG_OFF void pagecache_file_no_dirty_page(PAGECACHE *pagecache, PAGECACHE_FILE *file); #else diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c index f682397d996..4e1389b1163 100644 --- a/storage/maria/ma_pagecrc.c +++ b/storage/maria/ma_pagecrc.c @@ -28,7 +28,7 @@ static uint32 maria_page_crc(uint32 start, uchar *data, uint length) { - uint32 crc= crc32(start, data, length); + uint32 crc= my_checksum(start, data, length); /* we need this assert to get following comparison working */ compile_time_assert(MARIA_NO_CRC_BITMAP_PAGE == diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index b47364749d3..aa5c598c9c9 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -54,6 +54,7 @@ static my_bool skip_DDLs; /**< if REDO phase should skip DDL records */ static my_bool checkpoint_useful; static my_bool in_redo_phase; static my_bool trns_created; +static int aria_undo_aborted= 0; static ulong skipped_undo_phase; static ulonglong now; /**< for tracking execution time of phases */ static void (*save_error_handler_hook)(uint, const char *,myf); @@ -115,7 +116,7 @@ prototype_undo_exec_hook(UNDO_BULK_INSERT); static int run_redo_phase(LSN lsn, LSN end_lsn, enum maria_apply_log_way apply); static uint end_of_redo_phase(my_bool prepare_for_undo_phase); -static int run_undo_phase(uint uncommitted); +static int run_undo_phase(LSN end_undo_lsn, uint uncommitted); static void display_record_position(const LOG_DESC *log_desc, const TRANSLOG_HEADER_BUFFER *rec, uint number); @@ -236,8 +237,8 @@ int maria_recovery_from_log(void) #endif tprint(trace_file, "TRACE of the last Aria recovery from mysqld\n"); DBUG_ASSERT(maria_pagecache->inited); - res= maria_apply_log(LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, MARIA_LOG_APPLY, - trace_file, TRUE, TRUE, TRUE, &warnings_count); + res= maria_apply_log(LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, MARIA_LOG_APPLY, + trace_file, TRUE, TRUE, &warnings_count); if (!res) { if (warnings_count == 0 && recovery_found_crashed_tables == 0) @@ -258,7 +259,9 @@ int maria_recovery_from_log(void) @param from_lsn LSN from which log reading/applying should start; LSN_IMPOSSIBLE means "use last checkpoint" - @param end_lsn Apply until this. LSN_IMPOSSIBLE means until end. + @param end_redo_lsn Apply until this. LSN_IMPOSSIBLE means until end. + @param end_und_lsn Apply all undo >= end_undo_lsn. Set to LSN_MAX if + no undo's should be applied. @param apply how log records should be applied or not @param trace_file trace file where progress/debug messages will go @param skip_DDLs_arg Should DDL records (CREATE/RENAME/DROP/REPAIR) @@ -275,10 +278,10 @@ int maria_recovery_from_log(void) @retval !=0 Error */ -int maria_apply_log(LSN from_lsn, LSN end_lsn, +int maria_apply_log(LSN from_lsn, LSN end_redo_lsn, LSN end_undo_lsn, enum maria_apply_log_way apply, FILE *trace_file, - my_bool should_run_undo_phase, my_bool skip_DDLs_arg, + my_bool skip_DDLs_arg, my_bool take_checkpoints, uint *warnings_count) { int error= 0; @@ -287,14 +290,13 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, my_bool abort_message_printed= 0; DBUG_ENTER("maria_apply_log"); - DBUG_ASSERT(apply == MARIA_LOG_APPLY || !should_run_undo_phase); + DBUG_ASSERT(apply == MARIA_LOG_APPLY || end_undo_lsn == LSN_MAX); DBUG_ASSERT(!maria_multi_threaded); recovery_warnings= recovery_found_crashed_tables= 0; skipped_lsn_err_count= 0; maria_recovery_changed_data= 0; /* checkpoints can happen only if TRNs have been built */ - DBUG_ASSERT(should_run_undo_phase || !take_checkpoints); - DBUG_ASSERT(end_lsn == LSN_IMPOSSIBLE || should_run_undo_phase == 0); + DBUG_ASSERT(end_undo_lsn != LSN_MAX || !take_checkpoints); all_active_trans= (struct st_trn_for_recovery *) my_malloc(PSI_INSTRUMENT_ME, (SHORT_TRID_MAX + 1) * sizeof(struct st_trn_for_recovery), MYF(MY_ZEROFILL)); @@ -313,6 +315,7 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, recovery_message_printed= REC_MSG_NONE; checkpoint_useful= trns_created= FALSE; + aria_undo_aborted= 0; tracef= trace_file; #ifdef INSTANT_FLUSH_OF_MESSAGES /* enable this for instant flush of messages to trace file */ @@ -347,7 +350,7 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, now= microsecond_interval_timer(); in_redo_phase= TRUE; - if (run_redo_phase(from_lsn, end_lsn, apply)) + if (run_redo_phase(from_lsn, end_redo_lsn, apply)) { ma_message_no_user(0, "Redo phase failed"); trnman_destroy(); @@ -355,7 +358,8 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, } trnman_destroy(); - if (end_lsn != LSN_IMPOSSIBLE) + if (end_redo_lsn != LSN_IMPOSSIBLE && + (end_undo_lsn == LSN_MAX || end_undo_lsn == LSN_IMPOSSIBLE)) { abort_message_printed= 1; if (!trace_file) @@ -367,7 +371,7 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, } if ((uncommitted_trans= - end_of_redo_phase(should_run_undo_phase)) == (uint)-1) + end_of_redo_phase(end_undo_lsn != LSN_MAX)) == (uint)-1) { ma_message_no_user(0, "End of redo phase failed"); goto err; @@ -417,13 +421,19 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, } #endif - if (should_run_undo_phase) + if (end_undo_lsn != LSN_MAX) { - if (run_undo_phase(uncommitted_trans)) + if (run_undo_phase(end_undo_lsn, uncommitted_trans)) { ma_message_no_user(0, "Undo phase failed"); goto err; } + if (aria_undo_aborted) + ma_message_no_user(0, "Undo phase aborted in the middle on user request"); + else if (end_redo_lsn != LSN_IMPOSSIBLE) + my_message(HA_ERR_INITIALIZATION, + "Maria recovery aborted as end_lsn followed by end_undo was " + "reached", MYF(0)); } else if (uncommitted_trans > 0) { @@ -493,7 +503,8 @@ err: err2: if (trns_created) delete_all_transactions(); - error= 1; + if (!abort_message_printed) + error= 1; if (close_all_tables()) { ma_message_no_user(0, "closing of tables failed"); @@ -521,7 +532,7 @@ end: fprintf(stderr, "\n"); fflush(stderr); } - if (!error) + if (!error && !abort_message_printed) { ma_message_no_user(ME_NOTE, "recovery done"); maria_recovery_changed_data= 1; @@ -540,7 +551,7 @@ end: { my_message(HA_ERR_INITIALIZATION, "Aria recovery failed. Please run aria_chk -r on all Aria " - "tables and delete all aria_log.######## files", MYF(0)); + "tables (*.MAI) and delete all aria_log.######## files", MYF(0)); } procent_printed= 0; /* @@ -842,7 +853,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) if (cmp_translog_addr(share->state.create_rename_lsn, rec->lsn) >= 0) { tprint(tracef, "Table '%s' has create_rename_lsn " LSN_FMT " more " - "recent than record, ignoring creation", + "recent than record, ignoring creation\n", name, LSN_IN_PARTS(share->state.create_rename_lsn)); error= 0; goto end; @@ -956,6 +967,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) char *old_name, *new_name; int error= 1; MARIA_HA *info= NULL; + my_bool from_table_is_crashed= 0; DBUG_ENTER("exec_REDO_LOGREC_REDO_RENAME_TABLE"); if (skip_DDLs) @@ -974,7 +986,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) } old_name= (char *)log_record_buffer.str; new_name= old_name + strlen(old_name) + 1; - tprint(tracef, "Table '%s' to rename to '%s'; old-name table ", old_name, + tprint(tracef, "Table '%s' to be renamed to '%s'; old-name table ", old_name, new_name); /* Here is why we skip CREATE/DROP/RENAME when doing a recovery from @@ -1010,14 +1022,14 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) MARIA_SHARE *share= info->s; if (!share->base.born_transactional) { - tprint(tracef, ", is not transactional, ignoring renaming\n"); + tprint(tracef, "is not transactional, ignoring renaming"); ALERT_USER(); error= 0; goto end; } if (cmp_translog_addr(share->state.create_rename_lsn, rec->lsn) >= 0) { - tprint(tracef, ", has create_rename_lsn " LSN_FMT " more recent than" + tprint(tracef, "has create_rename_lsn " LSN_FMT " more recent than" " record, ignoring renaming", LSN_IN_PARTS(share->state.create_rename_lsn)); error= 0; @@ -1025,15 +1037,15 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) } if (maria_is_crashed(info)) { - tprint(tracef, ", is crashed, can't rename it"); - ALERT_USER(); - goto end; + tprint(tracef, "is crashed, can't be used for rename ; new-name table "); + from_table_is_crashed= 1; } if (close_one_table(info->s->open_file_name.str, rec->lsn) || maria_close(info)) goto end; info= NULL; - tprint(tracef, ", is ok for renaming; new-name table "); + if (!from_table_is_crashed) + tprint(tracef, "is ok for renaming; new-name table "); } else /* one or two files absent, or header corrupted... */ { @@ -1060,19 +1072,19 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) /* We should not have open instances on this table. */ if (share->reopen != 1) { - tprint(tracef, ", is already open (reopen=%u)\n", share->reopen); + tprint(tracef, "is already open (reopen=%u)", share->reopen); ALERT_USER(); goto end; } if (!share->base.born_transactional) { - tprint(tracef, ", is not transactional, ignoring renaming\n"); + tprint(tracef, "is not transactional, ignoring renaming"); ALERT_USER(); goto drop; } if (cmp_translog_addr(share->state.create_rename_lsn, rec->lsn) >= 0) { - tprint(tracef, ", has create_rename_lsn " LSN_FMT " more recent than" + tprint(tracef, "has create_rename_lsn " LSN_FMT " more recent than" " record, ignoring renaming", LSN_IN_PARTS(share->state.create_rename_lsn)); /* @@ -1090,7 +1102,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) } if (maria_is_crashed(info)) { - tprint(tracef, ", is crashed, can't rename it"); + tprint(tracef, "is crashed, can't rename it"); ALERT_USER(); goto end; } @@ -1098,11 +1110,19 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) goto end; info= NULL; /* abnormal situation */ - tprint(tracef, ", exists but is older than record, can't rename it"); + tprint(tracef, "exists but is older than record, can't rename it"); goto end; } else /* one or two files absent, or header corrupted... */ - tprint(tracef, ", can't be opened, probably does not exist"); + tprint(tracef, "can't be opened, probably does not exist"); + + if (from_table_is_crashed) + { + eprint(tracef, "Aborting rename as old table was crashed"); + ALERT_USER(); + goto end; + } + tprint(tracef, ", renaming '%s'", old_name); if (maria_rename(old_name, new_name)) { @@ -1168,7 +1188,7 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE) if (!info) { /* no such table, don't need to warn */ - return 0; + DBUG_RETURN(0); } if (maria_is_crashed(info)) @@ -1907,7 +1927,7 @@ prototype_redo_exec_hook(UNDO_ROW_INSERT) if (cmp_translog_addr(rec->lsn, share->state.is_of_horizon) >= 0) { tprint(tracef, " state has LSN " LSN_FMT " older than record, updating" - " rows' count\n", LSN_IN_PARTS(share->state.is_of_horizon)); + " row count\n", LSN_IN_PARTS(share->state.is_of_horizon)); share->state.state.records++; if (share->calc_checksum) { @@ -1925,7 +1945,7 @@ prototype_redo_exec_hook(UNDO_ROW_INSERT) info->s->state.changed|= (STATE_CHANGED | STATE_NOT_ANALYZED | STATE_NOT_ZEROFILLED | STATE_NOT_MOVABLE); } - tprint(tracef, " rows' count %lu\n", (ulong)info->s->state.state.records); + tprint(tracef, " row count: %lu\n", (ulong)info->s->state.state.records); /* Unpin all pages, stamp them with UNDO's LSN */ _ma_unpin_all_pages(info, rec->lsn); return 0; @@ -1963,7 +1983,7 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE) STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_ZEROFILLED | STATE_NOT_MOVABLE); } - tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); + tprint(tracef, " row count: %lu\n", (ulong)share->state.state.records); _ma_unpin_all_pages(info, rec->lsn); return 0; } @@ -2169,7 +2189,7 @@ prototype_redo_exec_hook(CLR_END) if (info == NULL) DBUG_RETURN(0); share= info->s; - tprint(tracef, " CLR_END was about %s, undo_lsn now LSN " LSN_FMT "\n", + tprint(tracef, " CLR_END was about %s, undo_lsn " LSN_FMT "\n", log_desc->name, LSN_IN_PARTS(previous_undo_lsn)); enlarge_buffer(rec); @@ -2226,7 +2246,7 @@ prototype_redo_exec_hook(CLR_END) STATE_NOT_ZEROFILLED | STATE_NOT_MOVABLE); } if (row_entry) - tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); + tprint(tracef, " row count: %lu\n", (ulong)share->state.state.records); _ma_unpin_all_pages(info, rec->lsn); DBUG_RETURN(0); } @@ -2238,7 +2258,7 @@ prototype_redo_exec_hook(CLR_END) prototype_redo_exec_hook(DEBUG_INFO) { - uchar *data; + char *data; enum translog_debug_info_type debug_info; enlarge_buffer(rec); @@ -2251,11 +2271,10 @@ prototype_redo_exec_hook(DEBUG_INFO) return 1; } debug_info= (enum translog_debug_info_type) log_record_buffer.str[0]; - data= log_record_buffer.str + 1; + data= (char*) log_record_buffer.str + 1; switch (debug_info) { case LOGREC_DEBUG_INFO_QUERY: - tprint(tracef, "Query: %.*s\n", rec->record_length - 1, - (char*) data); + tprint(tracef, "Query: %.*s\n", (int) rec->record_length - 1, data); break; default: DBUG_ASSERT(0); @@ -2328,7 +2347,7 @@ prototype_undo_exec_hook(UNDO_ROW_INSERT) FILEID_STORE_SIZE); info->trn= 0; /* trn->undo_lsn is updated in an inwrite_hook when writing the CLR_END */ - tprint(tracef, " rows' count %lu\n", (ulong)info->s->state.state.records); + tprint(tracef, " row count: %lu\n", (ulong)info->s->state.state.records); tprint(tracef, " undo_lsn now LSN " LSN_FMT "\n", LSN_IN_PARTS(trn->undo_lsn)); return error; @@ -2368,7 +2387,7 @@ prototype_undo_exec_hook(UNDO_ROW_DELETE) rec->record_length - (LSN_STORE_SIZE + FILEID_STORE_SIZE)); info->trn= 0; - tprint(tracef, " rows' count %lu\n undo_lsn now LSN " LSN_FMT "\n", + tprint(tracef, " row count: %lu\n undo_lsn now LSN " LSN_FMT "\n", (ulong)share->state.state.records, LSN_IN_PARTS(trn->undo_lsn)); return error; } @@ -2696,8 +2715,8 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) if (lsn_end != LSN_IMPOSSIBLE && rec2.lsn >= lsn_end) { tprint(tracef, - "lsn_end reached at " LSN_FMT ". " - "Skipping rest of redo entries", + "lsn_redo_end reached at " LSN_FMT ". " + "Skipping rest of redo entries\n", LSN_IN_PARTS(rec2.lsn)); translog_destroy_scanner(&scanner); translog_free_record_header(&rec); @@ -2782,7 +2801,7 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) switch (len) { case RECHEADER_READ_EOF: - tprint(tracef, "EOF on the log\n"); + tprint(tracef, "*** End of log ***\n"); break; case RECHEADER_READ_ERROR: tprint(tracef, "Error reading log\n"); @@ -2931,7 +2950,7 @@ static uint end_of_redo_phase(my_bool prepare_for_undo_phase) } -static int run_undo_phase(uint uncommitted) +static int run_undo_phase(LSN end_undo_lsn, uint uncommitted) { LSN last_undo __attribute__((unused)); DBUG_ENTER("run_undo_phase"); @@ -2957,7 +2976,20 @@ static int run_undo_phase(uint uncommitted) fflush(stderr); } if ((uncommitted--) == 0) + { + if (aria_undo_aborted <= 0) + { + aria_undo_aborted= 0; + break; + } + } + if (aria_undo_aborted) + { + tprint(tracef, + "lsn_undo_end found. Skipping rest of undo entries\n"); break; + } + trn= trnman_get_any_trn(); DBUG_ASSERT(trn != NULL); llstr(trn->trid, llbuf); @@ -2985,6 +3017,12 @@ static int run_undo_phase(uint uncommitted) DBUG_RETURN(1); } translog_free_record_header(&rec); + + if (last_undo == end_undo_lsn) + { + aria_undo_aborted= trn->undo_lsn ? 1 : -1; + break; + } } /* Force a crash to test recovery of recovery */ @@ -2993,6 +3031,7 @@ static int run_undo_phase(uint uncommitted) DBUG_ASSERT(--maria_recovery_force_crash_counter > 0); } + trn->undo_lsn= 0; /* Avoid abort in trnman_rollbac_trn */ if (trnman_rollback_trn(trn)) DBUG_RETURN(1); /* We could want to span a few threads (4?) instead of 1 */ @@ -3223,7 +3262,10 @@ static MARIA_HA *get_MARIA_HA_from_UNDO_record(const } DBUG_ASSERT(share->last_version != 0); _ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE); /* to flush state on close */ - tprint(tracef, ", applying record\n"); + if (in_redo_phase) + tprint(tracef, ", remembering undo\n"); + else + tprint(tracef, ", applying record\n"); return info; } diff --git a/storage/maria/ma_recovery.h b/storage/maria/ma_recovery.h index 0a75479365f..4373ef52983 100644 --- a/storage/maria/ma_recovery.h +++ b/storage/maria/ma_recovery.h @@ -26,10 +26,11 @@ C_MODE_START enum maria_apply_log_way { MARIA_LOG_APPLY, MARIA_LOG_DISPLAY_HEADER, MARIA_LOG_CHECK }; int maria_recovery_from_log(void); -int maria_apply_log(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply, +int maria_apply_log(LSN lsn, LSN lsn_end, LSN lsn_undo_end, + enum maria_apply_log_way apply, FILE *trace_file, - my_bool execute_undo_phase, my_bool skip_DDLs, - my_bool take_checkpoints, uint *warnings_count); + my_bool skip_DDLs, my_bool take_checkpoints, + uint *warnings_count); /* Table of tables to recover */ extern HASH tables_to_redo; extern ulong maria_recovery_force_crash_counter; diff --git a/storage/maria/ma_recovery_util.h b/storage/maria/ma_recovery_util.h index 0b02f8e51cb..39c16bc5dff 100644 --- a/storage/maria/ma_recovery_util.h +++ b/storage/maria/ma_recovery_util.h @@ -31,7 +31,12 @@ extern FILE *tracef; my_bool _ma_redo_not_needed_for_page(uint16 shortid, LSN lsn, pgcache_page_no_t page, my_bool index); +#ifdef WAITING_FOR_BUGFIX_TO_VSPRINTF void tprint(FILE *trace_file, const char *format, ...) ATTRIBUTE_FORMAT(printf, 2, 3); void eprint(FILE *trace_file, const char *format, ...) ATTRIBUTE_FORMAT(printf, 2, 3); +#else +void tprint(FILE *trace_file, const char *format, ...); +void eprint(FILE *trace_file, const char *format, ...); +#endif diff --git a/storage/maria/ma_sp_test.c b/storage/maria/ma_sp_test.c index 290a94872b5..ae8f3575438 100644 --- a/storage/maria/ma_sp_test.c +++ b/storage/maria/ma_sp_test.c @@ -17,7 +17,7 @@ /* Written by Alex Barkov, who has a shared copyright to this code */ #include -#include "maria.h" +#include "maria_def.h" #ifdef HAVE_SPATIAL #include "ma_sp_defs.h" diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index 9bf60c465b5..c781f996f04 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -282,7 +282,7 @@ void _ma_reset_state(MARIA_HA *info) (THR_WRITE_CONCURRENT_INSERT was used) */ -void _ma_get_status(void* param, my_bool concurrent_insert) +my_bool _ma_get_status(void* param, my_bool concurrent_insert) { MARIA_HA *info=(MARIA_HA*) param; DBUG_ENTER("_ma_get_status"); @@ -301,7 +301,7 @@ void _ma_get_status(void* param, my_bool concurrent_insert) info->state= &info->state_save; info->state->changed= 0; info->append_insert_at_end= concurrent_insert; - DBUG_VOID_RETURN; + DBUG_RETURN(0); } @@ -359,7 +359,7 @@ void _ma_update_status_with_lock(MARIA_HA *info) locked= 1; mysql_mutex_lock(&info->s->lock.mutex); } - (*info->s->lock.update_status)(info); + (*info->s->lock.update_status)(info->lock.status_param); if (locked) mysql_mutex_unlock(&info->s->lock.mutex); } @@ -379,11 +379,12 @@ void _ma_copy_status(void* to, void *from) } -void _ma_reset_update_flag(void *param, - my_bool concurrent_insert __attribute__((unused))) +my_bool _ma_reset_update_flag(void *param, + my_bool concurrent_insert __attribute__((unused))) { MARIA_HA *info=(MARIA_HA*) param; info->state->changed= 0; + return 0; } my_bool _ma_start_trans(void* param) @@ -477,7 +478,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit, /* The change was done without using transid on rows (like in bulk insert). In this case this thread is the only one - that is using the table and all rows will be visble + that is using the table and all rows will be visible for all transactions. */ _ma_reset_history(share); @@ -535,20 +536,17 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit, share, share->in_trans)); } } - share->in_trans--; - mysql_mutex_unlock(&share->intern_lock); + /* The following calls frees &share->intern_lock */ + decrement_share_in_trans(share); } else { -#ifdef DBUG_ASSERT_EXISTS /* - We need to keep share->in_trans correct in the debug library - because of the assert in maria_close() + We need to keep share->in_trans correct because of the check + in free_maria_share() */ mysql_mutex_lock(&share->intern_lock); - share->in_trans--; - mysql_mutex_unlock(&share->intern_lock); -#endif + decrement_share_in_trans(share); } my_free(tables); } @@ -590,6 +588,10 @@ void _ma_remove_table_from_trnman(MARIA_HA *info) if (tables->share == share) { *prev= tables->next; + /* + We don't have to and can't call decrement_share_in_trans(share) here + as we know there is an active MARIA_HA handler around. + */ share->in_trans--; my_free(tables); break; @@ -627,7 +629,7 @@ void _ma_remove_table_from_trnman(MARIA_HA *info) (THR_WRITE_CONCURRENT_INSERT was used) */ -void _ma_block_get_status(void* param, my_bool concurrent_insert) +my_bool _ma_block_get_status(void* param, my_bool concurrent_insert) { MARIA_HA *info=(MARIA_HA*) param; DBUG_ENTER("_ma_block_get_status"); @@ -635,9 +637,10 @@ void _ma_block_get_status(void* param, my_bool concurrent_insert) info->row_base_length= info->s->base_length; info->row_flag= info->s->base.default_row_flag; - if (concurrent_insert) + DBUG_ASSERT(!concurrent_insert || + info->lock.type == TL_WRITE_CONCURRENT_INSERT); + if (concurrent_insert || !info->autocommit) { - DBUG_ASSERT(info->lock.type == TL_WRITE_CONCURRENT_INSERT); info->row_flag|= ROW_FLAG_TRANSID; info->row_base_length+= TRANSID_SIZE; } @@ -645,7 +648,7 @@ void _ma_block_get_status(void* param, my_bool concurrent_insert) { DBUG_ASSERT(info->lock.type != TL_WRITE_CONCURRENT_INSERT); } - DBUG_VOID_RETURN; + DBUG_RETURN(0); } diff --git a/storage/maria/ma_state.h b/storage/maria/ma_state.h index 4f099a9105c..b27b75f54ab 100644 --- a/storage/maria/ma_state.h +++ b/storage/maria/ma_state.h @@ -13,6 +13,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ +#ifndef MA_STATE_INCLUDED +#define MA_STATE_INCLUDED +C_MODE_START + /* Struct to store tables in use by one transaction */ typedef struct st_maria_status_info @@ -61,18 +65,14 @@ MARIA_STATE_HISTORY *_ma_remove_not_visible_states(MARIA_STATE_HISTORY my_bool all, my_bool trman_is_locked); void _ma_reset_state(MARIA_HA *info); -void _ma_get_status(void* param, my_bool concurrent_insert); +my_bool _ma_get_status(void* param, my_bool concurrent_insert); void _ma_update_status(void* param); void _ma_update_status_with_lock(MARIA_HA *info); void _ma_restore_status(void *param); void _ma_copy_status(void* to, void *from); -void _ma_reset_update_flag(void *param, my_bool concurrent_insert); +my_bool _ma_reset_update_flag(void *param, my_bool concurrent_insert); my_bool _ma_start_trans(void* param); my_bool _ma_check_status(void *param); -void _ma_block_get_status(void* param, my_bool concurrent_insert); -void _ma_block_update_status(void *param); -void _ma_block_restore_status(void *param); -my_bool _ma_block_check_status(void *param); void maria_versioning(MARIA_HA *info, my_bool versioning); void _ma_set_share_data_file_length(struct st_maria_share *share, ulonglong new_length); @@ -86,3 +86,6 @@ void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share, my_bool all); void _ma_remove_table_from_trnman(MARIA_HA *info); void _ma_reset_history(struct st_maria_share *share); + +C_MODE_END +#endif diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index fe9d89de5bf..de5b852a78d 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -1,4 +1,5 @@ /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + Copyright (c) 2010, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,7 +33,7 @@ uchar maria_pack_file_magic[]= /* Unique number for this maria instance */ uchar maria_uuid[MY_UUID_SIZE]; uint maria_quick_table_bits=9; -ulong maria_block_size= MARIA_KEY_BLOCK_LENGTH; +ulong __attribute__((visibility("default"))) maria_block_size= MARIA_KEY_BLOCK_LENGTH; my_bool maria_flush= 0, maria_single_user= 0; my_bool maria_delay_key_write= 0, maria_page_checksums= 1; my_bool maria_inited= FALSE; @@ -146,3 +147,8 @@ PSI_file_key key_file_translog, key_file_kfile, key_file_dfile, /* Note that PSI_stage_info globals must always be declared. */ PSI_stage_info stage_waiting_for_a_resource= { 0, "Waiting for a resource", 0}; + +#ifdef WITH_S3_STORAGE_ENGINE +#include "s3_func.h" +struct s3_func __attribute__((visibility("default"))) s3f; +#endif diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index cdc34bb2438..58e6d5e083b 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -335,12 +335,6 @@ err: my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM) { - if (info->bulk_insert) - { - uint j; - for (j=0 ; j < share->base.keys ; j++) - maria_flush_bulk_insert(info, j); - } info->errkey= i < share->base.keys ? (int) i : -1; /* We delete keys in the reverse order of insertion. This is the order that @@ -366,6 +360,7 @@ err: { if (_ma_ft_del(info,i,buff,record,filepos)) { + fatal_error= 1; if (local_lock_tree) mysql_rwlock_unlock(&keyinfo->root_lock); break; @@ -380,6 +375,7 @@ err: filepos, info->trn->trid))) { + fatal_error= 1; if (local_lock_tree) mysql_rwlock_unlock(&keyinfo->root_lock); break; @@ -399,6 +395,13 @@ err: fatal_error= 1; } + if (info->bulk_insert) + { + uint j; + for (j=0 ; j < share->base.keys ; j++) + maria_flush_bulk_insert(info, j); + } + if (fatal_error) { maria_print_error(info->s, HA_ERR_CRASHED); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index e7327778bda..bf2cd5c6a92 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -1,4 +1,5 @@ /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + Copyright (c) 2009, 2020, MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,13 +16,15 @@ /* This file is included by all internal maria files */ +#ifndef MARIA_DEF_INCLUDED +#define MARIA_DEF_INCLUDED + #include #ifdef EMBEDDED_LIBRARY #undef WITH_S3_STORAGE_ENGINE #endif -C_MODE_START #include "maria.h" /* Structs & some defines */ #include "ma_pagecache.h" #include /* packing of keys */ @@ -36,16 +39,294 @@ C_MODE_START #include #include -/* For testing recovery */ -#ifdef TO_BE_REMOVED -#define IDENTICAL_PAGES_AFTER_RECOVERY 1 +#define MARIA_CANNOT_ROLLBACK + +C_MODE_START + +/* + Limit max keys according to HA_MAX_POSSIBLE_KEY; See myisamchk.h for details +*/ + +#if MAX_INDEXES > HA_MAX_POSSIBLE_KEY +#define MARIA_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ +#else +#define MARIA_MAX_KEY MAX_INDEXES /* Max allowed keys */ #endif + +#define MARIA_NAME_IEXT ".MAI" +#define MARIA_NAME_DEXT ".MAD" +/* Max extra space to use when sorting keys */ +#define MARIA_MAX_TEMP_LENGTH (2*1024L*1024L*1024L) +/* Possible values for maria_block_size (must be power of 2) */ +#define MARIA_KEY_BLOCK_LENGTH 8192 /* default key block length */ +#define MARIA_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ +#define MARIA_MAX_KEY_BLOCK_LENGTH 32768 +/* Minimal page cache when we only want to be able to scan a table */ +#define MARIA_MIN_PAGE_CACHE_SIZE (8192L*16L) + +/* + In the following macros '_keyno_' is 0 .. keys-1. + If there can be more keys than bits in the key_map, the highest bit + is for all upper keys. They cannot be switched individually. + This means that clearing of high keys is ignored, setting one high key + sets all high keys. +*/ +#define MARIA_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) +#define MARIA_KEYMAP_HIGH_MASK (1ULL << (MARIA_KEYMAP_BITS - 1)) +#define maria_get_mask_all_keys_active(_keys_) \ + (((_keys_) < MARIA_KEYMAP_BITS) ? \ + ((1ULL << (_keys_)) - 1ULL) : \ + (~ 0ULL)) +#if MARIA_MAX_KEY > MARIA_KEYMAP_BITS +#define maria_is_key_active(_keymap_,_keyno_) \ + (((_keyno_) < MARIA_KEYMAP_BITS) ? \ + MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \ + MY_TEST((_keymap_) & MARIA_KEYMAP_HIGH_MASK)) +#define maria_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (((_keyno_) < MARIA_KEYMAP_BITS) ? \ + (1ULL << (_keyno_)) : \ + MARIA_KEYMAP_HIGH_MASK) +#define maria_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (((_keyno_) < MARIA_KEYMAP_BITS) ? \ + (~ (1ULL << (_keyno_))) : \ + (~ (0ULL)) /*ignore*/ ) +#else +#define maria_is_key_active(_keymap_,_keyno_) \ + MY_TEST((_keymap_) & (1ULL << (_keyno_))) +#define maria_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (1ULL << (_keyno_)) +#define maria_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (~ (1ULL << (_keyno_))) +#endif +#define maria_is_any_key_active(_keymap_) \ + MY_TEST((_keymap_)) +#define maria_is_all_keys_active(_keymap_,_keys_) \ + ((_keymap_) == maria_get_mask_all_keys_active(_keys_)) +#define maria_set_all_keys_active(_keymap_,_keys_) \ + (_keymap_)= maria_get_mask_all_keys_active(_keys_) +#define maria_clear_all_keys_active(_keymap_) \ + (_keymap_)= 0 +#define maria_intersect_keys_active(_to_,_from_) \ + (_to_)&= (_from_) +#define maria_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ + ((_keymap1_) & (_keymap2_) & \ + maria_get_mask_all_keys_active(_keys_)) +#define maria_copy_keys_active(_to_,_maxkeys_,_from_) \ + (_to_)= (maria_get_mask_all_keys_active(_maxkeys_) & \ + (_from_)) + + /* Param to/from maria_info */ + +typedef struct st_maria_info +{ + ha_rows records; /* Records in database */ + ha_rows deleted; /* Deleted records in database */ + MARIA_RECORD_POS recpos; /* Pos for last used record */ + MARIA_RECORD_POS newrecpos; /* Pos if we write new record */ + MARIA_RECORD_POS dup_key_pos; /* Position to record with dup key */ + my_off_t data_file_length; /* Length of data file */ + my_off_t max_data_file_length, index_file_length; + my_off_t max_index_file_length, delete_length; + ulonglong auto_increment; + ulonglong key_map; /* Which keys are used */ + time_t create_time; /* When table was created */ + time_t check_time; + time_t update_time; + ulong record_offset; + double *rec_per_key; /* for sql optimizing */ + ulong reclength; /* Recordlength */ + ulong mean_reclength; /* Mean recordlength (if packed) */ + char *data_file_name, *index_file_name; + enum data_file_type data_file_type; + uint keys; /* Number of keys in use */ + uint options; /* HA_OPTION_... used */ + uint reflength; + int errkey, /* With key was dupplicated on err */ + sortkey; /* clustered by this key */ + File filenr; /* (uniq) filenr for datafile */ +} MARIA_INFO; + +struct st_maria_share; +struct st_maria_handler; /* For referense */ +struct st_maria_keydef; + +typedef struct st_maria_key /* Internal info about a key */ +{ + uchar *data; /* Data for key */ + struct st_maria_keydef *keyinfo; /* Definition for key */ + uint data_length; /* Length of key data */ + uint ref_length; /* record ref + transid */ + uint32 flag; /* 0 or SEARCH_PART_KEY */ +} MARIA_KEY; + +typedef struct st_maria_decode_tree /* Decode huff-table */ +{ + uint16 *table; + uint quick_table_bits; + uchar *intervalls; +} MARIA_DECODE_TREE; + + +typedef struct s3_info S3_INFO; + +extern ulong maria_block_size, maria_checkpoint_frequency; +extern ulong maria_concurrent_insert; +extern my_bool maria_flush, maria_single_user, maria_page_checksums; +extern my_off_t maria_max_temp_length; +extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size; +extern MY_TMPDIR *maria_tmpdir; +extern my_bool maria_encrypt_tables; + +/* + This is used to check if a symlink points into the mysql data home, + which is normally forbidden as it can be used to get access to + not privileged data +*/ +extern int (*maria_test_invalid_symlink)(const char *filename); + + /* Prototypes for maria-functions */ + +extern int maria_init(void); +extern void maria_end(void); +extern my_bool maria_upgrade(void); +extern int maria_close(MARIA_HA *file); +extern int maria_delete(MARIA_HA *file, const uchar *buff); +extern MARIA_HA *maria_open(const char *name, int mode, + uint wait_if_locked, S3_INFO *s3); +extern int maria_panic(enum ha_panic_function function); +extern int maria_rfirst(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rkey(MARIA_HA *file, uchar *buf, int inx, + const uchar *key, key_part_map keypart_map, + enum ha_rkey_function search_flag); +extern int maria_rlast(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rnext(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rnext_same(MARIA_HA *info, uchar *buf); +extern int maria_rprev(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rrnd(MARIA_HA *file, uchar *buf, + MARIA_RECORD_POS pos); +extern int maria_scan_init(MARIA_HA *file); +extern int maria_scan(MARIA_HA *file, uchar *buf); +extern void maria_scan_end(MARIA_HA *file); +extern int maria_rsame(MARIA_HA *file, uchar *record, int inx); +extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record, + int inx, MARIA_RECORD_POS pos); +extern int maria_update(MARIA_HA *file, const uchar *old, + const uchar *new_record); +extern int maria_write(MARIA_HA *file, const uchar *buff); +extern MARIA_RECORD_POS maria_position(MARIA_HA *file); +extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag); +extern int maria_lock_database(MARIA_HA *file, int lock_type); +extern int maria_delete_table(const char *name); +extern int maria_rename(const char *from, const char *to); +extern int maria_extra(MARIA_HA *file, + enum ha_extra_function function, void *extra_arg); +extern int maria_reset(MARIA_HA *file); +extern ha_rows maria_records_in_range(MARIA_HA *info, int inx, + const key_range *min_key, + const key_range *max_key, + page_range *page); +extern int maria_is_changed(MARIA_HA *info); +extern int maria_delete_all_rows(MARIA_HA *info); +extern uint maria_get_pointer_length(ulonglong file_length, uint def); +extern int maria_commit(MARIA_HA *info); +extern int maria_begin(MARIA_HA *info); +extern void maria_disable_logging(MARIA_HA *info); +extern void maria_enable_logging(MARIA_HA *info); + +#define HA_RECOVER_NONE 0 /* No automatic recover */ +#define HA_RECOVER_DEFAULT 1 /* Automatic recover active */ +#define HA_RECOVER_BACKUP 2 /* Make a backupfile on recover */ +#define HA_RECOVER_FORCE 4 /* Recover even if we loose rows */ +#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */ + +#define HA_RECOVER_ANY (HA_RECOVER_DEFAULT | HA_RECOVER_BACKUP | HA_RECOVER_FORCE | HA_RECOVER_QUICK) + +/* this is used to pass to mysql_mariachk_table */ + +#define MARIA_CHK_REPAIR 1 /* equivalent to mariachk -r */ +#define MARIA_CHK_VERIFY 2 /* Verify, run repair if failure */ + +typedef uint maria_bit_type; + +typedef struct st_maria_bit_buff +{ /* Used for packing of record */ + maria_bit_type current_byte; + uint bits; + uchar *pos, *end, *blob_pos, *blob_end; + uint error; +} MARIA_BIT_BUFF; + +/* functions in maria_check */ +void maria_chk_init(HA_CHECK *param); +void maria_chk_init_for_check(HA_CHECK *param, MARIA_HA *info); +int maria_chk_status(HA_CHECK *param, MARIA_HA *info); +int maria_chk_del(HA_CHECK *param, MARIA_HA *info, ulonglong test_flag); +int maria_chk_size(HA_CHECK *param, MARIA_HA *info); +int maria_chk_key(HA_CHECK *param, MARIA_HA *info); +int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend); +int maria_repair(HA_CHECK *param, MARIA_HA *info, char * name, my_bool); +int maria_sort_index(HA_CHECK *param, MARIA_HA *info, char * name); +int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name); +int maria_repair_by_sort(HA_CHECK *param, MARIA_HA *info, + const char *name, my_bool rep_quick); +int maria_repair_parallel(HA_CHECK *param, MARIA_HA *info, + const char *name, my_bool rep_quick); +int maria_change_to_newfile(const char *filename, const char *old_ext, + const char *new_ext, time_t backup_time, + myf myflags); +void maria_lock_memory(HA_CHECK *param); +int maria_update_state_info(HA_CHECK *param, MARIA_HA *info, uint update); +void maria_update_key_parts(MARIA_KEYDEF *keyinfo, double *rec_per_key_part, + ulonglong *unique, ulonglong *notnull, + ulonglong records); +int maria_filecopy(HA_CHECK *param, File to, File from, my_off_t start, + my_off_t length, const char *type); +int maria_movepoint(MARIA_HA *info, uchar *record, my_off_t oldpos, + my_off_t newpos, uint prot_key); +int maria_test_if_almost_full(MARIA_HA *info); +int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename); +int maria_disable_indexes(MARIA_HA *info); +int maria_enable_indexes(MARIA_HA *info); +int maria_indexes_are_disabled(MARIA_HA *info); +void maria_disable_indexes_for_rebuild(MARIA_HA *info, ha_rows rows, + my_bool all_keys); +my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, ulonglong key_map, + my_bool force); + +int maria_init_bulk_insert(MARIA_HA *info, size_t cache_size, ha_rows rows); +void maria_flush_bulk_insert(MARIA_HA *info, uint inx); +int maria_end_bulk_insert(MARIA_HA *info, my_bool abort); +int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves); +void maria_ignore_trids(MARIA_HA *info); +my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows); + +/* fulltext functions */ +FT_INFO *maria_ft_init_search(uint,void *, uint, uchar *, size_t, + CHARSET_INFO *, uchar *); + +/* 'Almost-internal' Maria functions */ + +void _ma_update_auto_increment_key(HA_CHECK *param, MARIA_HA *info, + my_bool repair); + + /* Do extra sanity checking */ #define SANITY_CHECKS 1 #ifdef EXTRA_DEBUG #define EXTRA_DEBUG_KEY_CHANGES +#endif +/* + The following defines can be used when one has problems with redo logging + Setting this will log the full key page which can be compared with the + redo-changed key page. This will however make the aria log files MUCH bigger. +*/ +#if defined(EXTRA_ARIA_DEBUG) #define EXTRA_STORE_FULL_PAGE_IN_KEY_CHANGES #endif +/* For testing recovery */ +#ifdef TO_BE_REMOVED +#define IDENTICAL_PAGES_AFTER_RECOVERY 1 +#endif #define MAX_NONMAPPED_INSERTS 1000 #define MARIA_MAX_TREE_LEVELS 32 @@ -326,6 +607,7 @@ typedef struct st_ma_base_info my_bool born_transactional; } MARIA_BASE_INFO; +uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); /* Structs used intern in database */ @@ -724,6 +1006,8 @@ struct st_maria_handler my_bool once_flags; /* For MARIA_MRG */ /* For bulk insert enable/disable transactions control */ my_bool switched_transactional; + /* If transaction will autocommit */ + my_bool autocommit; #ifdef _WIN32 my_bool owned_by_merge; /* This Maria table is part of a merge union */ #endif @@ -1334,7 +1618,7 @@ extern size_t _ma_nommap_pwrite(MARIA_HA *info, const uchar *Buffer, #define MA_STATE_INFO_WRITE_FULL_INFO 2 /* intern_lock taking is needed */ #define MA_STATE_INFO_WRITE_LOCK 4 -uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite); +uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite)__attribute__((visibility("default"))) ; uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite); uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state); uint _ma_base_info_write(File file, MARIA_BASE_INFO *base); @@ -1361,12 +1645,6 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, const uchar *record, MARIA_RECORD_POS pos); my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const uchar *a, const uchar *b, my_bool null_are_equal); -void _ma_get_status(void *param, my_bool concurrent_insert); -void _ma_update_status(void *param); -void _ma_restore_status(void *param); -void _ma_copy_status(void *to, void *from); -my_bool _ma_check_status(void *param); -void _ma_restore_status(void *param); void _ma_reset_status(MARIA_HA *maria); int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos); int _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos); @@ -1384,7 +1662,8 @@ void _ma_remap_file(MARIA_HA *info, my_off_t size); MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info, const uchar *record); my_bool _ma_write_abort_default(MARIA_HA *info); int maria_delete_table_files(const char *name, my_bool temporary, - myf flags); + myf flags)__attribute__((visibility("default"))) ; + /* This cannot be in my_base.h as it clashes with HA_SPATIAL. @@ -1466,6 +1745,7 @@ extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx); extern my_bool ma_killed_standalone(MARIA_HA *); extern uint _ma_file_callback_to_id(void *callback_data); +extern void free_maria_share(MARIA_SHARE *share); static inline void unmap_file(MARIA_HA *info __attribute__((unused))) { @@ -1474,4 +1754,15 @@ static inline void unmap_file(MARIA_HA *info __attribute__((unused))) _ma_unmap_file(info); #endif } + +static inline void decrement_share_in_trans(MARIA_SHARE *share) +{ + /* Internal tables doesn't have transactions */ + DBUG_ASSERT(!share->internal_table); + if (!--share->in_trans) + free_maria_share(share); + else + mysql_mutex_unlock(&share->intern_lock); +} C_MODE_END +#endif diff --git a/storage/maria/s3.cnf b/storage/maria/s3.cnf new file mode 100644 index 00000000000..94682cc14d7 --- /dev/null +++ b/storage/maria/s3.cnf @@ -0,0 +1,12 @@ +[mariadb] +plugin-load-add=ha_s3 + +# +# Uncomment and configure the S3 engine +# +#s3-host-name=s3.amazonaws.com +#s3-protocol-version=Amazon +#s3-bucket=... +#s3-access-key=... +#s3-secret-key=... +#s3-region=eu-north-1 diff --git a/storage/maria/s3_func.c b/storage/maria/s3_func.c index f1493455d48..bbaf048d534 100644 --- a/storage/maria/s3_func.c +++ b/storage/maria/s3_func.c @@ -986,7 +986,7 @@ int s3_get_object(ms3_st *s3_client, const char *aws_bucket, block->str= block->alloc_ptr; if (compression) { - size_t length; + ulong length; /* If not compressed */ if (!block->str[0]) @@ -1067,7 +1067,7 @@ int s3_delete_object(ms3_st *s3_client, const char *aws_bucket, const char *name, myf error_flags) { uint8_t error; - int result; + int result= 0; DBUG_ENTER("s3_delete_object"); DBUG_PRINT("enter", ("name: %s", name)); @@ -1500,7 +1500,7 @@ int s3_check_frm_version(ms3_st *s3_client, S3_INFO *s3_info) if (res) DBUG_PRINT("error", ("Wrong table version")); else - DBUG_PRINT("error", ("Version strings matches")); + DBUG_PRINT("exit", ("Version strings matches")); DBUG_RETURN(res); } diff --git a/storage/maria/s3_func.h b/storage/maria/s3_func.h index 09fb6802cca..8981517dd4d 100644 --- a/storage/maria/s3_func.h +++ b/storage/maria/s3_func.h @@ -1,6 +1,6 @@ #ifndef S3_FUNC_INCLUDED #define S3_FUNC_INCLUDED -/* Copyright (C) 2019 MariaDB Corporation Ab +/* Copyright (C) 2019, 2020 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,11 +20,23 @@ */ #ifdef WITH_S3_STORAGE_ENGINE -C_MODE_START #include +C_MODE_START #define DEFAULT_AWS_HOST_NAME "s3.amazonaws.com" +extern struct s3_func { + uint8_t (*set_option)(ms3_st *, ms3_set_option_t, void *); + void (*free)(S3_BLOCK *); + void (*deinit)(ms3_st *); + int32 (*unique_file_number)(void); + my_bool (*read_index_header)(ms3_st *, S3_INFO *, S3_BLOCK *); + int (*check_frm_version)(ms3_st *, S3_INFO *); + S3_INFO *(*info_copy)(S3_INFO *); + my_bool (*set_database_and_table_from_path)(S3_INFO *, const char *); + ms3_st *(*open_connection)(S3_INFO *); +} s3f; + extern TYPELIB s3_protocol_typelib; /* Store information about a s3 connection */ @@ -34,7 +46,6 @@ typedef struct s3_info /* Connection strings */ LEX_CSTRING access_key, secret_key, region, bucket, host_name; - /* Will be set by caller or by ma_open() */ LEX_CSTRING database, table; diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp index b10668cfcce..037a6a59487 100644 --- a/storage/mroonga/mrn_table.cpp +++ b/storage/mroonga/mrn_table.cpp @@ -932,7 +932,7 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) share->wrap_key_info = NULL; share->wrap_primary_key = MAX_KEY; } - memcpy(wrap_table_share, table->s, sizeof(*wrap_table_share)); + *wrap_table_share= *table->s; mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root)); wrap_table_share->keys = share->wrap_keys; wrap_table_share->key_info = share->wrap_key_info; @@ -1080,6 +1080,7 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path if (open_table_def(thd, share, GTS_TABLE)) { *error = ER_CANT_OPEN_FILE; + mrn_free_tmp_table_share(share); DBUG_RETURN(NULL); } DBUG_RETURN(share); diff --git a/storage/mroonga/vendor/groonga/lib/com.c b/storage/mroonga/vendor/groonga/lib/com.c index cc03d6462c3..7761f4838e2 100644 --- a/storage/mroonga/vendor/groonga/lib/com.c +++ b/storage/mroonga/vendor/groonga/lib/com.c @@ -343,7 +343,7 @@ grn_com_event_add(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_ { grn_com *c; /* todo : expand events */ - if (!ev || *ev->hash->n_entries == ev->max_nevents) { + if (!ev || *ev->hash->n_entries == (uint32_t) ev->max_nevents) { if (ev) { GRN_LOG(ctx, GRN_LOG_ERROR, "too many connections (%d)", ev->max_nevents); } return GRN_INVALID_ARGUMENT; } @@ -757,7 +757,7 @@ grn_com_send(grn_ctx *ctx, grn_com *cs, rc = ctx->rc; } } - if (ret != whole_size) { + if ((size_t) ret != whole_size) { GRN_LOG(ctx, GRN_LOG_ERROR, "sendmsg(%" GRN_FMT_SOCKET "): %" GRN_FMT_LLD " < %" GRN_FMT_LLU, cs->fd, (long long int)ret, (unsigned long long int)whole_size); diff --git a/storage/mroonga/vendor/groonga/lib/config.c b/storage/mroonga/vendor/groonga/lib/config.c index 8a0e3a5268c..6664e1270ad 100644 --- a/storage/mroonga/vendor/groonga/lib/config.c +++ b/storage/mroonga/vendor/groonga/lib/config.c @@ -51,7 +51,7 @@ grn_config_set(grn_ctx *ctx, if (value_size == -1) { value_size = strlen(value); } - if (value_size > GRN_CONFIG_MAX_VALUE_SIZE) { + if (value_size > (int32_t) GRN_CONFIG_MAX_VALUE_SIZE) { ERR(GRN_INVALID_ARGUMENT, "[config][set] too large value: max=<%" GRN_FMT_SIZE ">: <%d>", GRN_CONFIG_MAX_VALUE_SIZE, value_size); diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c index cba22aa0e64..46f3f783e59 100644 --- a/storage/mroonga/vendor/groonga/lib/db.c +++ b/storage/mroonga/vendor/groonga/lib/db.c @@ -445,6 +445,9 @@ grn_db_close(grn_ctx *ctx, grn_obj *db) ctx_used_db = ctx->impl && ctx->impl->db == db; if (ctx_used_db) { +#ifdef GRN_WITH_MECAB + grn_db_fin_mecab_tokenizer(ctx); +#endif grn_ctx_loader_clear(ctx); if (ctx->impl->parser) { grn_expr_parser_close(ctx); @@ -1299,7 +1302,7 @@ grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, grn_id id, byte *psubrec = (byte *)ri->subrecs; uint32_t n_subrecs = (uint32_t)GRN_RSET_N_SUBRECS(ri); uint32_t limit = value_size / (GRN_RSET_SCORE_SIZE + subrec_size); - if (limit > buf_size) { + if ((int) limit > buf_size) { limit = buf_size; } if (limit > n_subrecs) { @@ -1522,7 +1525,7 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si if (hooks) { // todo : grn_proc_ctx_open() grn_obj id_, flags_, oldvalue_, value_; - grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; GRN_UINT32_INIT(&id_, 0); GRN_UINT32_INIT(&flags_, 0); GRN_TEXT_INIT(&oldvalue_, 0); @@ -1748,7 +1751,7 @@ grn_table_get_key(grn_ctx *ctx, grn_obj *table, grn_id id, void *keybuf, int buf { grn_array *a = (grn_array *)table; if (a->obj.header.domain) { - if (buf_size >= a->value_size) { + if ((unsigned int) buf_size >= a->value_size) { r = grn_array_get_value(ctx, a, id, keybuf); } else { r = a->value_size; @@ -1823,7 +1826,7 @@ call_delete_hook(grn_ctx *ctx, grn_obj *table, grn_id rid, const void *key, unsi if (hooks) { // todo : grn_proc_ctx_open() grn_obj id_, flags_, oldvalue_, value_; - grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; GRN_UINT32_INIT(&id_, 0); GRN_UINT32_INIT(&flags_, 0); GRN_TEXT_INIT(&oldvalue_, GRN_OBJ_DO_SHALLOW_COPY); @@ -2463,7 +2466,7 @@ grn_table_cursor_open(grn_ctx *ctx, grn_obj *table, if (offset < 0) { ERR(GRN_TOO_SMALL_OFFSET, "can't use negative offset with GRN_CURSOR_PREFIX: %d", offset); - } else if (offset != 0 && offset >= table_size) { + } else if (offset != 0 && offset >= (int) table_size) { ERR(GRN_TOO_LARGE_OFFSET, "offset is not less than table size: offset:%d, table_size:%d", offset, table_size); @@ -5234,7 +5237,7 @@ grn_vector_get_element(grn_ctx *ctx, grn_obj *vector, ERR(GRN_INVALID_ARGUMENT, "invalid vector"); goto exit; } - if (vector->u.v.n_sections <= offset) { + if ((unsigned int) vector->u.v.n_sections <= offset) { ERR(GRN_RANGE_ERROR, "offset out of range"); goto exit; } @@ -7140,7 +7143,7 @@ call_hook(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags) if (hooks) { // todo : grn_proc_ctx_open() grn_obj id_, flags_; - grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; GRN_UINT32_INIT(&id_, 0); GRN_UINT32_INIT(&flags_, 0); GRN_UINT32_SET(ctx, &id_, id); @@ -7973,11 +7976,11 @@ grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values) grn_obj *domain = grn_column_table(ctx, obj); if (domain) { int table_size = (int)grn_table_size(ctx, domain); - if (0 < offset && offset <= table_size) { + if (0 < offset && offset <= (grn_id) table_size) { grn_ra *ra = (grn_ra *)obj; void *p = grn_ra_ref(ctx, ra, offset); if (p) { - if ((offset >> ra->element_width) == (table_size >> ra->element_width)) { + if ((offset >> ra->element_width) == ((unsigned int) table_size >> ra->element_width)) { nrecords = (table_size & ra->element_mask) + 1 - (offset & ra->element_mask); } else { nrecords = ra->element_mask + 1 - (offset & ra->element_mask); @@ -12578,7 +12581,7 @@ grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = target; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = target; index_data[n].section = section; } @@ -12640,7 +12643,7 @@ grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = target; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = target; index_data[n].section = section; } @@ -12667,7 +12670,7 @@ grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = target; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = target; index_data[n].section = section; } @@ -12721,7 +12724,7 @@ grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = target; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = target; index_data[n].section = section; } @@ -12956,7 +12959,7 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = target; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = target; index_data[n].section = section; } @@ -12982,7 +12985,7 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = index; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = index; index_data[n].section = section; } @@ -13003,7 +13006,7 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj, if (n < buf_size) { *ip++ = index; } - if (n < n_index_data) { + if ((unsigned int) n < n_index_data) { index_data[n].index = index; index_data[n].section = section; } @@ -13614,7 +13617,7 @@ grn_table_sort_key_from_str(grn_ctx *ctx, const char *str, unsigned int str_size grn_rc grn_table_sort_key_close(grn_ctx *ctx, grn_table_sort_key *keys, unsigned int nkeys) { - int i; + unsigned int i; if (keys) { for (i = 0; i < nkeys; i++) { grn_obj *key = keys[i].key; @@ -14019,7 +14022,7 @@ grn_ctx_merge_temporary_open_space(grn_ctx *ctx) GRN_API_ENTER; stack = &(ctx->impl->temporary_open_spaces.stack); - if (GRN_BULK_VSIZE(stack) < sizeof(grn_obj) * 2) { + if ((unsigned long) GRN_BULK_VSIZE(stack) < (unsigned long) sizeof(grn_obj) * 2) { ERR(GRN_INVALID_ARGUMENT, "[ctx][temporary-open-spaces][merge] " "merge requires at least two spaces"); diff --git a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h index e90dbfc0b31..81ac2ab6c46 100644 --- a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h +++ b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h @@ -30,6 +30,7 @@ grn_rc grn_tokenizers_init(void); grn_rc grn_tokenizers_fin(void); grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx); +void grn_db_fin_mecab_tokenizer(grn_ctx *ctx); grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx); #ifdef __cplusplus diff --git a/storage/mroonga/vendor/groonga/lib/proc.c b/storage/mroonga/vendor/groonga/lib/proc.c index 4897364146e..8ed39961488 100644 --- a/storage/mroonga/vendor/groonga/lib/proc.c +++ b/storage/mroonga/vendor/groonga/lib/proc.c @@ -989,7 +989,7 @@ parse_normalize_flags(grn_ctx *ctx, grn_obj *flag_names) } #define CHECK_FLAG(name)\ - if (((names_end - names) >= (sizeof(#name) - 1)) &&\ + if (((unsigned long) (names_end - names) >= (unsigned long) (sizeof(#name) - 1)) && \ (!memcmp(names, #name, sizeof(#name) - 1))) {\ flags |= GRN_STRING_ ## name;\ names += sizeof(#name) - 1;\ diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_column.c b/storage/mroonga/vendor/groonga/lib/proc/proc_column.c index 2e92f35fbbc..74d0d7a9e76 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_column.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_column.c @@ -41,7 +41,7 @@ grn_proc_column_parse_flags(grn_ctx *ctx, #define CHECK_FLAG(name) \ name_size = strlen(#name); \ - if ((end - text) >= name_size && \ + if ((unsigned long) (end - text) >= (unsigned long) name_size && \ memcmp(text, #name, name_size) == 0) { \ flags |= GRN_OBJ_ ## name; \ text += name_size; \ diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c b/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c index 7915ddfd329..391925d800b 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c @@ -495,7 +495,7 @@ dump_record(grn_ctx *ctx, grn_dumper *dumper, } } GRN_TEXT_PUTC(ctx, dumper->output, ']'); - if (GRN_TEXT_LEN(dumper->output) >= DUMP_FLUSH_THRESHOLD_SIZE) { + if ((size_t) GRN_TEXT_LEN(dumper->output) >= DUMP_FLUSH_THRESHOLD_SIZE) { grn_ctx_output_flush(ctx, 0); } } diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c b/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c index 943a8fdf74d..952fdbb170e 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c @@ -232,7 +232,7 @@ sequential_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_obj * key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); if (!prefix_match_size || - (prefix_match_size > 0 && key_length >= prefix_match_size && + (prefix_match_size > 0 && key_length >= (int) prefix_match_size && !memcmp(sx, key_name, prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, key_name, key_name + key_length, flags); @@ -250,7 +250,7 @@ sequential_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_obj * rid = GRN_RECORD_VALUE(&value); key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); if (!prefix_match_size || - (prefix_match_size > 0 && key_length >= prefix_match_size && + (prefix_match_size > 0 && key_length >= (int) prefix_match_size && !memcmp(sx, key_name, prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, key_name, key_name + key_length, flags); @@ -277,7 +277,7 @@ sequential_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_obj * grn_obj_unlink(ctx, &value); for (i = 0; i < heap->n_entries; i++) { - if (max_expansion > 0 && i >= max_expansion) { + if (max_expansion > 0 && (uint32_t) i >= max_expansion) { break; } { diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_select.c b/storage/mroonga/vendor/groonga/lib/proc/proc_select.c index 605fd42239f..d17571c3470 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_select.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_select.c @@ -297,7 +297,7 @@ grn_parse_table_group_calc_types(grn_ctx *ctx, } #define CHECK_TABLE_GROUP_CALC_TYPE(name)\ - if (((calc_types_end - calc_types) >= (sizeof(#name) - 1)) &&\ + if (((unsigned long) (calc_types_end - calc_types) >= (unsigned long) (sizeof(#name) - 1)) && \ (!memcmp(calc_types, #name, sizeof(#name) - 1))) {\ flags |= GRN_TABLE_GROUP_CALC_ ## name;\ calc_types += sizeof(#name) - 1;\ @@ -577,7 +577,7 @@ grn_columns_collect(grn_ctx *ctx, while (grn_table_cursor_next(ctx, cursor)) { void *key; char *variable_name; - int variable_name_len; + unsigned int variable_name_len; char *column_name; size_t column_name_len; void *value_raw; @@ -1057,7 +1057,7 @@ grn_proc_expr_query_flags_parse(grn_ctx *ctx, } #define CHECK_EXPR_FLAG(name) \ - if (((query_flags_end - query_flags) >= (sizeof(#name) - 1)) && \ + if (((unsigned long) (query_flags_end - query_flags) >= (unsigned long) (sizeof(#name) - 1)) && \ (memcmp(query_flags, #name, sizeof(#name) - 1) == 0) && \ (((query_flags_end - query_flags) == (sizeof(#name) - 1)) || \ (query_flags[sizeof(#name) - 1] == '|') || \ diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_table.c b/storage/mroonga/vendor/groonga/lib/proc/proc_table.c index c3cf2b21499..3c40992de49 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_table.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_table.c @@ -40,7 +40,7 @@ command_table_create_parse_flags(grn_ctx *ctx, #define CHECK_FLAG(name) \ name_size = strlen(#name); \ - if ((end - nptr) >= name_size && \ + if ((unsigned long) (end - nptr) >= (unsigned long) name_size && \ memcmp(nptr, #name, name_size) == 0) { \ flags |= GRN_OBJ_ ## name; \ nptr += name_size; \ diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c b/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c index d69b044c5ea..206ebf58afb 100644 --- a/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c @@ -39,7 +39,7 @@ parse_tokenize_flags(grn_ctx *ctx, grn_obj *flag_names) } #define CHECK_FLAG(name)\ - if (((names_end - names) >= (sizeof(#name) - 1)) &&\ + if (((unsigned long) (names_end - names) >= (unsigned long) (sizeof(#name) - 1)) &&\ (!memcmp(names, #name, sizeof(#name) - 1))) {\ flags |= GRN_TOKEN_CURSOR_ ## name;\ names += sizeof(#name) - 1;\ diff --git a/storage/mroonga/vendor/groonga/lib/store.c b/storage/mroonga/vendor/groonga/lib/store.c index d0fe974eddb..f579bc9ede6 100644 --- a/storage/mroonga/vendor/groonga/lib/store.c +++ b/storage/mroonga/vendor/groonga/lib/store.c @@ -349,7 +349,7 @@ static grn_ja * _grn_ja_create(grn_ctx *ctx, grn_ja *ja, const char *path, unsigned int max_element_size, uint32_t flags) { - int i; + unsigned int i; grn_io *io; struct grn_ja_header *header; struct grn_ja_header_v2 *header_v2; @@ -689,7 +689,7 @@ grn_ja_replace(grn_ctx *ctx, grn_ja *ja, grn_id id, return ctx->rc; } if (*pseg == JA_ESEG_VOID) { - int i = 0; + unsigned int i = 0; while (SEGMENTS_AT(ja, i)) { if (++i >= JA_N_DSEGMENTS) { ERR(GRN_NOT_ENOUGH_SPACE, "grn_ja file (%s) is full", ja->io->path); @@ -750,8 +750,9 @@ grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id, iw->tiny_p = 0; if (grn_io_lock(ctx, ja->io, grn_lock_timeout)) { return ctx->rc; } if (element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) { - int i, j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT; - for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) { + uint i; + int j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT; + for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) { if (SEGMENTS_AT(ja, i)) { j = i; } else { diff --git a/storage/mroonga/vendor/groonga/lib/tokenizers.c b/storage/mroonga/vendor/groonga/lib/tokenizers.c index 11f274e72db..3daacce7ef9 100644 --- a/storage/mroonga/vendor/groonga/lib/tokenizers.c +++ b/storage/mroonga/vendor/groonga/lib/tokenizers.c @@ -797,6 +797,36 @@ grn_db_init_mecab_tokenizer(grn_ctx *ctx) } } +void +grn_db_fin_mecab_tokenizer(grn_ctx *ctx) +{ + switch (GRN_CTX_GET_ENCODING(ctx)) { + case GRN_ENC_EUC_JP : + case GRN_ENC_UTF8 : + case GRN_ENC_SJIS : +#if defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) + { + GRN_PLUGIN_DECLARE_FUNCTIONS(tokenizers_mecab); + GRN_PLUGIN_IMPL_NAME_TAGGED(fin, tokenizers_mecab)(ctx); + } +#else /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + { + const char *mecab_plugin_name = "tokenizers/mecab"; + char *path; + path = grn_plugin_find_path(ctx, mecab_plugin_name); + if (path) { + GRN_FREE(path); + grn_plugin_unregister(ctx, mecab_plugin_name); + } + } +#endif /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + break; + default : + break; + } + return; +} + #define DEF_TOKENIZER(name, init, next, fin, vars)\ (grn_proc_create(ctx, (name), (sizeof(name) - 1),\ GRN_PROC_TOKENIZER, (init), (next), (fin), 3, (vars))) diff --git a/storage/mroonga/vendor/groonga/plugins/functions/string.c b/storage/mroonga/vendor/groonga/plugins/functions/string.c index 6cd7d953df9..0af2d6ab86c 100644 --- a/storage/mroonga/vendor/groonga/plugins/functions/string.c +++ b/storage/mroonga/vendor/groonga/plugins/functions/string.c @@ -238,7 +238,7 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args, start = p; } else { unsigned int char_length = 0; - size_t n_chars = 0; + int64_t n_chars = 0; for (; p < end && (char_length = grn_charlen(ctx, p, end)); @@ -252,7 +252,7 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args, if (start && length > 0) { unsigned int char_length = 0; - size_t n_chars = 0; + int64_t n_chars = 0; for (; p < end && (char_length = grn_charlen(ctx, p, end)); diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c index 3dd969a89c5..cabf2c94e53 100644 --- a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c +++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c @@ -31,6 +31,7 @@ #include #include +static unsigned int sole_mecab_init_counter = 0; static mecab_t *sole_mecab = NULL; static grn_plugin_mutex *sole_mecab_mutex = NULL; static grn_encoding sole_mecab_encoding = GRN_ENC_NONE; @@ -563,6 +564,11 @@ check_mecab_dictionary_encoding(grn_ctx *ctx) grn_rc GRN_PLUGIN_INIT(grn_ctx *ctx) { + ++sole_mecab_init_counter; + if (sole_mecab_init_counter > 1) + { + return GRN_SUCCESS; + } { char env[GRN_ENV_BUFFER_SIZE]; @@ -636,6 +642,11 @@ GRN_PLUGIN_REGISTER(grn_ctx *ctx) grn_rc GRN_PLUGIN_FIN(grn_ctx *ctx) { + --sole_mecab_init_counter; + if (sole_mecab_init_counter > 0) + { + return GRN_SUCCESS; + } if (sole_mecab) { mecab_destroy(sole_mecab); sole_mecab = NULL; diff --git a/storage/myisam/ftbench/Ecompare.pl b/storage/myisam/ftbench/Ecompare.pl index 07132ef9001..a97f126e64e 100755 --- a/storage/myisam/ftbench/Ecompare.pl +++ b/storage/myisam/ftbench/Ecompare.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2003, 2005 MySQL AB # Use is subject to license terms diff --git a/storage/myisam/ftbench/Ecreate.pl b/storage/myisam/ftbench/Ecreate.pl index 86af9f9c0a5..78962466c80 100755 --- a/storage/myisam/ftbench/Ecreate.pl +++ b/storage/myisam/ftbench/Ecreate.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2003, 2005 MySQL AB # Use is subject to license terms diff --git a/storage/myisam/ftbench/Ereport.pl b/storage/myisam/ftbench/Ereport.pl index d3f8961ec85..a8c7c57e1be 100755 --- a/storage/myisam/ftbench/Ereport.pl +++ b/storage/myisam/ftbench/Ereport.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2003, 2005 MySQL AB # Use is subject to license terms diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 88c6a4837e4..b97c9656ab1 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1175,6 +1175,7 @@ int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend) if (_mi_read_cache(¶m->read_cache,(uchar*) info->rec_buff, block_info.filepos, block_info.rec_len, READING_NEXT)) goto err; + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ if (_mi_pack_rec_unpack(info, &info->bit_buff, record, info->rec_buff, block_info.rec_len)) { @@ -1587,6 +1588,8 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info, sort_param.filepos=new_header_length; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; sort_info.dupp=0; sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master=1; @@ -2292,6 +2295,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, sort_info.buff=0; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(param->read_cache.file, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; sort_param.wordlist=NULL; init_alloc_root(mi_key_memory_MI_SORT_PARAM_wordroot, &sort_param.wordroot, @@ -2759,6 +2764,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, sort_info.buff=0; param->read_cache.end_of_file=sort_info.filelength= mysql_file_seek(param->read_cache.file, 0L, MY_SEEK_END, MYF(0)); + if (info->state->data_file_length == 0) + info->state->data_file_length= sort_info.filelength; if (share->data_file_type == DYNAMIC_RECORD) rec_length=MY_MAX(share->base.min_pack_length+1,share->base.min_block_length); @@ -3626,6 +3633,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) llstr(sort_param->pos,llbuff)); continue; } + sort_param->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record, sort_param->rec_buff, block_info.rec_len)) { diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c index 7990c3e8a80..d318b44720a 100644 --- a/storage/myisam/mi_delete_table.c +++ b/storage/myisam/mi_delete_table.c @@ -28,19 +28,23 @@ int mi_delete_table(const char *name) { + int error= 0; DBUG_ENTER("mi_delete_table"); #ifdef EXTRA_DEBUG check_table_is_closed(name,"delete"); #endif - if (mysql_file_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, MYF(MY_WME)) || - mysql_file_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, MYF(MY_WME))) - DBUG_RETURN(my_errno); + if (mysql_file_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, + MYF(MY_WME))) + error= my_errno; + if (mysql_file_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, + MYF(MY_WME))) + error= my_errno; // optionally present: mysql_file_delete_with_symlink(mi_key_file_dfile, name, ".OLD", MYF(0)); mysql_file_delete_with_symlink(mi_key_file_dfile, name, ".TMD", MYF(0)); - DBUG_RETURN(0); + DBUG_RETURN(error); } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 713ba0a3851..67b253761bc 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -284,7 +284,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) (THR_WRITE_CONCURRENT_INSERT was used) */ -void mi_get_status(void* param, my_bool concurrent_insert) +my_bool mi_get_status(void* param, my_bool concurrent_insert) { MI_INFO *info=(MI_INFO*) param; DBUG_ENTER("mi_get_status"); @@ -306,7 +306,7 @@ void mi_get_status(void* param, my_bool concurrent_insert) info->append_insert_at_end= concurrent_insert; if (concurrent_insert) info->s->state.state.uncacheable= TRUE; - DBUG_VOID_RETURN; + DBUG_RETURN(0); } diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index d5bfdac3008..ca8a8ef06c7 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -725,6 +725,8 @@ int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, uchar *buf) block_info.rec_len - block_info.offset, MYF(MY_NABP))) goto panic; info->update|= HA_STATE_AKTIV; + + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ DBUG_RETURN(_mi_pack_rec_unpack(info, &info->bit_buff, buf, info->rec_buff, block_info.rec_len)); panic: @@ -1352,8 +1354,9 @@ int _mi_read_rnd_pack_record(MI_INFO *info, uchar *buf, info->nextpos=block_info.filepos+block_info.rec_len; info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - DBUG_RETURN (_mi_pack_rec_unpack(info, &info->bit_buff, buf, - info->rec_buff, block_info.rec_len)); + info->rec_buff[block_info.rec_len]= 0; /* Keep valgrind happy */ + DBUG_RETURN(_mi_pack_rec_unpack(info, &info->bit_buff, buf, + info->rec_buff, block_info.rec_len)); err: DBUG_RETURN(my_errno); } @@ -1372,8 +1375,8 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, { ref_length=myisam->s->pack.ref_length; /* - We can't use mysql_file_pread() here because mi_read_rnd_pack_record assumes - position is ok + We can't use mysql_file_pread() here because mi_read_rnd_pack_record + assumes position is ok */ mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0)); if (mysql_file_read(file, header, ref_length, MYF(MY_NABP))) @@ -1408,15 +1411,17 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, } - /* rutines for bit buffer */ - /* Note buffer must be 6 byte bigger than longest row */ +/* + Rutines for bit buffer + Note: buffer must be 6 byte bigger than longest row +*/ static void init_bit_buffer(MI_BIT_BUFF *bit_buff, uchar *buffer, uint length) { bit_buff->pos=buffer; bit_buff->end=buffer+length; bit_buff->bits=bit_buff->error=0; - bit_buff->current_byte=0; /* Avoid purify errors */ + bit_buff->current_byte=0; /* Avoid valgrind errors */ } static uint fill_and_get_bits(MI_BIT_BUFF *bit_buff, uint count) @@ -1562,9 +1567,11 @@ void _mi_unmap_file(MI_INFO *info) } -static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, - MI_BLOCK_INFO *info, uchar **rec_buff_p, - uchar *header) +static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, + MI_BIT_BUFF *bit_buff, + MI_BLOCK_INFO *info, + uchar **rec_buff_p, + uchar *header) { header+= read_pack_length((uint) myisam->s->pack.version, header, &info->rec_len); @@ -1573,7 +1580,7 @@ static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, header+= read_pack_length((uint) myisam->s->pack.version, header, &info->blob_len); /* mi_alloc_rec_buff sets my_errno on error */ - if (!(mi_alloc_rec_buff(myisam, info->blob_len, + if (!(mi_alloc_rec_buff(myisam, info->blob_len , rec_buff_p))) return 0; /* not enough memory */ bit_buff->blob_pos= (uchar*) *rec_buff_p; @@ -1598,6 +1605,7 @@ static int _mi_read_mempack_record(MI_INFO *info, my_off_t filepos, uchar *buf) (uchar*) share->file_map+ filepos))) DBUG_RETURN(-1); + /* No need to end-zero pos here for valgrind as data is memory mapped */ DBUG_RETURN(_mi_pack_rec_unpack(info, &info->bit_buff, buf, pos, block_info.rec_len)); } diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index c4b274b3fe9..10d4987e1cb 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -1427,20 +1427,25 @@ static void descript(HA_CHECK *param, register MI_INFO *info, char * name) else type=(enum en_fieldtype) share->rec[field].type; end=strmov(buff,field_pack[type]); + if (end != buff) + { + *(end++)=','; + *(end++)=' '; + } if (share->options & HA_OPTION_COMPRESS_RECORD) { if (share->rec[field].pack_type & PACK_TYPE_SELECTED) - end=strmov(end,", not_always"); + end=strmov(end,"not_always, "); if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS) - end=strmov(end,", no empty"); + end=strmov(end,"no empty, "); if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL) { - sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits); + sprintf(end,"zerofill(%d), ",share->rec[field].space_length_bits); end=strend(end); } } - if (buff[0] == ',') - strmov(buff,buff+2); + if (end != buff) + end[-2]= 0; /* Remove ", " */ int10_to_str((long) share->rec[field].length,length,10); null_bit[0]=null_pos[0]=0; if (share->rec[field].null_bit) diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 19cc408b3fa..640a04fb3df 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -726,7 +726,7 @@ int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def, const uchar *record, my_off_t pos); int mi_unique_comp(MI_UNIQUEDEF *def, const uchar *a, const uchar *b, my_bool null_are_equal); -void mi_get_status(void *param, my_bool concurrent_insert); +my_bool mi_get_status(void *param, my_bool concurrent_insert); void mi_update_status(void *param); void mi_restore_status(void *param); void mi_copy_status(void *to, void *from); diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index 33d4c854c8b..c4c59d109f5 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -95,10 +95,11 @@ static int pfs_init_func(void *p) pfs_hton->create= pfs_create_handler; pfs_hton->show_status= pfs_show_status; - pfs_hton->flags= HTON_ALTER_NOT_SUPPORTED | - HTON_TEMPORARY_NOT_SUPPORTED | - HTON_NO_PARTITION | - HTON_NO_BINLOG_ROW_OPT; + pfs_hton->flags= (HTON_ALTER_NOT_SUPPORTED | + HTON_TEMPORARY_NOT_SUPPORTED | + HTON_NO_PARTITION | + HTON_NO_BINLOG_ROW_OPT | + HTON_AUTOMATIC_DELETE_TABLE); /* As long as the server implementation keeps using legacy_db_type, diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt index 1b4f9aa6a17..090ababf238 100644 --- a/storage/rocksdb/CMakeLists.txt +++ b/storage/rocksdb/CMakeLists.txt @@ -188,9 +188,6 @@ endif() TARGET_LINK_LIBRARIES(rocksdb rocksdb_aux_lib) - FIND_LIBRARY(LZ4_LIBRARY - NAMES liblz4${PIC_EXT}.a lz4 - HINTS ${WITH_LZ4}/lib) CHECK_FUNCTION_EXISTS(sched_getcpu HAVE_SCHED_GETCPU) IF(HAVE_SCHED_GETCPU) @@ -252,13 +249,6 @@ ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Cla SET_TARGET_PROPERTIES(rocksdb_tools sst_dump mariadb-ldb PROPERTIES COMPILE_FLAGS "-Wno-error") ENDIF() -# Enable ZSTD if available. Upstream rocksdb cmake will use WITH_ZSTD and set -# defines within their code. -FIND_PACKAGE(zstd) -IF (ZSTD_FOUND) - SET(WITH_ZSTD ON) -ENDIF() - IF(GIT_EXECUTABLE AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/rocksdb/.git) EXECUTE_PROCESS( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake index 1a3b2076c82..f7b2170978d 100644 --- a/storage/rocksdb/build_rocksdb.cmake +++ b/storage/rocksdb/build_rocksdb.cmake @@ -35,52 +35,47 @@ endif() # Optional compression libraries. -foreach(compression_lib LZ4 BZip2 ZSTD snappy) - FIND_PACKAGE(${compression_lib} QUIET) - - SET(WITH_ROCKSDB_${compression_lib} AUTO CACHE STRING - "Build RocksDB with ${compression_lib} compression. Possible values are 'ON', 'OFF', 'AUTO' and default is 'AUTO'") - - if(${WITH_ROCKSDB_${compression_lib}} STREQUAL "ON" AND NOT ${${compression_lib}_FOUND}) - MESSAGE(FATAL_ERROR - "${compression_lib} library was not found, but WITH_ROCKSDB${compression_lib} option is ON.\ - Either set WITH_ROCKSDB${compression_lib} to OFF, or make sure ${compression_lib} is installed") - endif() -endforeach() - -if(LZ4_FOUND AND (NOT WITH_ROCKSDB_LZ4 STREQUAL "OFF")) - add_definitions(-DLZ4) - include_directories(${LZ4_INCLUDE_DIR}) - list(APPEND THIRDPARTY_LIBS ${LZ4_LIBRARY}) -endif() - -if(BZIP2_FOUND AND (NOT WITH_ROCKSDB_BZip2 STREQUAL "OFF")) - add_definitions(-DBZIP2) - include_directories(${BZIP2_INCLUDE_DIR}) - list(APPEND THIRDPARTY_LIBS ${BZIP2_LIBRARIES}) -endif() - -if(SNAPPY_FOUND AND (NOT WITH_ROCKSDB_snappy STREQUAL "OFF")) - add_definitions(-DSNAPPY) - include_directories(${snappy_INCLUDE_DIR}) - list(APPEND THIRDPARTY_LIBS ${snappy_LIBRARIES}) -endif() - include(CheckFunctionExists) -if(ZSTD_FOUND AND (NOT WITH_ROCKSDB_zstd STREQUAL "OFF")) - SET(CMAKE_REQUIRED_LIBRARIES zstd) - CHECK_FUNCTION_EXISTS(ZDICT_trainFromBuffer ZSTD_VALID) - UNSET(CMAKE_REQUIRED_LIBRARIES) - if (WITH_ROCKSDB_ZSTD STREQUAL "ON" AND NOT ZSTD_VALID) +macro(check_lib package var) + STRING(TOUPPER ${package} PACKAGE_NAME) + SET(WITH_ROCKSDB_${package} AUTO CACHE STRING + "Build RocksDB with ${package} compression. Possible values are 'ON', 'OFF', 'AUTO' and default is 'AUTO'") + + IF (NOT ${WITH_ROCKSDB_${package}} STREQUAL "OFF") + FIND_PACKAGE(${package} QUIET) + IF (${${PACKAGE_NAME}_FOUND}) + IF(${ARGC} GREATER 2) + SET(CMAKE_REQUIRED_LIBRARIES ${${var}_LIBRARIES}) + CHECK_FUNCTION_EXISTS(${ARGV2} ${var}_VALID) + UNSET(CMAKE_REQUIRED_LIBRARIES) + ELSE() + SET(${var}_VALID TRUE) + ENDIF() + ENDIF() + ENDIF() + + IF(${${var}_VALID}) + MESSAGE_ONCE(rocksdb_${var} "Found ${package}: ${${var}_LIBRARIES}") + add_definitions(-D${PACKAGE_NAME}) + include_directories(${${var}_INCLUDE_DIR}) + list(APPEND THIRDPARTY_LIBS ${${var}_LIBRARIES}) + ELSEIF(${${PACKAGE_NAME}_FOUND}) + MESSAGE_ONCE(rocksdb_${var} "Found unusable ${package}: ${${var}_LIBRARIES} [${ARGV2}]") + ELSE() + MESSAGE_ONCE(rocksdb_${var} "Could NOT find ${package}") + ENDIF() + + IF (${WITH_ROCKSDB_${package}} STREQUAL "ON" AND NOT ${${PACKAGE_NAME}_FOUND}) MESSAGE(FATAL_ERROR - "WITH_ROCKSDB_ZSTD is ON and ZSTD library was found, but the version needs to be >= 1.1.3") + "${package} library was not found, but WITH_ROCKSDB_${package} option is ON.\ + Either set WITH_ROCKSDB_${package} to OFF, or make sure ${package} is installed") endif() - if (ZSTD_VALID) - add_definitions(-DZSTD) - include_directories(${ZSTD_INCLUDE_DIR}) - list(APPEND THIRDPARTY_LIBS ${ZSTD_LIBRARIES}) - endif() -endif() +endmacro() + +check_lib(LZ4 LZ4) +check_lib(BZip2 BZIP2) +check_lib(snappy snappy) # rocksdb/cmake/modules/Findsnappy.cmake violates the convention +check_lib(ZSTD ZSTD ZDICT_trainFromBuffer) add_definitions(-DZLIB) list(APPEND THIRDPARTY_LIBS ${ZLIB_LIBRARY}) diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 5d349f6fcce..6ddd20a750b 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -114,7 +114,6 @@ int thd_binlog_format(const MYSQL_THD thd); bool thd_binlog_filter_ok(const MYSQL_THD thd); } -MYSQL_PLUGIN_IMPORT bool my_disable_leak_check; extern my_bool opt_core_file; // Needed in rocksdb_init_func @@ -5727,13 +5726,6 @@ static int rocksdb_init_func(void *const p) { } #endif - /** - Rocksdb does not always shutdown its threads, when - plugin is shut down. Disable server's leak check - at exit to avoid crash. - */ - my_disable_leak_check = true; - err = my_error_register(rdb_get_error_messages, HA_ERR_ROCKSDB_FIRST, HA_ERR_ROCKSDB_LAST); if (err != 0) { @@ -6336,6 +6328,7 @@ ha_rocksdb::ha_rocksdb(my_core::handlerton *const hton, m_dup_sk_packed_tuple(nullptr), m_dup_sk_packed_tuple_old(nullptr), m_pack_buffer(nullptr), + m_record_buffer(nullptr), m_lock_rows(RDB_LOCK_NONE), m_keyread_only(false), m_insert_with_update(false), @@ -6550,6 +6543,7 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, uint key_len = 0; uint max_packed_sk_len = 0; uint pack_key_len = 0; + uint record_len = table->s->reclength + table->s->null_bytes; m_pk_descr = kd_arr[pk_index(table_arg, tbl_def_arg)]; if (has_hidden_pk(table_arg)) { @@ -6594,6 +6588,8 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, reinterpret_cast(my_malloc(PSI_INSTRUMENT_ME, max_packed_sk_len, MYF(0))); m_pack_buffer = reinterpret_cast(my_malloc(PSI_INSTRUMENT_ME, max_packed_sk_len, MYF(0))); + m_record_buffer = + reinterpret_cast(my_malloc(PSI_INSTRUMENT_ME, record_len, MYF(0))); m_scan_it_lower_bound = reinterpret_cast(my_malloc(PSI_INSTRUMENT_ME, max_packed_sk_len, MYF(0))); @@ -6615,6 +6611,7 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, m_sk_packed_tuple == nullptr || m_sk_packed_tuple_old == nullptr || m_end_key_packed_tuple == nullptr || m_pack_buffer == nullptr || m_scan_it_upper_bound == nullptr || m_scan_it_lower_bound == nullptr || + m_record_buffer == nullptr || (alloc_alter_buffers && (m_dup_sk_packed_tuple == nullptr || m_dup_sk_packed_tuple_old == nullptr))) { // One or more of the above allocations failed. Clean up and exit @@ -6648,6 +6645,9 @@ void ha_rocksdb::free_key_buffers() { my_free(m_pack_buffer); m_pack_buffer = nullptr; + my_free(m_record_buffer); + m_record_buffer = nullptr; + my_free(m_dup_sk_packed_tuple); m_dup_sk_packed_tuple = nullptr; @@ -8059,7 +8059,8 @@ int ha_rocksdb::position_to_correct_key( rc = HA_ERR_KEY_NOT_FOUND; } else if (find_flag == HA_READ_PREFIX_LAST) { uint size = kd.pack_index_tuple(table, m_pack_buffer, - m_sk_packed_tuple, key, keypart_map); + m_sk_packed_tuple, m_record_buffer, + key, keypart_map); rocksdb::Slice lookup_tuple( reinterpret_cast(m_sk_packed_tuple), size); @@ -8099,7 +8100,7 @@ int ha_rocksdb::calc_eq_cond_len(const Rdb_key_def &kd, if (end_key) { *end_key_packed_size = kd.pack_index_tuple(table, m_pack_buffer, m_end_key_packed_tuple, - end_key->key, end_key->keypart_map); + m_record_buffer, end_key->key, end_key->keypart_map); /* Calculating length of the equal conditions here. 4 byte index id is @@ -8470,7 +8471,8 @@ int ha_rocksdb::index_read_map_impl(uchar *const buf, const uchar *const key, This is a special case, use DB::Get. */ const uint size = kd.pack_index_tuple(table, m_pack_buffer, - m_pk_packed_tuple, key, keypart_map); + m_pk_packed_tuple, m_record_buffer, + key, keypart_map); bool skip_lookup = is_blind_delete_enabled(); rc = get_row_by_rowid(buf, m_pk_packed_tuple, size, skip_lookup, false); @@ -8496,14 +8498,14 @@ int ha_rocksdb::index_read_map_impl(uchar *const buf, const uchar *const key, .user_defined_key_parts) - 1; packed_size = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple, - key, tmp_map); + m_record_buffer, key, tmp_map); if (table->key_info[active_index].user_defined_key_parts != kd.get_key_parts()) { using_full_key = false; } } else { packed_size = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple, - key, keypart_map); + m_record_buffer, key, keypart_map); } if ((pushed_idx_cond && pushed_idx_cond_keyno == active_index) && @@ -8975,6 +8977,7 @@ int ha_rocksdb::get_row_by_rowid(uchar *const buf, const char *const rowid, Rdb_transaction *const tx = get_or_create_tx(table->in_use); DBUG_ASSERT(tx != nullptr); +#ifdef ENABLED_DEBUG_SYNC DEBUG_SYNC(ha_thd(), "rocksdb.get_row_by_rowid"); DBUG_EXECUTE_IF("dbug.rocksdb.get_row_by_rowid", { THD *thd = ha_thd(); @@ -8984,6 +8987,7 @@ int ha_rocksdb::get_row_by_rowid(uchar *const buf, const char *const rowid, DBUG_ASSERT(opt_debug_sync_timeout > 0); DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); +#endif /* ENABLED_DEBUG_SYNC */ bool found; rocksdb::Status s; @@ -11932,6 +11936,7 @@ ha_rows ha_rocksdb::records_in_range(uint inx, const key_range *const min_key, uint size1 = 0; if (min_key) { size1 = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple, + m_record_buffer, min_key->key, min_key->keypart_map); if (min_key->flag == HA_READ_PREFIX_LAST_OR_PREV || min_key->flag == HA_READ_PREFIX_LAST || @@ -11945,6 +11950,7 @@ ha_rows ha_rocksdb::records_in_range(uint inx, const key_range *const min_key, uint size2 = 0; if (max_key) { size2 = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple_old, + m_record_buffer, max_key->key, max_key->keypart_map); if (max_key->flag == HA_READ_PREFIX_LAST_OR_PREV || max_key->flag == HA_READ_PREFIX_LAST || diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 1820326090f..05b5341bfb1 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -235,6 +235,11 @@ class ha_rocksdb : public my_core::handler { */ uchar *m_pack_buffer; + /* + A buffer long enough to store table record + */ + uchar *m_record_buffer; + /* class to convert between Mysql format and RocksDB format*/ std::shared_ptr m_converter; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result index 2bf7d381ce8..2139b1bfe05 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result @@ -231,8 +231,6 @@ innodb_master_active_loops server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NU innodb_master_idle_loops server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times master thread performs its tasks when server is idle innodb_background_drop_table_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to process drop table list innodb_log_flush_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to flush log records -innodb_mem_validate_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to do memory validation -innodb_master_purge_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent by master thread to purge records innodb_dict_lru_usec server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Time (in microseconds) spent to process DICT LRU list innodb_dict_lru_count_active server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of tables evicted from DICT LRU list in the active loop innodb_dict_lru_count_idle server 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of tables evicted from DICT LRU list in the idle loop diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result index f2f9adebf46..53d59650cd2 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result @@ -2633,4 +2633,11 @@ DELETE t2, t1 FROM t2 LEFT JOIN t1 ON t2.id2 = t1.id2 AND t2.id1 = t1.id1 WHERE SET rocksdb_bulk_load_size= @save_rocksdb_bulk_load_size; SET rocksdb_commit_in_the_middle=0; DROP TABLE t1, t2; +# +# MDEV-21831: Assertion `length == pack_length()' failed in Field_inet6::sort_string upon +# INSERT into RocksDB table +# +CREATE TABLE t1 (a INET6 NOT NULL, KEY (a)) ENGINE=RocksDB; +INSERT INTO t1 VALUES ('41::1'),('61::1'); +DROP TABLE t1; SET GLOBAL ROCKSDB_PAUSE_BACKGROUND_WORK = @ORIG_PAUSE_BACKGROUND_WORK; diff --git a/storage/rocksdb/mysql-test/rocksdb/t/rocksdb.test b/storage/rocksdb/mysql-test/rocksdb/t/rocksdb.test index 84a9a5bbd5a..f7de167bd96 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/rocksdb.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/rocksdb.test @@ -1962,5 +1962,13 @@ SET rocksdb_bulk_load_size= @save_rocksdb_bulk_load_size; SET rocksdb_commit_in_the_middle=0; DROP TABLE t1, t2; +--echo # +--echo # MDEV-21831: Assertion `length == pack_length()' failed in Field_inet6::sort_string upon +--echo # INSERT into RocksDB table +--echo # + +CREATE TABLE t1 (a INET6 NOT NULL, KEY (a)) ENGINE=RocksDB; +INSERT INTO t1 VALUES ('41::1'),('61::1'); +DROP TABLE t1; SET GLOBAL ROCKSDB_PAUSE_BACKGROUND_WORK = @ORIG_PAUSE_BACKGROUND_WORK; diff --git a/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/all_vars.test b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/all_vars.test index fc700357155..7943d3e4c0b 100644 --- a/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/all_vars.test +++ b/storage/rocksdb/mysql-test/rocksdb_sys_vars/t/all_vars.test @@ -1,6 +1,5 @@ --source include/have_rocksdb.inc --source include/not_embedded.inc ---source include/not_threadpool.inc # This test verifies that *all* MyRocks system variables are tested by the # rocksdb_sys_vars suite. For every MyRocks system variable there must be a diff --git a/storage/rocksdb/rdb_converter.cc b/storage/rocksdb/rdb_converter.cc index e799d67f813..65f0b81cc7f 100644 --- a/storage/rocksdb/rdb_converter.cc +++ b/storage/rocksdb/rdb_converter.cc @@ -646,9 +646,9 @@ int Rdb_converter::verify_row_debug_checksum( rdb_netbuf_to_uint32((const uchar *)reader->read(RDB_CHECKSUM_SIZE)); const uint32_t computed_key_chksum = - my_core::crc32(0, rdb_slice_to_uchar_ptr(key), key->size()); + my_core::my_checksum(0, rdb_slice_to_uchar_ptr(key), key->size()); const uint32_t computed_val_chksum = - my_core::crc32(0, rdb_slice_to_uchar_ptr(value), + my_core::my_checksum(0, rdb_slice_to_uchar_ptr(value), value->size() - RDB_CHECKSUM_CHUNK_SIZE); DBUG_EXECUTE_IF("myrocks_simulate_bad_pk_checksum1", stored_key_chksum++;); @@ -816,10 +816,10 @@ int Rdb_converter::encode_value_slice( } if (store_row_debug_checksums) { - const uint32_t key_crc32 = my_core::crc32( + const uint32_t key_crc32 = my_core::my_checksum( 0, rdb_slice_to_uchar_ptr(&pk_packed_slice), pk_packed_slice.size()); const uint32_t val_crc32 = - my_core::crc32(0, rdb_mysql_str_to_uchar_str(&m_storage_record), + my_core::my_checksum(0, rdb_mysql_str_to_uchar_str(&m_storage_record), m_storage_record.length()); uchar key_crc_buf[RDB_CHECKSUM_SIZE]; uchar val_crc_buf[RDB_CHECKSUM_SIZE]; diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc index a7b44ff85ab..6e73535d1de 100644 --- a/storage/rocksdb/rdb_datadic.cc +++ b/storage/rocksdb/rdb_datadic.cc @@ -987,7 +987,7 @@ uint Rdb_key_def::get_memcmp_sk_parts(const TABLE *table, Convert index tuple into storage (i.e. mem-comparable) format @detail - Currently this is done by unpacking into table->record[0] and then + Currently this is done by unpacking into record_buffer and then packing index columns into storage format. @param pack_buffer Temporary area for packing varchar columns. Its @@ -996,6 +996,7 @@ uint Rdb_key_def::get_memcmp_sk_parts(const TABLE *table, uint Rdb_key_def::pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer, uchar *const packed_tuple, + uchar *const record_buffer, const uchar *const key_tuple, const key_part_map &keypart_map) const { DBUG_ASSERT(tbl != nullptr); @@ -1005,13 +1006,13 @@ uint Rdb_key_def::pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer, /* We were given a record in KeyTupleFormat. First, save it to record */ const uint key_len = calculate_key_len(tbl, m_keyno, key_tuple, keypart_map); - key_restore(tbl->record[0], key_tuple, &tbl->key_info[m_keyno], key_len); + key_restore(record_buffer, key_tuple, &tbl->key_info[m_keyno], key_len); uint n_used_parts = my_count_bits(keypart_map); if (keypart_map == HA_WHOLE_KEY) n_used_parts = 0; // Full key is used /* Then, convert the record into a mem-comparable form */ - return pack_record(tbl, pack_buffer, tbl->record[0], packed_tuple, nullptr, + return pack_record(tbl, pack_buffer, record_buffer, packed_tuple, nullptr, false, 0, n_used_parts); } @@ -1432,9 +1433,10 @@ uint Rdb_key_def::pack_record(const TABLE *const tbl, uchar *const pack_buffer, // ha_rocksdb::convert_record_to_storage_format // if (should_store_row_debug_checksums) { - const uint32_t key_crc32 = crc32(0, packed_tuple, tuple - packed_tuple); + const uint32_t key_crc32 = + my_checksum(0, packed_tuple, tuple - packed_tuple); const uint32_t val_crc32 = - crc32(0, unpack_info->ptr(), unpack_info->get_current_pos()); + my_checksum(0, unpack_info->ptr(), unpack_info->get_current_pos()); unpack_info->write_uint8(RDB_CHECKSUM_DATA_TAG); unpack_info->write_uint32(key_crc32); @@ -1690,9 +1692,9 @@ int Rdb_key_def::unpack_record(TABLE *const table, uchar *const buf, (const uchar *)unp_reader.read(RDB_CHECKSUM_SIZE)); const uint32_t computed_key_chksum = - crc32(0, (const uchar *)packed_key->data(), packed_key->size()); + my_checksum(0, packed_key->data(), packed_key->size()); const uint32_t computed_val_chksum = - crc32(0, (const uchar *)unpack_info->data(), + my_checksum(0, unpack_info->data(), unpack_info->size() - RDB_CHECKSUM_CHUNK_SIZE); DBUG_EXECUTE_IF("myrocks_simulate_bad_key_checksum1", @@ -3315,7 +3317,9 @@ bool Rdb_field_packing::setup(const Rdb_key_def *const key_descr, field->field_length = field->char_length() * cs->mbmaxlen. */ const CHARSET_INFO *cs = field->charset(); - m_max_image_len = cs->strnxfrmlen(field->field_length); + m_max_image_len = cs->strnxfrmlen(type == MYSQL_TYPE_STRING ? + field->pack_length() : + field->field_length); } const bool is_varchar = (type == MYSQL_TYPE_VARCHAR); const CHARSET_INFO *cs = field->charset(); diff --git a/storage/rocksdb/rdb_datadic.h b/storage/rocksdb/rdb_datadic.h index 7bcc45d3f62..903cecdc379 100644 --- a/storage/rocksdb/rdb_datadic.h +++ b/storage/rocksdb/rdb_datadic.h @@ -252,7 +252,8 @@ class Rdb_key_def { public: /* Convert a key from KeyTupleFormat to mem-comparable form */ uint pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer, - uchar *const packed_tuple, const uchar *const key_tuple, + uchar *const packed_tuple, uchar *const record_buffer, + const uchar *const key_tuple, const key_part_map &keypart_map) const; uchar *pack_field(Field *const field, Rdb_field_packing *pack_info, diff --git a/storage/sequence/sequence.cc b/storage/sequence/sequence.cc index 8684a5c60b9..31522b8f3b7 100644 --- a/storage/sequence/sequence.cc +++ b/storage/sequence/sequence.cc @@ -69,10 +69,15 @@ public: /* open/close/locking */ int create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) { return HA_ERR_WRONG_COMMAND; } + HA_CREATE_INFO *create_info) + { return HA_ERR_WRONG_COMMAND; } int open(const char *name, int mode, uint test_if_locked); int close(void); + int delete_table(const char *name) + { + return 0; + } THR_LOCK_DATA **store_lock(THD *, THR_LOCK_DATA **, enum thr_lock_type); /* table scan */ @@ -503,6 +508,7 @@ static int init(void *p) hton->savepoint_set= hton->savepoint_rollback= hton->savepoint_release= dummy_savepoint; hton->create_group_by= create_group_by_handler; + hton->flags= HTON_AUTOMATIC_DELETE_TABLE; return 0; } @@ -526,4 +532,3 @@ maria_declare_plugin(sequence) MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; - diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 8403c767796..d60a4d229e6 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -696,7 +696,7 @@ handlerton sphinx_hton = NULL, // create_cursor_read_view NULL, // set_cursor_read_view NULL, // close_cursor_read_view - HTON_CAN_RECREATE + HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE }; #else static handlerton * sphinx_hton_ptr = NULL; @@ -749,7 +749,7 @@ static int sphinx_init_func ( void * p ) hton->close_connection = sphinx_close_connection; hton->show_status = sphinx_show_status; hton->panic = sphinx_panic; - hton->flags = HTON_CAN_RECREATE; + hton->flags = HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE; #endif } SPH_RET(0); diff --git a/storage/spider/CMakeLists.txt b/storage/spider/CMakeLists.txt index 706b11ac141..397478bfc40 100644 --- a/storage/spider/CMakeLists.txt +++ b/storage/spider/CMakeLists.txt @@ -50,11 +50,14 @@ ELSEIF(PLUGIN_PARTITION MATCHES "^NO$") ELSE() INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/spider/hs_client) - INSTALL(FILES - ${CMAKE_SOURCE_DIR}/storage/spider/scripts/install_spider.sql - DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server - ) - MYSQL_ADD_PLUGIN(spider ${SPIDER_SOURCES} STORAGE_ENGINE MODULE_ONLY MODULE_OUTPUT_NAME "ha_spider") + IF(DEB) + SET(extra_options COMPONENT spider-engine) + ELSE() + SET(extra_options CONFIG spider.cnf) + ENDIF() + + MYSQL_ADD_PLUGIN(spider ${SPIDER_SOURCES} ${extra_options} + STORAGE_ENGINE MODULE_ONLY) IF(NOT TARGET spider) RETURN() ENDIF() diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index a7cfe45c8f7..ce9447a61a9 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -76,11 +76,8 @@ ha_spider::ha_spider( spider_alloc_calc_mem_init(mem_calc, 139); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); share = NULL; - trx = NULL; conns = NULL; need_mons = NULL; - condition = NULL; - cond_check = FALSE; blob_buff = NULL; conn_keys = NULL; spider_thread_id = 0; @@ -90,10 +87,9 @@ ha_spider::ha_spider( trx_hs_w_conn_adjustment = 0; #endif search_link_query_id = 0; - searched_bitmap = NULL; #ifdef WITH_PARTITION_STORAGE_ENGINE partition_handler_share = NULL; - pt_handler_share_creator = NULL; + pt_handler_share_owner = FALSE; #endif #ifdef HA_MRR_USE_DEFAULT_IMPL multi_range_keys = NULL; @@ -102,7 +98,6 @@ ha_spider::ha_spider( append_tblnm_alias = NULL; use_index_merge = FALSE; is_clone = FALSE; - clone_bitmap_init = FALSE; pt_clone_source_handler = NULL; pt_clone_last_searcher = NULL; ft_handler = NULL; @@ -116,6 +111,7 @@ ha_spider::ha_spider( #ifdef SPIDER_HAS_GROUP_BY_HANDLER use_fields = FALSE; #endif + dml_inited = FALSE; use_pre_call = FALSE; use_pre_action = FALSE; #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS @@ -128,10 +124,6 @@ ha_spider::ha_spider( hs_decrement = FALSE; hs_pushed_strref_num = 0; #endif - direct_update_fields = NULL; -#endif -#ifdef INFO_KIND_FORCE_LIMIT_BEGIN - info_limit = 9223372036854775807LL; #endif #ifdef HA_CAN_BULK_ACCESS is_bulk_access_clone = FALSE; @@ -188,11 +180,8 @@ ha_spider::ha_spider( spider_alloc_calc_mem_init(mem_calc, 0); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); share = NULL; - trx = NULL; conns = NULL; need_mons = NULL; - condition = NULL; - cond_check = FALSE; blob_buff = NULL; conn_keys = NULL; spider_thread_id = 0; @@ -202,10 +191,9 @@ ha_spider::ha_spider( trx_hs_w_conn_adjustment = 0; #endif search_link_query_id = 0; - searched_bitmap = NULL; #ifdef WITH_PARTITION_STORAGE_ENGINE partition_handler_share = NULL; - pt_handler_share_creator = NULL; + pt_handler_share_owner = FALSE; #endif #ifdef HA_MRR_USE_DEFAULT_IMPL multi_range_keys = NULL; @@ -214,7 +202,6 @@ ha_spider::ha_spider( append_tblnm_alias = NULL; use_index_merge = FALSE; is_clone = FALSE; - clone_bitmap_init = FALSE; pt_clone_source_handler = NULL; pt_clone_last_searcher = NULL; ft_handler = NULL; @@ -228,6 +215,7 @@ ha_spider::ha_spider( #ifdef SPIDER_HAS_GROUP_BY_HANDLER use_fields = FALSE; #endif + dml_inited = FALSE; use_pre_call = FALSE; use_pre_action = FALSE; #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS @@ -240,10 +228,6 @@ ha_spider::ha_spider( hs_decrement = FALSE; hs_pushed_strref_num = 0; #endif - direct_update_fields = NULL; -#endif -#ifdef INFO_KIND_FORCE_LIMIT_BEGIN - info_limit = 9223372036854775807LL; #endif #ifdef HA_CAN_BULK_ACCESS is_bulk_access_clone = FALSE; @@ -295,6 +279,19 @@ ha_spider::~ha_spider() { DBUG_ENTER("ha_spider::~ha_spider"); DBUG_PRINT("info",("spider this=%p", this)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (pt_handler_share_owner) + { + spider_free(spider_current_trx, partition_handler_share, MYF(0)); + pt_handler_share_owner = FALSE; + } + partition_handler_share = NULL; +#endif + if (wide_handler_owner) + { + spider_free(spider_current_trx, wide_handler, MYF(0)); + } + wide_handler = NULL; spider_free_mem_calc(spider_current_trx, mem_calc_id, sizeof(*this)); DBUG_VOID_RETURN; } @@ -340,14 +337,16 @@ int ha_spider::open( THD *thd = ha_thd(); int error_num, roop_count; int init_sql_alloc_size; + ha_spider *spider, *owner; + bool wide_handler_alloc = FALSE; + SPIDER_WIDE_SHARE *wide_share; #ifdef WITH_PARTITION_STORAGE_ENGINE - SPIDER_PARTITION_SHARE *partition_share; - uchar *idx_read_bitmap, *idx_write_bitmap, - *rnd_read_bitmap, *rnd_write_bitmap; uint part_num; - bool create_pt_handler_share = FALSE, pt_handler_mutex = FALSE, - may_be_clone = FALSE; - ha_spider **pt_handler_share_handlers; + bool pt_handler_share_alloc = FALSE; + bool pt_handler_mutex = FALSE; + ha_spider **pt_handler_share_handlers = NULL; + ha_partition *clone_source; + ha_spider *pt_handler_share_key; #ifdef SPIDER_HAS_HASH_VALUE_TYPE my_hash_value_type hash_value; #endif @@ -357,52 +356,50 @@ int ha_spider::open( dup_key_idx = (uint) -1; conn_kinds = SPIDER_CONN_KIND_MYSQL; - if (!spider_get_share(name, table, thd, this, &error_num)) - goto error_get_share; - thr_lock_data_init(&share->lock,&lock,NULL); - #ifdef WITH_PARTITION_STORAGE_ENGINE - partition_share = share->partition_share; table->file->get_no_parts("", &part_num); - if (partition_share) + if (part_num) { - pt_handler_mutex = TRUE; - pthread_mutex_lock(&partition_share->pt_handler_mutex); -/* - if ( - !partition_share->partition_handler_share || - partition_share->partition_handler_share->table != table - ) - create_pt_handler_share = TRUE; -*/ -#ifdef SPIDER_HAS_HASH_VALUE_TYPE - hash_value = my_calc_hash(&partition_share->pt_handler_hash, - (uchar*) &table, sizeof(TABLE *)); - if (!(partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE*) - my_hash_search_using_hash_value(&partition_share->pt_handler_hash, - hash_value, (uchar*) &table, sizeof(TABLE *)))) -#else - if (!(partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE*) - my_hash_search(&partition_share->pt_handler_hash, (uchar*) &table, - sizeof(TABLE *)))) -#endif + pt_handler_share_handlers = + (ha_spider **) ((ha_partition *) table->file)->get_child_handlers(); + spider = pt_handler_share_handlers[0]; + owner = pt_handler_share_handlers[part_num - 1]; + clone_source = ((ha_partition *) table->file)->get_clone_source(); + if (clone_source) { - create_pt_handler_share = TRUE; + pt_handler_share_key = (ha_spider *) + clone_source->get_child_handlers()[0]; + is_clone = TRUE; + } else { + pt_handler_share_key = spider; } + } else { +#endif + spider = this; + owner = this; +#ifdef WITH_PARTITION_STORAGE_ENGINE + clone_source = NULL; + pt_handler_share_key = this; } - - if (create_pt_handler_share) +#endif + if (!spider->wide_handler) { - if (!(searched_bitmap = (uchar *) - spider_bulk_malloc(spider_current_trx, 15, MYF(MY_WME), + uchar *searched_bitmap; + uchar *ft_discard_bitmap; + uchar *position_bitmap; + uchar *idx_read_bitmap; + uchar *idx_write_bitmap; + uchar *rnd_read_bitmap; + uchar *rnd_write_bitmap; + if (!(wide_handler = (SPIDER_WIDE_HANDLER *) + spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME | MY_ZEROFILL), + &wide_handler, sizeof(SPIDER_WIDE_HANDLER), &searched_bitmap, (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), &ft_discard_bitmap, (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), &position_bitmap, (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), - &partition_handler_share, - (uint) sizeof(SPIDER_PARTITION_HANDLER_SHARE), &idx_read_bitmap, (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), &idx_write_bitmap, @@ -411,103 +408,105 @@ int ha_spider::open( (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), &rnd_write_bitmap, (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), - &pt_handler_share_handlers, - (uint) sizeof(ha_spider *) * part_num, NullS)) ) { error_num = HA_ERR_OUT_OF_MEM; - goto error_searched_bitmap_alloc; + goto error_wide_handler_alloc; } - DBUG_PRINT("info",("spider create partition_handler_share")); - partition_handler_share->use_count = 1; -/* - if (partition_handler_share->use_count < part_num) - partition_share->partition_handler_share = partition_handler_share; -*/ - DBUG_PRINT("info",("spider table=%p", table)); - partition_handler_share->table = table; - partition_handler_share->searched_bitmap = NULL; - partition_handler_share->ft_discard_bitmap = NULL; - partition_handler_share->idx_read_bitmap = idx_read_bitmap; - partition_handler_share->idx_write_bitmap = idx_write_bitmap; - partition_handler_share->rnd_read_bitmap = rnd_read_bitmap; - partition_handler_share->rnd_write_bitmap = rnd_write_bitmap; - partition_handler_share->between_flg = FALSE; - partition_handler_share->idx_bitmap_is_set = FALSE; - partition_handler_share->rnd_bitmap_is_set = FALSE; - partition_handler_share->table_hash_value = hash_value; - partition_handler_share->creator = this; - partition_handler_share->parallel_search_query_id = 0; - pt_handler_share_creator = this; - if (part_num) - { - partition_handler_share->handlers = (void **) pt_handler_share_handlers; - partition_handler_share->handlers[0] = this; - } else - partition_handler_share->handlers = NULL; - uint old_elements = partition_share->pt_handler_hash.array.max_element; -#ifdef HASH_UPDATE_WITH_HASH_VALUE - if (my_hash_insert_with_hash_value(&partition_share->pt_handler_hash, - hash_value, (uchar*) partition_handler_share)) -#else - if (my_hash_insert(&partition_share->pt_handler_hash, - (uchar*) partition_handler_share)) -#endif - { - error_num = HA_ERR_OUT_OF_MEM; - goto error_hash_insert; - } - if (partition_share->pt_handler_hash.array.max_element > old_elements) - { - spider_alloc_calc_mem(spider_current_trx, - partition_share->pt_handler_hash, - (partition_share->pt_handler_hash.array.max_element - old_elements) * - partition_share->pt_handler_hash.array.size_of_element); - } - pthread_mutex_unlock(&partition_share->pt_handler_mutex); - pt_handler_mutex = FALSE; + spider->wide_handler = wide_handler; + owner->wide_handler = wide_handler; + wide_handler->searched_bitmap = searched_bitmap; + wide_handler->ft_discard_bitmap = ft_discard_bitmap; + wide_handler->position_bitmap = position_bitmap; + wide_handler->idx_read_bitmap = idx_read_bitmap; + wide_handler->idx_write_bitmap = idx_write_bitmap; + wide_handler->rnd_read_bitmap = rnd_read_bitmap; + wide_handler->rnd_write_bitmap = rnd_write_bitmap; + wide_handler->owner = owner; + if (table_share->tmp_table == NO_TMP_TABLE) + wide_handler->top_share = table->s; + owner->wide_handler_owner = TRUE; + memset(wide_handler->ft_discard_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0, + no_bytes_in_map(table->read_set)); + wide_handler_alloc = TRUE; } else { -#endif - if (!(searched_bitmap = (uchar *) - spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME), - &searched_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), - &ft_discard_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), - &position_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), - NullS)) - ) { - error_num = HA_ERR_OUT_OF_MEM; - goto error_searched_bitmap_alloc; - } + wide_handler = spider->wide_handler; + } + if (!share && !spider_get_share(name, table, thd, this, &error_num)) + goto error_get_share; + + wide_share = share->wide_share; + if (wide_handler_alloc) + { + thr_lock_data_init(&wide_share->lock, &wide_handler->lock, NULL); + } + #ifdef WITH_PARTITION_STORAGE_ENGINE - if (partition_share) + if (!wide_handler->partition_handler_share) + { + pt_handler_mutex = TRUE; + pthread_mutex_lock(&wide_share->pt_handler_mutex); +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + hash_value = my_calc_hash(&wide_share->pt_handler_hash, + (uchar*) pt_handler_share_key, sizeof(ha_spider *)); + if (!(partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE*) + my_hash_search_using_hash_value(&wide_share->pt_handler_hash, + hash_value, (uchar*) pt_handler_share_key, sizeof(ha_spider *)))) +#else + if (!(partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE*) + my_hash_search(&wide_share->pt_handler_hash, + (uchar*) pt_handler_share_key, sizeof(ha_spider *)))) +#endif { - DBUG_PRINT("info",("spider copy partition_handler_share")); -/* - partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE *) - partition_share->partition_handler_share; -*/ - if (part_num) - { - if (partition_handler_share->use_count >= part_num) - may_be_clone = TRUE; - else { - partition_handler_share->handlers[ - partition_handler_share->use_count] = this; - partition_handler_share->use_count++; - } + if (!(partition_handler_share = (SPIDER_PARTITION_HANDLER_SHARE *) + spider_bulk_malloc(spider_current_trx, 15, MYF(MY_WME | MY_ZEROFILL), + &partition_handler_share, sizeof(SPIDER_PARTITION_HANDLER_SHARE), + NullS)) + ) { + error_num = HA_ERR_OUT_OF_MEM; + goto error_partition_handler_share_alloc; + } + DBUG_PRINT("info",("spider create partition_handler_share")); + DBUG_PRINT("info",("spider table=%p", table)); + partition_handler_share->table = table; + partition_handler_share->table_hash_value = hash_value; + partition_handler_share->no_parts = part_num; + partition_handler_share->owner = owner; + partition_handler_share->parallel_search_query_id = 0; + spider->partition_handler_share = partition_handler_share; + owner->partition_handler_share = partition_handler_share; + owner->pt_handler_share_owner = TRUE; + partition_handler_share->handlers = pt_handler_share_handlers; + uint old_elements = wide_share->pt_handler_hash.array.max_element; +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (my_hash_insert_with_hash_value(&wide_share->pt_handler_hash, + hash_value, (uchar*) partition_handler_share)) +#else + if (my_hash_insert(&wide_share->pt_handler_hash, + (uchar*) partition_handler_share)) +#endif + { + error_num = HA_ERR_OUT_OF_MEM; + goto error_hash_insert; + } + if (wide_share->pt_handler_hash.array.max_element > old_elements) + { + spider_alloc_calc_mem(spider_current_trx, + wide_share->pt_handler_hash, + (wide_share->pt_handler_hash.array.max_element - + old_elements) * + wide_share->pt_handler_hash.array.size_of_element); } -/* - if (partition_handler_share->use_count == part_num) - partition_share->partition_handler_share = NULL; -*/ - pthread_mutex_unlock(&partition_share->pt_handler_mutex); - pt_handler_mutex = FALSE; } + pthread_mutex_unlock(&wide_share->pt_handler_mutex); + pt_handler_mutex = FALSE; + pt_handler_share_alloc = TRUE; + } else { + partition_handler_share = wide_handler->partition_handler_share; } #endif - memset(ft_discard_bitmap, 0xFF, no_bytes_in_map(table->read_set)); - memset(searched_bitmap, 0, no_bytes_in_map(table->read_set)); - init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); @@ -566,10 +565,6 @@ int ha_spider::open( } } -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (may_be_clone && thd_sql_command(thd) != SQLCOM_ALTER_TABLE) - is_clone = TRUE; -#endif if (is_clone) { #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -577,28 +572,38 @@ int ha_spider::open( { for (roop_count = 0; roop_count < (int) part_num; roop_count++) { - if (((ha_spider *) partition_handler_share->handlers[roop_count])-> - share == share) + if (partition_handler_share->handlers[roop_count]->share == share) { pt_clone_source_handler = - (ha_spider *) partition_handler_share->handlers[roop_count]; + partition_handler_share->handlers[roop_count]; break; } } } #endif - sql_command = pt_clone_source_handler->sql_command; - result_list.lock_type = pt_clone_source_handler->result_list.lock_type; - lock_mode = pt_clone_source_handler->lock_mode; + wide_handler->external_lock_type = + pt_clone_source_handler->wide_handler->external_lock_type; - if (!pt_clone_source_handler->clone_bitmap_init) + if (wide_handler_alloc) { - pt_clone_source_handler->set_select_column_mode(); - pt_clone_source_handler->clone_bitmap_init = TRUE; + wide_handler->lock_mode = + pt_clone_source_handler->wide_handler->lock_mode; + if (!partition_handler_share->clone_bitmap_init) + { + pt_clone_source_handler->set_select_column_mode(); + partition_handler_share->clone_bitmap_init = TRUE; + } + set_clone_searched_bitmap(); + wide_handler->position_bitmap_init = FALSE; + wide_handler->sql_command = + pt_clone_source_handler->wide_handler->sql_command; + } + } else { + if (share->semi_table_lock) + { + wide_handler->semi_table_lock = TRUE; } - set_clone_searched_bitmap(); - position_bitmap_init = FALSE; } #ifdef HA_CAN_BULK_ACCESS external_lock_cnt = 0; @@ -618,50 +623,55 @@ error_reset: error_init_blob_buff: error_init_result_list: #ifdef WITH_PARTITION_STORAGE_ENGINE - if ( - partition_handler_share && - pt_handler_share_creator == this - ) { - partition_share = share->partition_share; +error_hash_insert: + if (pt_handler_share_alloc) + { + wide_share = share->wide_share; if (!pt_handler_mutex) - pthread_mutex_lock(&partition_share->pt_handler_mutex); -/* - if (partition_share->partition_handler_share == partition_handler_share) - partition_share->partition_handler_share = NULL; -*/ + pthread_mutex_lock(&wide_share->pt_handler_mutex); #ifdef HASH_UPDATE_WITH_HASH_VALUE - my_hash_delete_with_hash_value(&partition_share->pt_handler_hash, + my_hash_delete_with_hash_value(&wide_share->pt_handler_hash, partition_handler_share->table_hash_value, (uchar*) partition_handler_share); #else - my_hash_delete(&partition_share->pt_handler_hash, + my_hash_delete(&wide_share->pt_handler_hash, (uchar*) partition_handler_share); #endif - pthread_mutex_unlock(&partition_share->pt_handler_mutex); + pthread_mutex_unlock(&wide_share->pt_handler_mutex); pt_handler_mutex = FALSE; + spider_free(spider_current_trx, partition_handler_share, MYF(0)); + spider->partition_handler_share = NULL; + owner->partition_handler_share = NULL; + owner->pt_handler_share_owner = FALSE; } -error_hash_insert: - partition_handler_share = NULL; - pt_handler_share_creator = NULL; -#endif - if (searched_bitmap) - { - spider_free(spider_current_trx, searched_bitmap, MYF(0)); - searched_bitmap = NULL; - } -error_searched_bitmap_alloc: -#ifdef WITH_PARTITION_STORAGE_ENGINE +error_partition_handler_share_alloc: if (pt_handler_mutex) - pthread_mutex_unlock(&partition_share->pt_handler_mutex); + pthread_mutex_unlock(&wide_share->pt_handler_mutex); + partition_handler_share = NULL; #endif spider_free_share(share); share = NULL; -error_get_share: if (conn_keys) { spider_free(spider_current_trx, conn_keys, MYF(0)); conn_keys = NULL; } +error_get_share: + if (wide_handler_alloc) + { +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (pt_handler_share_handlers) + { + pt_handler_share_handlers[0]->wide_handler = NULL; + } +#endif + spider_free(spider_current_trx, wide_handler, MYF(0)); + spider->wide_handler = NULL; + owner->wide_handler = NULL; + owner->wide_handler_owner = FALSE; + } + wide_handler = NULL; +error_wide_handler_alloc: DBUG_RETURN(error_num); } @@ -669,9 +679,7 @@ int ha_spider::close() { int error_num = 0, roop_count, error_num2; THD *thd = ha_thd(); -#ifdef WITH_PARTITION_STORAGE_ENGINE - SPIDER_PARTITION_SHARE *partition_share; -#endif + SPIDER_WIDE_SHARE *wide_share; backup_error_status(); DBUG_ENTER("ha_spider::close"); DBUG_PRINT("info",("spider this=%p", this)); @@ -697,8 +705,8 @@ int ha_spider::close() bulk_access_link_first->spider)); DBUG_PRINT("info",("spider bulk_access_link->spider->dbton_handler=%p", bulk_access_link_first->spider->dbton_handler)); - DBUG_PRINT("info",("spider ptr bulk_access_link->spider->dbton_handler=%p", - &bulk_access_link_first->spider->dbton_handler)); + DBUG_PRINT("info",("spider ptr bulk_access_link->spider->dbton_handler=" + "%p", &bulk_access_link_first->spider->dbton_handler)); bulk_access_link_current = bulk_access_link_first->next; delete_bulk_access_link(bulk_access_link_first); bulk_access_link_first = bulk_access_link_current; @@ -761,34 +769,30 @@ int ha_spider::close() conn_keys = NULL; } #ifdef WITH_PARTITION_STORAGE_ENGINE - if ( - partition_handler_share && - pt_handler_share_creator == this - ) { - partition_share = share->partition_share; - pthread_mutex_lock(&partition_share->pt_handler_mutex); -/* - if (partition_share->partition_handler_share == partition_handler_share) - partition_share->partition_handler_share = NULL; -*/ + if (pt_handler_share_owner) + { + wide_share = share->wide_share; + pthread_mutex_lock(&wide_share->pt_handler_mutex); #ifdef HASH_UPDATE_WITH_HASH_VALUE - my_hash_delete_with_hash_value(&partition_share->pt_handler_hash, + my_hash_delete_with_hash_value(&wide_share->pt_handler_hash, partition_handler_share->table_hash_value, (uchar*) partition_handler_share); #else - my_hash_delete(&partition_share->pt_handler_hash, + my_hash_delete(&wide_share->pt_handler_hash, (uchar*) partition_handler_share); #endif - pthread_mutex_unlock(&partition_share->pt_handler_mutex); + pthread_mutex_unlock(&wide_share->pt_handler_mutex); + spider_free(spider_current_trx, partition_handler_share, MYF(0)); + pt_handler_share_owner = FALSE; } partition_handler_share = NULL; - pt_handler_share_creator = NULL; #endif - if (searched_bitmap) + if (wide_handler_owner) { - spider_free(spider_current_trx, searched_bitmap, MYF(0)); - searched_bitmap = NULL; + spider_free(spider_current_trx, wide_handler, MYF(0)); + wide_handler_owner = FALSE; } + wide_handler = NULL; if (blob_buff) { delete [] blob_buff; @@ -832,35 +836,24 @@ int ha_spider::close() hs_pushed_ret_fields_size = 0; } #endif -#endif -#ifdef HA_CAN_BULK_ACCESS -/* - if (init_ha_mem_root) - { - free_root(&ha_mem_root, MYF(0)); - init_ha_mem_root = FALSE; - } -*/ #endif is_clone = FALSE; pt_clone_source_handler = NULL; share = NULL; - trx = NULL; conns = NULL; DBUG_RETURN(error_num); } -int ha_spider::check_access_kind( +int ha_spider::check_access_kind_for_connection( THD *thd, bool write_request ) { int error_num, roop_count; - DBUG_ENTER("ha_spider::check_access_kind"); + DBUG_ENTER("ha_spider::check_access_kind_for_connection"); DBUG_PRINT("info",("spider this=%p", this)); - sql_command = thd_sql_command(thd); conn_kinds = 0; - switch (sql_command) + switch (wide_handler->sql_command) { #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) case SQLCOM_HS_READ: @@ -962,33 +955,60 @@ int ha_spider::check_access_kind( { DBUG_RETURN(error_num); } - DBUG_PRINT("info",("spider sql_command=%u", sql_command)); + DBUG_PRINT("info",("spider wide_handler->semi_trx_isolation_chk = %s", + wide_handler->semi_trx_isolation_chk ? "TRUE" : "FALSE")); + if (wide_handler->semi_trx_isolation_chk) + { + SPIDER_SET_CONNS_PARAM(semi_trx_isolation_chk, TRUE, conns, + share->link_statuses, conn_link_idx, (int) share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + } + DBUG_PRINT("info",("spider wide_handler->semi_trx_chk = %s", + wide_handler->semi_trx_chk ? "TRUE" : "FALSE")); + if (wide_handler->semi_trx_chk) + { + SPIDER_SET_CONNS_PARAM(semi_trx_chk, TRUE, conns, share->link_statuses, + conn_link_idx, (int) share->link_count, SPIDER_LINK_STATUS_RECOVERY); + } else { + SPIDER_SET_CONNS_PARAM(semi_trx_chk, FALSE, conns, share->link_statuses, + conn_link_idx, (int) share->link_count, SPIDER_LINK_STATUS_RECOVERY); + } + DBUG_RETURN(0); +} + +void ha_spider::check_access_kind( + THD *thd +) { + DBUG_ENTER("ha_spider::check_access_kind"); + DBUG_PRINT("info",("spider this=%p", this)); + wide_handler->sql_command = thd_sql_command(thd); + DBUG_PRINT("info",("spider sql_command=%u", wide_handler->sql_command)); DBUG_PRINT("info",("spider thd->query_id=%lld", thd->query_id)); #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS #ifdef HS_HAS_SQLCOM - if (sql_command == SQLCOM_HS_UPDATE) - update_request = TRUE; + if (wide_handler->sql_command == SQLCOM_HS_UPDATE) + wide_handler->update_request = TRUE; else #endif - update_request = FALSE; + wide_handler->update_request = FALSE; #else if ( #ifdef HS_HAS_SQLCOM - sql_command == SQLCOM_HS_UPDATE || + wide_handler->sql_command == SQLCOM_HS_UPDATE || #endif - sql_command == SQLCOM_UPDATE || - sql_command == SQLCOM_UPDATE_MULTI || + wide_handler->sql_command == SQLCOM_UPDATE || + wide_handler->sql_command == SQLCOM_UPDATE_MULTI || /* for triggers */ - sql_command == SQLCOM_INSERT || - sql_command == SQLCOM_INSERT_SELECT || - sql_command == SQLCOM_DELETE || - sql_command == SQLCOM_DELETE_MULTI + wide_handler->sql_command == SQLCOM_INSERT || + wide_handler->sql_command == SQLCOM_INSERT_SELECT || + wide_handler->sql_command == SQLCOM_DELETE || + wide_handler->sql_command == SQLCOM_DELETE_MULTI ) - update_request = TRUE; + wide_handler->update_request = TRUE; else - update_request = FALSE; + wide_handler->update_request = FALSE; #endif - DBUG_RETURN(0); + DBUG_VOID_RETURN; } #ifdef HA_CAN_BULK_ACCESS @@ -1002,14 +1022,20 @@ int ha_spider::additional_lock( { if (is_bulk_access_clone) { - DBUG_RETURN(check_access_kind(thd, (lock_type >= TL_WRITE_ALLOW_WRITE))); + check_access_kind(thd); + DBUG_RETURN(check_access_kind_for_connection(thd, + (lock_type >= TL_WRITE_ALLOW_WRITE))); } else if (bulk_access_link_exec_tgt->called) { - DBUG_RETURN(bulk_access_link_exec_tgt->spider->check_access_kind( - thd, (lock_type >= TL_WRITE_ALLOW_WRITE))); + bulk_access_link_exec_tgt->spider->check_access_kind(thd); + DBUG_RETURN(bulk_access_link_exec_tgt->spider-> + check_access_kind_for_connection( + thd, (lock_type >= TL_WRITE_ALLOW_WRITE))); } } - DBUG_RETURN(check_access_kind(thd, (lock_type >= TL_WRITE_ALLOW_WRITE))); + check_access_kind(thd); + DBUG_RETURN(check_access_kind_for_connection(thd, + (lock_type >= TL_WRITE_ALLOW_WRITE))); } #endif @@ -1018,53 +1044,37 @@ THR_LOCK_DATA **ha_spider::store_lock( THR_LOCK_DATA **to, enum thr_lock_type lock_type ) { - int error_num, roop_count; DBUG_ENTER("ha_spider::store_lock"); DBUG_PRINT("info",("spider this=%p", this)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_STORE_LOCK && + wide_handler->stage_executor != this) + { + DBUG_RETURN(to); + } + wide_handler->stage = SPD_HND_STAGE_STORE_LOCK; + wide_handler->stage_executor = this; +#endif + wide_handler->lock_table_type = 0; if (lock_type == TL_IGNORE) { - *to++ = &lock; + *to++ = &wide_handler->lock; DBUG_RETURN(to); } - if ((error_num = check_access_kind(thd, - (lock_type >= TL_WRITE_ALLOW_WRITE)))) - { - store_error_num = error_num; - DBUG_RETURN(to); - } - DBUG_PRINT("info",("spider sql_command=%u", sql_command)); + check_access_kind(thd); + DBUG_PRINT("info",("spider sql_command=%u", wide_handler->sql_command)); DBUG_PRINT("info",("spider lock_type=%d", lock_type)); DBUG_PRINT("info",("spider thd->query_id=%lld", thd->query_id)); - if (sql_command == SQLCOM_ALTER_TABLE) - { - if (trx->query_id != thd->query_id) - { - spider_free_trx_alter_table(trx); - trx->query_id = thd->query_id; - trx->tmp_flg = FALSE; - } - if (!(SPIDER_ALTER_TABLE*) my_hash_search(&trx->trx_alter_table_hash, - (uchar*) share->table_name, share->table_name_length)) - { - if (spider_create_trx_alter_table(trx, share, FALSE)) - { - store_error_num = HA_ERR_OUT_OF_MEM; - DBUG_RETURN(to); - } - } - } - this->lock_type = lock_type; - selupd_lock_mode = spider_param_selupd_lock_mode(thd, - share->selupd_lock_mode); + wide_handler->lock_type = lock_type; if ( - sql_command != SQLCOM_DROP_TABLE && - sql_command != SQLCOM_ALTER_TABLE + wide_handler->sql_command != SQLCOM_DROP_TABLE && + wide_handler->sql_command != SQLCOM_ALTER_TABLE ) { - SPIDER_SET_CONNS_PARAM(semi_trx_chk, FALSE, conns, share->link_statuses, - conn_link_idx, (int) share->link_count, SPIDER_LINK_STATUS_RECOVERY); + wide_handler->semi_trx_chk = FALSE; } - switch (sql_command) + switch (wide_handler->sql_command) { case SQLCOM_SELECT: case SQLCOM_HA_READ: @@ -1072,17 +1082,14 @@ THR_LOCK_DATA **ha_spider::store_lock( case SQLCOM_HS_READ: #endif if (lock_type == TL_READ_WITH_SHARED_LOCKS) - lock_mode = 1; + wide_handler->lock_mode = 1; else if (lock_type <= TL_READ_NO_INSERT) { - lock_mode = 0; - SPIDER_SET_CONNS_PARAM(semi_trx_isolation_chk, TRUE, conns, - share->link_statuses, conn_link_idx, (int) share->link_count, - SPIDER_LINK_STATUS_RECOVERY); + wide_handler->lock_mode = 0; + wide_handler->semi_trx_isolation_chk = TRUE; } else - lock_mode = -1; - SPIDER_SET_CONNS_PARAM(semi_trx_chk, TRUE, conns, share->link_statuses, - conn_link_idx, (int) share->link_count, SPIDER_LINK_STATUS_RECOVERY); + wide_handler->lock_mode = -1; + wide_handler->semi_trx_chk = TRUE; break; case SQLCOM_UPDATE: case SQLCOM_UPDATE_MULTI: @@ -1103,39 +1110,37 @@ THR_LOCK_DATA **ha_spider::store_lock( #endif if (lock_type >= TL_READ && lock_type <= TL_READ_NO_INSERT) { - lock_mode = selupd_lock_mode; - SPIDER_SET_CONNS_PARAM(semi_trx_isolation_chk, TRUE, conns, - share->link_statuses, conn_link_idx, (int) share->link_count, - SPIDER_LINK_STATUS_RECOVERY); + wide_handler->lock_mode = -2; + wide_handler->semi_trx_isolation_chk = TRUE; } else - lock_mode = -1; - SPIDER_SET_CONNS_PARAM(semi_trx_chk, TRUE, conns, share->link_statuses, - conn_link_idx, (int) share->link_count, SPIDER_LINK_STATUS_RECOVERY); + wide_handler->lock_mode = -1; + wide_handler->semi_trx_chk = TRUE; break; default: - lock_mode = -1; + wide_handler->lock_mode = -1; } switch (lock_type) { case TL_READ_HIGH_PRIORITY: - high_priority = TRUE; + wide_handler->high_priority = TRUE; break; case TL_WRITE_DELAYED: - insert_delayed = TRUE; + wide_handler->insert_delayed = TRUE; break; case TL_WRITE_LOW_PRIORITY: - low_priority = TRUE; + wide_handler->low_priority = TRUE; break; default: break; } - if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + if (wide_handler->lock_type != TL_IGNORE && + wide_handler->lock.type == TL_UNLOCK) { if ( - sql_command == SQLCOM_DROP_TABLE || - sql_command == SQLCOM_ALTER_TABLE || - sql_command == SQLCOM_SHOW_CREATE + wide_handler->sql_command == SQLCOM_DROP_TABLE || + wide_handler->sql_command == SQLCOM_ALTER_TABLE || + wide_handler->sql_command == SQLCOM_SHOW_CREATE ) { if ( lock_type == TL_READ_NO_INSERT && @@ -1148,80 +1153,77 @@ THR_LOCK_DATA **ha_spider::store_lock( ) lock_type = TL_WRITE_ALLOW_WRITE; } else if ( - sql_command == SQLCOM_LOCK_TABLES || - (spider_param_lock_exchange(thd) == 1 && share->semi_table_lock)) + wide_handler->sql_command == SQLCOM_LOCK_TABLES || + (spider_param_lock_exchange(thd) == 1 && wide_handler->semi_table_lock)) { DBUG_PRINT("info",("spider lock exchange route")); - DBUG_PRINT("info",("spider lock_type=%u", this->lock_type)); + DBUG_PRINT("info",("spider lock_type=%u", wide_handler->lock_type)); if ( ( - this->lock_type == TL_READ || - this->lock_type == TL_READ_NO_INSERT || - this->lock_type == TL_WRITE_LOW_PRIORITY || - this->lock_type == TL_WRITE + wide_handler->lock_type == TL_READ || + wide_handler->lock_type == TL_READ_NO_INSERT || + wide_handler->lock_type == TL_WRITE_LOW_PRIORITY || + wide_handler->lock_type == TL_WRITE ) && !spider_param_local_lock_table(thd) ) { - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - SPIDER_CONN *conn = conns[roop_count]; - int appended = 0; - if ((error_num = dbton_handler[conn->dbton_id]-> - append_lock_tables_list(conn, roop_count, &appended))) + wide_handler->lock_table_type = 1; +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (partition_handler_share && partition_handler_share->handlers) + { + uint roop_count; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) { - store_error_num = error_num; - DBUG_RETURN(to); - } - if (appended) - { - conn->table_lock = 2; + if (unlikely((store_error_num = + partition_handler_share->handlers[roop_count]-> + append_lock_tables_list()))) + { + break; + } } + } else { +#endif + store_error_num = append_lock_tables_list(); +#ifdef WITH_PARTITION_STORAGE_ENGINE } +#endif } } else { DBUG_PRINT("info",("spider default lock route")); - DBUG_PRINT("info",("spider lock_type=%u", this->lock_type)); + DBUG_PRINT("info",("spider lock_type=%u", wide_handler->lock_type)); if ( - this->lock_type == TL_READ || - this->lock_type == TL_READ_NO_INSERT || - this->lock_type == TL_WRITE_LOW_PRIORITY || - this->lock_type == TL_WRITE + wide_handler->lock_type == TL_READ || + wide_handler->lock_type == TL_READ_NO_INSERT || + wide_handler->lock_type == TL_WRITE_LOW_PRIORITY || + wide_handler->lock_type == TL_WRITE ) { - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) + if ( + !spider_param_local_lock_table(thd) && + spider_param_semi_table_lock(thd, wide_handler->semi_table_lock) ) { - if ( - conns[roop_count] && - conns[roop_count]->table_lock != 1 && - spider_param_semi_table_lock(thd, share->semi_table_lock) && - !spider_param_local_lock_table(thd) - ) { - SPIDER_CONN *conn = conns[roop_count]; - int appended = 0; - if ((error_num = dbton_handler[conn->dbton_id]-> - append_lock_tables_list(conn, roop_count, &appended))) + wide_handler->lock_table_type = 2; +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (partition_handler_share && partition_handler_share->handlers) + { + uint roop_count; + for (roop_count = 0; + roop_count < partition_handler_share->no_parts; + ++roop_count) { - store_error_num = error_num; - DBUG_RETURN(to); - } - if (appended) - { - conn->table_lock = 3; + if (unlikely((store_error_num = + partition_handler_share->handlers[roop_count]-> + append_lock_tables_list()))) + { + break; + } } + } else { +#endif + store_error_num = append_lock_tables_list(); +#ifdef WITH_PARTITION_STORAGE_ENGINE } +#endif } } if ( @@ -1236,9 +1238,9 @@ THR_LOCK_DATA **ha_spider::store_lock( ) lock_type = TL_WRITE_ALLOW_WRITE; } - lock.type = lock_type; + wide_handler->lock.type = lock_type; } - *to++ = &lock; + *to++ = &wide_handler->lock; DBUG_RETURN(to); } @@ -1246,8 +1248,8 @@ int ha_spider::external_lock( THD *thd, int lock_type ) { - int error_num, roop_count; - bool sync_trx_isolation = spider_param_sync_trx_isolation(thd); + int error_num = 0; + SPIDER_TRX *trx; backup_error_status(); DBUG_ENTER("ha_spider::external_lock"); DBUG_PRINT("info",("spider this=%p", this)); @@ -1255,41 +1257,49 @@ int ha_spider::external_lock( #if MYSQL_VERSION_ID < 50500 DBUG_PRINT("info",("spider thd->options=%x", (int) thd->options)); #endif +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_EXTERNAL_LOCK && + wide_handler->stage_executor != this) + { + DBUG_RETURN(0); + } + wide_handler->stage = SPD_HND_STAGE_EXTERNAL_LOCK; + wide_handler->stage_executor = this; +#endif #ifdef HANDLER_HAS_NEED_INFO_FOR_AUTO_INC info_auto_called = FALSE; #endif - sql_command = thd_sql_command(thd); - if (sql_command == SQLCOM_BEGIN) - sql_command = SQLCOM_UNLOCK_TABLES; - if ( - sql_command == SQLCOM_UNLOCK_TABLES && - (error_num = spider_check_trx_and_get_conn(thd, this, - FALSE)) - ) { - DBUG_RETURN(error_num); - } + wide_handler->sql_command = thd_sql_command(thd); + if (wide_handler->sql_command == SQLCOM_BEGIN) + wide_handler->sql_command = SQLCOM_UNLOCK_TABLES; - DBUG_PRINT("info",("spider sql_command=%d", sql_command)); - DBUG_ASSERT(trx == spider_get_trx(thd, TRUE, &error_num)); + trx = spider_get_trx(thd, TRUE, &error_num); + if (error_num) + DBUG_RETURN(error_num); + wide_handler->trx = trx; + + DBUG_PRINT("info",("spider sql_command=%d", wide_handler->sql_command)); #ifdef HA_CAN_BULK_ACCESS - external_lock_cnt++; + wide_handler->external_lock_cnt++; #endif if ( lock_type == F_UNLCK && - sql_command != SQLCOM_UNLOCK_TABLES + wide_handler->sql_command != SQLCOM_UNLOCK_TABLES ) DBUG_RETURN(0); if (store_error_num) DBUG_RETURN(store_error_num); + wide_handler->external_lock_type = lock_type; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if ((conn_kinds & SPIDER_CONN_KIND_MYSQL)) { #endif if ( /* SQLCOM_RENAME_TABLE and SQLCOM_DROP_DB don't come here */ - sql_command == SQLCOM_DROP_TABLE || - sql_command == SQLCOM_ALTER_TABLE + wide_handler->sql_command == SQLCOM_DROP_TABLE || + wide_handler->sql_command == SQLCOM_ALTER_TABLE ) { if (trx->locked_connections) { @@ -1299,277 +1309,59 @@ int ha_spider::external_lock( } DBUG_RETURN(0); } - if (!conns[search_link_idx]) + if (unlikely((error_num = spider_internal_start_trx(this)))) { - my_message(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM, - ER_SPIDER_REMOTE_SERVER_GONE_AWAY_STR, MYF(0)); - DBUG_RETURN(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM); - } - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - if (sql_command == SQLCOM_TRUNCATE) - DBUG_RETURN(0); - else if (sql_command != SQLCOM_UNLOCK_TABLES) - { - DBUG_PRINT("info",("spider conns[%d]->join_trx=%u", - roop_count, conns[roop_count]->join_trx)); - if ( - (!conns[roop_count]->join_trx && - (error_num = spider_internal_start_trx(this, conns[roop_count], - roop_count))) - ) { - if ( - share->monitoring_kind[roop_count] && - need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_RETURN(check_error_mode(error_num)); - } - result_list.lock_type = lock_type; - reset_first_link_idx(); - if ( - conns[roop_count]->semi_trx_isolation == -2 && - conns[roop_count]->semi_trx_isolation_chk == TRUE && - sync_trx_isolation && - spider_param_semi_trx_isolation(trx->thd) >= 0 - ) { -/* - if (conns[roop_count]->trx_isolation != - spider_param_semi_trx_isolation(trx->thd)) - { -*/ - spider_conn_queue_semi_trx_isolation(conns[roop_count], - spider_param_semi_trx_isolation(trx->thd)); -/* - } - conns[roop_count]->semi_trx_isolation = - spider_param_semi_trx_isolation(trx->thd); - conns[roop_count]->trx_isolation = - thd_tx_isolation(conns[roop_count]->thd); - DBUG_PRINT("info",("spider conn=%p", conns[roop_count])); - DBUG_PRINT("info",("spider conn->trx_isolation=%d", - conns[roop_count]->trx_isolation)); -*/ - } else { - if (sync_trx_isolation) - { - if ((error_num = spider_check_and_set_trx_isolation( - conns[roop_count], &need_mons[roop_count]))) - { - if ( - share->monitoring_kind[roop_count] && - need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_RETURN(check_error_mode(error_num)); - } - } - conns[roop_count]->semi_trx_isolation = -1; - } - } - if (conns[roop_count]->table_lock >= 2) - { - if ( - conns[roop_count]->db_conn->have_lock_table_list() && - (error_num = spider_db_lock_tables(this, roop_count)) - ) { - if ( - share->monitoring_kind[roop_count] && - need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - conns[roop_count]->table_lock = 0; - DBUG_RETURN(check_error_mode(error_num)); - } - if (conns[roop_count]->table_lock == 2) - conns[roop_count]->table_lock = 1; - } else if (sql_command == SQLCOM_UNLOCK_TABLES || - spider_param_internal_unlock(thd) == 1) - { - if (conns[roop_count]->table_lock == 1) - { - conns[roop_count]->table_lock = 0; - if (!conns[roop_count]->trx_start) - conns[roop_count]->disable_reconnect = FALSE; - if ((error_num = spider_db_unlock_tables(this, roop_count))) - { - if ( - share->monitoring_kind[roop_count] && - need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_RETURN(check_error_mode(error_num)); - } - } - } + DBUG_RETURN(error_num); } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { - result_list.lock_type = lock_type; - reset_first_link_idx(); trans_register_ha(trx->thd, FALSE, spider_hton_ptr); if (thd_test_options(trx->thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) trans_register_ha(trx->thd, TRUE, spider_hton_ptr); } +#endif - if ((conn_kinds & SPIDER_CONN_KIND_HS_READ)) + if (wide_handler->lock_table_type > 0 || + wide_handler->sql_command == SQLCOM_UNLOCK_TABLES) { - SPIDER_CONN *hs_conn; - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - hs_conn = hs_r_conns[roop_count]; - if ( - hs_conn && - hs_conn->hsc_query_id != thd->query_id && - hs_conn->hs_pre_age == hs_conn->hs_age - ) { - double interval = spider_param_hs_ping_interval(thd); - time_t tmp_time = (time_t) time((time_t*) 0); - DBUG_PRINT("info", - ("spider difftime=%f", difftime(tmp_time, hs_conn->ping_time))); - DBUG_PRINT("info", ("spider interval=%f", interval)); - if ( - hs_conn->server_lost || - difftime(tmp_time, hs_conn->ping_time) >= interval - ) { - DBUG_PRINT("info", ("spider hsr[%d] need reconnect", roop_count)); - hs_conn->hs_pre_age++; - hs_conn->ping_time = tmp_time; - } - hs_conn->hsc_query_id = thd->query_id; - } + if (wide_handler->sql_command == SQLCOM_UNLOCK_TABLES) + { + /* lock tables does not call reset() */ + /* unlock tables does not call store_lock() */ + wide_handler->lock_table_type = 0; } - } - if ( -#if defined(HS_HAS_SQLCOM) && defined(HANDLER_HAS_DIRECT_UPDATE_ROWS) - ( -#endif - conn_kinds & SPIDER_CONN_KIND_HS_WRITE -#if defined(HS_HAS_SQLCOM) && defined(HANDLER_HAS_DIRECT_UPDATE_ROWS) - ) || - /* for direct_update */ - sql_command == SQLCOM_HS_UPDATE || - sql_command == SQLCOM_HS_DELETE -#endif - ) { - SPIDER_CONN *hs_conn; - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - hs_conn = hs_w_conns[roop_count]; - if ( - hs_conn && - hs_conn->hsc_query_id != thd->query_id && - hs_conn->hs_pre_age == hs_conn->hs_age - ) { - double interval = spider_param_hs_ping_interval(thd); - time_t tmp_time = (time_t) time((time_t*) 0); - DBUG_PRINT("info", - ("spider difftime=%f", difftime(tmp_time, hs_conn->ping_time))); - DBUG_PRINT("info", ("spider interval=%f", interval)); - if ( - hs_conn->server_lost || - difftime(tmp_time, hs_conn->ping_time) >= interval - ) { - DBUG_PRINT("info", ("spider hsw[%d] need reconnect", roop_count)); - hs_conn->hs_pre_age++; - hs_conn->ping_time = tmp_time; - } - hs_conn->hsc_query_id = thd->query_id; - } - } - } -#endif - DBUG_PRINT("info",("spider trx_start=%s", trx->trx_start ? "TRUE" : "FALSE")); + /* lock/unlock tables */ +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (partition_handler_share && partition_handler_share->handlers) + { + uint roop_count; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) + { + if (unlikely((error_num = + partition_handler_share->handlers[roop_count]->lock_tables()))) + { + DBUG_RETURN(error_num); + } + } + } else { +#endif + if (unlikely((error_num = lock_tables()))) + { + DBUG_RETURN(error_num); + } +#ifdef WITH_PARTITION_STORAGE_ENGINE + } +#endif + } + + DBUG_PRINT("info",("spider trx_start=%s", + trx->trx_start ? "TRUE" : "FALSE")); /* need to check after spider_internal_start_trx() */ if (trx->trx_start) { - switch (sql_command) + switch (wide_handler->sql_command) { case SQLCOM_SELECT: case SQLCOM_HA_READ: @@ -1604,6 +1396,24 @@ int ha_spider::external_lock( DBUG_RETURN(0); } +int ha_spider::start_stmt( + THD *thd, + thr_lock_type lock_type +) { + DBUG_ENTER("ha_spider::start_stmt"); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_START_STMT && + wide_handler->stage_executor != this) + { + DBUG_RETURN(0); + } + wide_handler->stage = SPD_HND_STAGE_START_STMT; + wide_handler->stage_executor = this; +#endif + DBUG_RETURN(0); +} + int ha_spider::reset() { int error_num = 0, error_num2, roop_count; @@ -1673,25 +1483,49 @@ int ha_spider::reset() #endif result_list.direct_distinct = FALSE; store_error_num = 0; -#ifdef WITH_PARTITION_STORAGE_ENGINE if ( - partition_handler_share && - partition_handler_share->searched_bitmap + wide_handler && + wide_handler->sql_command != SQLCOM_END ) { + wide_handler->sql_command = SQLCOM_END; + wide_handler->between_flg = FALSE; + wide_handler->idx_bitmap_is_set = FALSE; + wide_handler->rnd_bitmap_is_set = FALSE; + wide_handler->quick_mode = FALSE; + wide_handler->keyread = FALSE; + wide_handler->ignore_dup_key = FALSE; + wide_handler->write_can_replace = FALSE; + wide_handler->insert_with_update = FALSE; + wide_handler->low_priority = FALSE; + wide_handler->high_priority = FALSE; + wide_handler->insert_delayed = FALSE; + wide_handler->lock_table_type = 0; + wide_handler->semi_trx_isolation_chk = FALSE; + wide_handler->semi_trx_chk = FALSE; if (!is_clone) { - partition_handler_share->searched_bitmap = NULL; - partition_handler_share->ft_discard_bitmap = NULL; + memset(wide_handler->ft_discard_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0, + no_bytes_in_map(table->read_set)); } - partition_handler_share->between_flg = FALSE; - partition_handler_share->idx_bitmap_is_set = FALSE; - partition_handler_share->rnd_bitmap_is_set = FALSE; - } + while (wide_handler->condition) + { + tmp_cond = wide_handler->condition->next; + spider_free(spider_current_trx, wide_handler->condition, MYF(0)); + wide_handler->condition = tmp_cond; + } + wide_handler->cond_check = FALSE; +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + wide_handler->direct_update_fields = NULL; +#endif +#ifdef INFO_KIND_FORCE_LIMIT_BEGIN + wide_handler->info_limit = 9223372036854775807LL; +#endif +#ifdef WITH_PARTITION_STORAGE_ENGINE + wide_handler->stage = SPD_HND_STAGE_NONE; + wide_handler->stage_executor = NULL; #endif - if (!is_clone) - { - memset(ft_discard_bitmap, 0xFF, no_bytes_in_map(table->read_set)); - memset(searched_bitmap, 0, no_bytes_in_map(table->read_set)); } if (!(tmp_trx = spider_get_trx(thd, TRUE, &error_num2))) { @@ -1701,82 +1535,11 @@ int ha_spider::reset() } if (share) { - trx_bak = trx; - trx = tmp_trx; + trx_bak = wide_handler->trx; + wide_handler->trx = tmp_trx; if ((error_num2 = spider_db_free_result(this, FALSE))) error_num = error_num2; - trx = trx_bak; -/* - int semi_table_lock_conn = spider_param_semi_table_lock_connection(thd, - share->semi_table_lock_conn); - if (semi_table_lock_conn) - first_byte = '0' + - spider_param_semi_table_lock(thd, share->semi_table_lock); - else - first_byte = '0'; - DBUG_PRINT("info",("spider semi_table_lock_conn = %d", - semi_table_lock_conn)); - DBUG_PRINT("info",("spider semi_table_lock = %d", - spider_param_semi_table_lock(thd, share->semi_table_lock))); - DBUG_PRINT("info",("spider first_byte = %d", first_byte)); - if (tmp_trx->spider_thread_id != spider_thread_id || - (tmp_trx->trx_conn_adjustment != trx_conn_adjustment && - tmp_trx->trx_conn_adjustment - 1 != trx_conn_adjustment) || - first_byte != *conn_keys[0] - ) { - DBUG_PRINT("info",(first_byte != *conn_keys[0] ? - "spider change conn type" : tmp_trx != trx ? "spider change thd" : - "spider next trx")); - trx = tmp_trx; - spider_thread_id = tmp_trx->spider_thread_id; - trx_conn_adjustment = tmp_trx->trx_conn_adjustment; - - first_byte_bak = *conn_keys[0]; - *conn_keys[0] = first_byte; - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - *conn_keys[roop_count] = first_byte; - if ( - !(conns[roop_count] = - spider_get_conn(share, roop_count, conn_keys[roop_count], trx, - this, FALSE, TRUE, SPIDER_CONN_KIND_MYSQL, &error_num)) - ) { - if ( - share->monitoring_kind[roop_count] && - need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_PRINT("info",("spider get conn error")); - *conn_keys[0] = first_byte_bak; - conns[0] = NULL; - DBUG_RETURN(error_num); - } - } - } -*/ + wide_handler->trx = trx_bak; memset(need_mons, 0, sizeof(int) * share->link_count); memset(result_list.casual_read, 0, sizeof(int) * share->link_count); rm_bulk_tmp_table(); @@ -1806,19 +1569,12 @@ int ha_spider::reset() } } } - quick_mode = FALSE; - keyread = FALSE; - ignore_dup_key = FALSE; - write_can_replace = FALSE; - insert_with_update = FALSE; - low_priority = FALSE; - high_priority = FALSE; - insert_delayed = FALSE; + dml_inited = FALSE; use_pre_call = FALSE; use_pre_action = FALSE; pre_bitmap_checked = FALSE; bulk_insert = FALSE; - clone_bitmap_init = FALSE; + partition_handler_share->clone_bitmap_init = FALSE; result_list.tmp_table_join = FALSE; result_list.use_union = FALSE; result_list.use_both_key = FALSE; @@ -1826,13 +1582,6 @@ int ha_spider::reset() conn_kinds = SPIDER_CONN_KIND_MYSQL; use_index_merge = FALSE; init_rnd_handler = FALSE; - while (condition) - { - tmp_cond = condition->next; - spider_free(spider_current_trx, condition, MYF(0)); - condition = tmp_cond; - } - cond_check = FALSE; #ifdef HA_MRR_USE_DEFAULT_IMPL if (multi_range_keys) { @@ -1855,10 +1604,6 @@ int ha_spider::reset() #endif #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS do_direct_update = FALSE; - direct_update_fields = NULL; -#endif -#ifdef INFO_KIND_FORCE_LIMIT_BEGIN - info_limit = 9223372036854775807LL; #endif prev_index_rnd_init = SPD_NONE; result_list.have_sql_kind_backup = FALSE; @@ -1896,55 +1641,64 @@ int ha_spider::extra( DBUG_ENTER("ha_spider::extra"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider operation=%d", (int) operation)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_EXTRA && + wide_handler->stage_executor != this) + { + DBUG_RETURN(0); + } + wide_handler->stage = SPD_HND_STAGE_EXTRA; + wide_handler->stage_executor = this; +#endif switch (operation) { case HA_EXTRA_QUICK: - quick_mode = TRUE; + wide_handler->quick_mode = TRUE; break; case HA_EXTRA_KEYREAD: if (!is_clone) { - keyread = TRUE; + wide_handler->keyread = TRUE; #ifdef WITH_PARTITION_STORAGE_ENGINE - if (update_request) + if (wide_handler->update_request) { if (check_partitioned()) - keyread = FALSE; + wide_handler->keyread = FALSE; } #endif } break; case HA_EXTRA_NO_KEYREAD: - keyread = FALSE; + wide_handler->keyread = FALSE; break; case HA_EXTRA_IGNORE_DUP_KEY: - ignore_dup_key = TRUE; + wide_handler->ignore_dup_key = TRUE; break; case HA_EXTRA_NO_IGNORE_DUP_KEY: - ignore_dup_key = FALSE; + wide_handler->ignore_dup_key = FALSE; break; case HA_EXTRA_WRITE_CAN_REPLACE: - write_can_replace = TRUE; + wide_handler->write_can_replace = TRUE; break; case HA_EXTRA_WRITE_CANNOT_REPLACE: - write_can_replace = FALSE; + wide_handler->write_can_replace = FALSE; break; #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS case HA_EXTRA_INSERT_WITH_UPDATE: - insert_with_update = TRUE; - check_insert_dup_update_pushdown(); + wide_handler->insert_with_update = TRUE; break; #endif case HA_EXTRA_ATTACH_CHILDREN: DBUG_PRINT("info",("spider HA_EXTRA_ATTACH_CHILDREN")); - if (!(trx = spider_get_trx(ha_thd(), TRUE, &error_num))) + if (!(wide_handler->trx = spider_get_trx(ha_thd(), TRUE, &error_num))) DBUG_RETURN(error_num); break; #if MYSQL_VERSION_ID < 50500 #else case HA_EXTRA_ADD_CHILDREN_LIST: DBUG_PRINT("info",("spider HA_EXTRA_ADD_CHILDREN_LIST")); - if (!(trx = spider_get_trx(ha_thd(), TRUE, &error_num))) + if (!(wide_handler->trx = spider_get_trx(ha_thd(), TRUE, &error_num))) DBUG_RETURN(error_num); break; #endif @@ -1967,7 +1721,8 @@ int ha_spider::extra( part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++ ) { - spider_set_bit(searched_bitmap, key_part->field->field_index); + spider_set_bit(wide_handler->searched_bitmap, + key_part->field->field_index); } } else { DBUG_PRINT("info",("spider need all columns")); @@ -1977,7 +1732,7 @@ int ha_spider::extra( *field; field++ ) { - spider_set_bit(searched_bitmap, (*field)->field_index); + spider_set_bit(wide_handler->searched_bitmap, (*field)->field_index); } } break; @@ -2009,6 +1764,13 @@ int ha_spider::index_init( } } #endif + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } pushed_pos = NULL; active_index = idx; result_list.sorted = sorted; @@ -2020,20 +1782,21 @@ int ha_spider::index_init( if (pre_bitmap_checked) pre_bitmap_checked = FALSE; else { - if (result_list.lock_type == F_WRLCK) + if (wide_handler->external_lock_type == F_WRLCK) { pk_update = FALSE; /* check_and_start_bulk_update(SPD_BU_START_BY_INDEX_OR_RND_INIT); */ if ( - update_request && + wide_handler->update_request && share->have_recovery_link && (pk_update = spider_check_pk_update(table)) ) { bitmap_set_all(table->read_set); if (is_clone) - memset(searched_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); } } @@ -2127,7 +1890,7 @@ int ha_spider::index_read_map_internal( backup_error_status(); DBUG_ENTER("ha_spider::index_read_map_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -2172,7 +1935,7 @@ int ha_spider::index_read_map_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -2287,7 +2050,8 @@ int ha_spider::index_read_map_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -2299,8 +2063,8 @@ int ha_spider::index_read_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2363,7 +2127,7 @@ int ha_spider::index_read_map_internal( conn_kind[roop_count] != SPIDER_CONN_KIND_MYSQL ) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } else { @@ -2383,8 +2147,8 @@ int ha_spider::index_read_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2402,7 +2166,7 @@ int ha_spider::index_read_map_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -2417,8 +2181,8 @@ int ha_spider::index_read_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2448,8 +2212,8 @@ int ha_spider::index_read_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2638,7 +2402,7 @@ int ha_spider::index_read_last_map_internal( backup_error_status(); DBUG_ENTER("ha_spider::index_read_last_map_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -2692,7 +2456,7 @@ int ha_spider::index_read_last_map_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -2783,7 +2547,8 @@ int ha_spider::index_read_last_map_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -2795,8 +2560,8 @@ int ha_spider::index_read_last_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2856,7 +2621,7 @@ int ha_spider::index_read_last_map_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } else { @@ -2876,8 +2641,8 @@ int ha_spider::index_read_last_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2895,7 +2660,7 @@ int ha_spider::index_read_last_map_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -2910,8 +2675,8 @@ int ha_spider::index_read_last_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -2941,8 +2706,8 @@ int ha_spider::index_read_last_map_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3025,7 +2790,7 @@ int ha_spider::index_next( backup_error_status(); DBUG_ENTER("ha_spider::index_next"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3071,7 +2836,7 @@ int ha_spider::index_prev( backup_error_status(); DBUG_ENTER("ha_spider::index_prev"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3118,7 +2883,7 @@ int ha_spider::index_first_internal( backup_error_status(); DBUG_ENTER("ha_spider::index_first_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3161,7 +2926,7 @@ int ha_spider::index_first_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -3253,7 +3018,8 @@ int ha_spider::index_first_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -3265,8 +3031,8 @@ int ha_spider::index_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3327,7 +3093,7 @@ int ha_spider::index_first_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } else { @@ -3347,8 +3113,8 @@ int ha_spider::index_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3366,7 +3132,7 @@ int ha_spider::index_first_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -3381,8 +3147,8 @@ int ha_spider::index_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3412,8 +3178,8 @@ int ha_spider::index_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3506,7 +3272,7 @@ int ha_spider::index_last_internal( backup_error_status(); DBUG_ENTER("ha_spider::index_last_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3549,7 +3315,7 @@ int ha_spider::index_last_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -3641,7 +3407,8 @@ int ha_spider::index_last_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -3653,8 +3420,8 @@ int ha_spider::index_last_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3715,7 +3482,7 @@ int ha_spider::index_last_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } else { @@ -3735,8 +3502,8 @@ int ha_spider::index_last_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3754,7 +3521,7 @@ int ha_spider::index_last_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -3769,8 +3536,8 @@ int ha_spider::index_last_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3800,8 +3567,8 @@ int ha_spider::index_last_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -3895,7 +3662,7 @@ int ha_spider::index_next_same( backup_error_status(); DBUG_ENTER("ha_spider::index_next_same"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3947,7 +3714,7 @@ int ha_spider::read_range_first_internal( backup_error_status(); DBUG_ENTER("ha_spider::read_range_first_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -3997,7 +3764,7 @@ int ha_spider::read_range_first_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -4089,7 +3856,8 @@ int ha_spider::read_range_first_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -4101,8 +3869,8 @@ int ha_spider::read_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4162,7 +3930,7 @@ int ha_spider::read_range_first_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } else { @@ -4182,8 +3950,8 @@ int ha_spider::read_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4201,7 +3969,7 @@ int ha_spider::read_range_first_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -4216,8 +3984,8 @@ int ha_spider::read_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4247,8 +4015,8 @@ int ha_spider::read_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4338,7 +4106,7 @@ int ha_spider::read_range_next() backup_error_status(); DBUG_ENTER("ha_spider::read_range_next"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -4390,17 +4158,18 @@ ha_rows ha_spider::multi_range_read_info_const( DBUG_PRINT("info",("spider this=%p", this)); if (!pre_bitmap_checked) { - if (result_list.lock_type == F_WRLCK) + if (wide_handler->external_lock_type == F_WRLCK) { pk_update = FALSE; if ( - update_request && + wide_handler->update_request && share->have_recovery_link && (pk_update = spider_check_pk_update(table)) ) { bitmap_set_all(table->read_set); if (is_clone) - memset(searched_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); } } @@ -4454,17 +4223,18 @@ ha_rows ha_spider::multi_range_read_info( DBUG_PRINT("info",("spider this=%p", this)); if (!pre_bitmap_checked) { - if (result_list.lock_type == F_WRLCK) + if (wide_handler->external_lock_type == F_WRLCK) { pk_update = FALSE; if ( - update_request && + wide_handler->update_request && share->have_recovery_link && (pk_update = spider_check_pk_update(table)) ) { bitmap_set_all(table->read_set); if (is_clone) - memset(searched_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); } } @@ -4499,7 +4269,7 @@ int ha_spider::multi_range_read_init( uint mode, HANDLER_BUFFER *buf ) { - bka_mode = spider_param_bka_mode(trx->thd, share->bka_mode); + bka_mode = spider_param_bka_mode(wide_handler->trx->thd, share->bka_mode); backup_error_status(); DBUG_ENTER("ha_spider::multi_range_read_init"); DBUG_PRINT("info",("spider this=%p", this)); @@ -4546,12 +4316,12 @@ int ha_spider::read_multi_range_first_internal( backup_error_status(); DBUG_ENTER("ha_spider::multi_range_read_next_first"); #else - bka_mode = spider_param_bka_mode(trx->thd, share->bka_mode); + bka_mode = spider_param_bka_mode(wide_handler->trx->thd, share->bka_mode); backup_error_status(); DBUG_ENTER("ha_spider::read_multi_range_first_internal"); #endif DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -4606,7 +4376,7 @@ int ha_spider::read_multi_range_first_internal( result_list.multi_split_read <= 1 || (sql_kinds & SPIDER_SQL_KIND_HANDLER) ) { - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -4721,7 +4491,8 @@ int ha_spider::read_multi_range_first_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -4733,8 +4504,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4793,7 +4564,7 @@ int ha_spider::read_multi_range_first_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); #ifdef HA_MRR_USE_DEFAULT_IMPL @@ -4819,8 +4590,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4839,7 +4610,7 @@ int ha_spider::read_multi_range_first_internal( if (!error_num) { spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -4854,8 +4625,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4887,8 +4658,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4987,7 +4758,7 @@ int ha_spider::read_multi_range_first_internal( if (error_num) DBUG_RETURN(check_error_mode_eof(error_num)); } else { - bool tmp_high_priority = high_priority; + bool tmp_high_priority = wide_handler->high_priority; bool have_multi_range; #ifdef HA_MRR_USE_DEFAULT_IMPL const uchar *first_mrr_start_key; @@ -4996,7 +4767,7 @@ int ha_spider::read_multi_range_first_internal( uint first_mrr_end_key_length; have_second_range = FALSE; #endif - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -5382,7 +5153,7 @@ int ha_spider::read_multi_range_first_internal( (error_num = set_union_table_name_pos_sql()) ) DBUG_RETURN(error_num); - high_priority = FALSE; + wide_handler->high_priority = FALSE; if ( share->key_hint && (error_num = append_hint_after_table_sql_part( @@ -5457,7 +5228,7 @@ int ha_spider::read_multi_range_first_internal( #ifdef HA_MRR_USE_DEFAULT_IMPL while (!range_res); #endif - high_priority = tmp_high_priority; + wide_handler->high_priority = tmp_high_priority; if ((error_num = append_union_all_end_sql_part( SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); @@ -5516,7 +5287,8 @@ int ha_spider::read_multi_range_first_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -5528,8 +5300,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5591,7 +5363,7 @@ int ha_spider::read_multi_range_first_internal( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); #ifdef HA_MRR_USE_DEFAULT_IMPL @@ -5617,8 +5389,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5643,7 +5415,7 @@ int ha_spider::read_multi_range_first_internal( spider_set_bit(result_list.tmp_table_created, roop_count); result_list.tmp_tables_created = TRUE; spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_TMP_SQL, conn, @@ -5658,8 +5430,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5679,7 +5451,7 @@ int ha_spider::read_multi_range_first_internal( spider_db_discard_multiple_result(this, roop_count, conn); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -5694,8 +5466,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5725,8 +5497,8 @@ int ha_spider::read_multi_range_first_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6010,7 +5782,7 @@ int ha_spider::read_multi_range_next( DBUG_ENTER("ha_spider::read_multi_range_next"); #endif DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -6170,7 +5942,8 @@ int ha_spider::read_multi_range_next( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -6182,8 +5955,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6242,7 +6015,7 @@ int ha_spider::read_multi_range_next( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); #ifdef HA_MRR_USE_DEFAULT_IMPL @@ -6268,8 +6041,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6288,7 +6061,7 @@ int ha_spider::read_multi_range_next( if (!error_num) { spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -6303,8 +6076,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6336,8 +6109,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6533,7 +6306,7 @@ int ha_spider::read_multi_range_next( multi_range_ranges = multi_range_curr; #endif - bool tmp_high_priority = high_priority; + bool tmp_high_priority = wide_handler->high_priority; bool have_multi_range; multi_range_cnt = 0; error_num = 0; @@ -6841,7 +6614,7 @@ int ha_spider::read_multi_range_next( (error_num = set_union_table_name_pos_sql()) ) DBUG_RETURN(error_num); - high_priority = FALSE; + wide_handler->high_priority = FALSE; if ( share->key_hint && (error_num = append_hint_after_table_sql_part( @@ -6911,7 +6684,7 @@ int ha_spider::read_multi_range_next( #ifdef HA_MRR_USE_DEFAULT_IMPL while (!range_res); #endif - high_priority = tmp_high_priority; + wide_handler->high_priority = tmp_high_priority; if ((error_num = append_union_all_end_sql_part(SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); @@ -6969,7 +6742,8 @@ int ha_spider::read_multi_range_next( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -6981,8 +6755,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7044,7 +6818,7 @@ int ha_spider::read_multi_range_next( if (is_bulk_access_clone) { connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(trx, conn); + spider_trx_add_bulk_access_conn(wide_handler->trx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); #ifdef HA_MRR_USE_DEFAULT_IMPL @@ -7070,8 +6844,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7096,7 +6870,7 @@ int ha_spider::read_multi_range_next( spider_set_bit(result_list.tmp_table_created, roop_count); result_list.tmp_tables_created = TRUE; spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_TMP_SQL, conn, @@ -7111,8 +6885,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7132,7 +6906,7 @@ int ha_spider::read_multi_range_next( spider_db_discard_multiple_result(this, roop_count, conn); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -7147,8 +6921,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7178,8 +6952,8 @@ int ha_spider::read_multi_range_next( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7338,15 +7112,22 @@ int ha_spider::rnd_init( DBUG_ENTER("ha_spider::rnd_init"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider scan=%s", scan ? "TRUE" : "FALSE")); + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } pushed_pos = NULL; /* - if (result_list.lock_type == F_WRLCK) + if (wide_handler->external_lock_type == F_WRLCK) check_and_start_bulk_update(SPD_BU_START_BY_INDEX_OR_RND_INIT); */ rnd_scan_and_first = scan; if ( scan && - sql_command != SQLCOM_ALTER_TABLE + wide_handler->sql_command != SQLCOM_ALTER_TABLE ) { spider_set_result_list_param(this); pk_update = FALSE; @@ -7411,14 +7192,15 @@ int ha_spider::rnd_init( use_spatial_index = FALSE; if ( - update_request && + wide_handler->update_request && share->have_recovery_link && - result_list.lock_type == F_WRLCK && + wide_handler->external_lock_type == F_WRLCK && (pk_update = spider_check_pk_update(table)) ) { bitmap_set_all(table->read_set); if (is_clone) - memset(searched_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(wide_handler->searched_bitmap, 0xFF, + no_bytes_in_map(table->read_set)); } set_select_column_mode(); @@ -7488,17 +7270,17 @@ int ha_spider::rnd_next_internal( ) { int error_num; ha_spider *direct_limit_offset_spider = - (ha_spider *) partition_handler_share->creator; + (ha_spider *) partition_handler_share->owner; backup_error_status(); DBUG_ENTER("ha_spider::rnd_next_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); } /* do not copy table data at alter table */ - if (sql_command == SQLCOM_ALTER_TABLE) + if (wide_handler->sql_command == SQLCOM_ALTER_TABLE) DBUG_RETURN(HA_ERR_END_OF_FILE); #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS do_direct_update = FALSE; @@ -7644,7 +7426,8 @@ int ha_spider::rnd_next_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -7656,8 +7439,8 @@ int ha_spider::rnd_next_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7716,8 +7499,8 @@ int ha_spider::rnd_next_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7735,7 +7518,7 @@ int ha_spider::rnd_next_internal( DBUG_RETURN(check_error_mode_eof(error_num)); } spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, conn, @@ -7750,8 +7533,8 @@ int ha_spider::rnd_next_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7781,8 +7564,8 @@ int ha_spider::rnd_next_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7899,15 +7682,15 @@ void ha_spider::position( DBUG_PRINT("info",("spider self position")); DBUG_PRINT("info", ("spider current_row_num=%lld", result_list.current_row_num)); - if (!position_bitmap_init) + if (!wide_handler->position_bitmap_init) { if (select_column_mode) { spider_db_handler *dbton_hdl = dbton_handler[result_list.current->dbton_id]; - dbton_hdl->copy_minimum_select_bitmap(position_bitmap); + dbton_hdl->copy_minimum_select_bitmap(wide_handler->position_bitmap); } - position_bitmap_init = TRUE; + wide_handler->position_bitmap_init = TRUE; } spider_db_create_position(this, (SPIDER_POSITION *) ref); } @@ -7929,7 +7712,7 @@ int ha_spider::rnd_pos( ((uchar *) table->read_set->bitmap)[roop_count])); } #endif - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -8145,7 +7928,7 @@ int ha_spider::ft_read_internal( backup_error_status(); DBUG_ENTER("ha_spider::ft_read_internal"); DBUG_PRINT("info",("spider this=%p", this)); - if (trx->thd->killed) + if (wide_handler->trx->thd->killed) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); DBUG_RETURN(ER_QUERY_INTERRUPTED); @@ -8165,7 +7948,7 @@ int ha_spider::ft_read_internal( DBUG_PRINT("info",("spider result_list.finish_flg = FALSE")); result_list.finish_flg = FALSE; result_list.record_num = 0; - if (keyread) + if (wide_handler->keyread) result_list.keyread = TRUE; else result_list.keyread = FALSE; @@ -8266,7 +8049,8 @@ int ha_spider::ft_read_internal( #ifndef WITHOUT_SPIDER_BG_SEARCH if (result_list.bgs_phase > 0) { - if ((error_num = spider_check_and_init_casual_read(trx->thd, this, + if ((error_num = spider_check_and_init_casual_read( + wide_handler->trx->thd, this, roop_count))) DBUG_RETURN(error_num); if ((error_num = spider_bg_conn_search(this, roop_count, roop_start, @@ -8278,8 +8062,8 @@ int ha_spider::ft_read_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8332,8 +8116,8 @@ int ha_spider::ft_read_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8350,7 +8134,8 @@ int ha_spider::ft_read_internal( } DBUG_RETURN(check_error_mode_eof(error_num)); } - spider_conn_set_timeout_from_share(conn, roop_count, trx->thd, share); + spider_conn_set_timeout_from_share(conn, roop_count, + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_SELECT_SQL, conn, @@ -8365,8 +8150,8 @@ int ha_spider::ft_read_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8396,8 +8181,8 @@ int ha_spider::ft_read_internal( need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8496,7 +8281,7 @@ int ha_spider::info( #ifdef HANDLER_HAS_CAN_USE_FOR_AUTO_INC_INIT auto_inc_temporary = FALSE; #endif - sql_command = thd_sql_command(thd); + wide_handler->sql_command = thd_sql_command(thd); /* if ( sql_command == SQLCOM_DROP_TABLE || @@ -8517,8 +8302,8 @@ int ha_spider::info( } } if ( - sql_command == SQLCOM_DROP_TABLE || - sql_command == SQLCOM_ALTER_TABLE + wide_handler->sql_command == SQLCOM_DROP_TABLE || + wide_handler->sql_command == SQLCOM_ALTER_TABLE ) DBUG_RETURN(0); /* @@ -8549,7 +8334,7 @@ int ha_spider::info( pthread_mutex_unlock(&share->sts_mutex); else { if ((spider_init_error_table = - spider_get_init_error_table(trx, share, FALSE))) + spider_get_init_error_table(wide_handler->trx, share, FALSE))) { DBUG_PRINT("info",("spider diff=%f", difftime(tmp_time, spider_init_error_table->init_error_time))); @@ -8558,7 +8343,7 @@ int ha_spider::info( spider_param_table_init_error_interval()) { pthread_mutex_unlock(&share->sts_mutex); - if (sql_command == SQLCOM_SHOW_CREATE) + if (wide_handler->sql_command == SQLCOM_SHOW_CREATE) { if (thd->is_error()) { @@ -8584,9 +8369,7 @@ int ha_spider::info( if (flag & HA_STATUS_AUTO) { if ( -#ifdef WITH_PARTITION_STORAGE_ENGINE - share->partition_share && -#endif + share->wide_share && tmp_auto_increment_mode == 1 && !share->lgtm_tblhnd_share->auto_increment_init ) { @@ -8619,7 +8402,8 @@ int ha_spider::info( if ( spider_init_error_table || (spider_init_error_table = - spider_get_init_error_table(trx, share, TRUE)) + spider_get_init_error_table(wide_handler->trx, + share, TRUE)) ) { spider_init_error_table->init_error = error_num; if ((spider_init_error_table->init_error_with_message = @@ -8632,7 +8416,7 @@ int ha_spider::info( share->init_error = TRUE; share->init = TRUE; } - if (sql_command == SQLCOM_SHOW_CREATE) + if (wide_handler->sql_command == SQLCOM_SHOW_CREATE) { if (thd->is_error()) { @@ -8657,8 +8441,8 @@ int ha_spider::info( need_mons[search_link_idx] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, search_link_idx, (uint32) share->monitoring_sid[search_link_idx], @@ -8678,7 +8462,8 @@ int ha_spider::info( if ( spider_init_error_table || (spider_init_error_table = - spider_get_init_error_table(trx, share, TRUE)) + spider_get_init_error_table(wide_handler->trx, + share, TRUE)) ) { spider_init_error_table->init_error = error_num; /* @@ -8695,7 +8480,7 @@ int ha_spider::info( share->init_error = TRUE; share->init = TRUE; } - if (sql_command == SQLCOM_SHOW_CREATE) + if (wide_handler->sql_command == SQLCOM_SHOW_CREATE) { if (thd->is_error()) { @@ -8724,7 +8509,7 @@ int ha_spider::info( if ((error_num = spider_create_sts_thread(share))) { pthread_mutex_unlock(&share->sts_mutex); - if (sql_command == SQLCOM_SHOW_CREATE) + if (wide_handler->sql_command == SQLCOM_SHOW_CREATE) { if (thd->is_error()) { @@ -8755,7 +8540,7 @@ int ha_spider::info( { if ((error_num = check_crd())) { - if (sql_command == SQLCOM_SHOW_CREATE) + if (wide_handler->sql_command == SQLCOM_SHOW_CREATE) { if (thd->is_error()) { @@ -8794,8 +8579,7 @@ int ha_spider::info( #ifdef HANDLER_HAS_CAN_USE_FOR_AUTO_INC_INIT auto_inc_temporary = FALSE; #endif -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (share->partition_share && table->next_number_field) + if (share->wide_share && table->next_number_field) { ulonglong first_value, nb_reserved_values; if ( @@ -8832,12 +8616,9 @@ int ha_spider::info( share->lgtm_tblhnd_share->auto_increment_value; } } else { -#endif stats.auto_increment_value = share->lgtm_tblhnd_share->auto_increment_value; -#ifdef WITH_PARTITION_STORAGE_ENGINE } -#endif } } if (flag & HA_STATUS_ERRKEY) @@ -8876,7 +8657,7 @@ ha_rows ha_spider::records_in_range( pthread_mutex_unlock(&share->crd_mutex); else { if ((spider_init_error_table = - spider_get_init_error_table(trx, share, FALSE))) + spider_get_init_error_table(wide_handler->trx, share, FALSE))) { DBUG_PRINT("info",("spider diff=%f", difftime(tmp_time, spider_init_error_table->init_error_time))); @@ -8914,6 +8695,15 @@ ha_rows ha_spider::records_in_range( share->static_key_cardinality[inx] == -1 && difftime(tmp_time, share->crd_get_time) >= crd_interval ) { + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + if (check_error_mode(error_num)) + my_errno = error_num; + DBUG_RETURN(HA_POS_ERROR); + } + } if ( crd_interval == 0 || !pthread_mutex_trylock(&share->crd_mutex) @@ -8939,8 +8729,8 @@ ha_rows ha_spider::records_in_range( need_mons[search_link_idx] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, search_link_idx, (uint32) share->monitoring_sid[search_link_idx], @@ -8960,7 +8750,8 @@ ha_rows ha_spider::records_in_range( if ( spider_init_error_table || (spider_init_error_table = - spider_get_init_error_table(trx, share, TRUE)) + spider_get_init_error_table(wide_handler->trx, + share, TRUE)) ) { spider_init_error_table->init_error = error_num; /* @@ -9148,6 +8939,15 @@ ha_rows ha_spider::records_in_range( DBUG_RETURN((ha_rows) rows); } else if (crd_mode == 3) { + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + if (check_error_mode(error_num)) + my_errno = error_num; + DBUG_RETURN(HA_POS_ERROR); + } + } result_list.key_info = &table->key_info[inx]; DBUG_RETURN(spider_db_explain_select(start_key, end_key, this, search_link_idx)); @@ -9180,7 +8980,7 @@ int ha_spider::check_crd() pthread_mutex_unlock(&share->crd_mutex); else { if ((spider_init_error_table = - spider_get_init_error_table(trx, share, FALSE))) + spider_get_init_error_table(wide_handler->trx, share, FALSE))) { DBUG_PRINT("info",("spider diff=%f", difftime(tmp_time, spider_init_error_table->init_error_time))); @@ -9239,8 +9039,8 @@ int ha_spider::check_crd() need_mons[search_link_idx] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, search_link_idx, (uint32) share->monitoring_sid[search_link_idx], @@ -9260,7 +9060,7 @@ int ha_spider::check_crd() if ( spider_init_error_table || (spider_init_error_table = - spider_get_init_error_table(trx, share, TRUE)) + spider_get_init_error_table(wide_handler->trx, share, TRUE)) ) { spider_init_error_table->init_error = error_num; if ((spider_init_error_table->init_error_with_message = @@ -9320,7 +9120,7 @@ int ha_spider::pre_records() backup_error_status(); DBUG_ENTER("ha_spider::pre_records"); DBUG_PRINT("info",("spider this=%p", this)); - if (sql_command == SQLCOM_ALTER_TABLE) + if (wide_handler->sql_command == SQLCOM_ALTER_TABLE) { DBUG_RETURN(0); } @@ -9328,7 +9128,7 @@ int ha_spider::pre_records() { DBUG_RETURN(0); } - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; if ( spider_param_sync_autocommit(thd) && (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) @@ -9351,7 +9151,7 @@ ha_rows ha_spider::records() backup_error_status(); DBUG_ENTER("ha_spider::records"); DBUG_PRINT("info",("spider this=%p", this)); - if (sql_command == SQLCOM_ALTER_TABLE) + if (wide_handler->sql_command == SQLCOM_ALTER_TABLE) { use_pre_action = FALSE; DBUG_RETURN(0); @@ -9362,7 +9162,7 @@ ha_rows ha_spider::records() } if (!use_pre_action && !this->result_list.direct_limit_offset) { - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; if ( spider_param_sync_autocommit(thd) && (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) @@ -9390,7 +9190,14 @@ int ha_spider::pre_calculate_checksum() backup_error_status(); DBUG_ENTER("ha_spider::pre_calculate_checksum"); DBUG_PRINT("info",("spider this=%p", this)); - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } if ( spider_param_sync_autocommit(thd) && (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) @@ -9414,9 +9221,16 @@ int ha_spider::calculate_checksum() backup_error_status(); DBUG_ENTER("ha_spider::calculate_checksum"); DBUG_PRINT("info",("spider this=%p", this)); + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } if (!use_pre_action && !this->result_list.direct_limit_offset) { - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; if ( spider_param_sync_autocommit(thd) && (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) @@ -9506,6 +9320,36 @@ ulonglong ha_spider::table_flags() const DBUG_RETURN(flags); } +ulong ha_spider::table_flags_for_partition() +{ + DBUG_ENTER("ha_spider::table_flags_for_partition"); + DBUG_PRINT("info",("spider this=%p", this)); + ulong flags = +#ifdef HA_PT_CALL_AT_ONCE_STORE_LOCK + HA_PT_CALL_AT_ONCE_STORE_LOCK | +#endif +#ifdef HA_PT_CALL_AT_ONCE_EXTERNAL_LOCK + HA_PT_CALL_AT_ONCE_EXTERNAL_LOCK | +#endif +#ifdef HA_PT_CALL_AT_ONCE_START_STMT + HA_PT_CALL_AT_ONCE_START_STMT | +#endif +#ifdef HA_PT_CALL_AT_ONCE_EXTRA + HA_PT_CALL_AT_ONCE_EXTRA | +#endif +#ifdef HA_PT_CALL_AT_ONCE_COND_PUSH + HA_PT_CALL_AT_ONCE_COND_PUSH | +#endif +#ifdef HA_PT_CALL_AT_ONCE_INFO_PUSH + HA_PT_CALL_AT_ONCE_INFO_PUSH | +#endif +#ifdef HA_PT_CALL_AT_ONCE_TOP_TABLE + HA_PT_CALL_AT_ONCE_TOP_TABLE | +#endif + 0; + DBUG_RETURN(flags); +} + const char *ha_spider::index_type( uint key_number ) { @@ -9633,7 +9477,7 @@ int ha_spider::update_auto_increment() /* if ( next_insert_id >= auto_inc_interval_for_cur_row.maximum() && - trx->thd->auto_inc_intervals_forced.get_current() + wide_handler->trx->thd->auto_inc_intervals_forced.get_current() ) { force_auto_increment = TRUE; DBUG_PRINT("info",("spider force_auto_increment=TRUE")); @@ -9857,6 +9701,13 @@ int ha_spider::write_row( DBUG_RETURN(error_num); } #endif + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } #ifndef SPIDER_WITHOUT_HA_STATISTIC_INCREMENT ha_statistic_increment(&SSV::ha_write_count); #endif @@ -9919,19 +9770,21 @@ int ha_spider::write_row( if (!bulk_insert || bulk_size < 0) { direct_dup_insert = - spider_param_direct_dup_insert(trx->thd, share->direct_dup_insert); + spider_param_direct_dup_insert(wide_handler->trx->thd, + share->direct_dup_insert); DBUG_PRINT("info",("spider direct_dup_insert=%d", direct_dup_insert)); if ((error_num = spider_db_bulk_insert_init(this, table))) DBUG_RETURN(check_error_mode(error_num)); if (bulk_insert) bulk_size = #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS - (insert_with_update && !result_list.insert_dup_update_pushdown) || + (wide_handler->insert_with_update && + !result_list.insert_dup_update_pushdown) || #else - insert_with_update || + wide_handler->insert_with_update || #endif - (!direct_dup_insert && ignore_dup_key) ? - 0 : spider_param_bulk_size(trx->thd, share->bulk_size); + (!direct_dup_insert && wide_handler->ignore_dup_key) ? + 0 : spider_param_bulk_size(wide_handler->trx->thd, share->bulk_size); else bulk_size = 0; } @@ -9955,7 +9808,7 @@ int ha_spider::pre_write_row( ) { int error_num; ulonglong option_backup = 0; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::pre_write_row"); DBUG_PRINT("info",("spider this=%p", this)); #if MYSQL_VERSION_ID < 50500 @@ -10167,6 +10020,28 @@ int ha_spider::update_row( } #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS +bool ha_spider::check_direct_update_sql_part( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + uint roop_count, dbton_id; + spider_db_handler *dbton_hdl; + DBUG_ENTER("ha_spider::check_direct_update_sql_part"); + for (roop_count = 0; roop_count < share->use_sql_dbton_count; roop_count++) + { + dbton_id = share->use_sql_dbton_ids[roop_count]; + dbton_hdl = dbton_handler[dbton_id]; + if ( + dbton_hdl->first_link_idx >= 0 && + dbton_hdl->check_direct_update(select_lex, select_limit, offset_limit) + ) { + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS #ifdef SPIDER_MDEV_16246 int ha_spider::direct_update_rows_init( @@ -10193,7 +10068,7 @@ int ha_spider::direct_update_rows_init( st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::direct_update_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HA_CAN_BULK_ACCESS @@ -10222,6 +10097,13 @@ int ha_spider::direct_update_rows_init( #endif } #endif + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } direct_update_init( thd, #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -10250,6 +10132,7 @@ int ha_spider::direct_update_rows_init( !select_lex || select_lex->table_list.elements != 1 || check_update_columns_sql_part() || + check_direct_update_sql_part(select_lex, select_limit, offset_limit) || spider_db_append_condition(this, NULL, 0, TRUE) ) { DBUG_PRINT("info",("spider FALSE by condition")); @@ -10271,7 +10154,7 @@ int ha_spider::direct_update_rows_init( } result_list.direct_order_limit = TRUE; } - trx->direct_update_count++; + wide_handler->trx->direct_update_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10314,7 +10197,7 @@ int ha_spider::direct_update_rows_init( DBUG_RETURN(error_num); } #endif - trx->direct_update_count++; + wide_handler->trx->direct_update_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10343,10 +10226,10 @@ int ha_spider::direct_update_rows_init() st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - List_iterator it(*direct_update_fields); + List_iterator it(*wide_handler->direct_update_fields); Item *item; Field *field; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::direct_update_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); if (thd->variables.time_zone != UTC) @@ -10395,14 +10278,21 @@ int ha_spider::direct_update_rows_init() #endif } #endif + if (!dml_inited) + { + if (unlikely(dml_init())) + { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + } direct_update_init( thd, FALSE ); - if (!condition) - cond_check = FALSE; + if (!wide_handler->condition) + wide_handler->cond_check = FALSE; spider_get_select_limit(this, &select_lex, &select_limit, &offset_limit); - if (direct_update_fields) + if (wide_handler->direct_update_fields) { if ( #if MYSQL_VERSION_ID < 50500 @@ -10417,6 +10307,7 @@ int ha_spider::direct_update_rows_init() !select_lex || select_lex->table_list.elements != 1 || check_update_columns_sql_part() || + check_direct_update_sql_part(select_lex, select_limit, offset_limit) || spider_db_append_condition(this, NULL, 0, TRUE) ) { DBUG_PRINT("info",("spider FALSE by condition")); @@ -10438,20 +10329,20 @@ int ha_spider::direct_update_rows_init() } result_list.direct_order_limit = TRUE; } - trx->direct_update_count++; + wide_handler->trx->direct_update_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } DBUG_PRINT("info",("spider offset_limit=%lld", offset_limit)); - DBUG_PRINT("info",("spider sql_command=%u", sql_command)); + DBUG_PRINT("info",("spider sql_command=%u", wide_handler->sql_command)); DBUG_PRINT("info",("spider do_direct_update=%s", do_direct_update ? "TRUE" : "FALSE")); if ( !offset_limit && do_direct_update ) { - trx->direct_update_count++; + wide_handler->trx->direct_update_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10500,6 +10391,13 @@ int ha_spider::pre_direct_update_rows_init( bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } #ifdef SPIDER_MDEV_16246 pre_direct_init_result = direct_update_rows_init( update_fields, mode, ranges, range_count, sorted, new_data); @@ -10544,6 +10442,13 @@ int ha_spider::pre_direct_update_rows_init() bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } #ifdef SPIDER_MDEV_16246 pre_direct_init_result = direct_update_rows_init(update_fields); #else @@ -10760,6 +10665,28 @@ int ha_spider::delete_row( } #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS +bool ha_spider::check_direct_delete_sql_part( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + uint roop_count, dbton_id; + spider_db_handler *dbton_hdl; + DBUG_ENTER("ha_spider::check_direct_delete_sql_part"); + for (roop_count = 0; roop_count < share->use_sql_dbton_count; roop_count++) + { + dbton_id = share->use_sql_dbton_ids[roop_count]; + dbton_hdl = dbton_handler[dbton_id]; + if ( + dbton_hdl->first_link_idx >= 0 && + dbton_hdl->check_direct_delete(select_lex, select_limit, offset_limit) + ) { + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS int ha_spider::direct_delete_rows_init( uint mode, @@ -10773,7 +10700,7 @@ int ha_spider::direct_delete_rows_init( st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::direct_delete_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HA_CAN_BULK_ACCESS @@ -10795,6 +10722,13 @@ int ha_spider::direct_delete_rows_init( mode, ranges, range_count, sorted)); } #endif + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } direct_update_init( thd, #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -10820,6 +10754,7 @@ int ha_spider::direct_delete_rows_init( #endif !select_lex || select_lex->table_list.elements != 1 || + check_direct_delete_sql_part(select_lex, select_limit, offset_limit) || spider_db_append_condition(this, NULL, 0, TRUE) ) { DBUG_PRINT("info",("spider FALSE by condition")); @@ -10841,7 +10776,7 @@ int ha_spider::direct_delete_rows_init( } result_list.direct_order_limit = TRUE; } - trx->direct_delete_count++; + wide_handler->trx->direct_delete_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10864,7 +10799,7 @@ int ha_spider::direct_delete_rows_init( DBUG_RETURN(error_num); } #endif - trx->direct_delete_count++; + wide_handler->trx->direct_delete_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10878,7 +10813,7 @@ int ha_spider::direct_delete_rows_init() st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::direct_delete_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HA_CAN_BULK_ACCESS @@ -10899,12 +10834,19 @@ int ha_spider::direct_delete_rows_init() DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_delete_rows_init()); } #endif + if (!dml_inited) + { + if (unlikely(dml_init())) + { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + } direct_update_init( thd, FALSE ); - if (!condition) - cond_check = FALSE; + if (!wide_handler->condition) + wide_handler->cond_check = FALSE; spider_get_select_limit(this, &select_lex, &select_limit, &offset_limit); if ( #if MYSQL_VERSION_ID < 50500 @@ -10918,6 +10860,7 @@ int ha_spider::direct_delete_rows_init() #endif !select_lex || select_lex->table_list.elements != 1 || + check_direct_delete_sql_part(select_lex, select_limit, offset_limit) || spider_db_append_condition(this, NULL, 0, TRUE) ) { DBUG_PRINT("info",("spider FALSE by condition")); @@ -10939,7 +10882,7 @@ int ha_spider::direct_delete_rows_init() } result_list.direct_order_limit = TRUE; } - trx->direct_delete_count++; + wide_handler->trx->direct_delete_count++; DBUG_PRINT("info",("spider OK")); DBUG_RETURN(0); } @@ -10965,6 +10908,13 @@ int ha_spider::pre_direct_delete_rows_init( bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } pre_direct_init_result = direct_delete_rows_init( mode, ranges, range_count, sorted); DBUG_RETURN(pre_direct_init_result); @@ -10983,6 +10933,13 @@ int ha_spider::pre_direct_delete_rows_init() bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } + if (!dml_inited) + { + if (unlikely((error_num = dml_init()))) + { + DBUG_RETURN(error_num); + } + } pre_direct_init_result = direct_delete_rows_init(); DBUG_RETURN(pre_direct_init_result); } @@ -11146,7 +11103,8 @@ int ha_spider::delete_all_rows() sql_kind[roop_count] = SPIDER_SQL_KIND_SQL; if ((error_num = spider_db_delete_all_rows(this))) DBUG_RETURN(check_error_mode(error_num)); - if (sql_command == SQLCOM_TRUNCATE && table->found_next_number_field) + if (wide_handler->sql_command == SQLCOM_TRUNCATE && + table->found_next_number_field) { DBUG_PRINT("info",("spider reset auto increment")); pthread_mutex_lock(&share->lgtm_tblhnd_share->auto_increment_mutex); @@ -11175,7 +11133,7 @@ int ha_spider::truncate() table_share->db.str, table_share->table_name.str); DBUG_RETURN(ER_SPIDER_READ_ONLY_NUM); } - sql_command = SQLCOM_TRUNCATE; + wide_handler->sql_command = SQLCOM_TRUNCATE; if ((error_num = spider_check_trx_and_get_conn(thd, this, FALSE))) { DBUG_RETURN(error_num); @@ -11188,7 +11146,8 @@ int ha_spider::truncate() sql_kind[roop_count] = SPIDER_SQL_KIND_SQL; if ((error_num = spider_db_delete_all_rows(this))) DBUG_RETURN(check_error_mode(error_num)); - if (sql_command == SQLCOM_TRUNCATE && table->found_next_number_field) + if (wide_handler->sql_command == SQLCOM_TRUNCATE && + table->found_next_number_field) { DBUG_PRINT("info",("spider reset auto increment")); pthread_mutex_lock(&share->lgtm_tblhnd_share->auto_increment_mutex); @@ -11208,10 +11167,10 @@ int ha_spider::truncate() void ha_spider::bulk_req_exec() { int need_mon; - SPIDER_CONN *conn = trx->bulk_access_conn_first; + SPIDER_CONN *conn = wide_handler->trx->bulk_access_conn_first; DBUG_ENTER("ha_spider::bulk_req_exec"); DBUG_PRINT("info",("spider this=%p", this)); - DBUG_PRINT("info",("spider trx=%p", trx)); + DBUG_PRINT("info",("spider trx=%p", wide_handler->trx)); DBUG_PRINT("info",("spider first_conn=%p", conn)); while (conn) { @@ -11248,7 +11207,7 @@ void ha_spider::bulk_req_exec() } conn = conn->bulk_access_next; } - trx->bulk_access_conn_first = NULL; + wide_handler->trx->bulk_access_conn_first = NULL; DBUG_VOID_RETURN; } #endif @@ -11270,7 +11229,7 @@ double ha_spider::read_time( ) { DBUG_ENTER("ha_spider::read_time"); DBUG_PRINT("info",("spider this=%p", this)); - if (keyread) + if (wide_handler->keyread) { DBUG_PRINT("info",("spider read_time(keyread) = %.6f", share->read_rate * table->key_info[index].key_length * @@ -11553,6 +11512,27 @@ void ha_spider::update_create_info( ) { DBUG_ENTER("ha_spider::update_create_info"); DBUG_PRINT("info",("spider this=%p", this)); + if (wide_handler && wide_handler->sql_command == SQLCOM_ALTER_TABLE) + { + SPIDER_TRX *trx = wide_handler->trx; + THD *thd = trx->thd; + if (trx->query_id != thd->query_id) + { + spider_free_trx_alter_table(trx); + trx->query_id = thd->query_id; + trx->tmp_flg = FALSE; + } + if (!(SPIDER_ALTER_TABLE*) my_hash_search(&trx->trx_alter_table_hash, + (uchar*) share->table_name, share->table_name_length)) + { + if (spider_create_trx_alter_table(trx, share, FALSE)) + { + store_error_num = HA_ERR_OUT_OF_MEM; + DBUG_VOID_RETURN; + } + } + } + if (!create_info->connect_string.str) { create_info->connect_string.str = table->s->connect_string.str; @@ -12071,32 +12051,6 @@ bool ha_spider::is_fatal_error( DBUG_RETURN(TRUE); } -Field *ha_spider::get_top_table_field( - uint16 field_index -) { - Field *field; - DBUG_ENTER("ha_spider::get_top_table_field"); -#ifdef HA_CAN_BULK_ACCESS - if (is_bulk_access_clone) - { - DBUG_RETURN(pt_clone_source_handler->get_top_table_field(field_index)); - } -#endif - DBUG_PRINT("info",("spider field_index=%u", field_index)); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - if (set_top_table_fields) - { - field = top_table->field[field_index]; - } else { -#endif - field = table->field[field_index]; -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - } -#endif - DBUG_PRINT("info",("spider out field=%p", field)); - DBUG_RETURN(field); -} - Field *ha_spider::field_exchange( Field *field ) { @@ -12109,22 +12063,9 @@ Field *ha_spider::field_exchange( #endif DBUG_PRINT("info",("spider in field=%p", field)); DBUG_PRINT("info",("spider in field->table=%p", field->table)); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - if (set_top_table_fields) - { - DBUG_PRINT("info",("spider top_table=%p", top_table)); - if (field->table != top_table) - DBUG_RETURN(NULL); - if (!(field = top_table_field[field->field_index])) - DBUG_RETURN(NULL); - } else { -#endif - DBUG_PRINT("info",("spider table=%p", table)); - if (field->table != table) - DBUG_RETURN(NULL); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - } -#endif + DBUG_PRINT("info",("spider table=%p", table)); + if (field->table != table) + DBUG_RETURN(NULL); DBUG_PRINT("info",("spider out field=%p", field)); DBUG_RETURN(field); } @@ -12133,7 +12074,17 @@ const COND *ha_spider::cond_push( const COND *cond ) { DBUG_ENTER("ha_spider::cond_push"); - cond_check = FALSE; +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_COND_PUSH && + wide_handler->stage_executor != this) + { + DBUG_RETURN(NULL); + } + wide_handler->stage = SPD_HND_STAGE_COND_PUSH; + wide_handler->stage_executor = this; +#endif + wide_handler->cond_check = FALSE; if (cond) { SPIDER_CONDITION *tmp_cond; @@ -12142,8 +12093,8 @@ const COND *ha_spider::cond_push( ) DBUG_RETURN(cond); tmp_cond->cond = (COND *) cond; - tmp_cond->next = condition; - condition = tmp_cond; + tmp_cond->next = wide_handler->condition; + wide_handler->condition = tmp_cond; } DBUG_RETURN(NULL); } @@ -12151,11 +12102,21 @@ const COND *ha_spider::cond_push( void ha_spider::cond_pop() { DBUG_ENTER("ha_spider::cond_pop"); - if (condition) +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_COND_POP && + wide_handler->stage_executor != this) { - SPIDER_CONDITION *tmp_cond = condition->next; - spider_free(spider_current_trx, condition, MYF(0)); - condition = tmp_cond; + DBUG_VOID_RETURN; + } + wide_handler->stage = SPD_HND_STAGE_COND_POP; + wide_handler->stage_executor = this; +#endif + if (wide_handler->condition) + { + SPIDER_CONDITION *tmp_cond = wide_handler->condition->next; + spider_free(spider_current_trx, wide_handler->condition, MYF(0)); + wide_handler->condition = tmp_cond; } DBUG_VOID_RETURN; } @@ -12167,6 +12128,16 @@ int ha_spider::info_push( int error_num = 0; DBUG_ENTER("ha_spider::info_push"); DBUG_PRINT("info",("spider this=%p", this)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if ( + wide_handler->stage == SPD_HND_STAGE_INFO_PUSH && + wide_handler->stage_executor != this) + { + DBUG_RETURN(0); + } + wide_handler->stage = SPD_HND_STAGE_INFO_PUSH; + wide_handler->stage_executor = this; +#endif #ifdef HA_CAN_BULK_ACCESS if ( #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS @@ -12206,34 +12177,39 @@ int ha_spider::info_push( size_t roop_count; Field *field; SPIDER_HS_UINT32_INFO *tmp_info = (SPIDER_HS_UINT32_INFO *) info; - hs_pushed_ret_fields_num = tmp_info->info_size; - if (hs_pushed_ret_fields_size < hs_pushed_ret_fields_num) + wide_handler->hs_pushed_ret_fields_num = tmp_info->info_size; + if (wide_handler->hs_pushed_ret_fields_size < + wide_handler->hs_pushed_ret_fields_num) { - if (hs_pushed_ret_fields) - spider_free(spider_current_trx, hs_pushed_ret_fields, MYF(0)); - if (!(hs_pushed_ret_fields = (uint32 *) + if (wide_handler->hs_pushed_ret_fields) + spider_free(spider_current_trx, wide_handler->hs_pushed_ret_fields, + MYF(0)); + if (!(wide_handler->hs_pushed_ret_fields = (uint32 *) spider_bulk_malloc(spider_current_trx, 17, MYF(MY_WME), - &hs_pushed_ret_fields, - (uint) (sizeof(uint32) * hs_pushed_ret_fields_num), + &wide_handler->hs_pushed_ret_fields, + sizeof(uint32) * wide_handler->hs_pushed_ret_fields_num, NullS)) ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - hs_pushed_ret_fields_size = hs_pushed_ret_fields_num; + wide_handler->hs_pushed_ret_fields_size = + wide_handler->hs_pushed_ret_fields_num; } - memcpy(hs_pushed_ret_fields, tmp_info->info, - sizeof(uint32) * hs_pushed_ret_fields_num); + memcpy(wide_handler->hs_pushed_ret_fields, tmp_info->info, + sizeof(uint32) * wide_handler->hs_pushed_ret_fields_num); bitmap_clear_all(table->read_set); bitmap_clear_all(table->write_set); - hs_pushed_lcl_fields_num = 0; - for (roop_count = 0; roop_count < hs_pushed_ret_fields_num; roop_count++) + wide_handler->hs_pushed_lcl_fields_num = 0; + for (roop_count = 0; roop_count < wide_handler->hs_pushed_ret_fields_num; + roop_count++) { - field = get_top_table_field(hs_pushed_ret_fields[roop_count]); + field = get_top_table_field( + wide_handler->hs_pushed_ret_fields[roop_count]); if ((field = field_exchange(field))) { if (!bitmap_is_set(table->read_set, field->field_index)) { - ++hs_pushed_lcl_fields_num; + ++wide_handler->hs_pushed_lcl_fields_num; bitmap_set_bit(table->read_set, field->field_index); bitmap_set_bit(table->write_set, field->field_index); } @@ -12255,172 +12231,168 @@ int ha_spider::info_push( } #endif Field *field; - if (hs_pushed_ret_fields) + if (wide_handler->hs_pushed_ret_fields) { field = get_top_table_field( - hs_pushed_ret_fields[hs_pushed_strref_num]); + wide_handler->hs_pushed_ret_fields[ + wide_handler->hs_pushed_strref_num]); } else { field = get_top_table_field( - pt_clone_source_handler->hs_pushed_ret_fields[hs_pushed_strref_num]); + pt_clone_source_handler->wide_handler->hs_pushed_ret_fields[ + wide_handler->hs_pushed_strref_num]); } if (!field_exchange(field)) { - hs_pushed_strref_num++; + wide_handler->hs_pushed_strref_num++; break; } - hs_pushed_strref_num++; - if ((error_num = push_back_hs_upds(*((SPIDER_HS_STRING_REF*) info)))) + wide_handler->hs_pushed_strref_num++; + if (partition_handler_share && partition_handler_share->handlers) { - DBUG_RETURN(error_num); + size_t roop_count; + ha_spider **handlers = partition_handler_share->handlers; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) + { + if ((error_num = handlers[roop_count]->push_back_hs_upds( + *((SPIDER_HS_STRING_REF*) info)))) + { + DBUG_RETURN(error_num); + } + } + } else { + if ((error_num = push_back_hs_upds(*((SPIDER_HS_STRING_REF*) info)))) + { + DBUG_RETURN(error_num); + } } break; } case INFO_KIND_HS_CLEAR_STRING_REF: DBUG_PRINT("info",("spider INFO_KIND_HS_CLEAR_STRING_REF")); - hs_pushed_strref_num = 0; - if ((error_num = reset_hs_upds(SPIDER_SQL_TYPE_UPDATE_HS))) + wide_handler->hs_pushed_strref_num = 0; + if (partition_handler_share && partition_handler_share->handlers) { - DBUG_RETURN(error_num); + size_t roop_count; + ha_spider **handlers = partition_handler_share->handlers; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) + { + if ((error_num = handlers[roop_count]->reset_hs_upds( + SPIDER_SQL_TYPE_UPDATE_HS))) + { + DBUG_RETURN(error_num); + } + } + } else { + if ((error_num = reset_hs_upds(SPIDER_SQL_TYPE_UPDATE_HS))) + { + DBUG_RETURN(error_num); + } } break; case INFO_KIND_HS_INCREMENT_BEGIN: DBUG_PRINT("info",("spider INFO_KIND_HS_INCREMENT_BEGIN")); - hs_increment = TRUE; + wide_handler->hs_increment = TRUE; break; case INFO_KIND_HS_INCREMENT_END: DBUG_PRINT("info",("spider INFO_KIND_HS_INCREMENT_END")); - hs_increment = FALSE; + wide_handler->hs_increment = FALSE; break; case INFO_KIND_HS_DECREMENT_BEGIN: DBUG_PRINT("info",("spider INFO_KIND_HS_DECREMENT_BEGIN")); - hs_decrement = TRUE; + wide_handler->hs_decrement = TRUE; break; case INFO_KIND_HS_DECREMENT_END: DBUG_PRINT("info",("spider INFO_KIND_HS_DECREMENT_END")); - hs_decrement = FALSE; + wide_handler->hs_decrement = FALSE; break; #endif #ifdef INFO_KIND_UPDATE_FIELDS case INFO_KIND_UPDATE_FIELDS: DBUG_PRINT("info",("spider INFO_KIND_UPDATE_FIELDS")); - direct_update_fields = (List *) info; - update_request = TRUE; + wide_handler->direct_update_fields = (List *) info; + wide_handler->update_request = TRUE; #ifdef WITH_PARTITION_STORAGE_ENGINE - if (keyread && check_partitioned()) - keyread = FALSE; + if (wide_handler->keyread && check_partitioned()) + wide_handler->keyread = FALSE; #endif break; #endif #ifdef INFO_KIND_UPDATE_VALUES case INFO_KIND_UPDATE_VALUES: DBUG_PRINT("info",("spider INFO_KIND_UPDATE_VALUES")); - direct_update_values = (List *) info; + wide_handler->direct_update_values = (List *) info; break; #endif #ifdef INFO_KIND_FORCE_LIMIT_BEGIN case INFO_KIND_FORCE_LIMIT_BEGIN: DBUG_PRINT("info",("spider INFO_KIND_FORCE_LIMIT_BEGIN")); - info_limit = *((longlong *) info); -/* - trx->direct_aggregate_count++; -*/ + wide_handler->info_limit = *((longlong *) info); break; case INFO_KIND_FORCE_LIMIT_END: DBUG_PRINT("info",("spider INFO_KIND_FORCE_LIMIT_END")); - info_limit = 9223372036854775807LL; + wide_handler->info_limit = 9223372036854775807LL; break; #endif #endif #ifdef HA_CAN_BULK_ACCESS case INFO_KIND_BULK_ACCESS_BEGIN: DBUG_PRINT("info",("spider INFO_KIND_BULK_ACCESS_BEGIN")); - if (bulk_access_started) + if (partition_handler_share && partition_handler_share->handlers) { - if (!bulk_access_link_current->next) + size_t roop_count; + ha_spider **handlers = partition_handler_share->handlers; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) { - if (!(bulk_access_link_current->next = create_bulk_access_link())) + if ((error_num = handlers[roop_count]->bulk_access_begin(info))) { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + DBUG_RETURN(error_num); } - bulk_access_link_current->next->sequence_num = - bulk_access_link_current->sequence_num + 1; } - bulk_access_link_current = bulk_access_link_current->next; } else { - if (!bulk_access_link_first) + if ((error_num = bulk_access_begin(info))) { - if (!(bulk_access_link_first = create_bulk_access_link())) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - bulk_access_link_first->sequence_num = 0; + DBUG_RETURN(error_num); } - bulk_access_link_current = bulk_access_link_first; - bulk_access_started = TRUE; - bulk_access_executing = FALSE; } - if ( - (error_num = bulk_access_link_current->spider-> - sync_from_clone_source(this)) || - (error_num = bulk_access_link_current->spider-> - check_access_kind(trx->thd, (lock_type >= TL_WRITE_ALLOW_WRITE))) - ) { - DBUG_RETURN(error_num); - } -#ifdef HA_CAN_BULK_ACCESS -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - memset( - bulk_access_link_current->spider->result_list.hs_r_bulk_open_index, 0, - share->link_bitmap_size); - memset( - bulk_access_link_current->spider->result_list.hs_w_bulk_open_index, 0, - share->link_bitmap_size); -#endif -#endif -/* -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if ((error_num = bulk_access_link_current->spider->reset_hs_strs_pos( - SPIDER_SQL_TYPE_UPDATE_HS))) - { - DBUG_RETURN(error_num); - } -#endif -*/ - bulk_access_link_current->spider->bulk_access_executing = FALSE; - bulk_access_link_current->spider->bulk_access_pre_called = FALSE; - bulk_access_link_current->used = TRUE; - bulk_access_link_current->called = FALSE; - *((void **) info) = bulk_access_link_current; break; case INFO_KIND_BULK_ACCESS_CURRENT: DBUG_PRINT("info",("spider INFO_KIND_BULK_ACCESS_CURRENT")); - bulk_access_executing = TRUE; - bulk_access_link_exec_tgt = (SPIDER_BULK_ACCESS_LINK *) info; - if (bulk_access_link_exec_tgt->spider->pt_clone_source_handler != this) + if (partition_handler_share && partition_handler_share->handlers) { - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_PRINT("info",("spider pt_clone_source_handler=%p", - bulk_access_link_exec_tgt->spider->pt_clone_source_handler)); - /* partitioned */ - uint sequence_num = bulk_access_link_exec_tgt->sequence_num; - for ( - bulk_access_link_exec_tgt = bulk_access_link_first; - bulk_access_link_exec_tgt; - bulk_access_link_exec_tgt = bulk_access_link_exec_tgt->next - ) { - if (bulk_access_link_exec_tgt->sequence_num >= sequence_num) + size_t roop_count; + ha_spider **handlers = partition_handler_share->handlers; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) + { + if ((error_num = handlers[roop_count]->bulk_access_current(info))) { - DBUG_ASSERT( - bulk_access_link_exec_tgt->sequence_num == sequence_num); - break; + DBUG_RETURN(error_num); } } + } else { + if ((error_num = bulk_access_current(info))) + { + DBUG_RETURN(error_num); + } } - bulk_access_link_exec_tgt->spider->bulk_access_executing = TRUE; break; case INFO_KIND_BULK_ACCESS_END: DBUG_PRINT("info",("spider INFO_KIND_BULK_ACCESS_END")); - bulk_access_started = FALSE; + if (partition_handler_share && partition_handler_share->handlers) + { + size_t roop_count; + ha_spider **handlers = partition_handler_share->handlers; + for (roop_count = 0; roop_count < partition_handler_share->no_parts; + ++roop_count) + { + handlers[roop_count]->bulk_access_end(); + } + } else { + bulk_access_end(); + } break; #endif default: @@ -12446,16 +12418,6 @@ TABLE *ha_spider::get_table() DBUG_RETURN(table); } -TABLE *ha_spider::get_top_table() -{ - DBUG_ENTER("ha_spider::get_top_table"); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - if (set_top_table_fields) - DBUG_RETURN(top_table); -#endif - DBUG_RETURN(table); -} - void ha_spider::set_ft_discard_bitmap() { DBUG_ENTER("ha_spider::set_ft_discard_bitmap"); @@ -12486,7 +12448,8 @@ void ha_spider::set_ft_discard_bitmap() if (!field || !(field = field_exchange(field))) continue; DBUG_PRINT("info",("spider clear_bit=%u", field->field_index)); - spider_clear_bit(ft_discard_bitmap, field->field_index); + spider_clear_bit(wide_handler->ft_discard_bitmap, + field->field_index); } } } @@ -12512,7 +12475,8 @@ void ha_spider::set_ft_discard_bitmap() if (!field || !(field = field_exchange(field))) continue; DBUG_PRINT("info",("spider field_index=%u", field->field_index)); - if (!spider_bit_is_set(ft_discard_bitmap, field->field_index)) + if (!spider_bit_is_set(wide_handler->ft_discard_bitmap, + field->field_index)) { bool match_flag = FALSE; List_iterator_fast fmi(*select_lex->ftfunc_list); @@ -12538,7 +12502,8 @@ void ha_spider::set_ft_discard_bitmap() if (!match_flag) { DBUG_PRINT("info",("spider set_bit=%u", field->field_index)); - spider_set_bit(ft_discard_bitmap, field->field_index); + spider_set_bit(wide_handler->ft_discard_bitmap, + field->field_index); } } } @@ -12554,18 +12519,19 @@ void ha_spider::set_searched_bitmap() for (roop_count = 0; roop_count < (int) ((table_share->fields + 7) / 8); roop_count++) { - searched_bitmap[roop_count] = + wide_handler->searched_bitmap[roop_count] = ((uchar *) table->read_set->bitmap)[roop_count] | ((uchar *) table->write_set->bitmap)[roop_count]; DBUG_PRINT("info",("spider roop_count=%d", roop_count)); DBUG_PRINT("info",("spider searched_bitmap=%d", - searched_bitmap[roop_count])); + wide_handler->searched_bitmap[roop_count])); DBUG_PRINT("info",("spider read_set=%d", ((uchar *) table->read_set->bitmap)[roop_count])); DBUG_PRINT("info",("spider write_set=%d", ((uchar *) table->write_set->bitmap)[roop_count])); } - if (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_UPDATE_MULTI) + if (wide_handler->sql_command == SQLCOM_UPDATE || + wide_handler->sql_command == SQLCOM_UPDATE_MULTI) { DBUG_PRINT("info",("spider update option start")); Item *item; @@ -12581,7 +12547,7 @@ void ha_spider::set_searched_bitmap() DBUG_PRINT("info",("spider field is for different table")); continue; } - spider_set_bit(searched_bitmap, field->field_index); + spider_set_bit(wide_handler->searched_bitmap, field->field_index); DBUG_PRINT("info",("spider set searched_bitmap=%u", field->field_index)); } else { @@ -12595,23 +12561,26 @@ void ha_spider::set_searched_bitmap() void ha_spider::set_clone_searched_bitmap() { DBUG_ENTER("ha_spider::set_clone_searched_bitmap"); - DBUG_PRINT("info",("spider searched_bitmap=%p", searched_bitmap)); + DBUG_PRINT("info",("spider searched_bitmap=%p", + wide_handler->searched_bitmap)); #ifndef DBUG_OFF int roop_count; for (roop_count = 0; roop_count < (int) ((table_share->fields + 7) / 8); roop_count++) DBUG_PRINT("info", ("spider before searched_bitmap is %x", - ((uchar *) searched_bitmap)[roop_count])); + ((uchar *) wide_handler->searched_bitmap)[roop_count])); #endif - memcpy(searched_bitmap, pt_clone_source_handler->searched_bitmap, + memcpy(wide_handler->searched_bitmap, + pt_clone_source_handler->wide_handler->searched_bitmap, (table_share->fields + 7) / 8); #ifndef DBUG_OFF for (roop_count = 0; roop_count < (int) ((table_share->fields + 7) / 8); roop_count++) DBUG_PRINT("info", ("spider after searched_bitmap is %x", - ((uchar *) searched_bitmap)[roop_count])); + ((uchar *) wide_handler->searched_bitmap)[roop_count])); #endif - memcpy(ft_discard_bitmap, pt_clone_source_handler->ft_discard_bitmap, + memcpy(wide_handler->ft_discard_bitmap, + pt_clone_source_handler->wide_handler->ft_discard_bitmap, (table_share->fields + 7) / 8); DBUG_VOID_RETURN; } @@ -12643,7 +12612,7 @@ void ha_spider::set_searched_bitmap_from_item_list() if (!field || !(field = field_exchange(field))) continue; DBUG_PRINT("info",("spider field_index=%u", field->field_index)); - spider_set_bit(searched_bitmap, field->field_index); + spider_set_bit(wide_handler->searched_bitmap, field->field_index); } DBUG_VOID_RETURN; } @@ -12654,9 +12623,9 @@ void ha_spider::set_select_column_mode() KEY *key_info; KEY_PART_INFO *key_part; Field *field; - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::set_select_column_mode"); - position_bitmap_init = FALSE; + wide_handler->position_bitmap_init = FALSE; #ifndef DBUG_OFF for (roop_count = 0; roop_count < (int) ((table_share->fields + 7) / 8); roop_count++) @@ -12667,72 +12636,48 @@ void ha_spider::set_select_column_mode() share->select_column_mode); if (select_column_mode) { - DBUG_PRINT("info",("spider searched_bitmap=%p", searched_bitmap)); + DBUG_PRINT("info",("spider searched_bitmap=%p", + wide_handler->searched_bitmap)); + set_searched_bitmap(); + set_searched_bitmap_from_item_list(); + if (wide_handler->external_lock_type == F_WRLCK && + wide_handler->sql_command != SQLCOM_SELECT) + { #ifdef WITH_PARTITION_STORAGE_ENGINE - if ( - partition_handler_share && - partition_handler_share->searched_bitmap - ) { - if (partition_handler_share->searched_bitmap != searched_bitmap) - { - memcpy(searched_bitmap, partition_handler_share->searched_bitmap, - (table_share->fields + 7) / 8); - memcpy(ft_discard_bitmap, partition_handler_share->ft_discard_bitmap, - (table_share->fields + 7) / 8); - } - partition_handler_share->between_flg = FALSE; - DBUG_PRINT("info",("spider copy searched_bitmap")); - } else { + uint part_num = 0; + if (wide_handler->update_request) + part_num = check_partitioned(); #endif - set_searched_bitmap(); - set_searched_bitmap_from_item_list(); - if (result_list.lock_type == F_WRLCK && sql_command != SQLCOM_SELECT) - { + if ( #ifdef WITH_PARTITION_STORAGE_ENGINE - uint part_num = 0; - if (update_request) - part_num = check_partitioned(); + part_num || #endif - if ( -#ifdef WITH_PARTITION_STORAGE_ENGINE - part_num || -#endif - table_share->primary_key == MAX_KEY - ) { - /* need all columns */ - for (roop_count = 0; roop_count < (int) table_share->fields; - roop_count++) - spider_set_bit(searched_bitmap, roop_count); - } else { - /* need primary key columns */ - key_info = &table_share->key_info[table_share->primary_key]; - key_part = key_info->key_part; - for (roop_count = 0; - roop_count < (int) spider_user_defined_key_parts(key_info); - roop_count++) - { - field = key_part[roop_count].field; - spider_set_bit(searched_bitmap, field->field_index); - } - } -#ifndef DBUG_OFF - for (roop_count = 0; - roop_count < (int) ((table_share->fields + 7) / 8); + table_share->primary_key == MAX_KEY + ) { + /* need all columns */ + for (roop_count = 0; roop_count < (int) table_share->fields; roop_count++) - DBUG_PRINT("info", ("spider change bitmap is %x", - searched_bitmap[roop_count])); + spider_set_bit(wide_handler->searched_bitmap, roop_count); + } else { + /* need primary key columns */ + key_info = &table_share->key_info[table_share->primary_key]; + key_part = key_info->key_part; + for (roop_count = 0; + roop_count < (int) spider_user_defined_key_parts(key_info); + roop_count++) + { + field = key_part[roop_count].field; + spider_set_bit(wide_handler->searched_bitmap, field->field_index); + } + } +#ifndef DBUG_OFF + for (roop_count = 0; + roop_count < (int) ((table_share->fields + 7) / 8); + roop_count++) + DBUG_PRINT("info", ("spider change bitmap is %x", + wide_handler->searched_bitmap[roop_count])); #endif - } -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (partition_handler_share) - { - partition_handler_share->searched_bitmap = searched_bitmap; - partition_handler_share->ft_discard_bitmap = ft_discard_bitmap; - partition_handler_share->between_flg = TRUE; - DBUG_PRINT("info",("spider set searched_bitmap")); - } } -#endif } DBUG_VOID_RETURN; } @@ -12740,55 +12685,55 @@ void ha_spider::set_select_column_mode() #ifdef WITH_PARTITION_STORAGE_ENGINE void ha_spider::check_select_column(bool rnd) { - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::check_select_column"); select_column_mode = spider_param_select_column_mode(thd, share->select_column_mode); - if (select_column_mode && partition_handler_share) + if (select_column_mode) { if (!rnd) { - if (partition_handler_share->between_flg) + if (wide_handler->between_flg) { - memcpy(partition_handler_share->idx_read_bitmap, + memcpy(wide_handler->idx_read_bitmap, table->read_set->bitmap, (table_share->fields + 7) / 8); - memcpy(partition_handler_share->idx_write_bitmap, + memcpy(wide_handler->idx_write_bitmap, table->write_set->bitmap, (table_share->fields + 7) / 8); - partition_handler_share->between_flg = FALSE; - partition_handler_share->idx_bitmap_is_set = TRUE; + wide_handler->between_flg = FALSE; + wide_handler->idx_bitmap_is_set = TRUE; DBUG_PRINT("info",("spider set idx_bitmap")); - } else if (partition_handler_share->idx_bitmap_is_set) + } else if (wide_handler->idx_bitmap_is_set) { memcpy(table->read_set->bitmap, - partition_handler_share->idx_read_bitmap, + wide_handler->idx_read_bitmap, (table_share->fields + 7) / 8); memcpy(table->write_set->bitmap, - partition_handler_share->idx_write_bitmap, + wide_handler->idx_write_bitmap, (table_share->fields + 7) / 8); DBUG_PRINT("info",("spider copy idx_bitmap")); } } else { if ( - !partition_handler_share->rnd_bitmap_is_set && + !wide_handler->rnd_bitmap_is_set && ( - partition_handler_share->between_flg || - partition_handler_share->idx_bitmap_is_set + wide_handler->between_flg || + wide_handler->idx_bitmap_is_set ) ) { - memcpy(partition_handler_share->rnd_read_bitmap, + memcpy(wide_handler->rnd_read_bitmap, table->read_set->bitmap, (table_share->fields + 7) / 8); - memcpy(partition_handler_share->rnd_write_bitmap, + memcpy(wide_handler->rnd_write_bitmap, table->write_set->bitmap, (table_share->fields + 7) / 8); - partition_handler_share->between_flg = FALSE; - partition_handler_share->rnd_bitmap_is_set = TRUE; + wide_handler->between_flg = FALSE; + wide_handler->rnd_bitmap_is_set = TRUE; DBUG_PRINT("info",("spider set rnd_bitmap")); - } else if (partition_handler_share->rnd_bitmap_is_set) + } else if (wide_handler->rnd_bitmap_is_set) { memcpy(table->read_set->bitmap, - partition_handler_share->rnd_read_bitmap, + wide_handler->rnd_read_bitmap, (table_share->fields + 7) / 8); memcpy(table->write_set->bitmap, - partition_handler_share->rnd_write_bitmap, + wide_handler->rnd_write_bitmap, (table_share->fields + 7) / 8); DBUG_PRINT("info",("spider copy rnd_bitmap")); } @@ -13007,11 +12952,11 @@ int ha_spider::check_ha_range_eof() result_list.use_both_key ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider sql_kind[%u]=%u", search_link_idx, sql_kind[search_link_idx])); - DBUG_PRINT("info",("spider sql_command=%u", sql_command)); + DBUG_PRINT("info",("spider sql_command=%u", wide_handler->sql_command)); if ( result_list.use_both_key && (sql_kind[search_link_idx] & SPIDER_SQL_KIND_HANDLER) && - sql_command != SQLCOM_HA_READ + wide_handler->sql_command != SQLCOM_HA_READ ) { int cmp_result = key_cmp(result_list.key_info->key_part, end_key->key, end_key->length); @@ -13089,8 +13034,8 @@ int ha_spider::drop_tmp_tables() need_mons[roop_count] ) { tmp_error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -13110,7 +13055,7 @@ int ha_spider::drop_tmp_tables() if (!tmp_error_num) { spider_conn_set_timeout_from_share(conn, roop_count, - trx->thd, share); + wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_DROP_TMP_TABLE_SQL, conn, @@ -13125,8 +13070,8 @@ int ha_spider::drop_tmp_tables() need_mons[roop_count] ) { tmp_error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -13245,8 +13190,8 @@ int ha_spider::close_opened_handler( need_mons[link_idx] ) { error_num2 = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -13264,9 +13209,10 @@ int ha_spider::close_opened_handler( error_num = error_num2; } spider_clear_bit(m_handler_opened, link_idx); - if (release_conn) + if (release_conn && !conns[link_idx]->join_trx) { - spider_free_conn_from_trx(trx, conns[link_idx], FALSE, FALSE, NULL); + spider_free_conn_from_trx(wide_handler->trx, conns[link_idx], + FALSE, FALSE, NULL); conns[link_idx] = NULL; } } @@ -13281,8 +13227,8 @@ int ha_spider::close_opened_handler( need_mons[link_idx] ) { error_num2 = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -13300,16 +13246,18 @@ int ha_spider::close_opened_handler( error_num = error_num2; } spider_clear_bit(r_handler_opened, link_idx); - if (release_conn) + if (release_conn && !hs_w_conns[link_idx]->join_trx) { if ( !hs_r_conns[link_idx]->opened_handlers && - trx->trx_hs_r_conn_adjustment == trx_hs_r_conn_adjustment && - spider_param_hs_r_conn_recycle_mode(trx->thd) != 2 + wide_handler->trx->trx_hs_r_conn_adjustment == + trx_hs_r_conn_adjustment && + spider_param_hs_r_conn_recycle_mode(wide_handler->trx->thd) != 2 ) { - trx->trx_hs_r_conn_adjustment++; + wide_handler->trx->trx_hs_r_conn_adjustment++; } - spider_free_conn_from_trx(trx, hs_r_conns[link_idx], FALSE, FALSE, NULL); + spider_free_conn_from_trx(wide_handler->trx, hs_r_conns[link_idx], + FALSE, FALSE, NULL); hs_r_conns[link_idx] = NULL; } } @@ -13323,8 +13271,8 @@ int ha_spider::close_opened_handler( need_mons[link_idx] ) { error_num2 = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -13342,16 +13290,18 @@ int ha_spider::close_opened_handler( error_num = error_num2; } spider_clear_bit(w_handler_opened, link_idx); - if (release_conn) + if (release_conn && !hs_w_conns[link_idx]->join_trx) { if ( !hs_w_conns[link_idx]->opened_handlers && - trx->trx_hs_w_conn_adjustment == trx_hs_w_conn_adjustment && - spider_param_hs_w_conn_recycle_mode(trx->thd) != 2 + wide_handler->trx->trx_hs_w_conn_adjustment == + trx_hs_w_conn_adjustment && + spider_param_hs_w_conn_recycle_mode(wide_handler->trx->thd) != 2 ) { - trx->trx_hs_w_conn_adjustment++; + wide_handler->trx->trx_hs_w_conn_adjustment++; } - spider_free_conn_from_trx(trx, hs_w_conns[link_idx], FALSE, FALSE, NULL); + spider_free_conn_from_trx(wide_handler->trx, hs_w_conns[link_idx], + FALSE, FALSE, NULL); hs_w_conns[link_idx] = NULL; } } @@ -13425,8 +13375,8 @@ int ha_spider::index_handler_init() need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -13532,8 +13482,8 @@ int ha_spider::rnd_handler_init() need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, + wide_handler->trx, + wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -13720,7 +13670,7 @@ void ha_spider::check_pre_call( thd->query_id != partition_handler_share->parallel_search_query_id ) { partition_handler_share->parallel_search_query_id = thd->query_id; - ++trx->parallel_search_count; + ++wide_handler->trx->parallel_search_count; } use_pre_call = use_parallel; if (!use_pre_call) @@ -13742,7 +13692,7 @@ void ha_spider::check_pre_call( #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS void ha_spider::check_insert_dup_update_pushdown() { - THD *thd = trx->thd; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("ha_spider::check_insert_dup_update_pushdown"); DBUG_PRINT("info",("spider this=%p", this)); if (!spider_param_direct_dup_insert(thd, share->direct_dup_insert)) @@ -13750,8 +13700,8 @@ void ha_spider::check_insert_dup_update_pushdown() DBUG_PRINT("info",("spider FALSE by direct_dup_insert")); DBUG_VOID_RETURN; } - direct_update_fields = &thd->lex->update_list; - direct_update_values = &thd->lex->value_list; + wide_handler->direct_update_fields = &thd->lex->update_list; + wide_handler->direct_update_values = &thd->lex->value_list; if (!append_dup_update_pushdown_sql_part(NULL, 0)) { result_list.insert_dup_update_pushdown = TRUE; @@ -13846,14 +13796,14 @@ int ha_spider::sync_from_clone_source( if (!synced_from_clone_source) { DBUG_PRINT("info",("spider synced from clone source all")); - trx = spider->trx; + wide_handler->trx = spider->wide_handler->trx; sql_command = spider->sql_command; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) conn_kinds = spider->conn_kinds; memcpy(conn_kind, spider->conn_kind, sizeof(uint) * share->link_count); #endif - result_list.lock_type = spider->result_list.lock_type; - lock_type = spider->lock_type; + wide_handler->external_lock_type = + spider->wide_handler->external_lock_type; selupd_lock_mode = spider->selupd_lock_mode; update_request = spider->update_request; lock_mode = spider->lock_mode; @@ -13894,8 +13844,8 @@ int ha_spider::sync_from_clone_source( conn_kinds = spider->conn_kinds; memcpy(conn_kind, spider->conn_kind, sizeof(uint) * share->link_count); #endif - result_list.lock_type = spider->result_list.lock_type; - lock_type = spider->lock_type; + wide_handler->external_lock_type = + spider->wide_handler->external_lock_type; selupd_lock_mode = spider->selupd_lock_mode; update_request = spider->update_request; lock_mode = spider->lock_mode; @@ -13903,7 +13853,8 @@ int ha_spider::sync_from_clone_source( insert_delayed = spider->insert_delayed; low_priority = spider->low_priority; - if ((error_num = spider_check_trx_and_get_conn(spider->trx->thd, + if ((error_num = spider_check_trx_and_get_conn( + spider->wide_handler->trx->thd, this, TRUE))) { DBUG_RETURN(error_num); @@ -13945,6 +13896,7 @@ void ha_spider::sync_from_clone_source_base( dbton_hdl = dbton_handler[dbton_id]; dbton_hdl2 = spider->dbton_handler[dbton_id]; dbton_hdl->first_link_idx = dbton_hdl2->first_link_idx; + dbton_hdl->strict_group_by = dbton_hdl2->strict_group_by; } DBUG_VOID_RETURN; } @@ -13960,6 +13912,7 @@ void ha_spider::set_first_link_idx() dbton_id = share->use_dbton_ids[roop_count2]; dbton_hdl = dbton_handler[dbton_id]; dbton_hdl->first_link_idx = -1; + dbton_hdl->strict_group_by = FALSE; } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, @@ -13978,6 +13931,10 @@ void ha_spider::set_first_link_idx() { dbton_hdl->first_link_idx = roop_count; } + if (share->strict_group_bys[all_link_idx]) + { + dbton_hdl->strict_group_by = TRUE; + } } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) dbton_id = share->hs_dbton_ids[all_link_idx]; @@ -13988,6 +13945,10 @@ void ha_spider::set_first_link_idx() { dbton_hdl->first_link_idx = roop_count; } + if (share->strict_group_bys[all_link_idx]) + { + dbton_hdl->strict_group_by = TRUE; + } } #endif } @@ -14896,7 +14857,7 @@ int ha_spider::append_sum_select_sql_part( DBUG_RETURN(error_num); } } - trx->direct_aggregate_count++; + wide_handler->trx->direct_aggregate_count++; DBUG_RETURN(0); } #endif @@ -15860,14 +15821,16 @@ int ha_spider::mk_bulk_tmp_table_and_bulk_start() if ( !tmp_table[roop_count] && !(tmp_table[roop_count] = spider_mk_sys_tmp_table( - trx->thd, table, &result_list.upd_tmp_tbl_prms[roop_count], + wide_handler->trx->thd, table, + &result_list.upd_tmp_tbl_prms[roop_count], &field_name, result_list.update_sqls[roop_count].charset())) ) #else if ( !tmp_table[roop_count] && !(tmp_table[roop_count] = spider_mk_sys_tmp_table( - trx->thd, table, &result_list.upd_tmp_tbl_prms[roop_count], "a", + wide_handler->trx->thd, table, + &result_list.upd_tmp_tbl_prms[roop_count], "a", result_list.update_sqls[roop_count].charset())) ) #endif @@ -15887,7 +15850,8 @@ error_2: if (tmp_table[roop_count - 1]) { tmp_table[roop_count - 1]->file->ha_end_bulk_insert(); - spider_rm_sys_tmp_table(trx->thd, tmp_table[roop_count - 1], + spider_rm_sys_tmp_table(wide_handler->trx->thd, + tmp_table[roop_count - 1], &result_list.upd_tmp_tbl_prms[roop_count - 1]); tmp_table[roop_count - 1] = NULL; } @@ -15916,7 +15880,8 @@ void ha_spider::rm_bulk_tmp_table() { if (tmp_table[roop_count - 1]) { - spider_rm_sys_tmp_table(trx->thd, tmp_table[roop_count - 1], + spider_rm_sys_tmp_table(wide_handler->trx->thd, + tmp_table[roop_count - 1], &result_list.upd_tmp_tbl_prms[roop_count - 1]); tmp_table[roop_count - 1] = NULL; } @@ -16052,3 +16017,512 @@ int ha_spider::set_union_table_name_pos_sql() } DBUG_RETURN(0); } + +int ha_spider::append_lock_tables_list() +{ + int error_num, roop_count; + DBUG_ENTER("ha_spider::append_lock_tables_list"); + DBUG_PRINT("info",("spider lock_table_type=%u", + wide_handler->lock_table_type)); + + if ((error_num = spider_check_trx_and_get_conn(wide_handler->trx->thd, this, + FALSE))) + { + DBUG_RETURN(error_num); + } + + if (wide_handler->lock_table_type == 1) + { + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + SPIDER_CONN *conn = conns[roop_count]; + int appended = 0; + if ((error_num = dbton_handler[conn->dbton_id]-> + append_lock_tables_list(conn, roop_count, &appended))) + { + DBUG_RETURN(error_num); + } + if (appended) + { + conn->table_lock = 2; + } + } + } else if (wide_handler->lock_table_type == 2) + { + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + if ( + conns[roop_count] && + conns[roop_count]->table_lock != 1 && + spider_param_semi_table_lock(wide_handler->trx->thd, + share->semi_table_lock) + ) { + SPIDER_CONN *conn = conns[roop_count]; + int appended = 0; + if ((error_num = dbton_handler[conn->dbton_id]-> + append_lock_tables_list(conn, roop_count, &appended))) + { + DBUG_RETURN(error_num); + } + if (appended) + { + conn->table_lock = 3; + } + } + } + } + DBUG_RETURN(0); +} + +int ha_spider::lock_tables() +{ + int error_num, roop_count; + DBUG_ENTER("ha_spider::lock_tables"); + DBUG_PRINT("info",("spider lock_table_type=%u", + wide_handler->lock_table_type)); + +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if ((conn_kinds & SPIDER_CONN_KIND_MYSQL)) + { +#endif + if (!conns[search_link_idx]) + { + my_message(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM, + ER_SPIDER_REMOTE_SERVER_GONE_AWAY_STR, MYF(0)); + DBUG_RETURN(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM); + } + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + if (wide_handler->sql_command != SQLCOM_UNLOCK_TABLES) + { + DBUG_PRINT("info",("spider conns[%d]->join_trx=%u", + roop_count, conns[roop_count]->join_trx)); + if ( + (!conns[roop_count]->join_trx && + (error_num = spider_internal_start_trx_for_connection(this, + conns[roop_count], + roop_count))) + ) { + if ( + share->monitoring_kind[roop_count] && + need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + wide_handler->trx, + wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(check_error_mode(error_num)); + } + reset_first_link_idx(); + } + if (conns[roop_count]->table_lock >= 2) + { + if ( + conns[roop_count]->db_conn->have_lock_table_list() && + (error_num = spider_db_lock_tables(this, roop_count)) + ) { + if ( + share->monitoring_kind[roop_count] && + need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + wide_handler->trx, + wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + conns[roop_count]->table_lock = 0; + DBUG_RETURN(check_error_mode(error_num)); + } + if (conns[roop_count]->table_lock == 2) + conns[roop_count]->table_lock = 1; + } else if (wide_handler->sql_command == SQLCOM_UNLOCK_TABLES || + spider_param_internal_unlock(wide_handler->trx->thd) == 1) + { + if (conns[roop_count]->table_lock == 1) + { + conns[roop_count]->table_lock = 0; + if (!conns[roop_count]->trx_start) + conns[roop_count]->disable_reconnect = FALSE; + if ((error_num = spider_db_unlock_tables(this, roop_count))) + { + if ( + share->monitoring_kind[roop_count] && + need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + wide_handler->trx, + wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(check_error_mode(error_num)); + } + } + } + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } +#endif + DBUG_RETURN(0); +} + +int ha_spider::dml_init() +{ + int error_num, roop_count; + SPIDER_TRX *trx = wide_handler->trx; + THD *thd = trx->thd; + bool sync_trx_isolation = spider_param_sync_trx_isolation(thd); + DBUG_ENTER("ha_spider::dml_init"); + if (wide_handler->lock_mode == -2) + { + wide_handler->lock_mode = spider_param_selupd_lock_mode(thd, + share->selupd_lock_mode); + } + if ((error_num = check_access_kind_for_connection(thd, + (wide_handler->lock_type >= TL_WRITE_ALLOW_WRITE)))) + { + DBUG_RETURN(error_num); + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if ((conn_kinds & SPIDER_CONN_KIND_MYSQL)) + { +#endif + if (!conns[search_link_idx]) + { + my_message(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM, + ER_SPIDER_REMOTE_SERVER_GONE_AWAY_STR, MYF(0)); + DBUG_RETURN(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM); + } + if (wide_handler->sql_command == SQLCOM_TRUNCATE) + DBUG_RETURN(0); + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + DBUG_PRINT("info",("spider conns[%d]->join_trx=%u", + roop_count, conns[roop_count]->join_trx)); + if ( + (!conns[roop_count]->join_trx && + (error_num = spider_internal_start_trx_for_connection(this, + conns[roop_count], + roop_count))) + ) { + if ( + share->monitoring_kind[roop_count] && + need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + trx, + trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(check_error_mode(error_num)); + } + reset_first_link_idx(); + if ( + conns[roop_count]->semi_trx_isolation == -2 && + conns[roop_count]->semi_trx_isolation_chk == TRUE && + sync_trx_isolation && + spider_param_semi_trx_isolation(trx->thd) >= 0 + ) { + spider_conn_queue_semi_trx_isolation(conns[roop_count], + spider_param_semi_trx_isolation(trx->thd)); + } else { + if (sync_trx_isolation) + { + if ((error_num = spider_check_and_set_trx_isolation( + conns[roop_count], &need_mons[roop_count]))) + { + if ( + share->monitoring_kind[roop_count] && + need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + trx, + trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(check_error_mode(error_num)); + } + } + conns[roop_count]->semi_trx_isolation = -1; + } + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } else { + reset_first_link_idx(); + } + if ((conn_kinds & SPIDER_CONN_KIND_HS_READ)) + { + SPIDER_CONN *hs_conn; + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + hs_conn = hs_r_conns[roop_count]; + if ( + hs_conn && + hs_conn->hsc_query_id != thd->query_id && + hs_conn->hs_pre_age == hs_conn->hs_age + ) { + double interval = spider_param_hs_ping_interval(thd); + time_t tmp_time = (time_t) time((time_t*) 0); + DBUG_PRINT("info", + ("spider difftime=%f", difftime(tmp_time, hs_conn->ping_time))); + DBUG_PRINT("info", ("spider interval=%f", interval)); + if ( + hs_conn->server_lost || + difftime(tmp_time, hs_conn->ping_time) >= interval + ) { + DBUG_PRINT("info", ("spider hsr[%d] need reconnect", roop_count)); + hs_conn->hs_pre_age++; + hs_conn->ping_time = tmp_time; + } + hs_conn->hsc_query_id = thd->query_id; + } + } + } + if ( +#if defined(HS_HAS_SQLCOM) && defined(HANDLER_HAS_DIRECT_UPDATE_ROWS) + ( +#endif + conn_kinds & SPIDER_CONN_KIND_HS_WRITE +#if defined(HS_HAS_SQLCOM) && defined(HANDLER_HAS_DIRECT_UPDATE_ROWS) + ) || + /* for direct_update */ + wide_handler->sql_command == SQLCOM_HS_UPDATE || + wide_handler->sql_command == SQLCOM_HS_DELETE +#endif + ) { + SPIDER_CONN *hs_conn; + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + hs_conn = hs_w_conns[roop_count]; + if ( + hs_conn && + hs_conn->hsc_query_id != thd->query_id && + hs_conn->hs_pre_age == hs_conn->hs_age + ) { + double interval = spider_param_hs_ping_interval(thd); + time_t tmp_time = (time_t) time((time_t*) 0); + DBUG_PRINT("info", + ("spider difftime=%f", difftime(tmp_time, hs_conn->ping_time))); + DBUG_PRINT("info", ("spider interval=%f", interval)); + if ( + hs_conn->server_lost || + difftime(tmp_time, hs_conn->ping_time) >= interval + ) { + DBUG_PRINT("info", ("spider hsw[%d] need reconnect", roop_count)); + hs_conn->hs_pre_age++; + hs_conn->ping_time = tmp_time; + } + hs_conn->hsc_query_id = thd->query_id; + } + } + } +#endif +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + if (wide_handler->insert_with_update) + { + check_insert_dup_update_pushdown(); + } +#endif + dml_inited = TRUE; + DBUG_RETURN(0); +} + +#ifdef HA_CAN_BULK_ACCESS +int ha_spider::bulk_access_begin( + void *info +) { + DBUG_ENTER("ha_spider::bulk_access_begin"); + DBUG_PRINT("info",("spider this=%p", this)); + if (bulk_access_started) + { + if (!bulk_access_link_current->next) + { + if (!(bulk_access_link_current->next = create_bulk_access_link())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + bulk_access_link_current->next->sequence_num = + bulk_access_link_current->sequence_num + 1; + } + bulk_access_link_current = bulk_access_link_current->next; + } else { + if (!bulk_access_link_first) + { + if (!(bulk_access_link_first = create_bulk_access_link())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + bulk_access_link_first->sequence_num = 0; + } + bulk_access_link_current = bulk_access_link_first; + bulk_access_started = TRUE; + bulk_access_executing = FALSE; + } + bulk_access_link_current->spider-> + check_access_kind(wide_handler->trx->thd); + if ( + (error_num = bulk_access_link_current->spider-> + sync_from_clone_source(this)) || + (error_num = bulk_access_link_current->spider-> + check_access_kind_for_connection(wide_handler->trx->thd, + (lock_type >= TL_WRITE_ALLOW_WRITE))) + ) { + DBUG_RETURN(error_num); + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + memset( + bulk_access_link_current->spider->result_list.hs_r_bulk_open_index, 0, + share->link_bitmap_size); + memset( + bulk_access_link_current->spider->result_list.hs_w_bulk_open_index, 0, + share->link_bitmap_size); +#endif + bulk_access_link_current->spider->bulk_access_executing = FALSE; + bulk_access_link_current->spider->bulk_access_pre_called = FALSE; + bulk_access_link_current->used = TRUE; + bulk_access_link_current->called = FALSE; + *((void **) info) = bulk_access_link_current; + DBUG_RETURN(0); +} + +int ha_spider::bulk_access_current( + void *info +) { + DBUG_ENTER("ha_spider::bulk_access_current"); + DBUG_PRINT("info",("spider this=%p", this)); + bulk_access_executing = TRUE; + bulk_access_link_exec_tgt = (SPIDER_BULK_ACCESS_LINK *) info; + if (bulk_access_link_exec_tgt->spider->pt_clone_source_handler != this) + { + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_PRINT("info",("spider pt_clone_source_handler=%p", + bulk_access_link_exec_tgt->spider->pt_clone_source_handler)); + /* partitioned */ + uint sequence_num = bulk_access_link_exec_tgt->sequence_num; + for ( + bulk_access_link_exec_tgt = bulk_access_link_first; + bulk_access_link_exec_tgt; + bulk_access_link_exec_tgt = bulk_access_link_exec_tgt->next + ) { + if (bulk_access_link_exec_tgt->sequence_num >= sequence_num) + { + DBUG_ASSERT( + bulk_access_link_exec_tgt->sequence_num == sequence_num); + break; + } + } + } + bulk_access_link_exec_tgt->spider->bulk_access_executing = TRUE; + DBUG_RETURN(0); +} + +void ha_spider::bulk_access_end() +{ + DBUG_ENTER("ha_spider::bulk_access_end"); + DBUG_PRINT("info",("spider this=%p", this)); + bulk_access_started = FALSE; + DBUG_VOID_RETURN; +} +#endif diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 4a7b685527d..db184baf682 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -52,9 +52,7 @@ struct st_spider_ft_info class ha_spider: public handler { public: - THR_LOCK_DATA lock; SPIDER_SHARE *share; - SPIDER_TRX *trx; ulonglong spider_thread_id; ulonglong trx_conn_adjustment; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -90,18 +88,16 @@ public: int search_link_idx; int result_link_idx; SPIDER_RESULT_LIST result_list; - SPIDER_CONDITION *condition; spider_string *blob_buff; - uchar *searched_bitmap; - uchar *ft_discard_bitmap; - bool position_bitmap_init; - uchar *position_bitmap; SPIDER_POSITION *pushed_pos; SPIDER_POSITION pushed_pos_buf; #ifdef WITH_PARTITION_STORAGE_ENGINE + bool pt_handler_share_owner = FALSE; SPIDER_PARTITION_HANDLER_SHARE *partition_handler_share; - ha_spider *pt_handler_share_creator; #endif + bool wide_handler_owner = FALSE; + SPIDER_WIDE_HANDLER *wide_handler = NULL; + #ifdef HA_CAN_BULK_ACCESS int pre_direct_init_result; bool is_bulk_access_clone; @@ -116,10 +112,8 @@ public: bool init_ha_mem_root; MEM_ROOT ha_mem_root; */ - ulonglong external_lock_cnt; #endif bool is_clone; - bool clone_bitmap_init; ha_spider *pt_clone_source_handler; ha_spider *pt_clone_last_searcher; bool use_index_merge; @@ -161,22 +155,11 @@ public: ha_spider *next; + bool dml_inited; bool rnd_scan_and_first; - bool quick_mode; - bool keyread; - bool ignore_dup_key; - bool write_can_replace; - bool insert_with_update; - bool low_priority; - bool high_priority; - bool insert_delayed; bool use_pre_call; bool use_pre_action; bool pre_bitmap_checked; - enum thr_lock_type lock_type; - int lock_mode; - uint sql_command; - int selupd_lock_mode; bool bulk_insert; #ifdef HANDLER_HAS_NEED_INFO_FOR_AUTO_INC bool info_auto_called; @@ -189,12 +172,9 @@ public: int store_error_num; uint dup_key_idx; int select_column_mode; - bool update_request; bool pk_update; bool force_auto_increment; int bka_mode; - bool cond_check; - int cond_check_error; int error_mode; ulonglong store_last_insert_id; @@ -216,14 +196,7 @@ public: uint32 **hs_w_ret_fields; size_t *hs_r_ret_fields_num; size_t *hs_w_ret_fields_num; - uint32 *hs_pushed_ret_fields; - size_t hs_pushed_ret_fields_num; - size_t hs_pushed_ret_fields_size; - size_t hs_pushed_lcl_fields_num; uchar *tmp_column_bitmap; - bool hs_increment; - bool hs_decrement; - uint32 hs_pushed_strref_num; #endif #endif #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS @@ -232,11 +205,6 @@ public: bool maybe_do_hs_direct_update; #endif uint direct_update_kinds; - List *direct_update_fields; - List *direct_update_values; -#endif -#ifdef INFO_KIND_FORCE_LIMIT_BEGIN - longlong info_limit; #endif spider_index_rnd_init prev_index_rnd_init; #ifdef HANDLER_HAS_DIRECT_AGGREGATE @@ -283,10 +251,13 @@ public: uint test_if_locked ); int close(); - int check_access_kind( + int check_access_kind_for_connection( THD *thd, bool write_request ); + void check_access_kind( + THD *thd + ); #ifdef HA_CAN_BULK_ACCESS int additional_lock( THD *thd, @@ -302,6 +273,10 @@ public: THD *thd, int lock_type ); + int start_stmt( + THD *thd, + thr_lock_type lock_type + ); int reset(); int extra( enum ha_extra_function operation @@ -525,6 +500,7 @@ public: #endif const char *table_type() const; ulonglong table_flags() const; + ulong table_flags_for_partition(); const char *index_type( uint key_number ); @@ -609,6 +585,11 @@ public: ); #endif #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + bool check_direct_update_sql_part( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS #ifdef SPIDER_MDEV_16246 inline int direct_update_rows_init( @@ -733,6 +714,11 @@ public: const uchar *buf ); #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + bool check_direct_delete_sql_part( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS inline int direct_delete_rows_init() { @@ -869,9 +855,6 @@ public: int error_num, uint flags ); - Field *get_top_table_field( - uint16 field_index - ); Field *field_exchange( Field *field ); @@ -887,7 +870,6 @@ public: void return_record_by_parent(); #endif TABLE *get_table(); - TABLE *get_top_table(); void set_ft_discard_bitmap(); void set_searched_bitmap(); void set_clone_searched_bitmap(); @@ -1255,4 +1237,16 @@ public: #endif int init_union_table_name_pos_sql(); int set_union_table_name_pos_sql(); + int append_lock_tables_list(); + int lock_tables(); + int dml_init(); +#ifdef HA_CAN_BULK_ACCESS + int bulk_access_begin( + void *info + ); + int bulk_access_current( + void *info + ); + void bulk_access_end(); +#endif }; diff --git a/storage/spider/mysql-test/spider/bugfix/include/insert_select_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/insert_select_deinit.inc new file mode 100644 index 00000000000..b8b2f200689 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/insert_select_deinit.inc @@ -0,0 +1,16 @@ +--connection master_1 +set session spider_direct_dup_insert= @old_spider_direct_dup_insert; +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_1_2= $MASTER_1_COMMENT_2_1_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_DROP_TABLES2= $CHILD2_1_DROP_TABLES2_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES2= $CHILD2_1_CREATE_TABLES2_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/insert_select_init.inc b/storage/spider/mysql-test/spider/bugfix/include/insert_select_init.inc new file mode 100644 index 00000000000..62a8821a3c9 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/insert_select_init.inc @@ -0,0 +1,43 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_1_2_BACKUP= $MASTER_1_COMMENT_2_1_2 +let $MASTER_1_COMMENT_2_1_2= + COMMENT='table "tbl_b", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_DROP_TABLES2_BACKUP= $CHILD2_1_DROP_TABLES2 +let $CHILD2_1_DROP_TABLES2= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + skey int NOT NULL, + dt date NOT NULL, + tm time NOT NULL, + KEY idx1 (skey,dt,tm) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_CREATE_TABLES2_BACKUP= $CHILD2_1_CREATE_TABLES2 +let $CHILD2_1_CREATE_TABLES2= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + dt datetime NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (dt) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey, dt FROM tbl_b ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_direct_dup_insert= @@spider_direct_dup_insert; +set session spider_direct_dup_insert= 1; diff --git a/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc new file mode 100644 index 00000000000..34376d50584 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/self_reference_deinit.inc @@ -0,0 +1,10 @@ +--connection master_1 +set spider_same_server_link= @old_spider_same_server_link; +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc b/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc new file mode 100644 index 00000000000..b7e2c4d02ca --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/self_reference_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", host "127.0.0.1", port "$MASTER_1_MYPORT", user "root"'; +--connection master_1 +set @old_spider_same_server_link= @@spider_same_server_link; +set spider_same_server_link= ON; diff --git a/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc new file mode 100644 index 00000000000..2b0f9cbb701 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc @@ -0,0 +1,18 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection child2_1 +set global sql_mode= @old_sql_mode; +--connection master_1 +set session spider_sync_sql_mode= @old_spider_sync_sql_mode; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_init.inc b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_init.inc new file mode 100644 index 00000000000..15c2a9eed7c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_init.inc @@ -0,0 +1,60 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +if (!$HAVE_PARTITION) +{ + --source strict_group_by_deinit.inc + --enable_result_log + --enable_query_log + --enable_warnings + skip Test requires partitioning; +} +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a"' + PARTITION BY KEY(pkey) ( + PARTITION pt1 COMMENT='srv "s_2_1"', + PARTITION pt2 COMMENT='srv "s_2_2"' + ); +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey, skey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey, skey FROM tbl_a ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_sync_sql_mode= @@spider_sync_sql_mode; +set session spider_sync_sql_mode= FALSE; +--connection child2_1 +set @old_sql_mode= @@sql_mode; +set global sql_mode= 'ONLY_FULL_GROUP_BY'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/insert_select.result b/storage/spider/mysql-test/spider/bugfix/r/insert_select.result new file mode 100644 index 00000000000..0783995e287 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/insert_select.result @@ -0,0 +1,102 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_direct_dup_insert= @@spider_direct_dup_insert; +set session spider_direct_dup_insert= 1; + +this test is for MDEV-16399 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES2 +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +skey int NOT NULL, +dt date NOT NULL, +tm time NOT NULL, +KEY idx1 (skey,dt,tm) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +dt datetime NOT NULL, +PRIMARY KEY (pkey), +KEY idx1 (dt) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2 +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00'); +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00'); +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00'); +FLUSH TABLES; + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 4 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 3 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 2 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 1 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 0 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 9 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 8 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 7 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 6 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 5 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 4) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 3) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 2) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 1) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 0) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 9) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 8) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 7) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 6) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +select t0.`skey` `skey`,cast((concat(t0.`dt` , _latin1' ' , t0.`tm`)) as datetime) `CAST(CONCAT(dt, ' ', tm) AS datetime)` from `auto_test_remote`.`tbl_a` t0 where ((t0.`skey` = 5) and (t0.`dt` > _latin1'2012-11-21')) lock in share mode +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey, dt FROM tbl_b ORDER BY pkey; +pkey dt +0 2013-01-01 13:00:00 +1 2012-12-01 11:00:00 +2 2012-11-30 11:00:00 +3 2012-11-29 11:00:00 +4 2012-11-28 11:00:00 +5 2012-11-27 11:00:00 +6 2012-11-26 11:00:00 +7 2012-11-25 11:00:00 +8 2012-11-24 11:00:00 +9 2012-11-23 11:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_direct_dup_insert= @old_spider_direct_dup_insert; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/self_reference.result b/storage/spider/mysql-test/spider/bugfix/r/self_reference.result new file mode 100644 index 00000000000..1ce9c60a93f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/self_reference.result @@ -0,0 +1,36 @@ +for master_1 +for child2 +for child3 +connection master_1; +set @old_spider_same_server_link= @@spider_same_server_link; +set spider_same_server_link= ON; + +this test is for MDEV-6268 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; + +create table +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 + +select test 1 +connection master_1; +SELECT pkey FROM tbl_a; +ERROR HY000: An infinite loop is detected when opening table auto_test_local.tbl_a + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection master_1; +set spider_same_server_link= @old_spider_same_server_link; +for master_1 +for child2 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result index d7a0c1044a7..d50da8a7613 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result +++ b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result @@ -48,7 +48,7 @@ SET SESSION sql_log_bin= 0; connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; argument -set session time_zone = '+00:00' +set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-' SET NAMES utf8 set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;set session sql_mode = 'strict_trans_tables,error_for_division_by_zero,no_auto_create_user,no_engine_substitution';start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' diff --git a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result index 5048fbb423c..1bf6fbccbc9 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result +++ b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result @@ -50,7 +50,7 @@ pkey connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%'; argument -set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length,empty_string_is_null,simultaneous_assignment,time_round_fractional';set session time_zone = '+00:00';start transaction +set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length,empty_string_is_null,simultaneous_assignment,time_round_fractional';set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-';start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%' SELECT pkey FROM tbl_a ORDER BY pkey; pkey diff --git a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result index 08f9a6007aa..3ec96a66031 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result +++ b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result @@ -50,7 +50,7 @@ pkey connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%'; argument -set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length';set session time_zone = '+00:00';start transaction +set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length';set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-';start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%' SELECT pkey FROM tbl_a ORDER BY pkey; pkey diff --git a/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result b/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result new file mode 100644 index 00000000000..f2287dea65a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result @@ -0,0 +1,124 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_sync_sql_mode= @@spider_sync_sql_mode; +set session spider_sync_sql_mode= FALSE; +connection child2_1; +set @old_sql_mode= @@sql_mode; +set global sql_mode= 'ONLY_FULL_GROUP_BY'; + +this test is for MDEV-18988 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +skey int NOT NULL, +PRIMARY KEY (pkey), +KEY idx1 (skey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19); +INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +FLUSH TABLES; +SELECT count(pkey) cnt, skey FROM tbl_a; +cnt skey +30 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select count(`pkey`),min(`pkey`),min(`skey`) from `auto_test_remote`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey, skey FROM tbl_a ORDER BY pkey; +pkey skey +1 1 +3 3 +5 5 +7 7 +9 9 +11 11 +13 13 +15 15 +17 17 +19 19 +21 6 +23 8 +25 10 +27 12 +29 14 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select count(`pkey`),min(`pkey`),min(`skey`) from `auto_test_remote2`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey, skey FROM tbl_a ORDER BY pkey; +pkey skey +0 0 +2 2 +4 4 +6 6 +8 8 +10 10 +12 12 +14 14 +16 16 +18 18 +20 5 +22 7 +24 9 +26 11 +28 13 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection child2_1; +set global sql_mode= @old_sql_mode; +connection master_1; +set session spider_sync_sql_mode= @old_spider_sync_sql_mode; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/insert_select.cnf b/storage/spider/mysql-test/spider/bugfix/t/insert_select.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/insert_select.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/insert_select.test b/storage/spider/mysql-test/spider/bugfix/t/insert_select.test new file mode 100644 index 00000000000..381e72f7b1b --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/insert_select.test @@ -0,0 +1,99 @@ +--source ../include/insert_select_init.inc +--echo +--echo this test is for MDEV-16399 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +echo CHILD2_1_CREATE_TABLES2; +eval $CHILD2_1_CREATE_TABLES2; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + skey int NOT NULL, + dt date NOT NULL, + tm time NOT NULL, + KEY idx1 (skey,dt,tm) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + skey int NOT NULL, + dt date NOT NULL, + tm time NOT NULL, + KEY idx1 (skey,dt,tm) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + dt datetime NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (dt) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + dt datetime NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (dt) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1_2; +--enable_query_log +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00'); +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00'); +INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00'); +FLUSH TABLES; + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 4 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 3 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 2 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 1 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 0 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 9 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 8 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 7 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 6 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); +INSERT IGNORE INTO tbl_b (SELECT skey, CAST(CONCAT(dt, ' ', tm) AS datetime) FROM tbl_a WHERE skey = 5 AND dt > DATE_ADD('2012-12-01', INTERVAL -10 DAY)); + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/insert_select_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf b/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf new file mode 100644 index 00000000000..b0853e32654 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference.cnf @@ -0,0 +1,2 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference.test b/storage/spider/mysql-test/spider/bugfix/t/self_reference.test new file mode 100644 index 00000000000..b93cf8ef715 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference.test @@ -0,0 +1,45 @@ +--source ../include/self_reference_init.inc +--echo +--echo this test is for MDEV-6268 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; +--enable_warnings + +--echo +--echo create table + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log + +--echo +--echo select test 1 + +--connection master_1 +--error 12719 +SELECT pkey FROM tbl_a; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--enable_warnings +--source ../include/self_reference_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test index 652fbb1c11c..c608ae018ea 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test +++ b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test @@ -70,6 +70,7 @@ sync_with_master; SET SESSION sql_log_bin= 0; --connection child2_1 +--replace_regex /-[0-9a-f]{12}-[0-9a-f]+-/-xxxxxxxxxxxx-xxxxx-/ eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_TABLES; diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc b/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc index ae7c15c5081..f094b1f80a3 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc +++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc @@ -48,6 +48,7 @@ TRUNCATE TABLE mysql.general_log; SELECT * FROM tbl_a ORDER BY pkey; --connection child2_1 +--replace_regex /-[0-9a-f]{12}-[0-9a-f]+-/-xxxxxxxxxxxx-xxxxx-/ eval $CHILD2_1_SELECT_ARGUMENT1; eval $CHILD2_1_SELECT_TABLES; diff --git a/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test new file mode 100644 index 00000000000..8b8da46d56c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test @@ -0,0 +1,98 @@ +--source ../include/strict_group_by_init.inc +--echo +--echo this test is for MDEV-18988 +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19); +INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +FLUSH TABLES; +SELECT count(pkey) cnt, skey FROM tbl_a; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/strict_group_by_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/include/deinit_spider.inc b/storage/spider/mysql-test/spider/include/deinit_spider.inc index 51cc075edaa..dd474c59bc7 100644 --- a/storage/spider/mysql-test/spider/include/deinit_spider.inc +++ b/storage/spider/mysql-test/spider/include/deinit_spider.inc @@ -33,6 +33,7 @@ DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_direct_sql; +UNINSTALL PLUGIN spider_wrapper_protocols; UNINSTALL PLUGIN spider_alloc_mem; UNINSTALL PLUGIN spider; DROP TABLE IF EXISTS mysql.spider_xa; @@ -46,6 +47,10 @@ DROP TABLE IF EXISTS mysql.spider_table_sts; DROP TABLE IF EXISTS mysql.spider_table_crd; if ($VERSION_COMPILE_OS_WIN) { + if ($MASTER_1_MYPORT) + { + DROP SERVER s_1; + } if ($CHILD2_1_MYPORT) { DROP SERVER s_2_1; @@ -73,6 +78,10 @@ if ($VERSION_COMPILE_OS_WIN) } if (!$VERSION_COMPILE_OS_WIN) { + if ($MASTER_1_MYSOCK) + { + DROP SERVER s_1; + } if ($CHILD2_1_MYSOCK) { DROP SERVER s_2_1; diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index 69d1fae425e..6a22ffcc1fd 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -3,6 +3,16 @@ let $VERSION_COMPILE_OS_WIN= if ($VERSION_COMPILE_OS_WIN) { INSTALL PLUGIN spider SONAME 'ha_spider.dll'; + if ($MASTER_1_MYPORT) + { + eval CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + PORT $MASTER_1_MYPORT + ); + } if ($CHILD2_1_MYPORT) { eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( @@ -67,6 +77,16 @@ if ($VERSION_COMPILE_OS_WIN) if (!$VERSION_COMPILE_OS_WIN) { INSTALL PLUGIN spider SONAME 'ha_spider.so'; + if ($MASTER_1_MYSOCK) + { + eval CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( + HOST 'localhost', + DATABASE 'auto_test_local', + USER 'root', + PASSWORD '', + SOCKET '$MASTER_1_MYSOCK' + ); + } if ($CHILD2_1_MYSOCK) { eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( @@ -131,6 +151,11 @@ if (!$VERSION_COMPILE_OS_WIN) let $SERVER_NAME= `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '-', 2), '-', -1)`; +if (`SELECT IF('$SERVER_NAME' REGEXP '^[0-9]+\$', 1, 0)`) +{ + let $SERVER_NAME= + `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '-', 3), '-', -1)`; +} let $SERVER_MAJOR_VERSION= `SELECT SUBSTRING_INDEX(version(), '.', 1)`; let $SERVER_MINOR_VERSION= diff --git a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result index e68b4a2c82d..a9b88d50628 100644 --- a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result +++ b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result @@ -51,7 +51,7 @@ SET SESSION sql_log_bin= 0; connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; argument -set session time_zone = '+00:00' +set session time_zone = '+00:00';set @`spider_lc_./auto_test_remote/tbl_a` = '-xxxxxxxxxxxx-xxxxx-./auto_test_local/tbl_a-' SET NAMES utf8 set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;set session sql_mode = 'strict_trans_tables,error_for_division_by_zero,no_auto_create_user,no_engine_substitution';start transaction SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' diff --git a/storage/spider/mysql-test/spider/r/spider_wrapper_protocols.result b/storage/spider/mysql-test/spider/r/spider_wrapper_protocols.result new file mode 100644 index 00000000000..f1a7b6208ac --- /dev/null +++ b/storage/spider/mysql-test/spider/r/spider_wrapper_protocols.result @@ -0,0 +1,22 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +SELECT * FROM information_schema.spider_wrapper_protocols; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test index 507e5340779..f7f41358f51 100644 --- a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test +++ b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test @@ -108,6 +108,7 @@ if ($USE_CHILD_GROUP2) --connection child2_1 if ($USE_GENERAL_LOG) { + --replace_regex /-[0-9a-f]{12}-[0-9a-f]+-/-xxxxxxxxxxxx-xxxxx-/ eval $CHILD2_1_SELECT_ARGUMENT1; } eval $CHILD2_1_SELECT_TABLES; diff --git a/storage/spider/mysql-test/spider/t/spider_wrapper_protocols.test b/storage/spider/mysql-test/spider/t/spider_wrapper_protocols.test new file mode 100644 index 00000000000..d0753cf73c4 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/spider_wrapper_protocols.test @@ -0,0 +1,16 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source test_init.inc +--enable_query_log + +--connection master_1 +SELECT * FROM information_schema.spider_wrapper_protocols; + +--disable_query_log +--source test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings +--echo +--echo end of test diff --git a/storage/spider/scripts/install_spider.sql b/storage/spider/scripts/install_spider.sql deleted file mode 100644 index 403bd99fd68..00000000000 --- a/storage/spider/scripts/install_spider.sql +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2010-2019 Kentoku Shiba -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# 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 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-1335 USA - -drop procedure if exists mysql.spider_plugin_installer; -delimiter // -create procedure mysql.spider_plugin_installer() -begin - set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0); - set @have_spider_i_s_plugin := 0; - select @have_spider_i_s_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER'; - set @have_spider_plugin := 0; - select @have_spider_plugin := 1 from mysql.plugin where name = 'spider'; - if @have_spider_i_s_plugin = 0 then - if @have_spider_plugin = 1 then - -- spider plugin is present in mysql.plugin but not in - -- information_schema.plugins. Remove spider plugin entry - -- in mysql.plugin first. - delete from mysql.plugin where name = 'spider'; - end if; - -- Install spider plugin - if @win_plugin = 0 then - install plugin spider soname 'ha_spider.so'; - else - install plugin spider soname 'ha_spider.dll'; - end if; - end if; -end;// -delimiter ; -call mysql.spider_plugin_installer; -drop procedure mysql.spider_plugin_installer; diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 3164356ddf6..100fe922825 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2019 Kentoku Shiba +/* Copyright (C) 2008-2020 Kentoku Shiba Copyright (C) 2019, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ #include "probes_mysql.h" #include "sql_class.h" #include "sql_partition.h" +#include "sql_table.h" #include "tztime.h" #endif #include "spd_err.h" @@ -56,6 +57,8 @@ inline void SPIDER_set_next_thread_id(THD *A) extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; +extern struct charset_info_st *spd_charset_utf8mb3_bin; +extern LEX_CSTRING spider_unique_id; pthread_mutex_t spider_conn_id_mutex; pthread_mutex_t spider_ipport_conn_mutex; ulonglong spider_conn_id = 1; @@ -66,6 +69,7 @@ extern pthread_attr_t spider_pt_attr; #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key spd_key_mutex_mta_conn; extern PSI_mutex_key spd_key_mutex_conn_i; +extern PSI_mutex_key spd_key_mutex_conn_loop_check; extern PSI_cond_key spd_key_cond_conn_i; #ifndef WITHOUT_SPIDER_BG_SEARCH extern PSI_mutex_key spd_key_mutex_bg_conn_chain; @@ -145,6 +149,102 @@ uchar *spider_ipport_conn_get_key( DBUG_RETURN((uchar*) ip_port->key); } +static uchar *spider_loop_check_full_get_key( + SPIDER_CONN_LOOP_CHECK *ptr, + size_t *length, + my_bool not_used __attribute__ ((unused)) +) { + DBUG_ENTER("spider_loop_check_full_get_key"); + *length = ptr->full_name.length; + DBUG_RETURN((uchar*) ptr->full_name.str); +} + +static uchar *spider_loop_check_to_get_key( + SPIDER_CONN_LOOP_CHECK *ptr, + size_t *length, + my_bool not_used __attribute__ ((unused)) +) { + DBUG_ENTER("spider_loop_check_to_get_key"); + *length = ptr->to_name.length; + DBUG_RETURN((uchar*) ptr->to_name.str); +} + +int spider_conn_init( + SPIDER_CONN *conn +) { + int error_num = HA_ERR_OUT_OF_MEM; + DBUG_ENTER("spider_conn_init"); +#if MYSQL_VERSION_ID < 50500 + if (pthread_mutex_init(&conn->loop_check_mutex, MY_MUTEX_INIT_FAST)) +#else + if (mysql_mutex_init(spd_key_mutex_conn_loop_check, &conn->loop_check_mutex, + MY_MUTEX_INIT_FAST)) +#endif + { + goto error_loop_check_mutex_init; + } + if ( + my_hash_init(PSI_INSTRUMENT_ME, &conn->loop_checked, spd_charset_utf8mb3_bin, 32, 0, 0, + (my_hash_get_key) spider_loop_check_full_get_key, 0, 0) + ) { + goto error_loop_checked_hash_init; + } + spider_alloc_calc_mem_init(conn->loop_checked, 268); + spider_alloc_calc_mem(spider_current_trx, + conn->loop_checked, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + if ( + my_hash_init(PSI_INSTRUMENT_ME, &conn->loop_check_queue, spd_charset_utf8mb3_bin, 32, 0, 0, + (my_hash_get_key) spider_loop_check_to_get_key, 0, 0) + ) { + goto error_loop_check_queue_hash_init; + } + spider_alloc_calc_mem_init(conn->loop_check_queue, 269); + spider_alloc_calc_mem(spider_current_trx, + conn->loop_check_queue, + conn->loop_check_queue.array.max_element * + conn->loop_check_queue.array.size_of_element); + DBUG_RETURN(0); + +error_loop_check_queue_hash_init: + spider_free_mem_calc(spider_current_trx, + conn->loop_checked_id, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + my_hash_free(&conn->loop_checked); +error_loop_checked_hash_init: + pthread_mutex_destroy(&conn->loop_check_mutex); +error_loop_check_mutex_init: + DBUG_RETURN(error_num); +} + +void spider_conn_done( + SPIDER_CONN *conn +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + DBUG_ENTER("spider_conn_done"); + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_checked, l))) + { + spider_free(spider_current_trx, lcptr, MYF(0)); + ++l; + } + spider_free_mem_calc(spider_current_trx, + conn->loop_check_queue_id, + conn->loop_check_queue.array.max_element * + conn->loop_check_queue.array.size_of_element); + my_hash_free(&conn->loop_check_queue); + spider_free_mem_calc(spider_current_trx, + conn->loop_checked_id, + conn->loop_checked.array.max_element * + conn->loop_checked.array.size_of_element); + my_hash_free(&conn->loop_checked); + pthread_mutex_destroy(&conn->loop_check_mutex); + DBUG_VOID_RETURN; +} + int spider_reset_conn_setted_parameter( SPIDER_CONN *conn, THD *thd @@ -183,7 +283,7 @@ int spider_reset_conn_setted_parameter( conn->default_database.length(default_database_length); } else conn->default_database.length(0); - DBUG_RETURN(0); + DBUG_RETURN(spider_conn_reset_queue_loop_check(conn)); } int spider_free_conn_alloc( @@ -199,6 +299,7 @@ int spider_free_conn_alloc( delete conn->db_conn; conn->db_conn = NULL; } + spider_conn_done(conn); DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); pthread_mutex_destroy(&conn->mta_conn_mutex); conn->default_database.free(); @@ -312,6 +413,10 @@ void spider_free_conn_from_trx( } } else { /* conn_recycle_mode == 0 */ + if (conn->quick_target) + { + spider_db_free_result((ha_spider *) conn->quick_target, TRUE); + } spider_free_conn(conn); } } else if (roop_count) @@ -459,8 +564,9 @@ SPIDER_CONN *spider_create_conn( SPIDER_CONN *conn; SPIDER_IP_PORT_CONN *ip_port_conn; char *tmp_name, *tmp_host, *tmp_username, *tmp_password, *tmp_socket; - char *tmp_wrapper, *tmp_ssl_ca, *tmp_ssl_capath, *tmp_ssl_cert; + char *tmp_wrapper, *tmp_db, *tmp_ssl_ca, *tmp_ssl_capath, *tmp_ssl_cert; char *tmp_ssl_cipher, *tmp_ssl_key, *tmp_default_file, *tmp_default_group; + char *tmp_dsn; DBUG_ENTER("spider_create_conn"); if (unlikely(!UTC)) @@ -474,6 +580,15 @@ SPIDER_CONN *spider_create_conn( if (conn_kind == SPIDER_CONN_KIND_MYSQL) { #endif + bool tables_on_different_db_are_joinable; + if (share->sql_dbton_ids[link_idx] != SPIDER_DBTON_SIZE) + { + tables_on_different_db_are_joinable = + spider_dbton[share->sql_dbton_ids[link_idx]].db_util-> + tables_on_different_db_are_joinable(); + } else { + tables_on_different_db_are_joinable = TRUE; + } if (!(conn = (SPIDER_CONN *) spider_bulk_malloc(spider_current_trx, 18, MYF(MY_WME | MY_ZEROFILL), &conn, (uint) (sizeof(*conn)), @@ -486,6 +601,8 @@ SPIDER_CONN *spider_create_conn( &tmp_socket, (uint) (share->tgt_sockets_lengths[link_idx] + 1), &tmp_wrapper, (uint) (share->tgt_wrappers_lengths[link_idx] + 1), + &tmp_db, (uint) (tables_on_different_db_are_joinable ? + 0 : share->tgt_dbs_lengths[link_idx] + 1), &tmp_ssl_ca, (uint) (share->tgt_ssl_cas_lengths[link_idx] + 1), &tmp_ssl_capath, (uint) (share->tgt_ssl_capaths_lengths[link_idx] + 1), @@ -499,6 +616,8 @@ SPIDER_CONN *spider_create_conn( (uint) (share->tgt_default_files_lengths[link_idx] + 1), &tmp_default_group, (uint) (share->tgt_default_groups_lengths[link_idx] + 1), + &tmp_dsn, + (uint) (share->tgt_dsns_lengths[link_idx] + 1), &need_mon, (uint) (sizeof(int)), NullS)) ) { @@ -534,6 +653,13 @@ SPIDER_CONN *spider_create_conn( conn->tgt_wrapper = tmp_wrapper; memcpy(conn->tgt_wrapper, share->tgt_wrappers[link_idx], share->tgt_wrappers_lengths[link_idx]); + if (!tables_on_different_db_are_joinable) + { + conn->tgt_db_length = share->tgt_dbs_lengths[link_idx]; + conn->tgt_db = tmp_db; + memcpy(conn->tgt_db, share->tgt_dbs[link_idx], + share->tgt_dbs_lengths[link_idx]); + } conn->tgt_ssl_ca_length = share->tgt_ssl_cas_lengths[link_idx]; if (conn->tgt_ssl_ca_length) { @@ -591,6 +717,15 @@ SPIDER_CONN *spider_create_conn( share->tgt_default_groups_lengths[link_idx]); } else conn->tgt_default_group = NULL; + conn->tgt_dsn_length = + share->tgt_dsns_lengths[link_idx]; + if (conn->tgt_dsn_length) + { + conn->tgt_dsn = tmp_dsn; + memcpy(conn->tgt_dsn, share->tgt_dsns[link_idx], + share->tgt_dsns_lengths[link_idx]); + } else + conn->tgt_dsn = NULL; conn->tgt_port = share->tgt_ports[link_idx]; conn->tgt_ssl_vsc = share->tgt_ssl_vscs[link_idx]; conn->dbton_id = share->sql_dbton_ids[link_idx]; @@ -737,6 +872,11 @@ SPIDER_CONN *spider_create_conn( goto error_mta_conn_mutex_init; } + if (unlikely((*error_num = spider_conn_init(conn)))) + { + goto error_conn_init; + } + spider_conn_queue_connect(share, conn, link_idx); conn->ping_time = (time_t) time((time_t*) 0); conn->connect_error_time = conn->ping_time; @@ -788,12 +928,10 @@ SPIDER_CONN *spider_create_conn( DBUG_RETURN(conn); -/* -error_init_lock_table_hash: - DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); - pthread_mutex_destroy(&conn->mta_conn_mutex); -*/ error_too_many_ipport_count: + spider_conn_done(conn); +error_conn_init: + pthread_mutex_destroy(&conn->mta_conn_mutex); error_mta_conn_mutex_init: error_db_conn_init: delete conn->db_conn; @@ -1228,6 +1366,20 @@ SPIDER_CONN *spider_get_conn( conn->queued_ping = FALSE; } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (conn_kind == SPIDER_CONN_KIND_MYSQL) + { +#endif + if (unlikely(spider && spider->wide_handler->top_share && + (*error_num = spider_conn_queue_loop_check( + conn, spider, base_link_idx)))) + { + goto error; + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } +#endif + DBUG_PRINT("info",("spider conn=%p", conn)); DBUG_RETURN(conn); @@ -1283,7 +1435,7 @@ int spider_check_and_get_casual_read_conn( if ( !(spider->conns[link_idx] = spider_get_conn(spider->share, link_idx, - spider->conn_keys[link_idx], spider->trx, + spider->conn_keys[link_idx], spider->wide_handler->trx, spider, FALSE, TRUE, SPIDER_CONN_KIND_MYSQL, &error_num)) ) { @@ -1480,6 +1632,424 @@ void spider_conn_queue_UTC_time_zone( DBUG_VOID_RETURN; } +int spider_conn_queue_and_merge_loop_check( + SPIDER_CONN *conn, + SPIDER_CONN_LOOP_CHECK *lcptr +) { + int error_num = HA_ERR_OUT_OF_MEM; + char *tmp_name, *from_name, *cur_name, *to_name, *full_name, *from_value, + *merged_value; + SPIDER_CONN_LOOP_CHECK *lcqptr, *lcrptr; + DBUG_ENTER("spider_conn_queue_and_merge_loop_check"); + DBUG_PRINT("info", ("spider conn=%p", conn)); +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *) + my_hash_search_using_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, + (uchar *) lcptr->to_name.str, lcptr->to_name.length)))) +#else + if (unlikely(!(lcqptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search( + &conn->loop_check_queue, + (uchar *) lcptr->to_name.str, lcptr->to_name.length)))) +#endif + { + DBUG_PRINT("info", ("spider create merged_value and insert")); + lcptr->merged_value.length = spider_unique_id.length + + lcptr->cur_name.length + lcptr->from_value.length + 1; + tmp_name = (char *) lcptr->merged_value.str; + memcpy(tmp_name, spider_unique_id.str, spider_unique_id.length); + tmp_name += spider_unique_id.length; + memcpy(tmp_name, lcptr->cur_name.str, lcptr->cur_name.length); + tmp_name += lcptr->cur_name.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, lcptr->from_value.str, lcptr->from_value.length + 1); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_check_queue, (uchar *) lcptr))) +#endif + { + goto error_hash_insert_queue; + } + lcptr->flag |= SPIDER_LOP_CHK_QUEUED; + } else { + DBUG_PRINT("info", ("spider append merged_value and replace")); + if (unlikely(!spider_bulk_malloc(spider_current_trx, 271, MYF(MY_WME), + &lcrptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)), + &from_name, (uint) (lcqptr->from_name.length + 1), + &cur_name, (uint) (lcqptr->cur_name.length + 1), + &to_name, (uint) (lcqptr->to_name.length + 1), + &full_name, (uint) (lcqptr->full_name.length + 1), + &from_value, (uint) (lcqptr->from_value.length + 1), + &merged_value, (uint) (lcqptr->merged_value.length + + spider_unique_id.length + lcptr->cur_name.length + + lcptr->from_value.length + 2), + NullS) + )) { + goto error_alloc_loop_check_replace; + } +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + lcrptr->hash_value_to = lcqptr->hash_value_to; + lcrptr->hash_value_full = lcqptr->hash_value_full; +#endif + lcrptr->from_name.str = from_name; + lcrptr->from_name.length = lcqptr->from_name.length; + memcpy(from_name, lcqptr->from_name.str, lcqptr->from_name.length + 1); + lcrptr->cur_name.str = cur_name; + lcrptr->cur_name.length = lcqptr->cur_name.length; + memcpy(cur_name, lcqptr->cur_name.str, lcqptr->cur_name.length + 1); + lcrptr->to_name.str = to_name; + lcrptr->to_name.length = lcqptr->to_name.length; + memcpy(to_name, lcqptr->to_name.str, lcqptr->to_name.length + 1); + lcrptr->full_name.str = full_name; + lcrptr->full_name.length = lcqptr->full_name.length; + memcpy(full_name, lcqptr->full_name.str, lcqptr->full_name.length + 1); + lcrptr->from_value.str = from_value; + lcrptr->from_value.length = lcqptr->from_value.length; + memcpy(from_value, lcqptr->from_value.str, lcqptr->from_value.length + 1); + lcrptr->merged_value.str = merged_value; + lcrptr->merged_value.length = lcqptr->merged_value.length; + memcpy(merged_value, + lcqptr->merged_value.str, lcqptr->merged_value.length); + merged_value += lcqptr->merged_value.length; + memcpy(merged_value, spider_unique_id.str, spider_unique_id.length); + merged_value += spider_unique_id.length; + memcpy(merged_value, lcptr->cur_name.str, lcptr->cur_name.length); + merged_value += lcptr->cur_name.length; + *merged_value = '-'; + ++merged_value; + memcpy(merged_value, lcptr->from_value.str, lcptr->from_value.length + 1); + + DBUG_PRINT("info", ("spider free lcqptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcqptr->hash_value_full, (uchar *) lcqptr); + my_hash_delete_with_hash_value(&conn->loop_check_queue, + lcqptr->hash_value_to, (uchar *) lcqptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcqptr); + my_hash_delete(&conn->loop_check_queue, (uchar*) lcqptr); +#endif + spider_free(spider_current_trx, lcqptr, MYF(0)); + + lcptr = lcrptr; +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_checked, (uchar *) lcptr))) +#endif + { + goto error_hash_insert; + } +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value_to, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_check_queue, (uchar *) lcptr))) +#endif + { + goto error_hash_insert_queue; + } + lcptr->flag = SPIDER_LOP_CHK_MERAGED; + lcptr->next = NULL; + if (!conn->loop_check_meraged_first) + { + conn->loop_check_meraged_first = lcptr; + conn->loop_check_meraged_last = lcptr; + } else { + conn->loop_check_meraged_last->next = lcptr; + conn->loop_check_meraged_last = lcptr; + } + } + DBUG_RETURN(0); + +error_alloc_loop_check_replace: +error_hash_insert_queue: +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif +error_hash_insert: + spider_free(spider_current_trx, lcptr, MYF(0)); + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(error_num); +} + +int spider_conn_reset_queue_loop_check( + SPIDER_CONN *conn +) { + int error_num; + SPIDER_CONN_LOOP_CHECK *lcptr; + DBUG_ENTER("spider_conn_reset_queue_loop_check"); + uint l = 0; + pthread_mutex_lock(&conn->loop_check_mutex); + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_checked, l))) + { + if (!lcptr->flag) + { + DBUG_PRINT("info", ("spider free lcptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif + spider_free(spider_current_trx, lcptr, MYF(0)); + } + ++l; + } + + lcptr = conn->loop_check_ignored_first; + while (lcptr) + { + lcptr->flag = 0; + if ((error_num = spider_conn_queue_and_merge_loop_check(conn, lcptr))) + { + goto error_queue_and_merge; + } + lcptr = lcptr->next; + } + conn->loop_check_meraged_first = NULL; + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(0); + +error_queue_and_merge: + lcptr = lcptr->next; + while (lcptr) + { + lcptr->flag = 0; + lcptr = lcptr->next; + } + conn->loop_check_meraged_first = NULL; + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(error_num); +} + +int spider_conn_queue_loop_check( + SPIDER_CONN *conn, + ha_spider *spider, + int link_idx +) { + int error_num = HA_ERR_OUT_OF_MEM; + uint conn_link_idx = spider->conn_link_idx[link_idx], buf_sz; + char path[FN_REFLEN + 1]; + char *tmp_name, *from_name, *cur_name, *to_name, *full_name, *from_value, + *merged_value; + user_var_entry *loop_check; + char *loop_check_buf; + THD *thd = spider->wide_handler->trx->thd; + TABLE_SHARE *top_share = spider->wide_handler->top_share; + SPIDER_SHARE *share = spider->share; + SPIDER_CONN_LOOP_CHECK *lcptr; + LEX_CSTRING lex_str, from_str, to_str; + DBUG_ENTER("spider_conn_queue_loop_check"); + DBUG_PRINT("info", ("spider conn=%p", conn)); + lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN; + buf_sz = lex_str.length + 2; + loop_check_buf = (char *) my_alloca(buf_sz); + if (unlikely(!loop_check_buf)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + lex_str.str = loop_check_buf; + memcpy(loop_check_buf, + SPIDER_SQL_LOP_CHK_PRM_PRF_STR, SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + memcpy(loop_check_buf + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN, + top_share->path.str, top_share->path.length); + loop_check_buf[lex_str.length] = '\0'; + DBUG_PRINT("info", ("spider param name=%s", lex_str.str)); + loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); + if (!loop_check || loop_check->type != STRING_RESULT) + { + DBUG_PRINT("info", ("spider client is not Spider")); + lex_str.str = ""; + lex_str.length = 0; + from_str.str = ""; + from_str.length = 0; + } else { + lex_str.str = loop_check->value; + lex_str.length = loop_check->length; + DBUG_PRINT("info", ("spider from_str=%s", lex_str.str)); + if (unlikely(!(tmp_name = strchr(loop_check->value, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 1")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 2")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 3")); + from_str.str = ""; + from_str.length = 0; + } + else if (unlikely(!(tmp_name = strchr(tmp_name + 1, '-')))) + { + DBUG_PRINT("info", ("spider invalid value for loop checking 4")); + from_str.str = ""; + from_str.length = 0; + } + else + { + from_str.str = lex_str.str; + from_str.length = tmp_name - lex_str.str + 1; + } + } + my_afree(loop_check_buf); + + to_str.length = build_table_filename(path, FN_REFLEN, + share->tgt_dbs[conn_link_idx] ? share->tgt_dbs[conn_link_idx] : "", + share->tgt_table_names[conn_link_idx], "", 0); + to_str.str = path; + DBUG_PRINT("info", ("spider to=%s", to_str.str)); + buf_sz = from_str.length + top_share->path.length + to_str.length + 3; + loop_check_buf = (char *) my_alloca(buf_sz); + if (unlikely(!loop_check_buf)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + DBUG_PRINT("info", ("spider top_share->path=%s", top_share->path.str)); + memcpy(loop_check_buf, from_str.str, from_str.length); + tmp_name = loop_check_buf + from_str.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, top_share->path.str, top_share->path.length); + tmp_name += top_share->path.length; + *tmp_name = '-'; + ++tmp_name; + memcpy(tmp_name, to_str.str, to_str.length); + tmp_name += to_str.length; + *tmp_name = '\0'; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + my_hash_value_type hash_value = my_calc_hash(&conn->loop_checked, + (uchar *) loop_check_buf, buf_sz - 1); +#endif + pthread_mutex_lock(&conn->loop_check_mutex); +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + lcptr = (SPIDER_CONN_LOOP_CHECK *) + my_hash_search_using_hash_value(&conn->loop_checked, hash_value, + (uchar *) loop_check_buf, buf_sz - 1); +#else + lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_search( + &conn->loop_checked, (uchar *) loop_check_buf, buf_sz - 1); +#endif + if (unlikely( + !lcptr || + ( + !lcptr->flag && + ( + lcptr->from_value.length != lex_str.length || + memcmp(lcptr->from_value.str, lex_str.str, lex_str.length) + ) + ) + )) + { + if (unlikely(lcptr)) + { + DBUG_PRINT("info", ("spider free lcptr")); +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_checked, (uchar*) lcptr); +#endif + spider_free(spider_current_trx, lcptr, MYF(0)); + } + DBUG_PRINT("info", ("spider alloc_lcptr")); + if (unlikely(!spider_bulk_malloc(spider_current_trx, 272, MYF(MY_WME), + &lcptr, (uint) (sizeof(SPIDER_CONN_LOOP_CHECK)), + &from_name, (uint) (from_str.length + 1), + &cur_name, (uint) (top_share->path.length + 1), + &to_name, (uint) (to_str.length + 1), + &full_name, (uint) (buf_sz), + &from_value, (uint) (lex_str.length + 1), + &merged_value, (uint) (spider_unique_id.length + top_share->path.length + + lex_str.length + 2), + NullS) + )) { + my_afree(loop_check_buf); + goto error_alloc_loop_check; + } + lcptr->flag = 0; + lcptr->from_name.str = from_name; + lcptr->from_name.length = from_str.length; + memcpy(from_name, from_str.str, from_str.length + 1); + lcptr->cur_name.str = cur_name; + lcptr->cur_name.length = top_share->path.length; + memcpy(cur_name, top_share->path.str, top_share->path.length + 1); + lcptr->to_name.str = to_name; + lcptr->to_name.length = to_str.length; + memcpy(to_name, to_str.str, to_str.length + 1); + lcptr->full_name.str = full_name; + lcptr->full_name.length = buf_sz - 1; + memcpy(full_name, loop_check_buf, buf_sz); + lcptr->from_value.str = from_value; + lcptr->from_value.length = lex_str.length; + memcpy(from_value, lex_str.str, lex_str.length + 1); + lcptr->merged_value.str = merged_value; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + lcptr->hash_value_to = my_calc_hash(&conn->loop_checked, + (uchar *) to_str.str, to_str.length); + lcptr->hash_value_full = hash_value; +#endif +#ifdef HASH_UPDATE_WITH_HASH_VALUE + if (unlikely(my_hash_insert_with_hash_value(&conn->loop_checked, + lcptr->hash_value_full, (uchar *) lcptr))) +#else + if (unlikely(my_hash_insert(&conn->loop_checked, (uchar *) lcptr))) +#endif + { + my_afree(loop_check_buf); + goto error_hash_insert; + } + } else { + if (!lcptr->flag) + { + DBUG_PRINT("info", ("spider add to ignored list")); + lcptr->flag |= SPIDER_LOP_CHK_IGNORED; + lcptr->next = NULL; + if (!conn->loop_check_ignored_first) + { + conn->loop_check_ignored_first = lcptr; + conn->loop_check_ignored_last = lcptr; + } else { + conn->loop_check_ignored_last->next = lcptr; + conn->loop_check_ignored_last = lcptr; + } + } + pthread_mutex_unlock(&conn->loop_check_mutex); + my_afree(loop_check_buf); + DBUG_PRINT("info", ("spider be sent or queued already")); + DBUG_RETURN(0); + } + my_afree(loop_check_buf); + + if ((error_num = spider_conn_queue_and_merge_loop_check(conn, lcptr))) + { + goto error_queue_and_merge; + } + pthread_mutex_unlock(&conn->loop_check_mutex); + DBUG_RETURN(0); + +error_hash_insert: + spider_free(spider_current_trx, lcptr, MYF(0)); +error_queue_and_merge: + pthread_mutex_unlock(&conn->loop_check_mutex); +error_alloc_loop_check: + DBUG_RETURN(error_num); +} + void spider_conn_queue_start_transaction( SPIDER_CONN *conn ) { @@ -1745,7 +2315,8 @@ int spider_set_conn_bg_param( int error_num, roop_count, bgs_mode; SPIDER_SHARE *share = spider->share; SPIDER_RESULT_LIST *result_list = &spider->result_list; - THD *thd = spider->trx->thd; + SPIDER_WIDE_HANDLER *wide_handler = spider->wide_handler; + THD *thd = wide_handler->trx->thd; DBUG_ENTER("spider_set_conn_bg_param"); DBUG_PRINT("info",("spider spider=%p", spider)); bgs_mode = @@ -1754,10 +2325,11 @@ int spider_set_conn_bg_param( result_list->bgs_phase = 0; else if ( bgs_mode <= 2 && - (result_list->lock_type == F_WRLCK || spider->lock_mode == 2) + (wide_handler->external_lock_type == F_WRLCK || + wide_handler->lock_mode == 2) ) result_list->bgs_phase = 0; - else if (bgs_mode <= 1 && spider->lock_mode == 1) + else if (bgs_mode <= 1 && wide_handler->lock_mode == 1) result_list->bgs_phase = 0; else { result_list->bgs_phase = 1; @@ -1804,12 +2376,12 @@ int spider_set_conn_bg_param( for ( roop_count = spider_conn_link_idx_next(share->link_statuses, spider->conn_link_idx, -1, share->link_count, - spider->lock_mode ? + spider->wide_handler->lock_mode ? SPIDER_LINK_STATUS_RECOVERY : SPIDER_LINK_STATUS_OK); roop_count < (int) share->link_count; roop_count = spider_conn_link_idx_next(share->link_statuses, spider->conn_link_idx, roop_count, share->link_count, - spider->lock_mode ? + spider->wide_handler->lock_mode ? SPIDER_LINK_STATUS_RECOVERY : SPIDER_LINK_STATUS_OK) ) { if ((error_num = spider_create_conn_thread(spider->conns[roop_count]))) @@ -2291,6 +2863,21 @@ int spider_bg_conn_search( } } result_list->bgs_phase = 2; + if (conn->db_conn->limit_mode() == 1) + { + conn->db_conn->set_limit(result_list->limit_num); + if (!discard_result) + { + if ((error_num = spider_db_store_result_for_reuse_cursor( + spider, link_idx, result_list->table))) + { + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(error_num); + } + } + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(0); + } } result_list->bgs_working = TRUE; conn->bg_search = TRUE; @@ -2425,6 +3012,21 @@ int spider_bg_conn_search( DBUG_RETURN(error_num); } } + if (conn->db_conn->limit_mode() == 1) + { + conn->db_conn->set_limit(result_list->limit_num); + if (!discard_result) + { + if ((error_num = spider_db_store_result_for_reuse_cursor( + spider, link_idx, result_list->table))) + { + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(error_num); + } + } + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(0); + } } conn->bg_target = spider; conn->link_idx = link_idx; @@ -2688,7 +3290,7 @@ void *spider_bg_conn_action( conn->link_idx); result_list->tmp_tables_created = TRUE; spider_conn_set_timeout_from_share(conn, conn->link_idx, - spider->trx->thd, share); + spider->wide_handler->trx->thd, share); if (dbton_handler->execute_sql( SPIDER_SQL_TYPE_TMP_SQL, conn, @@ -2706,7 +3308,7 @@ void *spider_bg_conn_action( if (!result_list->bgs_error) { spider_conn_set_timeout_from_share(conn, conn->link_idx, - spider->trx->thd, share); + spider->wide_handler->trx->thd, share); if (dbton_handler->execute_sql( sql_type, conn, @@ -2949,6 +3551,7 @@ void *spider_bg_sts_action( SPIDER_TRX *trx; int error_num = 0, roop_count; ha_spider spider; + SPIDER_WIDE_HANDLER wide_handler; int *need_mons; SPIDER_CONN **conns; uint *conn_link_idx; @@ -3042,7 +3645,8 @@ void *spider_bg_sts_action( DBUG_RETURN(NULL); } share->bg_sts_thd = thd; - spider.trx = trx; + spider.wide_handler = &wide_handler; + wide_handler.trx = trx; spider.share = share; spider.conns = conns; spider.conn_link_idx = conn_link_idx; @@ -3314,6 +3918,7 @@ void *spider_bg_crd_action( SPIDER_TRX *trx; int error_num = 0, roop_count; ha_spider spider; + SPIDER_WIDE_HANDLER wide_handler; TABLE table; int *need_mons; SPIDER_CONN **conns; @@ -3411,7 +4016,8 @@ void *spider_bg_crd_action( table.s = share->table_share; table.field = share->table_share->field; table.key_info = share->table_share->key_info; - spider.trx = trx; + spider.wide_handler = &wide_handler; + wide_handler.trx = trx; spider.change_table_ptr(&table, share->table_share); spider.share = share; spider.conns = conns; @@ -4097,11 +4703,12 @@ int spider_conn_get_link_status( int spider_conn_lock_mode( ha_spider *spider ) { - SPIDER_RESULT_LIST *result_list = &spider->result_list; + SPIDER_WIDE_HANDLER *wide_handler = spider->wide_handler; DBUG_ENTER("spider_conn_lock_mode"); - if (result_list->lock_type == F_WRLCK || spider->lock_mode == 2) + if (wide_handler->external_lock_type == F_WRLCK || + wide_handler->lock_mode == 2) DBUG_RETURN(SPIDER_LOCK_MODE_EXCLUSIVE); - else if (spider->lock_mode == 1) + else if (wide_handler->lock_mode == 1) DBUG_RETURN(SPIDER_LOCK_MODE_SHARED); DBUG_RETURN(SPIDER_LOCK_MODE_NO_LOCK); } @@ -4124,7 +4731,7 @@ bool spider_conn_use_handler( int lock_mode, int link_idx ) { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; int use_handler = spider_param_use_handler(thd, spider->share->use_handlers[link_idx]); DBUG_ENTER("spider_conn_use_handler"); @@ -4197,7 +4804,7 @@ bool spider_conn_use_handler( DBUG_RETURN(FALSE); } if ( - spider->sql_command == SQLCOM_HA_READ && + spider->wide_handler->sql_command == SQLCOM_HA_READ && ( !(use_handler & 2) || ( @@ -4212,7 +4819,7 @@ bool spider_conn_use_handler( DBUG_RETURN(TRUE); } if ( - spider->sql_command != SQLCOM_HA_READ && + spider->wide_handler->sql_command != SQLCOM_HA_READ && lock_mode == SPIDER_LOCK_MODE_NO_LOCK && spider_param_sync_trx_isolation(thd) && thd_tx_isolation(thd) != ISO_SERIALIZABLE && diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h index 1612593a1cb..92da278eecc 100644 --- a/storage/spider/spd_conn.h +++ b/storage/spider/spd_conn.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2008-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,26 @@ #define SPIDER_SIMPLE_CHECKSUM_TABLE 4 #endif +#define SPIDER_LOP_CHK_QUEUED (1 << 0) +#define SPIDER_LOP_CHK_MERAGED (1 << 1) +#define SPIDER_LOP_CHK_IGNORED (1 << 2) + +typedef struct st_spider_conn_loop_check +{ + uint flag; +#ifdef SPIDER_HAS_HASH_VALUE_TYPE + my_hash_value_type hash_value_to; + my_hash_value_type hash_value_full; +#endif + LEX_CSTRING from_name; + LEX_CSTRING cur_name; + LEX_CSTRING to_name; + LEX_CSTRING full_name; + LEX_CSTRING from_value; + LEX_CSTRING merged_value; + st_spider_conn_loop_check *next; +} SPIDER_CONN_LOOP_CHECK; + uchar *spider_conn_get_key( SPIDER_CONN *conn, size_t *length, @@ -38,6 +58,14 @@ uchar *spider_ipport_conn_get_key( my_bool not_used __attribute__ ((unused)) ); +int spider_conn_init( + SPIDER_CONN *conn +); + +void spider_conn_done( + SPIDER_CONN *conn +); + int spider_reset_conn_setted_parameter( SPIDER_CONN *conn, THD *thd @@ -155,6 +183,21 @@ void spider_conn_queue_UTC_time_zone( SPIDER_CONN *conn ); +int spider_conn_queue_and_merge_loop_check( + SPIDER_CONN *conn, + SPIDER_CONN_LOOP_CHECK *lcptr +); + +int spider_conn_reset_queue_loop_check( + SPIDER_CONN *conn +); + +int spider_conn_queue_loop_check( + SPIDER_CONN *conn, + ha_spider *spider, + int link_idx +); + void spider_conn_queue_start_transaction( SPIDER_CONN *conn ); diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index 19023a00da3..ed08cb8a6af 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2009-2018 Kentoku Shiba +/* Copyright (C) 2009-2019 Kentoku Shiba + Copyright (C) 2019 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -839,6 +840,7 @@ long long spider_copy_tables_body( spider_string *tmp_sql = NULL; SPIDER_COPY_TABLE_CONN *table_conn, *src_tbl_conn, *dst_tbl_conn; SPIDER_CONN *tmp_conn; + SPIDER_WIDE_HANDLER *wide_handler; spider_db_copy_table *select_ct, *insert_ct; MEM_ROOT mem_root; longlong bulk_insert_rows; @@ -1128,13 +1130,15 @@ long long spider_copy_tables_body( __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &tmp_spider->dbton_handler, sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE, + &wide_handler, sizeof(SPIDER_WIDE_HANDLER), NullS)) ) { my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); goto error; } tmp_spider->share = table_conn->share; - tmp_spider->trx = copy_tables->trx; + tmp_spider->wide_handler = wide_handler; + wide_handler->trx = copy_tables->trx; /* if (spider_db_append_set_names(table_conn->share)) { @@ -1147,7 +1151,7 @@ long long spider_copy_tables_body( tmp_sql[roop_count].set_charset(copy_tables->access_charset); tmp_spider->result_list.sqls = &tmp_sql[roop_count]; tmp_spider->need_mons = &table_conn->need_mon; - tmp_spider->lock_type = TL_READ; + tmp_spider->wide_handler->lock_type = TL_READ; tmp_spider->conn_link_idx = &tmp_conn_link_idx; uint dbton_id = tmp_spider->share->use_dbton_ids[0]; if (!(tmp_spider->dbton_handler[dbton_id] = @@ -1172,13 +1176,15 @@ long long spider_copy_tables_body( __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &tmp_spider->dbton_handler, sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE, + &wide_handler, sizeof(SPIDER_WIDE_HANDLER), NullS)) ) { my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); goto error; } tmp_spider->share = table_conn->share; - tmp_spider->trx = copy_tables->trx; + tmp_spider->wide_handler = wide_handler; + wide_handler->trx = copy_tables->trx; /* if (spider_db_append_set_names(table_conn->share)) { @@ -1191,7 +1197,7 @@ long long spider_copy_tables_body( tmp_sql[roop_count].set_charset(copy_tables->access_charset); tmp_spider->result_list.sqls = &tmp_sql[roop_count]; tmp_spider->need_mons = &table_conn->need_mon; - tmp_spider->lock_type = TL_WRITE; + tmp_spider->wide_handler->lock_type = TL_WRITE; tmp_spider->conn_link_idx = &tmp_conn_link_idx; uint dbton_id = tmp_spider->share->use_dbton_ids[0]; if (!(tmp_spider->dbton_handler[dbton_id] = diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 657e81671ee..2df148b6ea4 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -278,9 +278,9 @@ int spider_db_ping( ) { DBUG_ENTER("spider_db_ping"); #ifndef DBUG_OFF - if (spider->trx->thd) + if (spider->wide_handler->trx->thd) DBUG_PRINT("info", ("spider thd->query_id is %lld", - spider->trx->thd->query_id)); + spider->wide_handler->trx->thd->query_id)); #endif DBUG_RETURN(spider_db_ping_internal(spider->share, conn, spider->conn_link_idx[link_idx], &spider->need_mons[link_idx])); @@ -402,6 +402,12 @@ int spider_db_conn_queue_action( (error_num = spider_dbton[conn->dbton_id].db_util-> append_time_zone(&sql_str, conn->queued_time_zone_val)) ) || + ( + conn->loop_check_queue.records && + conn->db_conn->set_loop_check_in_bulk_sql() && + (error_num = spider_dbton[conn->dbton_id].db_util-> + append_loop_check(&sql_str, conn)) + ) || ( conn->queued_trx_start && conn->db_conn->trx_start_in_bulk_sql() && @@ -450,8 +456,8 @@ int spider_db_conn_queue_action( (!conn->queued_autocommit_val && conn->autocommit != 0) ) && !conn->db_conn->set_autocommit_in_bulk_sql() && - (error_num = spider_dbton[conn->dbton_id].db_util-> - append_autocommit(&sql_str, conn->queued_autocommit_val)) + (error_num = conn->db_conn-> + set_autocommit(conn->queued_autocommit_val, (int *) conn->need_mon)) ) { DBUG_RETURN(error_num); } @@ -462,8 +468,8 @@ int spider_db_conn_queue_action( (!conn->queued_sql_log_off_val && conn->sql_log_off != 0) ) && !conn->db_conn->set_sql_log_off_in_bulk_sql() && - (error_num = spider_dbton[conn->dbton_id].db_util-> - append_sql_log_off(&sql_str, conn->queued_sql_log_off_val)) + (error_num = conn->db_conn-> + set_sql_log_off(conn->queued_sql_log_off_val, (int *) conn->need_mon)) ) { DBUG_RETURN(error_num); } @@ -471,8 +477,9 @@ int spider_db_conn_queue_action( conn->queued_wait_timeout && conn->queued_wait_timeout_val != conn->wait_timeout && !conn->db_conn->set_wait_timeout_in_bulk_sql() && - (error_num = spider_dbton[conn->dbton_id].db_util-> - append_wait_timeout(&sql_str, conn->queued_wait_timeout_val)) + (error_num = conn->db_conn-> + set_wait_timeout(conn->queued_wait_timeout_val, + (int *) conn->need_mon)) ) { DBUG_RETURN(error_num); } @@ -480,8 +487,9 @@ int spider_db_conn_queue_action( conn->queued_sql_mode && conn->queued_sql_mode_val != conn->sql_mode && !conn->db_conn->set_sql_mode_in_bulk_sql() && - (error_num = spider_dbton[conn->dbton_id].db_util-> - append_sql_mode(&sql_str, conn->queued_sql_mode_val)) + (error_num = conn->db_conn-> + set_sql_mode(conn->queued_sql_mode_val, + (int *) conn->need_mon)) ) { DBUG_RETURN(error_num); } @@ -489,8 +497,16 @@ int spider_db_conn_queue_action( conn->queued_time_zone && conn->queued_time_zone_val != conn->time_zone && !conn->db_conn->set_time_zone_in_bulk_sql() && - (error_num = spider_dbton[conn->dbton_id].db_util-> - append_time_zone(&sql_str, conn->queued_time_zone_val)) + (error_num = conn->db_conn-> + set_time_zone(conn->queued_time_zone_val, + (int *) conn->need_mon)) + ) { + DBUG_RETURN(error_num); + } + if ( + conn->loop_check_queue.records && + !conn->db_conn->set_loop_check_in_bulk_sql() && + (error_num = conn->db_conn->set_loop_check((int *) conn->need_mon)) ) { DBUG_RETURN(error_num); } @@ -600,6 +616,11 @@ int spider_db_conn_queue_action( DBUG_PRINT("info", ("spider conn->time_zone=%p", conn->time_zone)); } + + if (conn->loop_check_queue.records) + { + conn->db_conn->fin_loop_check(); + } spider_conn_clear_queue(conn); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else if (conn->server_lost) @@ -939,6 +960,7 @@ int spider_db_set_names_internal( } if ( spider_param_use_default_database(trx->thd) && + share->tgt_dbs[all_link_idx] && ( !conn->default_database.length() || conn->default_database.length() != @@ -984,7 +1006,8 @@ int spider_db_set_names( int link_idx ) { DBUG_ENTER("spider_db_set_names"); - DBUG_RETURN(spider_db_set_names_internal(spider->trx, spider->share, conn, + DBUG_RETURN(spider_db_set_names_internal(spider->wide_handler->trx, + spider->share, conn, spider->conn_link_idx[link_idx], &spider->need_mons[link_idx])); } @@ -1017,8 +1040,8 @@ int spider_db_query_with_set_names( spider->need_mons[link_idx] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -1035,7 +1058,8 @@ int spider_db_query_with_set_names( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, @@ -1051,8 +1075,8 @@ int spider_db_query_with_set_names( spider->need_mons[link_idx] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -1104,8 +1128,8 @@ int spider_db_query_for_bulk_update( spider->need_mons[link_idx] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -1122,7 +1146,8 @@ int spider_db_query_for_bulk_update( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); spider_db_handler *dbton_hdl = spider->dbton_handler[conn->dbton_id]; if (dbton_hdl->execute_sql( @@ -1142,8 +1167,8 @@ int spider_db_query_for_bulk_update( spider->need_mons[link_idx] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -1159,7 +1184,7 @@ int spider_db_query_for_bulk_update( ); } if ( - spider->ignore_dup_key && + spider->wide_handler->ignore_dup_key && ( error_num == ER_DUP_ENTRY || error_num == ER_DUP_KEY || @@ -1167,7 +1192,7 @@ int spider_db_query_for_bulk_update( ) ) { ++(*dup_key_found); - spider->trx->thd->clear_error(); + spider->wide_handler->trx->thd->clear_error(); DBUG_RETURN(0); } DBUG_RETURN(error_num); @@ -1187,8 +1212,8 @@ int spider_db_query_for_bulk_update( spider->need_mons[link_idx] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, link_idx, (uint32) share->monitoring_sid[link_idx], @@ -2798,7 +2823,7 @@ int spider_db_fetch_for_item_sum_func( ) { int error_num; SPIDER_SHARE *share = spider->share; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; DBUG_ENTER("spider_db_fetch_for_item_sum_func"); DBUG_PRINT("info",("spider Sumfunctype = %d", item_sum->sum_func())); switch (item_sum->sum_func()) @@ -3526,7 +3551,8 @@ int spider_db_fetch_minimum_columns( ) { DBUG_PRINT("info", ("spider field_index %u", (*field)->field_index)); DBUG_PRINT("info", ("spider searched_bitmap %u", - spider_bit_is_set(spider->searched_bitmap, (*field)->field_index))); + spider_bit_is_set(spider->wide_handler->searched_bitmap, + (*field)->field_index))); DBUG_PRINT("info", ("spider read_set %u", bitmap_is_set(table->read_set, (*field)->field_index))); DBUG_PRINT("info", ("spider write_set %u", @@ -3708,7 +3734,7 @@ int spider_db_free_result( SPIDER_RESULT *result; SPIDER_RESULT *prev; SPIDER_SHARE *share = spider->share; - SPIDER_TRX *trx = spider->trx; + SPIDER_TRX *trx = spider->wide_handler->trx; SPIDER_POSITION *position; int roop_count, error_num; DBUG_ENTER("spider_db_free_result"); @@ -4015,7 +4041,8 @@ int spider_db_store_result( #endif result_list->quick_phase == 2 ) { - if (result_list->low_mem_read) + if (result_list->low_mem_read && + result_list->current->result->limit_mode() == 0) { do { spider_db_free_one_result(result_list, @@ -4064,8 +4091,9 @@ int spider_db_store_result( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; @@ -4163,12 +4191,13 @@ int spider_db_store_result( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; - if (!(current->result = conn->db_conn->use_result(&request_key, + if (!(current->result = conn->db_conn->use_result(spider, &request_key, &error_num))) { if (!error_num) @@ -4372,15 +4401,20 @@ int spider_db_store_result( result_list->quick_mode == 3 || result_list->limit_num == roop_count ) { - current->result->free_result(); - if (!current->result_tmp_tbl) - { - delete current->result; - current->result = NULL; + if ( + result_list->limit_num != roop_count || + conn->db_conn->limit_mode() != 1 + ) { + current->result->free_result(); + if (!current->result_tmp_tbl) + { + delete current->result; + current->result = NULL; + } + DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); + conn->quick_target = NULL; + spider->quick_targets[link_idx] = NULL; } - DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); - conn->quick_target = NULL; - spider->quick_targets[link_idx] = NULL; } #ifndef WITHOUT_SPIDER_BG_SEARCH DBUG_PRINT("info", ("spider bgs_phase=%d", result_list->bgs_phase)); @@ -4428,8 +4462,8 @@ int spider_db_store_result( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; @@ -4461,6 +4495,431 @@ int spider_db_store_result( DBUG_RETURN(0); } +int spider_db_store_result_for_reuse_cursor( + ha_spider *spider, + int link_idx, + TABLE *table +) { + int error_num; + SPIDER_CONN *conn; + SPIDER_RESULT_LIST *result_list = &spider->result_list; + SPIDER_RESULT *current; + DBUG_ENTER("spider_db_store_result_for_reuse_cursor"); +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + DBUG_ASSERT(spider->conn_kind[link_idx] == SPIDER_CONN_KIND_MYSQL); +#endif + conn = spider->conns[link_idx]; + DBUG_PRINT("info",("spider conn->connection_id=%llu", + conn->connection_id)); + DBUG_PRINT("info",("spider spider->connection_ids[%d]=%llu", + link_idx, spider->connection_ids[link_idx])); + if (conn->connection_id != spider->connection_ids[link_idx]) + { + my_message(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM, + ER_SPIDER_REMOTE_SERVER_GONE_AWAY_STR, MYF(0)); +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + DBUG_RETURN(ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM); + } + if (!result_list->current) + { + if (!result_list->first) + { + if (!(result_list->first = (SPIDER_RESULT *) + spider_malloc(spider_current_trx, 4, sizeof(*result_list->first), + MYF(MY_WME | MY_ZEROFILL))) + ) { +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + TMP_TABLE_PARAM *tmp_tbl_prm = (TMP_TABLE_PARAM *) + &result_list->first->result_tmp_tbl_prm; + tmp_tbl_prm->init(); + tmp_tbl_prm->field_count = 3; + result_list->last = result_list->first; + result_list->current = result_list->first; + } else { + result_list->current = result_list->first; + } + result_list->bgs_current = result_list->current; + current = (SPIDER_RESULT*) result_list->current; + } else { + if ( +#ifndef WITHOUT_SPIDER_BG_SEARCH + result_list->bgs_phase > 0 || +#endif + result_list->quick_phase > 0 + ) { + if (result_list->bgs_current == result_list->last) + { + if (!(result_list->last = (SPIDER_RESULT *) + spider_malloc(spider_current_trx, 5, sizeof(*result_list->last), + MYF(MY_WME | MY_ZEROFILL))) + ) { +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + TMP_TABLE_PARAM *tmp_tbl_prm = (TMP_TABLE_PARAM *) + &result_list->last->result_tmp_tbl_prm; + tmp_tbl_prm->init(); + tmp_tbl_prm->field_count = 3; + result_list->bgs_current->next = result_list->last; + result_list->last->prev = result_list->bgs_current; + result_list->bgs_current = result_list->last; + } else { + result_list->bgs_current = result_list->bgs_current->next; + } + if ( +#ifndef WITHOUT_SPIDER_BG_SEARCH + result_list->bgs_phase == 1 || +#endif + result_list->quick_phase == 2 + ) { + result_list->current = result_list->bgs_current; + result_list->quick_phase = 0; + } + current = (SPIDER_RESULT*) result_list->bgs_current; + } else { + if (result_list->current == result_list->last) + { + if (!(result_list->last = (SPIDER_RESULT *) + spider_malloc(spider_current_trx, 6, sizeof(*result_list->last), + MYF(MY_WME | MY_ZEROFILL))) + ) { +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + TMP_TABLE_PARAM *tmp_tbl_prm = (TMP_TABLE_PARAM *) + &result_list->last->result_tmp_tbl_prm; + tmp_tbl_prm->init(); + tmp_tbl_prm->field_count = 3; + result_list->current->next = result_list->last; + result_list->last->prev = result_list->current; + result_list->current = result_list->last; + } else { + result_list->current = result_list->current->next; + } + result_list->bgs_current = result_list->current; + current = (SPIDER_RESULT*) result_list->current; + } + } + + if (result_list->quick_mode == 0) + { + if (spider_bit_is_set(spider->db_request_phase, link_idx)) + { + spider_clear_bit(spider->db_request_phase, link_idx); + } + current->result = current->prev->result; + current->result->set_limit(result_list->limit_num); +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + current->record_num = current->result->num_rows(); + current->dbton_id = current->result->dbton_id; + result_list->record_num += current->record_num; + DBUG_PRINT("info",("spider current->record_num=%lld", + current->record_num)); + DBUG_PRINT("info",("spider result_list->record_num=%lld", + result_list->record_num)); + DBUG_PRINT("info",("spider result_list->internal_limit=%lld", + result_list->internal_limit)); + DBUG_PRINT("info",("spider result_list->split_read=%lld", + result_list->split_read)); + if ( + result_list->internal_limit <= result_list->record_num || + result_list->split_read > current->record_num + ) { + DBUG_PRINT("info",("spider set finish_flg point 2")); + DBUG_PRINT("info",("spider current->finish_flg = TRUE")); + DBUG_PRINT("info",("spider result_list->finish_flg = TRUE")); + current->finish_flg = TRUE; + result_list->finish_flg = TRUE; + } +#ifndef WITHOUT_SPIDER_BG_SEARCH + if (result_list->bgs_phase <= 1) + { +#endif + result_list->current_row_num = 0; +#ifndef WITHOUT_SPIDER_BG_SEARCH + } +#endif + } else { + DBUG_ASSERT(current->prev); + DBUG_ASSERT(current->prev->result); + /* has_result() for case of result with result_tmp_tbl */ + if (current->prev->result->has_result()) + { + current->result = current->prev->result; + current->result->set_limit(result_list->limit_num); + current->prev->result = NULL; + result_list->limit_num -= current->prev->record_num; +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + } else { + if (spider_bit_is_set(spider->db_request_phase, link_idx)) + { + spider_clear_bit(spider->db_request_phase, link_idx); + } + current->result = current->prev->result; + current->result->set_limit(result_list->limit_num); + DBUG_PRINT("info", ("spider conn[%p]->quick_target=%p", conn, spider)); + conn->quick_target = spider; + spider->quick_targets[link_idx] = spider; +/* + if (!conn->mta_conn_mutex_unlock_later) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } +*/ + } + current->dbton_id = current->result->dbton_id; + SPIDER_DB_ROW *row; + if (!(row = current->result->fetch_row())) + { + error_num = current->result->get_errno(); + DBUG_PRINT("info",("spider set finish_flg point 3")); + DBUG_PRINT("info",("spider current->finish_flg = TRUE")); + DBUG_PRINT("info",("spider result_list->finish_flg = TRUE")); + current->finish_flg = TRUE; + result_list->finish_flg = TRUE; + current->result->free_result(); + delete current->result; + current->result = NULL; + DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); + conn->quick_target = NULL; + spider->quick_targets[link_idx] = NULL; + if ( +#ifndef WITHOUT_SPIDER_BG_SEARCH + result_list->bgs_phase <= 1 && +#endif + result_list->quick_phase == 0 + ) { + result_list->current_row_num = 0; + table->status = STATUS_NOT_FOUND; + } + if (error_num && error_num != HA_ERR_END_OF_FILE) + DBUG_RETURN(error_num); + /* This shouldn't return HA_ERR_END_OF_FILE */ + DBUG_RETURN(0); + } + SPIDER_DB_ROW *tmp_row; + uint field_count = current->result->num_fields(); + SPIDER_POSITION *position; + longlong page_size; + int roop_count = 0; + if (!result_list->quick_page_size) + { + if (result_list->quick_mode == 3) + { + page_size = 0; + } else { + result_list->quick_page_size = result_list->limit_num; + page_size = result_list->limit_num; + } + } else { + page_size = + result_list->limit_num < result_list->quick_page_size ? + result_list->limit_num : result_list->quick_page_size; + } + current->field_count = field_count; + if (!(position = (SPIDER_POSITION *) + spider_bulk_malloc(spider_current_trx, 7, MYF(MY_WME | MY_ZEROFILL), + &position, (uint) (sizeof(SPIDER_POSITION) * page_size), + &tmp_row, (uint) (sizeof(SPIDER_DB_ROW) * field_count), + NullS)) + ) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + current->pos_page_size = (int) page_size; + current->first_position = position; + current->tmp_tbl_row = tmp_row; + if (result_list->quick_mode == 3) + { + while (page_size > roop_count && row) + { + if (result_list->quick_page_byte < row->get_byte_size()) + { + current->pos_page_size = roop_count; + page_size = roop_count; + result_list->quick_page_size = roop_count; + result_list->quick_page_byte = 0; + break; + } else { + result_list->quick_page_byte -= row->get_byte_size(); + } + if (!(position->row = row->clone())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + position++; + roop_count++; + row = current->result->fetch_row(); + } + } else { + do { + if (!(position->row = row->clone())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + position++; + roop_count++; + if (result_list->quick_page_byte < row->get_byte_size()) + { + current->pos_page_size = roop_count; + page_size = roop_count; + result_list->quick_page_size = roop_count; + result_list->quick_page_byte = 0; + break; + } else { + result_list->quick_page_byte -= row->get_byte_size(); + } + } while ( + page_size > roop_count && + (row = current->result->fetch_row()) + ); + } + if ( + result_list->quick_mode == 3 && + page_size == roop_count && + result_list->limit_num > roop_count && + row + ) { + THD *thd = current_thd; + char buf[MAX_FIELD_WIDTH]; + spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin); + tmp_str.init_calc_mem(120); + + DBUG_PRINT("info",("spider store result to temporary table")); + DBUG_ASSERT(!current->result_tmp_tbl); +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor + LEX_CSTRING field_name1 = {STRING_WITH_LEN("a")}; + LEX_CSTRING field_name2 = {STRING_WITH_LEN("b")}; + LEX_CSTRING field_name3 = {STRING_WITH_LEN("c")}; + if (!(current->result_tmp_tbl = spider_mk_sys_tmp_table_for_result( + thd, table, ¤t->result_tmp_tbl_prm, &field_name1, &field_name2, + &field_name3, &my_charset_bin))) +#else + if (!(current->result_tmp_tbl = spider_mk_sys_tmp_table_for_result( + thd, table, ¤t->result_tmp_tbl_prm, "a", "b", "c", + &my_charset_bin))) +#endif + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + current->result_tmp_tbl_thd = thd; + TABLE *tmp_tbl = current->result_tmp_tbl; + tmp_tbl->file->extra(HA_EXTRA_WRITE_CACHE); + tmp_tbl->file->ha_start_bulk_insert((ha_rows) 0); + do { + if ((error_num = row->store_to_tmp_table(tmp_tbl, &tmp_str))) + { + tmp_tbl->file->ha_end_bulk_insert(); + DBUG_RETURN(error_num); + } + roop_count++; + } while ( + result_list->limit_num > roop_count && + (row = current->result->fetch_row()) + ); + tmp_tbl->file->ha_end_bulk_insert(); + page_size = result_list->limit_num; + } + current->record_num = roop_count; + result_list->record_num += roop_count; + if ( + result_list->internal_limit <= result_list->record_num || + page_size > roop_count || + ( + result_list->quick_mode == 3 && + result_list->limit_num > roop_count + ) + ) { + DBUG_PRINT("info",("spider set finish_flg point 4")); + DBUG_PRINT("info",("spider current->finish_flg = TRUE")); + DBUG_PRINT("info",("spider result_list->finish_flg = TRUE")); + current->finish_flg = TRUE; + result_list->finish_flg = TRUE; + current->result->free_result(); + if (!current->result_tmp_tbl) + { + delete current->result; + current->result = NULL; + } + DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); + conn->quick_target = NULL; + spider->quick_targets[link_idx] = NULL; + } else if ( + result_list->quick_mode == 3 || + result_list->limit_num == roop_count + ) { + if (result_list->limit_num != roop_count) + { + current->result->free_result(); + if (!current->result_tmp_tbl) + { + delete current->result; + current->result = NULL; + } + DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); + conn->quick_target = NULL; + spider->quick_targets[link_idx] = NULL; + } + } +#ifndef WITHOUT_SPIDER_BG_SEARCH + DBUG_PRINT("info", ("spider bgs_phase=%d", result_list->bgs_phase)); +#endif + DBUG_PRINT("info", ("spider quick_phase=%d", result_list->quick_phase)); + if ( +#ifndef WITHOUT_SPIDER_BG_SEARCH + result_list->bgs_phase <= 1 && +#endif + result_list->quick_phase == 0 + ) { + result_list->current_row_num = 0; + } + DBUG_PRINT("info", ("spider result_list->current=%p", result_list->current)); + DBUG_PRINT("info", ("spider current=%p", current)); + DBUG_PRINT("info", ("spider first_position=%p", current->first_position)); + DBUG_PRINT("info", ("spider current_row_num=%lld", result_list->current_row_num)); + DBUG_PRINT("info", ("spider first_position[]=%p", ¤t->first_position[result_list->current_row_num])); + DBUG_PRINT("info", ("spider row=%p", current->first_position[result_list->current_row_num].row)); + } + DBUG_RETURN(0); +} + void spider_db_discard_result( ha_spider *spider, int link_idx, @@ -4474,12 +4933,12 @@ void spider_db_discard_result( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, &error_num))) { result->free_result(); delete result; @@ -4500,8 +4959,8 @@ void spider_db_discard_multiple_result( { spider_clear_bit(spider->db_request_phase, link_idx); } - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; @@ -4509,7 +4968,7 @@ void spider_db_discard_multiple_result( { if (!conn->db_conn->cmp_request_key_to_snd(&request_key)) break; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, &error_num))) { result->free_result(); delete result; @@ -4791,65 +5250,82 @@ int spider_db_seek_next( pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); } - conn->need_mon = &spider->need_mons[link_idx]; - conn->mta_conn_mutex_lock_already = TRUE; - conn->mta_conn_mutex_unlock_later = TRUE; - if ((error_num = spider_db_set_names(spider, conn, link_idx))) + if (conn->db_conn->limit_mode() == 1) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); - if ( - spider->need_mons[link_idx] - ) { - error_num = fields->ping_table_mon_from_table(link_idx_chain); - } - DBUG_PRINT("info",("spider error_num 7a=%d", error_num)); - DBUG_RETURN(error_num); - } - spider_conn_set_timeout_from_share(conn, link_idx, - spider->trx->thd, share); - if (dbton_handler->execute_sql( - sql_type, - conn, - result_list->quick_mode, - &spider->need_mons[link_idx]) - ) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - error_num = spider_db_errorno(conn); - if ( - spider->need_mons[link_idx] - ) { - error_num = fields->ping_table_mon_from_table(link_idx_chain); - } - DBUG_PRINT("info",("spider error_num 8a=%d", error_num)); - DBUG_RETURN(error_num); - } - spider->connection_ids[link_idx] = conn->connection_id; - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - if (fields->is_first_link_ok_chain(link_idx_chain)) - { - if ((error_num = spider_db_store_result(spider, link_idx, - table))) + conn->db_conn->set_limit(result_list->limit_num); + if (fields->is_first_link_ok_chain(link_idx_chain)) { + if ((error_num = spider_db_store_result_for_reuse_cursor( + spider, link_idx, table))) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(error_num); + } + } + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + } else { + conn->need_mon = &spider->need_mons[link_idx]; + conn->mta_conn_mutex_lock_already = TRUE; + conn->mta_conn_mutex_unlock_later = TRUE; + if ((error_num = spider_db_set_names(spider, conn, link_idx))) + { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); if ( - error_num != HA_ERR_END_OF_FILE && spider->need_mons[link_idx] ) { - error_num = - fields->ping_table_mon_from_table(link_idx_chain); + error_num = fields->ping_table_mon_from_table(link_idx_chain); } - DBUG_PRINT("info",("spider error_num 9a=%d", error_num)); + DBUG_PRINT("info",("spider error_num 7a=%d", error_num)); DBUG_RETURN(error_num); } - spider->result_link_idx = link_ok; - } else { - spider_db_discard_result(spider, link_idx, conn); - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); + if (dbton_handler->execute_sql( + sql_type, + conn, + result_list->quick_mode, + &spider->need_mons[link_idx]) + ) { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + error_num = spider_db_errorno(conn); + if ( + spider->need_mons[link_idx] + ) { + error_num = fields->ping_table_mon_from_table(link_idx_chain); + } + DBUG_PRINT("info",("spider error_num 8a=%d", error_num)); + DBUG_RETURN(error_num); + } + spider->connection_ids[link_idx] = conn->connection_id; + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + if (fields->is_first_link_ok_chain(link_idx_chain)) + { + if ((error_num = spider_db_store_result(spider, link_idx, + table))) + { + if ( + error_num != HA_ERR_END_OF_FILE && + spider->need_mons[link_idx] + ) { + error_num = + fields->ping_table_mon_from_table(link_idx_chain); + } + DBUG_PRINT("info",("spider error_num 9a=%d", error_num)); + DBUG_RETURN(error_num); + } + spider->result_link_idx = link_ok; + } else { + spider_db_discard_result(spider, link_idx, conn); + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } } } } else { @@ -4885,90 +5361,38 @@ int spider_db_seek_next( pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); } - conn->need_mon = &spider->need_mons[roop_count]; - conn->mta_conn_mutex_lock_already = TRUE; - conn->mta_conn_mutex_unlock_later = TRUE; - if ((error_num = spider_db_set_names(spider, conn, roop_count))) + if (conn->db_conn->limit_mode() == 1) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_PRINT("info",("spider error_num 7=%d", error_num)); - DBUG_RETURN(error_num); - } - spider_conn_set_timeout_from_share(conn, roop_count, - spider->trx->thd, share); - if (dbton_handler->execute_sql( - sql_type, - conn, - result_list->quick_mode, - &spider->need_mons[roop_count]) - ) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - error_num = spider_db_errorno(conn); - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_PRINT("info",("spider error_num 8=%d", error_num)); - DBUG_RETURN(error_num); - } - spider->connection_ids[roop_count] = conn->connection_id; - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - if (roop_count == link_ok) - { - if ((error_num = spider_db_store_result(spider, roop_count, - table))) + conn->db_conn->set_limit(result_list->limit_num); + if (roop_count == link_ok) { + if ((error_num = spider_db_store_result_for_reuse_cursor( + spider, link_idx, table))) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(error_num); + } + } + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + } else { + conn->need_mon = &spider->need_mons[roop_count]; + conn->mta_conn_mutex_lock_already = TRUE; + conn->mta_conn_mutex_unlock_later = TRUE; + if ((error_num = spider_db_set_names(spider, conn, roop_count))) + { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); if ( - error_num != HA_ERR_END_OF_FILE && share->monitoring_kind[roop_count] && spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -4983,14 +5407,83 @@ int spider_db_seek_next( TRUE ); } - DBUG_PRINT("info",("spider error_num 9=%d", error_num)); + DBUG_PRINT("info",("spider error_num 7=%d", error_num)); DBUG_RETURN(error_num); } - spider->result_link_idx = link_ok; - } else { - spider_db_discard_result(spider, roop_count, conn); - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); + if (dbton_handler->execute_sql( + sql_type, + conn, + result_list->quick_mode, + &spider->need_mons[roop_count]) + ) { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + error_num = spider_db_errorno(conn); + if ( + share->monitoring_kind[roop_count] && + spider->need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + spider->wide_handler->trx, + spider->wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + spider->conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_PRINT("info",("spider error_num 8=%d", error_num)); + DBUG_RETURN(error_num); + } + spider->connection_ids[roop_count] = conn->connection_id; + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + if (roop_count == link_ok) + { + if ((error_num = spider_db_store_result(spider, roop_count, + table))) + { + if ( + error_num != HA_ERR_END_OF_FILE && + share->monitoring_kind[roop_count] && + spider->need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + spider->wide_handler->trx, + spider->wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + spider->conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_PRINT("info",("spider error_num 9=%d", error_num)); + DBUG_RETURN(error_num); + } + spider->result_link_idx = link_ok; + } else { + spider_db_discard_result(spider, roop_count, conn); + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } } } #ifdef SPIDER_HAS_GROUP_BY_HANDLER @@ -5139,87 +5632,38 @@ int spider_db_seek_last( SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); } DBUG_PRINT("info",("spider sql_type=%lu", sql_type)); - conn->need_mon = &spider->need_mons[roop_count]; - conn->mta_conn_mutex_lock_already = TRUE; - conn->mta_conn_mutex_unlock_later = TRUE; - if ((error_num = spider_db_set_names(spider, conn, roop_count))) + if (conn->db_conn->limit_mode() == 1) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_RETURN(error_num); - } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, - share); - if (dbton_handler->execute_sql( - sql_type, - conn, - result_list->quick_mode, - &spider->need_mons[roop_count]) - ) { - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - error_num = spider_db_errorno(conn); - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_RETURN(error_num); - } - spider->connection_ids[roop_count] = conn->connection_id; - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - if (roop_count == link_ok) - { - if ((error_num = spider_db_store_result(spider, roop_count, table))) + conn->db_conn->set_limit(result_list->limit_num); + if (roop_count == link_ok) { + if ((error_num = spider_db_store_result_for_reuse_cursor( + spider, roop_count, table))) + { + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + DBUG_RETURN(error_num); + } + } + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->bg_conn_mutex); + } else { + conn->need_mon = &spider->need_mons[roop_count]; + conn->mta_conn_mutex_lock_already = TRUE; + conn->mta_conn_mutex_unlock_later = TRUE; + if ((error_num = spider_db_set_names(spider, conn, roop_count))) + { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); if ( - error_num != HA_ERR_END_OF_FILE && share->monitoring_kind[roop_count] && spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5236,11 +5680,78 @@ int spider_db_seek_last( } DBUG_RETURN(error_num); } - spider->result_link_idx = link_ok; - } else { - spider_db_discard_result(spider, roop_count, conn); - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, + share); + if (dbton_handler->execute_sql( + sql_type, + conn, + result_list->quick_mode, + &spider->need_mons[roop_count]) + ) { + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + error_num = spider_db_errorno(conn); + if ( + share->monitoring_kind[roop_count] && + spider->need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + spider->wide_handler->trx, + spider->wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + spider->conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(error_num); + } + spider->connection_ids[roop_count] = conn->connection_id; + conn->mta_conn_mutex_lock_already = FALSE; + conn->mta_conn_mutex_unlock_later = FALSE; + if (roop_count == link_ok) + { + if ((error_num = spider_db_store_result(spider, roop_count, table))) + { + if ( + error_num != HA_ERR_END_OF_FILE && + share->monitoring_kind[roop_count] && + spider->need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + spider->wide_handler->trx, + spider->wide_handler->trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + spider->conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_RETURN(error_num); + } + spider->result_link_idx = link_ok; + } else { + spider_db_discard_result(spider, roop_count, conn); + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + } } } result_list->current_row_num = result_list->current->record_num - 1; @@ -5356,8 +5867,8 @@ int spider_db_seek_last( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5374,7 +5885,8 @@ int spider_db_seek_last( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_handler->execute_sql( sql_type, @@ -5390,8 +5902,8 @@ int spider_db_seek_last( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5421,8 +5933,8 @@ int spider_db_seek_last( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5521,7 +6033,7 @@ void spider_db_create_position( pos->direct_aggregate = result_list->direct_aggregate; #endif pos->sql_kind = spider->sql_kind[spider->result_link_idx]; - pos->position_bitmap = spider->position_bitmap; + pos->position_bitmap = spider->wide_handler->position_bitmap; pos->ft_first = spider->ft_first; pos->ft_current = spider->ft_current; pos->result = current; @@ -5893,7 +6405,7 @@ int spider_db_simple_action( bool pre_call ) { int error_num; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_CONN *conn; DBUG_ENTER("spider_db_simple_action"); if (pre_call) @@ -5965,14 +6477,19 @@ void spider_db_set_cardinarity( { key_part = &key_info->key_part[roop_count2]; field = key_part->field; - rec_per_key = (ha_rows) share->stat.records / - share->cardinality[field->field_index]; - if (rec_per_key > ~(ulong) 0) - key_info->rec_per_key[roop_count2] = ~(ulong) 0; - else if (rec_per_key == 0) + if (share->cardinality[field->field_index]) + { + rec_per_key = (ha_rows) share->stat.records / + share->cardinality[field->field_index]; + if (rec_per_key > ~(ulong) 0) + key_info->rec_per_key[roop_count2] = ~(ulong) 0; + else if (rec_per_key == 0) + key_info->rec_per_key[roop_count2] = 1; + else + key_info->rec_per_key[roop_count2] = (ulong) rec_per_key; + } else { key_info->rec_per_key[roop_count2] = 1; - else - key_info->rec_per_key[roop_count2] = (ulong) rec_per_key; + } DBUG_PRINT("info", ("spider column id=%d", field->field_index)); DBUG_PRINT("info", @@ -6043,7 +6560,8 @@ int spider_db_bulk_insert_init( SPIDER_LINK_STATUS_RECOVERY) ) { if (spider->conns[roop_count]) - spider->conns[roop_count]->ignore_dup_key = spider->ignore_dup_key; + spider->conns[roop_count]->ignore_dup_key = + spider->wide_handler->ignore_dup_key; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if ( spider_conn_use_handler(spider, spider->lock_mode, roop_count) && @@ -6063,8 +6581,8 @@ int spider_db_bulk_insert_init( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6084,7 +6602,8 @@ int spider_db_bulk_insert_init( spider->set_handler_opened(roop_count); } #else - spider_conn_use_handler(spider, spider->lock_mode, roop_count); + spider_conn_use_handler(spider, spider->wide_handler->lock_mode, + roop_count); #endif } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -6118,7 +6637,7 @@ int spider_db_bulk_insert( SPIDER_RESULT_LIST *result_list = &spider->result_list; #endif SPIDER_SHARE *share = spider->share; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; bool mta_conn_mutex_lock_already_backup; bool mta_conn_mutex_unlock_later_backup; DBUG_ENTER("spider_db_bulk_insert"); @@ -6236,8 +6755,8 @@ int spider_db_bulk_insert( spider->need_mons[roop_count2] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count2, (uint32) share->monitoring_sid[roop_count2], @@ -6254,7 +6773,8 @@ int spider_db_bulk_insert( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count2, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count2, + spider->wide_handler->trx->thd, share); if (dbton_handler->execute_sql( sql_type, @@ -6286,8 +6806,8 @@ int spider_db_bulk_insert( spider->need_mons[roop_count2] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count2, (uint32) share->monitoring_sid[roop_count2], @@ -6327,12 +6847,14 @@ int spider_db_bulk_insert( spider_clear_bit(spider->db_request_phase, roop_count2); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[roop_count2]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { result->free_result(); delete result; @@ -6447,7 +6969,7 @@ int spider_db_bulk_bulk_insert( SPIDER_SHARE *share = spider->share; SPIDER_CONN *conn, *first_insert_conn = NULL; TABLE *table = spider->get_table(); - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; DBUG_ENTER("spider_db_bulk_bulk_insert"); for ( roop_count2 = spider_conn_link_idx_next(share->link_statuses, @@ -6496,12 +7018,14 @@ int spider_db_bulk_bulk_insert( spider_clear_bit(spider->db_request_phase, roop_count2); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[roop_count2]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { result->free_result(); delete result; @@ -6568,7 +7092,7 @@ int spider_db_update_auto_increment( int link_idx ) { int roop_count; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; ulonglong last_insert_id, affected_rows; SPIDER_SHARE *share = spider->share; TABLE *table = spider->get_table(); @@ -6730,7 +7254,7 @@ int spider_db_bulk_update_end( ha_rows *dup_key_found ) { int error_num = 0, error_num2, roop_count; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; SPIDER_CONN *conn; bool is_error = thd->is_error(); @@ -6905,7 +7429,7 @@ int spider_db_update( conn = spider->conns[roop_count]; spider_db_handler *dbton_hdl = spider->dbton_handler[conn->dbton_id]; #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000 - conn->ignore_dup_key = spider->ignore_dup_key; + conn->ignore_dup_key = spider->wide_handler->ignore_dup_key; #endif if (dbton_hdl->need_lock_before_set_sql_for_exec( SPIDER_SQL_TYPE_UPDATE_SQL)) @@ -6938,8 +7462,8 @@ int spider_db_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -6956,7 +7480,8 @@ int spider_db_update( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_UPDATE_SQL, @@ -6975,8 +7500,8 @@ int spider_db_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7009,7 +7534,8 @@ int spider_db_update( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_INSERT_SQL, @@ -7028,8 +7554,8 @@ int spider_db_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7113,7 +7639,7 @@ int spider_db_direct_update( SQL access -> SQL remote access with dirct_update spider->do_direct_update && spider->direct_update_kinds == SPIDER_SQL_KIND_SQL && - spider->direct_update_fields + spider->wide_handler->direct_update_fields Handlersocket access -> SQL remote access with dirct_update spider->do_direct_update && @@ -7255,7 +7781,7 @@ int spider_db_direct_update( if (spider->is_bulk_access_clone) { spider->connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(spider->trx, conn); + spider_trx_add_bulk_access_conn(spider->wide_handler->trx, conn); } else { #endif conn->need_mon = &spider->need_mons[roop_count]; @@ -7272,8 +7798,8 @@ int spider_db_direct_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7290,7 +7816,8 @@ int spider_db_direct_update( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if ( (error_num = dbton_hdl->execute_sql( @@ -7312,8 +7839,8 @@ int spider_db_direct_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7350,12 +7877,14 @@ int spider_db_direct_update( spider_clear_bit(spider->db_request_phase, roop_count); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[roop_count]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { if (!counted) { @@ -7430,7 +7959,7 @@ int spider_db_direct_update( SQL access -> SQL remote access with dirct_update spider->do_direct_update && spider->direct_update_kinds == SPIDER_SQL_KIND_SQL && - spider->direct_update_fields + spider->wide_handler->direct_update_fields */ #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS @@ -7515,7 +8044,7 @@ int spider_db_direct_update( if (spider->is_bulk_access_clone) { spider->connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(spider->trx, conn); + spider_trx_add_bulk_access_conn(spider->wide_handler->trx, conn); } else { #endif conn->need_mon = &spider->need_mons[roop_count]; @@ -7532,8 +8061,8 @@ int spider_db_direct_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7550,7 +8079,8 @@ int spider_db_direct_update( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if ( (error_num = dbton_hdl->execute_sql( @@ -7559,7 +8089,8 @@ int spider_db_direct_update( -1, &spider->need_mons[roop_count]) ) && - (error_num != HA_ERR_FOUND_DUPP_KEY || !spider->ignore_dup_key) + (error_num != HA_ERR_FOUND_DUPP_KEY || + !spider->wide_handler->ignore_dup_key) ) { conn->mta_conn_mutex_lock_already = FALSE; conn->mta_conn_mutex_unlock_later = FALSE; @@ -7572,8 +8103,8 @@ int spider_db_direct_update( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7673,12 +8204,14 @@ int spider_db_bulk_direct_update( spider_clear_bit(spider->db_request_phase, roop_count); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[roop_count]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { if (!counted) { @@ -7909,7 +8442,7 @@ int spider_db_direct_delete( if (spider->is_bulk_access_clone) { spider->connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(spider->trx, conn); + spider_trx_add_bulk_access_conn(spider->wide_handler->trx, conn); } else { #endif conn->need_mon = &spider->need_mons[roop_count]; @@ -7926,8 +8459,8 @@ int spider_db_direct_delete( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7944,7 +8477,8 @@ int spider_db_direct_delete( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, @@ -7960,8 +8494,8 @@ int spider_db_direct_delete( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -7998,12 +8532,14 @@ int spider_db_direct_delete( spider_clear_bit(spider->db_request_phase, roop_count); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[roop_count]; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { if (!counted) { @@ -8131,7 +8667,7 @@ int spider_db_direct_delete( if (spider->is_bulk_access_clone) { spider->connection_ids[roop_count] = conn->connection_id; - spider_trx_add_bulk_access_conn(spider->trx, conn); + spider_trx_add_bulk_access_conn(spider->wide_handler->trx, conn); } else { #endif conn->need_mon = &spider->need_mons[roop_count]; @@ -8148,8 +8684,8 @@ int spider_db_direct_delete( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8166,7 +8702,8 @@ int spider_db_direct_delete( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( sql_type, @@ -8182,8 +8719,8 @@ int spider_db_direct_delete( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8268,7 +8805,8 @@ int spider_db_delete_all_rows( conn->need_mon = &spider->need_mons[roop_count]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, roop_count)) || @@ -8297,8 +8835,8 @@ int spider_db_delete_all_rows( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8326,8 +8864,8 @@ int spider_db_delete_all_rows( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8344,7 +8882,8 @@ int spider_db_delete_all_rows( } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, roop_count, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, roop_count, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_DELETE_SQL, @@ -8360,8 +8899,8 @@ int spider_db_delete_all_rows( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8388,8 +8927,8 @@ int spider_db_delete_all_rows( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8426,7 +8965,7 @@ int spider_db_disable_keys( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_disable_keys"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8447,8 +8986,8 @@ int spider_db_disable_keys( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8479,7 +9018,7 @@ int spider_db_enable_keys( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_enable_keys"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8500,8 +9039,8 @@ int spider_db_enable_keys( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8533,7 +9072,7 @@ int spider_db_check_table( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_check_table"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8554,8 +9093,8 @@ int spider_db_check_table( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8587,7 +9126,7 @@ int spider_db_repair_table( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_repair_table"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8608,8 +9147,8 @@ int spider_db_repair_table( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8640,7 +9179,7 @@ int spider_db_analyze_table( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_analyze_table"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8661,8 +9200,8 @@ int spider_db_analyze_table( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8693,7 +9232,7 @@ int spider_db_optimize_table( spider_db_handler *dbton_hdl; DBUG_ENTER("spider_db_optimize_table"); if ( - spider_param_internal_optimize(spider->trx->thd, + spider_param_internal_optimize(spider->wide_handler->trx->thd, share->internal_optimize) == 1 ) { for ( @@ -8714,8 +9253,8 @@ int spider_db_optimize_table( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8764,8 +9303,8 @@ int spider_db_flush_tables( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8812,8 +9351,8 @@ int spider_db_flush_logs( spider->need_mons[roop_count] ) { error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -8992,7 +9531,7 @@ int spider_db_print_item_type_default( spider_string *str ) { DBUG_ENTER("spider_db_print_item_type_default"); - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; if (spider_param_skip_default_condition(thd, share->skip_default_condition)) @@ -9492,7 +10031,7 @@ int spider_db_open_item_string( { THD *thd = NULL; TABLE *table; - my_bitmap_map *saved_map; + my_bitmap_map *saved_map = NULL; Time_zone *saved_time_zone; String str_value; char tmp_buf[MAX_FIELD_WIDTH]; @@ -9535,7 +10074,9 @@ int spider_db_open_item_string( goto end; } } - if (str->charset() != tmp_str2->charset()) + DBUG_PRINT("info",("spider dbton_id=%u", dbton_id)); + if (str->charset() != tmp_str2->charset() && + spider_dbton[dbton_id].db_util->append_charset_name_before_string()) { if ((error_num = spider_db_append_charset_name_before_string(str, tmp_str2->charset()))) @@ -9854,12 +10395,13 @@ int spider_db_append_condition( DBUG_RETURN(error_num); } } else { - if (spider->cond_check) - DBUG_RETURN(spider->cond_check_error); - spider->cond_check = TRUE; - if ((spider->cond_check_error = spider->append_condition_sql_part( - NULL, 0, SPIDER_SQL_TYPE_SELECT_SQL, TRUE))) - DBUG_RETURN(spider->cond_check_error); + if (spider->wide_handler->cond_check) + DBUG_RETURN(spider->wide_handler->cond_check_error); + spider->wide_handler->cond_check = TRUE; + if ((spider->wide_handler->cond_check_error = + spider->append_condition_sql_part( + NULL, 0, SPIDER_SQL_TYPE_SELECT_SQL, TRUE))) + DBUG_RETURN(spider->wide_handler->cond_check_error); } DBUG_RETURN(0); } @@ -9876,8 +10418,8 @@ int spider_db_append_update_columns( ) { int error_num; bool add_comma = FALSE; - List_iterator_fast fi(*spider->direct_update_fields), - vi(*spider->direct_update_values); + List_iterator_fast fi(*spider->wide_handler->direct_update_fields), + vi(*spider->wide_handler->direct_update_values); Item *field, *value; DBUG_ENTER("spider_db_append_update_columns"); while ((field = fi++)) @@ -9921,6 +10463,31 @@ int spider_db_append_update_columns( } #endif +#ifdef HANDLER_HAS_DIRECT_AGGREGATE +bool spider_db_check_select_colum_in_group( + st_select_lex *select_lex, + Field *field +) { + ORDER *group; + DBUG_ENTER("spider_db_check_select_colum_in_group"); + for (group = (ORDER *) select_lex->group_list.first; group; + group = group->next) + { + Item *item = *group->item; + if (item->type() == Item::FIELD_ITEM) + { + Item_field *item_field = (Item_field *) item; + if (item_field->field == field) + { + /* This field can be used directly */ + DBUG_RETURN(TRUE); + } + } + } + DBUG_RETURN(FALSE); +} +#endif + uint spider_db_check_ft_idx( Item_func *item_func, ha_spider *spider @@ -10189,7 +10756,7 @@ int spider_db_udf_direct_sql( if (direct_sql->real_table_used) { if (spider_sys_open_tables(c_thd, &direct_sql->table_list_first, - &direct_sql->open_tables_backup)) + &direct_sql->open_tables_backup)) { direct_sql->real_table_used = FALSE; DBUG_RETURN(my_errno); @@ -10219,7 +10786,7 @@ int spider_db_udf_direct_sql( need_trx_end = TRUE; } else { #endif - if (c_thd->transaction.stmt.ha_list) + if (c_thd->transaction->stmt.ha_list) need_trx_end = FALSE; else need_trx_end = TRUE; @@ -10314,7 +10881,7 @@ int spider_db_udf_direct_sql( request_key.handler = direct_sql; request_key.request_id = 1; request_key.next = NULL; - if ((result = conn->db_conn->use_result(&request_key, &error_num))) + if ((result = conn->db_conn->use_result(NULL, &request_key, &error_num))) { end_of_file = FALSE; if (roop_count >= 0) @@ -10547,10 +11114,12 @@ int spider_db_udf_direct_sql_select_db( bool tmp_mta_conn_mutex_lock_already; SPIDER_DB_CONN *db_conn = conn->db_conn; DBUG_ENTER("spider_db_udf_direct_sql_select_db"); + if ( #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if (direct_sql->access_mode == 0) - { + direct_sql->access_mode == 0 && #endif + spider_dbton[conn->dbton_id].db_util->database_has_default_value() + ) { if (!conn->mta_conn_mutex_lock_already) { pthread_mutex_lock(&conn->mta_conn_mutex); @@ -10597,9 +11166,7 @@ int spider_db_udf_direct_sql_select_db( SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); } -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } -#endif DBUG_RETURN(0); } @@ -10708,10 +11275,12 @@ int spider_db_udf_ping_table( int need_mon = 0; uint tmp_conn_link_idx = 0; ha_spider spider; + SPIDER_WIDE_HANDLER wide_handler; uchar db_request_phase = 0; ulonglong db_request_id = 0; spider.share = share; - spider.trx = trx; + spider.wide_handler = &wide_handler; + wide_handler.trx = trx; spider.need_mons = &need_mon; spider.conn_link_idx = &tmp_conn_link_idx; spider.db_request_phase = &db_request_phase; @@ -10941,28 +11510,41 @@ int spider_db_udf_ping_table_append_select( str->q_append(SPIDER_SQL_SELECT_STR, SPIDER_SQL_SELECT_LEN); str->q_append(SPIDER_SQL_ONE_STR, SPIDER_SQL_ONE_LEN); str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); - if ((error_num = spider_db_append_name_with_quote_str(str, - share->tgt_dbs[0], dbton_id))) - DBUG_RETURN(error_num); - if (str->reserve(SPIDER_SQL_DOT_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN); + if (share->tgt_dbs[0]) + { + if ((error_num = spider_db_append_name_with_quote_str(str, + share->tgt_dbs[0], dbton_id))) + DBUG_RETURN(error_num); + if (str->reserve(SPIDER_SQL_DOT_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN); + } if ((error_num = spider_db_append_name_with_quote_str(str, share->tgt_table_names[0], share->sql_dbton_ids[0]))) DBUG_RETURN(error_num); - limit_str_length = my_sprintf(limit_str, (limit_str, "%lld", limit)); - if (str->reserve( - (use_where ? (where_str->length() * 2) : 0) + - SPIDER_SQL_LIMIT_LEN + limit_str_length - )) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - if (use_where) + if (spider_dbton[dbton_id].db_util->limit_mode() == 1) { - str->append_escape_string(where_str->ptr(), where_str->length()); + if (use_where) + { + if (str->reserve(where_str->length() * 2)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->append_escape_string(where_str->ptr(), where_str->length()); + } + } else { + limit_str_length = my_sprintf(limit_str, (limit_str, "%lld", limit)); + if (str->reserve( + (use_where ? (where_str->length() * 2) : 0) + + SPIDER_SQL_LIMIT_LEN + limit_str_length + )) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (use_where) + { + str->append_escape_string(where_str->ptr(), where_str->length()); + } + str->q_append(SPIDER_SQL_LIMIT_STR, SPIDER_SQL_LIMIT_LEN); + str->q_append(limit_str, limit_str_length); } - str->q_append(SPIDER_SQL_LIMIT_STR, SPIDER_SQL_LIMIT_LEN); - str->q_append(limit_str, limit_str_length); DBUG_RETURN(0); } @@ -10991,6 +11573,7 @@ int spider_db_udf_ping_table_mon_next( int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); ha_spider spider; + SPIDER_WIDE_HANDLER wide_handler; SPIDER_TRX trx; DBUG_ENTER("spider_db_udf_ping_table_mon_next"); char *sql_buf = (char *) my_alloca(init_sql_alloc_size); @@ -11005,7 +11588,8 @@ int spider_db_udf_ping_table_mon_next( sql_str.length(0); trx.thd = thd; spider.share = share; - spider.trx = &trx; + spider.wide_handler = &wide_handler; + wide_handler.trx = &trx; spider.need_mons = &need_mon; spider.conn_link_idx = &tmp_conn_link_idx; @@ -11242,7 +11826,7 @@ int spider_db_udf_copy_tables( request_key.handler = copy_tables; request_key.request_id = 1; request_key.next = NULL; - if ((result = tmp_conn->db_conn->use_result(&request_key, &error_num))) + if ((result = tmp_conn->db_conn->use_result(NULL, &request_key, &error_num))) { SPIDER_DB_ROW *row; roop_count = 0; @@ -11606,7 +12190,8 @@ int spider_db_open_handler( goto error; } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_HANDLER, @@ -11690,10 +12275,11 @@ int spider_db_open_handler( if (spider->is_bulk_access_clone && !spider->bulk_access_executing) { spider->connection_ids[link_idx] = conn->connection_id; - spider_trx_add_bulk_access_conn(spider->trx, conn); + spider_trx_add_bulk_access_conn(spider->wide_handler->trx, conn); } else { #endif - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_SELECT_HS, @@ -11711,12 +12297,14 @@ int spider_db_open_handler( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = + spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; - if (!(result = conn->db_conn->use_result(&request_key, &error_num))) + if (!(result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { if (!error_num) { @@ -11850,12 +12438,13 @@ int spider_db_bulk_open_handler( spider_clear_bit(spider->db_request_phase, link_idx); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = spider->db_request_id[link_idx]; request_key.next = NULL; - if (!(result = conn->db_conn->use_result(&request_key, &error_num))) + if (!(result = conn->db_conn->use_result(spider, &request_key, + &error_num))) { if (!error_num) { @@ -11907,7 +12496,8 @@ int spider_db_close_handler( SPIDER_SQL_TYPE_HANDLER, link_idx))) DBUG_RETURN(error_num); - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_HANDLER, diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h index d4e527e4bf2..0b69253c43b 100644 --- a/storage/spider/spd_db_conn.h +++ b/storage/spider/spd_db_conn.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2008-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,6 +40,10 @@ #define SPIDER_SQL_OPEN_PAREN_LEN (sizeof(SPIDER_SQL_OPEN_PAREN_STR) - 1) #define SPIDER_SQL_CLOSE_PAREN_STR ")" #define SPIDER_SQL_CLOSE_PAREN_LEN (sizeof(SPIDER_SQL_CLOSE_PAREN_STR) - 1) +#define SPIDER_SQL_OPEN_BRACE_STR "{" +#define SPIDER_SQL_OPEN_BRACE_LEN (sizeof(SPIDER_SQL_OPEN_BRACE_STR) - 1) +#define SPIDER_SQL_CLOSE_BRACE_STR "}" +#define SPIDER_SQL_CLOSE_BRACE_LEN (sizeof(SPIDER_SQL_CLOSE_BRACE_STR) - 1) #define SPIDER_SQL_COMMA_STR "," #define SPIDER_SQL_COMMA_LEN (sizeof(SPIDER_SQL_COMMA_STR) - 1) #define SPIDER_SQL_UNION_ALL_STR ")union all(" @@ -608,6 +612,12 @@ int spider_db_store_result( TABLE *table ); +int spider_db_store_result_for_reuse_cursor( + ha_spider *spider, + int link_idx, + TABLE *table +); + void spider_db_discard_result( ha_spider *spider, int link_idx, @@ -1052,6 +1062,13 @@ int spider_db_append_update_columns( ); #endif +#ifdef HANDLER_HAS_DIRECT_AGGREGATE +bool spider_db_check_select_colum_in_group( + st_select_lex *select_lex, + Field *field +); +#endif + uint spider_db_check_ft_idx( Item_func *item_func, ha_spider *spider diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index 9ffe59375c1..b3e73b856a3 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -127,7 +127,10 @@ SPIDER_DBTON spider_dbton_handlersocket = { NULL, spider_handlersocket_create_conn, spider_handlersocket_support_direct_join, - &spider_db_handlersocket_utility + &spider_db_handlersocket_utility, + "For communicating using the handlersocket protocol", + "0.1.0", + SPIDER_MATURITY_BETA }; #ifndef HANDLERSOCKET_MYSQL_UTIL @@ -1438,6 +1441,7 @@ spider_db_result *spider_db_handlersocket::store_result( } spider_db_result *spider_db_handlersocket::use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ) { diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h index de76e2c7163..f7a454b66af 100644 --- a/storage/spider/spd_db_handlersocket.h +++ b/storage/spider/spd_db_handlersocket.h @@ -330,6 +330,7 @@ public: int *error_num ); spider_db_result *use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ); diff --git a/storage/spider/spd_db_include.cc b/storage/spider/spd_db_include.cc index 7f600142187..b9a0532d1b9 100644 --- a/storage/spider/spd_db_include.cc +++ b/storage/spider/spd_db_include.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2018-2019 Kentoku Shiba +/* Copyright (C) 2018-2020 Kentoku Shiba + Copyright (C) 2018-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +32,9 @@ #include "spd_err.h" #include "spd_db_include.h" #include "spd_include.h" +#include "spd_conn.h" + +extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; spider_db_result::spider_db_result( SPIDER_DB_CONN *in_db_conn @@ -51,6 +55,13 @@ int spider_db_result::fetch_table_checksum( } #endif +uint spider_db_result::limit_mode() +{ + DBUG_ENTER("spider_db_result::limit_mode"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(spider_dbton[dbton_id].db_util->limit_mode()); +} + spider_db_conn::spider_db_conn( SPIDER_CONN *in_conn ) : conn(in_conn), dbton_id(in_conn->dbton_id) @@ -60,6 +71,107 @@ spider_db_conn::spider_db_conn( DBUG_VOID_RETURN; } +bool spider_db_conn::set_loop_check_in_bulk_sql() +{ + DBUG_ENTER("spider_db_conn::set_loop_check_in_bulk_sql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(FALSE); +} + +int spider_db_conn::set_loop_check( + int *need_mon +) { + DBUG_ENTER("spider_db_conn::set_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + /* nothing to do */ + DBUG_RETURN(0); +} + +int spider_db_conn::fin_loop_check() +{ + st_spider_conn_loop_check *lcptr; + DBUG_ENTER("spider_db_conn::fin_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + if (conn->loop_check_queue.records) + { + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + lcptr->flag = 0; + ++l; + } + my_hash_reset(&conn->loop_check_queue); + } + lcptr = conn->loop_check_ignored_first; + while (lcptr) + { + lcptr->flag = 0; + lcptr = lcptr->next; + } + conn->loop_check_ignored_first = NULL; + lcptr = conn->loop_check_meraged_first; + while (lcptr) + { + lcptr->flag = 0; + lcptr = lcptr->next; + } + conn->loop_check_meraged_first = NULL; + DBUG_RETURN(0); +} + +uint spider_db_conn::limit_mode() +{ + DBUG_ENTER("spider_db_conn::limit_mode"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(spider_dbton[dbton_id].db_util->limit_mode()); +} + +int spider_db_util::append_loop_check( + spider_string *str, + SPIDER_CONN *conn +) { + DBUG_ENTER("spider_db_util::append_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + /* nothing to do */ + DBUG_RETURN(0); +} + +bool spider_db_util::tables_on_different_db_are_joinable() +{ + DBUG_ENTER("spider_db_util::tables_on_different_db_are_joinable"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + +bool spider_db_util::socket_has_default_value() +{ + DBUG_ENTER("spider_db_util::socket_has_default_value"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + +bool spider_db_util::database_has_default_value() +{ + DBUG_ENTER("spider_db_util::database_has_default_value"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + +bool spider_db_util::append_charset_name_before_string() +{ + DBUG_ENTER("spider_db_util::append_charset_name_before_string"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(FALSE); +} + +uint spider_db_util::limit_mode() +{ + DBUG_ENTER("spider_db_util::limit_mode"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(0); +} + #ifdef HA_HAS_CHECKSUM_EXTENDED bool spider_db_share::checksum_support() { @@ -76,3 +188,39 @@ int spider_db_handler::checksum_table( DBUG_RETURN(0); } #endif + +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS +bool spider_db_handler::check_direct_update( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + DBUG_ENTER("spider_db_handler::check_direct_update"); + DBUG_PRINT("info",("spider this=%p", this)); + if ( + select_limit != 9223372036854775807LL || + offset_limit != 0 || + select_lex->order_list.elements + ) { + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + +bool spider_db_handler::check_direct_delete( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + DBUG_ENTER("spider_db_handler::check_direct_delete"); + DBUG_PRINT("info",("spider this=%p", this)); + if ( + select_limit != 9223372036854775807LL || + offset_limit != 0 || + select_lex->order_list.elements + ) { + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} +#endif diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 8d4f972648a..bff3d95cacb 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -93,11 +94,15 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_SEMICOLON_STR ";" #define SPIDER_SQL_SEMICOLON_LEN sizeof(SPIDER_SQL_SEMICOLON_STR) - 1 +#define SPIDER_SQL_COLON_STR ":" +#define SPIDER_SQL_COLON_LEN sizeof(SPIDER_SQL_COLON_STR) - 1 #define SPIDER_SQL_VALUE_QUOTE_STR "'" #define SPIDER_SQL_VALUE_QUOTE_LEN (sizeof(SPIDER_SQL_VALUE_QUOTE_STR) - 1) #define SPIDER_SQL_DOT_STR "." #define SPIDER_SQL_DOT_LEN (sizeof(SPIDER_SQL_DOT_STR) - 1) +#define SPIDER_SQL_HYPHEN_STR "-" +#define SPIDER_SQL_HYPHEN_LEN (sizeof(SPIDER_SQL_HYPHEN_STR) - 1) #define SPIDER_SQL_EQUAL_STR " = " #define SPIDER_SQL_EQUAL_LEN (sizeof(SPIDER_SQL_EQUAL_STR) - 1) @@ -213,6 +218,11 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_CONNECTION_LEN (sizeof(SPIDER_SQL_CONNECTION_STR) - 1) #define SPIDER_SQL_LCL_NAME_QUOTE_STR "`" #define SPIDER_SQL_LCL_NAME_QUOTE_LEN (sizeof(SPIDER_SQL_LCL_NAME_QUOTE_STR) - 1) +#define SPIDER_SQL_MIN_STR "min" +#define SPIDER_SQL_MIN_LEN (sizeof(SPIDER_SQL_MIN_STR) - 1) + +#define SPIDER_SQL_LOP_CHK_PRM_PRF_STR "spider_lc_" +#define SPIDER_SQL_LOP_CHK_PRM_PRF_LEN (sizeof(SPIDER_SQL_LOP_CHK_PRM_PRF_STR) - 1) #define SPIDER_CONN_KIND_MYSQL (1 << 0) #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -874,6 +884,10 @@ public: spider_string *str, Time_zone *time_zone ) = 0; + virtual int append_loop_check( + spider_string *str, + SPIDER_CONN *conn + ); virtual int append_start_transaction( spider_string *str ) = 0; @@ -944,6 +958,11 @@ public: spider_string *str ) = 0; #endif + virtual bool tables_on_different_db_are_joinable(); + virtual bool socket_has_default_value(); + virtual bool database_has_default_value(); + virtual bool append_charset_name_before_string(); + virtual uint limit_mode(); }; class spider_db_row @@ -994,12 +1013,12 @@ public: class spider_db_result { -protected: - SPIDER_DB_CONN *db_conn; public: - uint dbton_id; + SPIDER_DB_CONN *db_conn; + uint dbton_id; spider_db_result(SPIDER_DB_CONN *in_db_conn); virtual ~spider_db_result() {} + virtual void set_limit(longlong value) {} virtual bool has_result() = 0; virtual void free_result() = 0; virtual SPIDER_DB_ROW *current_row() = 0; @@ -1054,19 +1073,20 @@ public: CHARSET_INFO *access_charset ) = 0; #endif + virtual uint limit_mode(); }; class spider_db_conn { -protected: - SPIDER_CONN *conn; public: - uint dbton_id; + SPIDER_CONN *conn; + uint dbton_id; spider_db_conn( SPIDER_CONN *in_conn ); virtual ~spider_db_conn() {} virtual int init() = 0; + virtual void set_limit(longlong value) {} virtual bool is_connected() = 0; virtual void bg_connect() = 0; virtual int connect( @@ -1105,6 +1125,7 @@ public: int *error_num ) = 0; virtual spider_db_result *use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ) = 0; @@ -1186,6 +1207,11 @@ public: Time_zone *time_zone, int *need_mon ) = 0; + virtual bool set_loop_check_in_bulk_sql(); + virtual int set_loop_check( + int *need_mon + ); + virtual int fin_loop_check(); virtual int show_master_status( SPIDER_TRX *trx, SPIDER_SHARE *share, @@ -1268,6 +1294,7 @@ public: virtual bool cmp_request_key_to_snd( st_spider_db_request_key *request_key ) = 0; + virtual uint limit_mode(); }; class spider_db_share @@ -1327,6 +1354,7 @@ public: #ifdef SPIDER_HAS_GROUP_BY_HANDLER SPIDER_LINK_IDX_CHAIN *link_idx_chain; #endif + bool strict_group_by; spider_db_handler(ha_spider *spider, spider_db_share *db_share) : dbton_id(db_share->dbton_id), spider(spider), db_share(db_share), first_link_idx(-1) {} @@ -1808,6 +1836,18 @@ public: ulong sql_type ) = 0; #endif +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + virtual bool check_direct_update( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); + virtual bool check_direct_delete( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); +#endif }; class spider_db_copy_table @@ -1883,6 +1923,23 @@ enum spider_db_access_type SPIDER_DB_ACCESS_TYPE_NOSQL }; +#define SPIDER_MATURITY_UNKNOWN 0 +#define SPIDER_MATURITY_EXPERIMENTAL 1 +#define SPIDER_MATURITY_ALPHA 2 +#define SPIDER_MATURITY_BETA 3 +#define SPIDER_MATURITY_GAMMA 4 +#define SPIDER_MATURITY_STABLE 5 + +static const LEX_CSTRING maturity_name[] = +{ + { STRING_WITH_LEN("Unknown") }, + { STRING_WITH_LEN("Experimental") }, + { STRING_WITH_LEN("Alpha") }, + { STRING_WITH_LEN("Beta") }, + { STRING_WITH_LEN("Gamma") }, + { STRING_WITH_LEN("Stable") } +}; + typedef struct st_spider_dbton { uint dbton_id; @@ -1898,6 +1955,9 @@ typedef struct st_spider_dbton SPIDER_DB_CONN *(*create_db_conn)(SPIDER_CONN *conn); bool (*support_direct_join)(); spider_db_util *db_util; + const char *descr; + const char *version_info; + unsigned int maturity; } SPIDER_DBTON; typedef struct st_spider_position @@ -2045,7 +2105,6 @@ typedef struct st_spider_result_list #endif int quick_phase; bool keyread; - int lock_type; TABLE *table; #ifndef WITHOUT_SPIDER_BG_SEARCH volatile int bgs_error; diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index c18f72afa42..1337717dcad 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -100,6 +100,9 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR; #define SPIDER_SQL_TIME_ZONE_STR "set session time_zone = '" #define SPIDER_SQL_TIME_ZONE_LEN sizeof(SPIDER_SQL_TIME_ZONE_STR) - 1 +#define SPIDER_SQL_SET_USER_VAL_STR "set @`" +#define SPIDER_SQL_SET_USER_VAL_LEN sizeof(SPIDER_SQL_SET_USER_VAL_STR) - 1 + #define SPIDER_SQL_COMMIT_STR "commit" #define SPIDER_SQL_COMMIT_LEN sizeof(SPIDER_SQL_COMMIT_STR) - 1 #define SPIDER_SQL_ROLLBACK_STR "rollback" @@ -326,7 +329,10 @@ SPIDER_DBTON spider_dbton_mysql = { spider_mysql_create_copy_table, spider_mysql_create_conn, spider_mysql_support_direct_join, - &spider_db_mysql_utility + &spider_db_mysql_utility, + "For communicating to MySQL using native protocol", + "3.4.0", + SPIDER_MATURITY_STABLE }; SPIDER_DBTON spider_dbton_mariadb = { @@ -340,7 +346,10 @@ SPIDER_DBTON spider_dbton_mariadb = { spider_mariadb_create_copy_table, spider_mariadb_create_conn, spider_mariadb_support_direct_join, - &spider_db_mariadb_utility + &spider_db_mariadb_utility, + "For communicating to MariaDB using native protocol", + "3.4.0", + SPIDER_MATURITY_STABLE }; spider_db_mbase_row::spider_db_mbase_row( @@ -2280,19 +2289,23 @@ bool spider_db_mbase::is_xa_nota_error( DBUG_RETURN(xa_nota); } -void spider_db_mbase::print_warnings( +int spider_db_mbase::print_warnings( struct tm *l_time ) { + int error_num = 0; DBUG_ENTER("spider_db_mbase::print_warnings"); DBUG_PRINT("info",("spider this=%p", this)); if (db_conn->status == MYSQL_STATUS_READY) { + if ( #if MYSQL_VERSION_ID < 50500 - if (!(db_conn->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)) + !(db_conn->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) && + db_conn->last_used_con->warning_count #else - if (!(db_conn->server_status & SERVER_MORE_RESULTS_EXISTS)) + !(db_conn->server_status & SERVER_MORE_RESULTS_EXISTS) && + db_conn->warning_count #endif - { + ) { /* pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); @@ -2318,7 +2331,7 @@ void spider_db_mbase::print_warnings( SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); */ - DBUG_VOID_RETURN; + DBUG_RETURN(0); } /* no record is ok */ } @@ -2330,17 +2343,33 @@ void spider_db_mbase::print_warnings( if (num_fields != 3) { mysql_free_result(res); - DBUG_VOID_RETURN; + DBUG_RETURN(0); } - while (row) + if (l_time) { - fprintf(stderr, "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] " - "from [%s] %ld to %ld: %s %s %s\n", - l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, - l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, (ulong) db_conn->thread_id, - (ulong) current_thd->thread_id, row[0], row[1], row[2]); - row = mysql_fetch_row(res); + while (row) + { + fprintf(stderr, "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] " + "from [%s] %ld to %ld: %s %s %s\n", + l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, + l_time->tm_hour, l_time->tm_min, l_time->tm_sec, + conn->tgt_host, (ulong) db_conn->thread_id, + (ulong) current_thd->thread_id, row[0], row[1], row[2]); + row = mysql_fetch_row(res); + } + } else { + while (row) + { + DBUG_PRINT("info",("spider row[0]=%s", row[0])); + DBUG_PRINT("info",("spider row[1]=%s", row[1])); + DBUG_PRINT("info",("spider row[2]=%s", row[2])); + longlong res_num = + (longlong) my_strtoll10(row[1], (char**) NULL, &error_num); + DBUG_PRINT("info",("spider res_num=%lld", res_num)); + my_printf_error((int) res_num, row[2], MYF(0)); + error_num = (int) res_num; + row = mysql_fetch_row(res); + } } if (res) mysql_free_result(res); @@ -2352,7 +2381,7 @@ void spider_db_mbase::print_warnings( } } } - DBUG_VOID_RETURN; + DBUG_RETURN(error_num); } spider_db_result *spider_db_mbase::store_result( @@ -2384,6 +2413,7 @@ spider_db_result *spider_db_mbase::store_result( } spider_db_result *spider_db_mbase::use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ) { @@ -3047,6 +3077,99 @@ int spider_db_mbase::set_time_zone( DBUG_RETURN(0); } +bool spider_db_mbase::set_loop_check_in_bulk_sql() +{ + DBUG_ENTER("spider_db_mbase::set_loop_check_in_bulk_sql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + +int spider_db_mbase::set_loop_check( + int *need_mon +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + char sql_buf[MAX_FIELD_WIDTH]; + spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); + DBUG_ENTER("spider_db_mbase::set_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + sql_str.init_calc_mem(270); + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, 0))) + { + sql_str.length(0); + if (sql_str.reserve(SPIDER_SQL_SET_USER_VAL_LEN + + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN + lcptr->to_name.length + + SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_EQUAL_LEN + + SPIDER_SQL_VALUE_QUOTE_LEN + + lcptr->merged_value.length + SPIDER_SQL_VALUE_QUOTE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + sql_str.q_append(SPIDER_SQL_SET_USER_VAL_STR, SPIDER_SQL_SET_USER_VAL_LEN); + sql_str.q_append(SPIDER_SQL_LOP_CHK_PRM_PRF_STR, + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + sql_str.q_append(lcptr->to_name.str, lcptr->to_name.length); + sql_str.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); + sql_str.q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + sql_str.q_append(lcptr->merged_value.str, lcptr->merged_value.length); + sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + + if (spider_db_query( + conn, + sql_str.ptr(), + sql_str.length(), + -1, + need_mon) + ) { + DBUG_RETURN(spider_db_errorno(conn)); + } + SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); + pthread_mutex_unlock(&conn->mta_conn_mutex); + +#ifdef HASH_UPDATE_WITH_HASH_VALUE + my_hash_delete_with_hash_value(&conn->loop_check_queue, + lcptr->hash_value, (uchar *) lcptr); +#else + my_hash_delete(&conn->loop_check_queue, (uchar*) lcptr); +#endif + } + DBUG_RETURN(0); +} + +int spider_db_mbase::fin_loop_check() +{ + st_spider_conn_loop_check *lcptr; + DBUG_ENTER("spider_db_mbase::fin_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + if (conn->loop_check_queue.records) + { + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + lcptr->flag = 0; + ++l; + } + my_hash_reset(&conn->loop_check_queue); + } + lcptr = conn->loop_check_ignored_first; + while (lcptr) + { + lcptr->flag = 0; + lcptr = lcptr->next; + } + conn->loop_check_ignored_first = NULL; + lcptr = conn->loop_check_meraged_first; + while (lcptr) + { + lcptr->flag = 0; + lcptr = lcptr->next; + } + conn->loop_check_meraged_first = NULL; + DBUG_RETURN(0); +} + int spider_db_mbase::exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, @@ -3416,7 +3539,7 @@ int spider_db_mbase::append_lock_tables( { tmp_spider = tmp_link_for_hash->spider; tmp_link_idx = tmp_link_for_hash->link_idx; - switch (tmp_spider->lock_type) + switch (tmp_spider->wide_handler->lock_type) { case TL_READ: lock_type = SPIDER_DB_TABLE_LOCK_READ_LOCAL; @@ -3432,7 +3555,8 @@ int spider_db_mbase::append_lock_tables( break; default: // no lock - DBUG_PRINT("info",("spider lock_type=%d", tmp_spider->lock_type)); + DBUG_PRINT("info",("spider lock_type=%d", + tmp_spider->wide_handler->lock_type)); DBUG_RETURN(0); } conn_link_idx = tmp_spider->conn_link_idx[tmp_link_idx]; @@ -5186,6 +5310,47 @@ int spider_db_mbase_util::append_time_zone( DBUG_RETURN(0); } +int spider_db_mbase_util::append_loop_check( + spider_string *str, + SPIDER_CONN *conn +) { + SPIDER_CONN_LOOP_CHECK *lcptr; + DBUG_ENTER("spider_db_mbase_util::append_loop_check"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_PRINT("info",("spider str=%s", str->c_ptr_safe())); + uint l = 0; + while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( + &conn->loop_check_queue, l))) + { + DBUG_PRINT("info",("spider lcptr=%p", lcptr)); + if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_SET_USER_VAL_LEN + + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN + lcptr->to_name.length + + SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_EQUAL_LEN + + SPIDER_SQL_VALUE_QUOTE_LEN + + lcptr->merged_value.length + SPIDER_SQL_VALUE_QUOTE_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + if (str->length()) + { + str->q_append(SPIDER_SQL_SEMICOLON_STR, SPIDER_SQL_SEMICOLON_LEN); + } + str->q_append(SPIDER_SQL_SET_USER_VAL_STR, SPIDER_SQL_SET_USER_VAL_LEN); + str->q_append(SPIDER_SQL_LOP_CHK_PRM_PRF_STR, + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + str->q_append(lcptr->to_name.str, lcptr->to_name.length); + str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); + str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + str->q_append(lcptr->merged_value.str, lcptr->merged_value.length); + str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); + + ++l; + DBUG_PRINT("info",("spider str=%s", str->c_ptr_safe())); + } + DBUG_RETURN(0); +} + int spider_db_mbase_util::append_start_transaction( spider_string *str ) { @@ -6135,7 +6300,8 @@ int spider_db_mbase_util::open_item_func( } break; case Item_func::UDF_FUNC: - use_pushdown_udf = spider_param_use_pushdown_udf(spider->trx->thd, + use_pushdown_udf = spider_param_use_pushdown_udf( + spider->wide_handler->trx->thd, spider->share->use_pushdown_udf); if (!use_pushdown_udf) DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); @@ -6276,7 +6442,7 @@ int spider_db_mbase_util::open_item_func( DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); #endif default: - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; if (spider_param_skip_default_condition(thd, share->skip_default_condition)) @@ -7114,6 +7280,13 @@ int spider_db_mbase_util::append_having( } #endif +bool spider_db_mbase_util::append_charset_name_before_string() +{ + DBUG_ENTER("spider_db_mbase_util::append_charset_name_before_string"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(TRUE); +} + spider_mbase_share::spider_mbase_share( st_spider_share *share, uint dbton_id, @@ -7972,9 +8145,11 @@ int spider_mbase_share::discover_table_structure( if (!conn->disable_reconnect) { ha_spider tmp_spider; + SPIDER_WIDE_HANDLER wide_handler; int need_mon = 0; uint tmp_conn_link_idx = 0; - tmp_spider.trx = trx; + tmp_spider.wide_handler = &wide_handler; + wide_handler.trx = trx; tmp_spider.share = spider_share; tmp_spider.need_mons = &need_mon; tmp_spider.conn_link_idx = &tmp_conn_link_idx; @@ -8263,7 +8438,7 @@ spider_mariadb_handler::~spider_mariadb_handler() int spider_mbase_handler::init() { uint roop_count; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; st_spider_share *share = spider->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); @@ -8699,7 +8874,7 @@ int spider_mbase_handler::append_create_tmp_bka_table( ) { int error_num; SPIDER_SHARE *share = spider->share; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; char *bka_engine = spider_param_bka_engine(thd, share->bka_engine); uint bka_engine_length = strlen(bka_engine), cset_length = strlen(table_charset->csname), @@ -9101,10 +9276,10 @@ int spider_mbase_handler::append_insert( direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_INSERT; if ( ( - spider->write_can_replace || + spider->wide_handler->write_can_replace || /* for direct_dup_insert without patch for partition */ - spider->sql_command == SQLCOM_REPLACE || - spider->sql_command == SQLCOM_REPLACE_SELECT + spider->wide_handler->sql_command == SQLCOM_REPLACE || + spider->wide_handler->sql_command == SQLCOM_REPLACE_SELECT ) && spider->direct_dup_insert ) { @@ -9117,13 +9292,13 @@ int spider_mbase_handler::append_insert( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_INSERT_STR, SPIDER_SQL_INSERT_LEN); } - if (spider->low_priority) + if (spider->wide_handler->low_priority) { if (str->reserve(SPIDER_SQL_LOW_PRIORITY_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_LOW_PRIORITY_STR, SPIDER_SQL_LOW_PRIORITY_LEN); } - else if (spider->insert_delayed) + else if (spider->wide_handler->insert_delayed) { if (share->internal_delayed) { @@ -9133,28 +9308,28 @@ int spider_mbase_handler::append_insert( } } else if ( - spider->lock_type >= TL_WRITE && - !spider->write_can_replace && + spider->wide_handler->lock_type >= TL_WRITE && + !spider->wide_handler->write_can_replace && /* for direct_dup_insert without patch for partition */ - spider->sql_command != SQLCOM_REPLACE && - spider->sql_command != SQLCOM_REPLACE_SELECT + spider->wide_handler->sql_command != SQLCOM_REPLACE && + spider->wide_handler->sql_command != SQLCOM_REPLACE_SELECT ) { if (str->reserve(SPIDER_SQL_HIGH_PRIORITY_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_HIGH_PRIORITY_STR, SPIDER_SQL_HIGH_PRIORITY_LEN); } if ( - spider->ignore_dup_key && + spider->wide_handler->ignore_dup_key && spider->direct_dup_insert && - !spider->write_can_replace && + !spider->wide_handler->write_can_replace && #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS - (!spider->insert_with_update || !dup_update_sql.length()) && + (!spider->wide_handler->insert_with_update || !dup_update_sql.length()) && #else - !spider->insert_with_update && + !spider->wide_handler->insert_with_update && #endif /* for direct_dup_insert without patch for partition */ - spider->sql_command != SQLCOM_REPLACE && - spider->sql_command != SQLCOM_REPLACE_SELECT + spider->wide_handler->sql_command != SQLCOM_REPLACE && + spider->wide_handler->sql_command != SQLCOM_REPLACE_SELECT ) { direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE; if (str->reserve(SPIDER_SQL_SQL_IGNORE_LEN)) @@ -9181,15 +9356,15 @@ int spider_mbase_handler::append_update( if (str->reserve(SPIDER_SQL_UPDATE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_UPDATE_STR, SPIDER_SQL_UPDATE_LEN); - if (spider->low_priority) + if (spider->wide_handler->low_priority) { if (str->reserve(SPIDER_SQL_LOW_PRIORITY_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_LOW_PRIORITY_STR, SPIDER_SQL_LOW_PRIORITY_LEN); } if ( - spider->ignore_dup_key && - !spider->insert_with_update + spider->wide_handler->ignore_dup_key && + !spider->wide_handler->insert_with_update ) { if (str->reserve(SPIDER_SQL_SQL_IGNORE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9220,20 +9395,20 @@ int spider_mbase_handler::append_delete( if (str->reserve(SPIDER_SQL_DELETE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_DELETE_STR, SPIDER_SQL_DELETE_LEN); - if (spider->low_priority) + if (spider->wide_handler->low_priority) { if (str->reserve(SPIDER_SQL_LOW_PRIORITY_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_LOW_PRIORITY_STR, SPIDER_SQL_LOW_PRIORITY_LEN); } - if (spider->quick_mode) + if (spider->wide_handler->quick_mode) { if (str->reserve(SPIDER_SQL_SQL_QUICK_MODE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SQL_QUICK_MODE_STR, SPIDER_SQL_SQL_QUICK_MODE_LEN); } - if (spider->ignore_dup_key) + if (spider->wide_handler->ignore_dup_key) { if (str->reserve(SPIDER_SQL_SQL_IGNORE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9396,7 +9571,7 @@ int spider_mbase_handler::append_direct_update_set( DBUG_ENTER("spider_mbase_handler::append_direct_update_set"); if ( spider->direct_update_kinds == SPIDER_SQL_KIND_SQL && - spider->direct_update_fields + spider->wide_handler->direct_update_fields ) { if (str->reserve(SPIDER_SQL_SET_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9539,6 +9714,7 @@ int spider_mbase_handler::append_select( ulong sql_type ) { SPIDER_RESULT_LIST *result_list = &spider->result_list; + SPIDER_WIDE_HANDLER *wide_handler = spider->wide_handler; DBUG_ENTER("spider_mbase_handler::append_select"); if (sql_type == SPIDER_SQL_TYPE_HANDLER) { @@ -9555,13 +9731,15 @@ int spider_mbase_handler::append_select( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_DISTINCT_STR, SPIDER_SQL_DISTINCT_LEN); } - if (result_list->lock_type != F_WRLCK && spider->lock_mode < 1) + if (wide_handler->external_lock_type != F_WRLCK && + wide_handler->lock_mode < 1) { /* no lock */ #ifdef SPIDER_SQL_CACHE_IS_IN_LEX - LEX *lex = spider->trx->thd->lex; + LEX *lex = wide_handler->trx->thd->lex; #else - st_select_lex *select_lex = &spider->trx->thd->lex->select_lex; + st_select_lex *select_lex = + &wide_handler->trx->thd->lex->select_lex; #endif if ( #ifdef SPIDER_SQL_CACHE_IS_IN_LEX @@ -9599,7 +9777,7 @@ int spider_mbase_handler::append_select( SPIDER_SQL_SQL_NO_CACHE_LEN); } } - if (spider->high_priority) + if (wide_handler->high_priority) { if (str->reserve(SPIDER_SQL_HIGH_PRIORITY_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9632,10 +9810,58 @@ int spider_mbase_handler::append_table_select_part( int spider_mbase_handler::append_table_select( spider_string *str ) { +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_table_select"); - table_name_pos = str->length() + mysql_share->table_select_pos; - if (str->append(*(mysql_share->table_select))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } + if (select_lex) + { + TABLE *table = spider->get_table(); + Field **field; + int field_length; + for (field = table->field; *field; field++) + { + field_length = + mysql_share->column_name_str[(*field)->field_index].length(); + if (!spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { + if (str->reserve(field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); + } + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } else { +#endif + table_name_pos = str->length() + mysql_share->table_select_pos; + if (str->append(*(mysql_share->table_select))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif DBUG_RETURN(0); } @@ -9663,10 +9889,63 @@ int spider_mbase_handler::append_key_select( spider_string *str, uint idx ) { +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_key_select"); - table_name_pos = str->length() + mysql_share->key_select_pos[idx]; - if (str->append(mysql_share->key_select[idx])) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } + if (select_lex) + { + TABLE *table = spider->get_table(); + KEY *key_info = &table->key_info[idx]; + KEY_PART_INFO *key_part; + Field *field; + uint part_num; + int field_length; + for (key_part = key_info->key_part, part_num = 0; + part_num < spider_user_defined_key_parts(key_info); + key_part++, part_num++) + { + field = key_part->field; + field_length = mysql_share->column_name_str[field->field_index].length(); + if (!spider_db_check_select_colum_in_group(select_lex, field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, field->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { + if (str->reserve(field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, field->field_index); + } + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } else { +#endif + table_name_pos = str->length() + mysql_share->key_select_pos[idx]; + if (str->append(mysql_share->key_select[idx])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif DBUG_RETURN(0); } @@ -9697,7 +9976,23 @@ int spider_mbase_handler::append_minimum_select( Field **field; int field_length; bool appended = FALSE; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_minimum_select"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -9708,10 +10003,27 @@ int spider_mbase_handler::append_minimum_select( */ field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); appended = TRUE; } @@ -9734,16 +10046,50 @@ int spider_mbase_handler::append_table_select_with_alias( TABLE *table = spider->get_table(); Field **field; int field_length; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_table_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif for (field = table->field; *field; field++) { field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } str->length(str->length() - SPIDER_SQL_COMMA_LEN); @@ -9760,17 +10106,51 @@ int spider_mbase_handler::append_key_select_with_alias( Field *field; uint part_num; int field_length; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_key_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif for (key_part = key_info->key_part, part_num = 0; part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++) { field = key_part->field; field_length = mysql_share->column_name_str[field->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, field->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, field->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, field->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } str->length(str->length() - SPIDER_SQL_COMMA_LEN); @@ -9786,7 +10166,23 @@ int spider_mbase_handler::append_minimum_select_with_alias( Field **field; int field_length; bool appended = FALSE; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_minimum_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -9797,11 +10193,29 @@ int spider_mbase_handler::append_minimum_select_with_alias( */ field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); appended = TRUE; } @@ -10597,7 +11011,7 @@ int spider_mbase_handler::append_update_where( ) { uint field_name_length; Field **field; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; bool no_pk = (table->s->primary_key == MAX_KEY); DBUG_ENTER("spider_mbase_handler::append_update_where"); @@ -10763,7 +11177,7 @@ int spider_mbase_handler::append_condition_part( ha_where_pos = str->length(); if ( - spider->sql_command == SQLCOM_HA_READ || + spider->wide_handler->sql_command == SQLCOM_HA_READ || !spider->result_list.use_both_key ) { if (sql_part2.length()) @@ -10792,7 +11206,7 @@ int spider_mbase_handler::append_condition( ulong sql_type ) { int error_num, restart_pos = 0, start_where_pos; - SPIDER_CONDITION *tmp_cond = spider->condition; + SPIDER_CONDITION *tmp_cond = spider->wide_handler->condition; DBUG_ENTER("spider_mbase_handler::append_condition"); if (str && start_where) { @@ -10803,7 +11217,7 @@ int spider_mbase_handler::append_condition( if (spider->is_clone && !tmp_cond) { - tmp_cond = spider->pt_clone_source_handler->condition; + tmp_cond = spider->pt_clone_source_handler->wide_handler->condition; } while (tmp_cond) @@ -12275,7 +12689,7 @@ int spider_mbase_handler::append_from( str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); table_name_pos = str->length(); append_table_name_with_adjusting(str, link_idx, sql_type); - if(spider_param_index_hint_pushdown(spider->trx->thd)) + if(spider_param_index_hint_pushdown(spider->wide_handler->trx->thd)) { if((error_num = append_index_hint(str, link_idx, sql_type))) { @@ -12356,7 +12770,8 @@ int spider_mbase_handler::append_optimize_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_mbase_handler::append_optimize_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -12401,7 +12816,8 @@ int spider_mbase_handler::append_analyze_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_mbase_handler::append_analyze_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -12448,7 +12864,8 @@ int spider_mbase_handler::append_repair_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_mbase_handler::append_repair_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -12658,7 +13075,7 @@ int spider_mbase_handler::append_delete_all_rows( int error_num; DBUG_ENTER("spider_mbase_handler::append_delete_all_rows"); DBUG_PRINT("info",("spider this=%p", this)); - if (spider->sql_command == SQLCOM_TRUNCATE) + if (spider->wide_handler->sql_command == SQLCOM_TRUNCATE) { if ((error_num = append_truncate(str, sql_type, first_link_idx))) DBUG_RETURN(error_num); @@ -12964,7 +13381,7 @@ bool spider_mbase_handler::bulk_tmp_table_created() int spider_mbase_handler::mk_bulk_tmp_table_and_bulk_start() { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; TABLE *table = spider->get_table(); DBUG_ENTER("spider_mbase_handler::mk_bulk_tmp_table_and_bulk_start"); DBUG_PRINT("info",("spider this=%p", this)); @@ -12993,7 +13410,8 @@ void spider_mbase_handler::rm_bulk_tmp_table() DBUG_PRINT("info",("spider this=%p", this)); if (upd_tmp_tbl) { - spider_rm_sys_tmp_table(spider->trx->thd, upd_tmp_tbl, &upd_tmp_tbl_prm); + spider_rm_sys_tmp_table(spider->wide_handler->trx->thd, upd_tmp_tbl, + &upd_tmp_tbl_prm); upd_tmp_tbl = NULL; } DBUG_VOID_RETURN; @@ -13067,9 +13485,12 @@ int spider_mbase_handler::append_lock_tables_list( spider_db_mbase *db_conn = (spider_db_mbase *) conn->db_conn; DBUG_ENTER("spider_mbase_handler::append_lock_tables_list"); DBUG_PRINT("info",("spider this=%p", this)); + DBUG_PRINT("info",("spider db_conn=%p", db_conn)); tmp_link_for_hash2 = &link_for_hash[link_idx]; tmp_link_for_hash2->db_table_str = &mysql_share->db_table_str[conn_link_idx]; + DBUG_PRINT("info",("spider db_table_str=%s", + tmp_link_for_hash2->db_table_str->c_ptr_safe())); #ifdef SPIDER_HAS_HASH_VALUE_TYPE tmp_link_for_hash2->db_table_str_hash_value = mysql_share->db_table_str_hash_value[conn_link_idx]; @@ -13090,7 +13511,8 @@ int spider_mbase_handler::append_lock_tables_list( DBUG_RETURN(error_num); *appended = 1; } else { - if (tmp_link_for_hash->spider->lock_type < spider->lock_type) + if (tmp_link_for_hash->spider->wide_handler->lock_type < + spider->wide_handler->lock_type) { #ifdef HASH_UPDATE_WITH_HASH_VALUE my_hash_delete_with_hash_value( @@ -13130,7 +13552,7 @@ int spider_mbase_handler::append_lock_tables_list( int spider_mbase_handler::realloc_sql( ulong *realloced ) { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; st_spider_share *share = spider->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); @@ -13587,7 +14009,8 @@ int spider_mbase_handler::show_table_status( conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; conn->disable_connect_retry = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -13624,7 +14047,8 @@ int spider_mbase_handler::show_table_status( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -13648,8 +14072,8 @@ int spider_mbase_handler::show_table_status( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -13720,7 +14144,8 @@ int spider_mbase_handler::show_table_status( conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; conn->disable_connect_retry = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -13757,7 +14182,8 @@ int spider_mbase_handler::show_table_status( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -13781,8 +14207,8 @@ int spider_mbase_handler::show_table_status( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -13841,6 +14267,10 @@ int spider_mbase_handler::show_table_status( DBUG_RETURN(error_num); } } + if ((error_num = ((spider_db_mbase *) conn->db_conn)->print_warnings(NULL))) + { + DBUG_RETURN(error_num); + } if (share->static_records_for_status != -1) { share->stat.records = (ha_rows) share->static_records_for_status; @@ -13887,7 +14317,8 @@ int spider_mbase_handler::show_index( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -13922,7 +14353,8 @@ int spider_mbase_handler::show_index( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -13944,8 +14376,8 @@ int spider_mbase_handler::show_index( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -14020,7 +14452,8 @@ int spider_mbase_handler::show_index( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -14055,7 +14488,8 @@ int spider_mbase_handler::show_index( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14077,8 +14511,8 @@ int spider_mbase_handler::show_index( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -14208,7 +14642,8 @@ int spider_mbase_handler::simple_action( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -14245,7 +14680,8 @@ int spider_mbase_handler::simple_action( DBUG_PRINT("info", ("spider error_num=%d 2", error_num)); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14269,8 +14705,8 @@ int spider_mbase_handler::simple_action( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -14329,7 +14765,7 @@ int spider_mbase_handler::show_records( DBUG_PRINT("info", ("spider error_num=%d", error_num)); DBUG_RETURN(error_num); } - spider->trx->direct_aggregate_count++; + spider->wide_handler->trx->direct_aggregate_count++; DBUG_RETURN(0); } @@ -14378,7 +14814,8 @@ ha_rows spider_mbase_handler::explain_select( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -14417,7 +14854,8 @@ ha_rows spider_mbase_handler::explain_select( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(HA_POS_ERROR); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (spider_db_query( conn, @@ -14446,8 +14884,8 @@ ha_rows spider_mbase_handler::explain_select( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -14516,7 +14954,8 @@ int spider_mbase_handler::lock_tables( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (spider_db_query( conn, @@ -14537,7 +14976,7 @@ int spider_mbase_handler::lock_tables( if (!conn->table_locked) { conn->table_locked = TRUE; - spider->trx->locked_connections++; + spider->wide_handler->trx->locked_connections++; } DBUG_RETURN(0); } @@ -14552,7 +14991,7 @@ int spider_mbase_handler::unlock_tables( { spider_string *str = &sql; conn->table_locked = FALSE; - spider->trx->locked_connections--; + spider->wide_handler->trx->locked_connections--; str->length(0); if ((error_num = conn->db_conn->append_unlock_tables(str))) @@ -14561,7 +15000,8 @@ int spider_mbase_handler::unlock_tables( } if (str->length()) { - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (spider_db_query( conn, @@ -14606,7 +15046,8 @@ int spider_mbase_handler::disable_keys( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14655,7 +15096,8 @@ int spider_mbase_handler::enable_keys( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14705,7 +15147,8 @@ int spider_mbase_handler::check_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14755,7 +15198,8 @@ int spider_mbase_handler::repair_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14804,7 +15248,8 @@ int spider_mbase_handler::analyze_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14853,7 +15298,8 @@ int spider_mbase_handler::optimize_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14890,7 +15336,8 @@ int spider_mbase_handler::flush_tables( { DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -14915,7 +15362,8 @@ int spider_mbase_handler::flush_logs( SPIDER_SHARE *share = spider->share; DBUG_ENTER("spider_mbase_handler::flush_logs"); DBUG_PRINT("info",("spider this=%p", this)); - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -15037,16 +15485,17 @@ void spider_mbase_handler::minimum_select_bitmap_create() } } } - DBUG_PRINT("info",("spider searched_bitmap=%p", spider->searched_bitmap)); + DBUG_PRINT("info",("spider searched_bitmap=%p", + spider->wide_handler->searched_bitmap)); for (field_p = table->field; *field_p; field_p++) { uint field_index = (*field_p)->field_index; DBUG_PRINT("info",("spider field_index=%u", field_index)); DBUG_PRINT("info",("spider ft_discard_bitmap=%s", - spider_bit_is_set(spider->ft_discard_bitmap, field_index) ? + spider_bit_is_set(spider->wide_handler->ft_discard_bitmap, field_index) ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider searched_bitmap=%s", - spider_bit_is_set(spider->searched_bitmap, field_index) ? + spider_bit_is_set(spider->wide_handler->searched_bitmap, field_index) ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider read_set=%s", bitmap_is_set(table->read_set, field_index) ? @@ -15055,9 +15504,9 @@ void spider_mbase_handler::minimum_select_bitmap_create() bitmap_is_set(table->write_set, field_index) ? "TRUE" : "FALSE")); if ( - spider_bit_is_set(spider->ft_discard_bitmap, field_index) && + spider_bit_is_set(spider->wide_handler->ft_discard_bitmap, field_index) && ( - spider_bit_is_set(spider->searched_bitmap, field_index) || + spider_bit_is_set(spider->wide_handler->searched_bitmap, field_index) || bitmap_is_set(table->read_set, field_index) || bitmap_is_set(table->write_set, field_index) ) @@ -15495,6 +15944,28 @@ int spider_mbase_handler::append_order_by( } #endif +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS +bool spider_mbase_handler::check_direct_update( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + DBUG_ENTER("spider_mbase_handler::check_direct_update"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(FALSE); +} + +bool spider_mbase_handler::check_direct_delete( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit +) { + DBUG_ENTER("spider_mbase_handler::check_direct_delete"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(FALSE); +} +#endif + spider_mbase_copy_table::spider_mbase_copy_table( spider_mbase_share *db_share ) : spider_db_copy_table( diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 547a98c8dff..45565154136 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -91,6 +91,10 @@ public: spider_string *str, Time_zone *time_zone ); + int append_loop_check( + spider_string *str, + SPIDER_CONN *conn + ); int append_start_transaction( spider_string *str ); @@ -195,6 +199,7 @@ public: spider_string *str ); #endif + bool append_charset_name_before_string(); }; class spider_db_mysql_util: public spider_db_mbase_util @@ -439,7 +444,7 @@ public: bool is_xa_nota_error( int error_num ); - void print_warnings( + int print_warnings( struct tm *l_time ); spider_db_result *store_result( @@ -448,6 +453,7 @@ public: int *error_num ); spider_db_result *use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ); @@ -529,6 +535,11 @@ public: Time_zone *time_zone, int *need_mon ); + bool set_loop_check_in_bulk_sql(); + int set_loop_check( + int *need_mon + ); + int fin_loop_check(); int exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, @@ -1663,6 +1674,18 @@ public: spider_fields *fields ); #endif +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + bool check_direct_update( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); + bool check_direct_delete( + st_select_lex *select_lex, + longlong select_limit, + longlong offset_limit + ); +#endif }; class spider_mysql_handler: public spider_mbase_handler diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index fd3efd2bd67..7cc32316f68 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -336,7 +336,10 @@ SPIDER_DBTON spider_dbton_oracle = { spider_oracle_create_copy_table, spider_oracle_create_conn, spider_oracle_support_direct_join, - &spider_db_oracle_utility + &spider_db_oracle_utility, + "For communicating Oracle using native protocol", + "1.0.0", + SPIDER_MATURITY_BETA }; spider_db_oracle_row::spider_db_oracle_row() : @@ -1700,6 +1703,7 @@ spider_db_result *spider_db_oracle::store_result( } spider_db_result *spider_db_oracle::use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ) { @@ -2315,7 +2319,7 @@ int spider_db_oracle::append_lock_tables( tmp_spider = tmp_link_for_hash->spider; tmp_link_idx = tmp_link_for_hash->link_idx; - switch (tmp_spider->lock_type) + switch (tmp_spider->wide_handler->lock_type) { case TL_READ: lock_type = SPIDER_DB_TABLE_LOCK_READ_LOCAL; @@ -2331,7 +2335,8 @@ int spider_db_oracle::append_lock_tables( break; default: // no lock - DBUG_PRINT("info",("spider lock_type=%d", tmp_spider->lock_type)); + DBUG_PRINT("info",("spider lock_type=%d", + tmp_spider->wide_handler->lock_type)); DBUG_RETURN(0); } conn_link_idx = tmp_spider->conn_link_idx[tmp_link_idx]; @@ -4015,7 +4020,8 @@ int spider_db_oracle_util::open_item_func( } break; case Item_func::UDF_FUNC: - use_pushdown_udf = spider_param_use_pushdown_udf(spider->trx->thd, + use_pushdown_udf = spider_param_use_pushdown_udf( + spider->wide_handler->trx->thd, spider->share->use_pushdown_udf); if (!use_pushdown_udf) DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); @@ -4156,7 +4162,7 @@ int spider_db_oracle_util::open_item_func( DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); #endif default: - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; if (spider_param_skip_default_condition(thd, share->skip_default_condition)) @@ -5487,7 +5493,7 @@ spider_oracle_handler::~spider_oracle_handler() int spider_oracle_handler::init() { uint roop_count; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; st_spider_share *share = spider->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); @@ -5869,7 +5875,7 @@ int spider_oracle_handler::append_create_tmp_bka_table( ) { int error_num; SPIDER_SHARE *share = spider->share; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; char *bka_engine = spider_param_bka_engine(thd, share->bka_engine); uint bka_engine_length = strlen(bka_engine), cset_length = strlen(table_charset->csname); @@ -6479,7 +6485,7 @@ int spider_oracle_handler::append_direct_update_set( DBUG_ENTER("spider_oracle_handler::append_direct_update_set"); if ( spider->direct_update_kinds == SPIDER_SQL_KIND_SQL && - spider->direct_update_fields + spider->wide_handler->direct_update_fields ) { if (str->reserve(SPIDER_SQL_SET_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -6587,8 +6593,8 @@ int spider_oracle_handler::append_update_columns( uint alias_length ) { int error_num; - List_iterator_fast fi(*spider->direct_update_fields), - vi(*spider->direct_update_values); + List_iterator_fast fi(*spider->wide_handler->direct_update_fields), + vi(*spider->wide_handler->direct_update_values); Item *field, *value; DBUG_ENTER("spider_oracle_handler::append_update_columns"); while ((field = fi++)) @@ -7618,7 +7624,7 @@ int spider_oracle_handler::append_update_where( ) { uint field_name_length; Field **field; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; bool no_pk = (table->s->primary_key == MAX_KEY); DBUG_ENTER("spider_oracle_handler::append_update_where"); @@ -9816,7 +9822,8 @@ int spider_oracle_handler::append_optimize_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_oracle_handler::append_optimize_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -9861,7 +9868,8 @@ int spider_oracle_handler::append_analyze_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_oracle_handler::append_analyze_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -9908,7 +9916,8 @@ int spider_oracle_handler::append_repair_table( ) { SPIDER_SHARE *share = spider->share; int conn_link_idx = spider->conn_link_idx[link_idx]; - int local_length = spider_param_internal_optimize_local(spider->trx->thd, + int local_length = spider_param_internal_optimize_local( + spider->wide_handler->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; DBUG_ENTER("spider_oracle_handler::append_repair_table"); DBUG_PRINT("info",("spider this=%p", this)); @@ -10425,7 +10434,7 @@ bool spider_oracle_handler::bulk_tmp_table_created() int spider_oracle_handler::mk_bulk_tmp_table_and_bulk_start() { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; TABLE *table = spider->get_table(); DBUG_ENTER("spider_oracle_handler::mk_bulk_tmp_table_and_bulk_start"); DBUG_PRINT("info",("spider this=%p", this)); @@ -10454,7 +10463,8 @@ void spider_oracle_handler::rm_bulk_tmp_table() DBUG_PRINT("info",("spider this=%p", this)); if (upd_tmp_tbl) { - spider_rm_sys_tmp_table(spider->trx->thd, upd_tmp_tbl, &upd_tmp_tbl_prm); + spider_rm_sys_tmp_table(spider->wide_handler->trx->thd, upd_tmp_tbl, + &upd_tmp_tbl_prm); upd_tmp_tbl = NULL; } DBUG_VOID_RETURN; @@ -10551,7 +10561,8 @@ int spider_oracle_handler::append_lock_tables_list( DBUG_RETURN(error_num); *appended = 1; } else { - if (tmp_link_for_hash->spider->lock_type < spider->lock_type) + if (tmp_link_for_hash->spider->wide_handler->lock_type < + spider->wide_handler->lock_type) { #ifdef HASH_UPDATE_WITH_HASH_VALUE my_hash_delete_with_hash_value( @@ -10591,7 +10602,7 @@ int spider_oracle_handler::append_lock_tables_list( int spider_oracle_handler::realloc_sql( ulong *realloced ) { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; st_spider_share *share = spider->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); @@ -11130,7 +11141,8 @@ int spider_oracle_handler::show_table_status( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11167,7 +11179,8 @@ int spider_oracle_handler::show_table_status( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11189,8 +11202,8 @@ int spider_oracle_handler::show_table_status( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11245,7 +11258,8 @@ int spider_oracle_handler::show_table_status( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11280,7 +11294,8 @@ int spider_oracle_handler::show_table_status( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11302,8 +11317,8 @@ int spider_oracle_handler::show_table_status( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11369,7 +11384,8 @@ int spider_oracle_handler::show_index( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11406,7 +11422,8 @@ int spider_oracle_handler::show_index( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11428,8 +11445,8 @@ int spider_oracle_handler::show_index( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11488,7 +11505,8 @@ int spider_oracle_handler::show_index( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11523,7 +11541,8 @@ int spider_oracle_handler::show_index( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11545,8 +11564,8 @@ int spider_oracle_handler::show_index( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11612,7 +11631,8 @@ int spider_oracle_handler::show_records( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11649,7 +11669,8 @@ int spider_oracle_handler::show_records( DBUG_PRINT("info", ("spider error_num=%d 2", error_num)); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11673,8 +11694,8 @@ int spider_oracle_handler::show_records( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11707,7 +11728,7 @@ int spider_oracle_handler::show_records( DBUG_PRINT("info", ("spider error_num=%d 7", error_num)); DBUG_RETURN(error_num); } - spider->trx->direct_aggregate_count++; + spider->wide_handler->trx->direct_aggregate_count++; DBUG_RETURN(0); } @@ -11729,7 +11750,8 @@ int spider_oracle_handler::show_autoinc( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11766,7 +11788,8 @@ int spider_oracle_handler::show_autoinc( DBUG_PRINT("info", ("spider error_num=%d 2", error_num)); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -11790,8 +11813,8 @@ int spider_oracle_handler::show_autoinc( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11866,8 +11889,8 @@ int spider_oracle_handler::show_last_insert_id( DBUG_RETURN(error_num); } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -11923,7 +11946,8 @@ ha_rows spider_oracle_handler::explain_select( conn->need_mon = &spider->need_mons[link_idx]; conn->mta_conn_mutex_lock_already = TRUE; conn->mta_conn_mutex_unlock_later = TRUE; - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if ( (error_num = spider_db_set_names(spider, conn, link_idx)) || @@ -11962,7 +11986,8 @@ ha_rows spider_oracle_handler::explain_select( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(HA_POS_ERROR); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (spider_db_query( conn, @@ -11991,8 +12016,8 @@ ha_rows spider_oracle_handler::explain_select( } } st_spider_db_request_key request_key; - request_key.spider_thread_id = spider->trx->spider_thread_id; - request_key.query_id = spider->trx->thd->query_id; + request_key.spider_thread_id = spider->wide_handler->trx->spider_thread_id; + request_key.query_id = spider->wide_handler->trx->thd->query_id; request_key.handler = spider; request_key.request_id = 1; request_key.next = NULL; @@ -12062,7 +12087,8 @@ int spider_oracle_handler::lock_tables( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, spider->share); if (spider_db_query( conn, @@ -12083,7 +12109,7 @@ int spider_oracle_handler::lock_tables( if (!conn->table_locked) { conn->table_locked = TRUE; - spider->trx->locked_connections++; + spider->wide_handler->trx->locked_connections++; } } while (str->length()); DBUG_RETURN(0); @@ -12133,7 +12159,8 @@ int spider_oracle_handler::disable_keys( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12182,7 +12209,8 @@ int spider_oracle_handler::enable_keys( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12232,7 +12260,8 @@ int spider_oracle_handler::check_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12282,7 +12311,8 @@ int spider_oracle_handler::repair_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12331,7 +12361,8 @@ int spider_oracle_handler::analyze_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12380,7 +12411,8 @@ int spider_oracle_handler::optimize_table( pthread_mutex_unlock(&conn->mta_conn_mutex); DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12417,7 +12449,8 @@ int spider_oracle_handler::flush_tables( { DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, @@ -12442,7 +12475,8 @@ int spider_oracle_handler::flush_logs( SPIDER_SHARE *share = spider->share; DBUG_ENTER("spider_oracle_handler::flush_logs"); DBUG_PRINT("info",("spider this=%p", this)); - spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, + spider_conn_set_timeout_from_share(conn, link_idx, + spider->wide_handler->trx->thd, share); if (spider_db_query( conn, diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h index fb00a2eebb1..c8c1522599f 100644 --- a/storage/spider/spd_db_oracle.h +++ b/storage/spider/spd_db_oracle.h @@ -380,6 +380,7 @@ public: int *error_num ); spider_db_result *use_result( + ha_spider *spider, st_spider_db_request_key *request_key, int *error_num ); diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 406d189fcc9..e14e8d95363 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -1,5 +1,5 @@ -/* Copyright (C) 2009-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2009-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -206,17 +206,79 @@ int spider_udf_direct_sql_create_conn_key( char *tmp_name, port_str[6]; DBUG_ENTER("spider_udf_direct_sql_create_conn_key"); - /* tgt_db not use */ + uint roop_count2; + bool tables_on_different_db_are_joinable = TRUE; + direct_sql->dbton_id = SPIDER_DBTON_SIZE; + DBUG_PRINT("info",("spider direct_sql->tgt_wrapper=%s", + direct_sql->tgt_wrapper)); + for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) + { + DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, + spider_dbton[roop_count2].wrapper ? + spider_dbton[roop_count2].wrapper : "NULL")); + if ( + spider_dbton[roop_count2].wrapper && + !strcmp(direct_sql->tgt_wrapper, spider_dbton[roop_count2].wrapper) + ) { +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (direct_sql->access_mode == 0) + { +#endif + if (spider_dbton[roop_count2].db_access_type == + SPIDER_DB_ACCESS_TYPE_SQL) + { + direct_sql->dbton_id = roop_count2; + break; + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } else { + if (spider_dbton[roop_count2].db_access_type == + SPIDER_DB_ACCESS_TYPE_NOSQL) + { + direct_sql->dbton_id = roop_count2; + break; + } + } +#endif + } + } + if (direct_sql->dbton_id == SPIDER_DBTON_SIZE) + { +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (direct_sql->access_mode == 0) + { +#endif + my_printf_error( + ER_SPIDER_SQL_WRAPPER_IS_INVALID_NUM, + ER_SPIDER_SQL_WRAPPER_IS_INVALID_STR, + MYF(0), direct_sql->tgt_wrapper); + DBUG_RETURN(ER_SPIDER_SQL_WRAPPER_IS_INVALID_NUM); +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + } else { + my_printf_error( + ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM, + ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_STR, + MYF(0), direct_sql->tgt_wrapper); + DBUG_RETURN(ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM); + } +#endif + } + #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (direct_sql->access_mode == 0) { #endif + tables_on_different_db_are_joinable = + spider_dbton[direct_sql->dbton_id].db_util-> + tables_on_different_db_are_joinable(); direct_sql->conn_key_length = 1 + direct_sql->tgt_wrapper_length + 1 + direct_sql->tgt_host_length + 1 + 5 + 1 + direct_sql->tgt_socket_length + 1 + + (tables_on_different_db_are_joinable ? + 0 : direct_sql->tgt_default_db_name_length + 1) + direct_sql->tgt_username_length + 1 + direct_sql->tgt_password_length + 1 + direct_sql->tgt_ssl_ca_length + 1 @@ -226,7 +288,8 @@ int spider_udf_direct_sql_create_conn_key( + direct_sql->tgt_ssl_key_length + 1 + 1 + 1 + direct_sql->tgt_default_file_length + 1 - + direct_sql->tgt_default_group_length; + + direct_sql->tgt_default_group_length + 1 + + direct_sql->tgt_dsn_length; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { direct_sql->conn_key_length @@ -263,6 +326,16 @@ int spider_udf_direct_sql_create_conn_key( if (direct_sql->access_mode == 0) { #endif + if (!tables_on_different_db_are_joinable) + { + if (direct_sql->tgt_default_db_name) + { + DBUG_PRINT("info",("spider tgt_default_db_name=%s", + direct_sql->tgt_default_db_name)); + tmp_name = strmov(tmp_name + 1, direct_sql->tgt_default_db_name); + } else + tmp_name++; + } if (direct_sql->tgt_username) { DBUG_PRINT("info",("spider tgt_username=%s", direct_sql->tgt_username)); @@ -323,65 +396,16 @@ int spider_udf_direct_sql_create_conn_key( tmp_name = strmov(tmp_name + 1, direct_sql->tgt_default_group); } else tmp_name++; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - } -#endif - uint roop_count2; - direct_sql->dbton_id = SPIDER_DBTON_SIZE; - DBUG_PRINT("info",("spider direct_sql->tgt_wrapper=%s", - direct_sql->tgt_wrapper)); - for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) - { - DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, - spider_dbton[roop_count2].wrapper ? - spider_dbton[roop_count2].wrapper : "NULL")); - if ( - spider_dbton[roop_count2].wrapper && - !strcmp(direct_sql->tgt_wrapper, spider_dbton[roop_count2].wrapper) - ) { -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if (direct_sql->access_mode == 0) - { -#endif - if (spider_dbton[roop_count2].db_access_type == - SPIDER_DB_ACCESS_TYPE_SQL) - { - direct_sql->dbton_id = roop_count2; - break; - } -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - } else { - if (spider_dbton[roop_count2].db_access_type == - SPIDER_DB_ACCESS_TYPE_NOSQL) - { - direct_sql->dbton_id = roop_count2; - break; - } - } -#endif - } - } - if (direct_sql->dbton_id == SPIDER_DBTON_SIZE) - { -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if (direct_sql->access_mode == 0) + if (direct_sql->tgt_dsn) { -#endif - my_printf_error( - ER_SPIDER_SQL_WRAPPER_IS_INVALID_NUM, - ER_SPIDER_SQL_WRAPPER_IS_INVALID_STR, - MYF(0), direct_sql->tgt_wrapper); - DBUG_RETURN(ER_SPIDER_SQL_WRAPPER_IS_INVALID_NUM); + DBUG_PRINT("info",("spider tgt_dsn=%s", + direct_sql->tgt_dsn)); + tmp_name = strmov(tmp_name + 1, direct_sql->tgt_dsn); + } else + tmp_name++; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - } else { - my_printf_error( - ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM, - ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_STR, - MYF(0), direct_sql->tgt_wrapper); - DBUG_RETURN(ER_SPIDER_NOSQL_WRAPPER_IS_INVALID_NUM); - } -#endif } +#endif #ifdef SPIDER_HAS_HASH_VALUE_TYPE direct_sql->conn_key_hash_value = my_calc_hash(&spider_open_connections, (uchar*) direct_sql->conn_key, direct_sql->conn_key_length); @@ -396,9 +420,11 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( SPIDER_CONN *conn; SPIDER_IP_PORT_CONN *ip_port_conn; char *tmp_name, *tmp_host, *tmp_username, *tmp_password, *tmp_socket; - char *tmp_wrapper, *tmp_ssl_ca, *tmp_ssl_capath, *tmp_ssl_cert; + char *tmp_wrapper, *tmp_db, *tmp_ssl_ca, *tmp_ssl_capath, *tmp_ssl_cert; char *tmp_ssl_cipher, *tmp_ssl_key, *tmp_default_file, *tmp_default_group; + char *tmp_dsn; int *need_mon; + bool tables_on_different_db_are_joinable = TRUE; DBUG_ENTER("spider_udf_direct_sql_create_conn"); if (unlikely(!UTC)) @@ -412,6 +438,9 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( if (direct_sql->access_mode == 0) { #endif + tables_on_different_db_are_joinable = + spider_dbton[direct_sql->dbton_id].db_util-> + tables_on_different_db_are_joinable(); if (!(conn = (SPIDER_CONN *) spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL), &conn, (uint) (sizeof(*conn)), @@ -421,6 +450,8 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( &tmp_password, (uint) (direct_sql->tgt_password_length + 1), &tmp_socket, (uint) (direct_sql->tgt_socket_length + 1), &tmp_wrapper, (uint) (direct_sql->tgt_wrapper_length + 1), + &tmp_db, (uint) (tables_on_different_db_are_joinable ? + 0 : direct_sql->tgt_default_db_name_length + 1), &tmp_ssl_ca, (uint) (direct_sql->tgt_ssl_ca_length + 1), &tmp_ssl_capath, (uint) (direct_sql->tgt_ssl_capath_length + 1), &tmp_ssl_cert, (uint) (direct_sql->tgt_ssl_cert_length + 1), @@ -430,6 +461,8 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( (uint) (direct_sql->tgt_default_file_length + 1), &tmp_default_group, (uint) (direct_sql->tgt_default_group_length + 1), + &tmp_dsn, + (uint) (direct_sql->tgt_dsn_length + 1), &need_mon, (uint) (sizeof(int)), NullS)) ) { @@ -475,6 +508,13 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( conn->tgt_socket = tmp_socket; memcpy(conn->tgt_socket, direct_sql->tgt_socket, direct_sql->tgt_socket_length); + if (!tables_on_different_db_are_joinable) + { + conn->tgt_db_length = direct_sql->tgt_default_db_name_length; + conn->tgt_db = tmp_db; + memcpy(conn->tgt_db, direct_sql->tgt_default_db_name, + direct_sql->tgt_default_db_name_length); + } conn->tgt_username_length = direct_sql->tgt_username_length; conn->tgt_username = tmp_username; memcpy(conn->tgt_username, direct_sql->tgt_username, @@ -539,6 +579,14 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( direct_sql->tgt_default_group_length); } else conn->tgt_default_group = NULL; + conn->tgt_dsn_length = direct_sql->tgt_dsn_length; + if (conn->tgt_dsn_length) + { + conn->tgt_dsn = tmp_dsn; + memcpy(conn->tgt_dsn, direct_sql->tgt_dsn, + direct_sql->tgt_dsn_length); + } else + conn->tgt_dsn = NULL; conn->tgt_ssl_vsc = direct_sql->tgt_ssl_vsc; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { @@ -595,6 +643,11 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( goto error_mta_conn_mutex_init; } + if (unlikely((*error_num = spider_conn_init(conn)))) + { + goto error_conn_init; + } + if ((*error_num = spider_db_udf_direct_sql_connect(direct_sql, conn))) goto error; conn->ping_time = (time_t) time((time_t*) 0); @@ -648,8 +701,10 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( error: DBUG_ASSERT(!conn->mta_conn_mutex_file_pos.file_name); - pthread_mutex_destroy(&conn->mta_conn_mutex); error_too_many_ipport_count: + spider_conn_done(conn); +error_conn_init: + pthread_mutex_destroy(&conn->mta_conn_mutex); error_mta_conn_mutex_init: error_db_conn_init: delete conn->db_conn; @@ -1202,6 +1257,7 @@ int spider_udf_parse_direct_sql_param( SPIDER_PARAM_INT("cto", connect_timeout, 0); SPIDER_PARAM_STR("dff", tgt_default_file); SPIDER_PARAM_STR("dfg", tgt_default_group); + SPIDER_PARAM_STR("dsn", tgt_dsn); SPIDER_PARAM_LONGLONG("prt", priority, 0); SPIDER_PARAM_INT("rto", net_read_timeout, 0); SPIDER_PARAM_STR("sca", tgt_ssl_ca); @@ -1331,6 +1387,10 @@ int spider_udf_set_direct_sql_param_default( SPIDER_TRX *trx, SPIDER_DIRECT_SQL *direct_sql ) { + bool check_socket; + bool check_database; + bool socket_has_default_value; + bool database_has_default_value; int error_num, roop_count; DBUG_ENTER("spider_udf_set_direct_sql_param_default"); if (direct_sql->server_name) @@ -1339,7 +1399,65 @@ int spider_udf_set_direct_sql_param_default( DBUG_RETURN(error_num); } + if ( +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + direct_sql->access_mode == 0 && +#endif + !direct_sql->tgt_socket && + (!direct_sql->tgt_host || !strcmp(direct_sql->tgt_host, my_localhost)) + ) { + check_socket = TRUE; + } else { + check_socket = FALSE; + } if (!direct_sql->tgt_default_db_name) + { + check_database = TRUE; + } else { + check_database = FALSE; + } + if (check_socket || check_database) + { + socket_has_default_value = check_socket; + database_has_default_value = check_database; + if (direct_sql->tgt_wrapper) + { + for (roop_count = 0; roop_count < SPIDER_DBTON_SIZE; roop_count++) + { + DBUG_PRINT("info",("spider direct_sql->tgt_wrapper=%s", + direct_sql->tgt_wrapper)); + DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count, + spider_dbton[roop_count].wrapper ? + spider_dbton[roop_count].wrapper : "NULL")); + if ( + spider_dbton[roop_count].wrapper && + !strcmp(direct_sql->tgt_wrapper, + spider_dbton[roop_count].wrapper) + ) { + if (spider_dbton[roop_count].db_access_type == + SPIDER_DB_ACCESS_TYPE_SQL) + { + if (check_socket) + { + socket_has_default_value = spider_dbton[roop_count]. + db_util->socket_has_default_value(); + } + if (check_database) + { + database_has_default_value = spider_dbton[roop_count]. + db_util->database_has_default_value(); + } + break; + } + } + } + } + } else { + socket_has_default_value = FALSE; + database_has_default_value = FALSE; + } + + if (database_has_default_value) { DBUG_PRINT("info",("spider create default tgt_default_db_name")); direct_sql->tgt_default_db_name_length = SPIDER_THD_db_length(trx->thd); @@ -1435,13 +1553,8 @@ int spider_udf_set_direct_sql_param_default( if (direct_sql->tgt_ssl_vsc == -1) direct_sql->tgt_ssl_vsc = 0; - if ( -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - direct_sql->access_mode == 0 && -#endif - !direct_sql->tgt_socket && - !strcmp(direct_sql->tgt_host, my_localhost) - ) { + if (socket_has_default_value) + { DBUG_PRINT("info",("spider create default tgt_socket")); direct_sql->tgt_socket_length = strlen((char *) MYSQL_UNIX_ADDR); if ( @@ -1568,6 +1681,10 @@ void spider_udf_free_direct_sql_alloc( { spider_free(spider_current_trx, direct_sql->tgt_default_group, MYF(0)); } + if (direct_sql->tgt_dsn) + { + spider_free(spider_current_trx, direct_sql->tgt_dsn, MYF(0)); + } if (direct_sql->conn_key) { spider_free(spider_current_trx, direct_sql->conn_key, MYF(0)); @@ -1813,7 +1930,7 @@ long long spider_direct_sql_body( if (conn->bg_init) pthread_mutex_unlock(&conn->bg_conn_mutex); if (direct_sql->modified_non_trans_table) - thd->transaction.stmt.modified_non_trans_table = TRUE; + thd->transaction->stmt.modified_non_trans_table = TRUE; if (error_num == HA_ERR_OUT_OF_MEM) my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); goto error; @@ -1821,7 +1938,7 @@ long long spider_direct_sql_body( if (conn->bg_init) pthread_mutex_unlock(&conn->bg_conn_mutex); if (direct_sql->modified_non_trans_table) - thd->transaction.stmt.modified_non_trans_table = TRUE; + thd->transaction->stmt.modified_non_trans_table = TRUE; #ifndef WITHOUT_SPIDER_BG_SEARCH } if (!bg) @@ -1930,7 +2047,7 @@ void spider_direct_sql_deinit_body( if (bg_direct_sql->modified_non_trans_table) { THD *thd = current_thd; - thd->transaction.stmt.modified_non_trans_table = TRUE; + thd->transaction->stmt.modified_non_trans_table = TRUE; } pthread_cond_destroy(&bg_direct_sql->bg_cond); pthread_mutex_destroy(&bg_direct_sql->bg_mutex); @@ -1961,7 +2078,7 @@ long long spider_direct_sql_bg_end( pthread_cond_wait(&bg_direct_sql->bg_cond, &bg_direct_sql->bg_mutex); pthread_mutex_unlock(&bg_direct_sql->bg_mutex); if (bg_direct_sql->modified_non_trans_table) - thd->transaction.stmt.modified_non_trans_table = TRUE; + thd->transaction->stmt.modified_non_trans_table = TRUE; if (bg_direct_sql->bg_error) { my_message(bg_direct_sql->bg_error, bg_direct_sql->bg_error_msg, MYF(0)); diff --git a/storage/spider/spd_environ.h b/storage/spider/spd_environ.h index 728cc7e1781..528bed160c9 100644 --- a/storage/spider/spd_environ.h +++ b/storage/spider/spd_environ.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2018 Kentoku Shiba & 2017 MariaDB corp +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2017-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,4 +54,8 @@ #define SPIDER_LIKE_FUNC_HAS_GET_NEGATED #define HA_HAS_CHECKSUM_EXTENDED #endif + +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100500 +#define SPIDER_I_S_USE_SHOW_FOR_COLUMN +#endif #endif /* SPD_ENVIRON_INCLUDED */ diff --git a/storage/spider/spd_err.h b/storage/spider/spd_err.h index 9889fcfa7fb..60b2a084714 100644 --- a/storage/spider/spd_err.h +++ b/storage/spider/spd_err.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -120,13 +121,19 @@ #define ER_SPIDER_ORACLE_STR "Error from Oracle %d %d %s" #define ER_SPIDER_ORACLE_NUM 12712 #define ER_SPIDER_ORACLE_ERR "Oracle error" +#define ER_SPIDER_DATASOURCE_STR "Error from %s %d %s %s" +#define ER_SPIDER_DATASOURCE_NUM 12712 #define ER_SPIDER_CON_COUNT_ERROR 12713 #define ER_SPIDER_CON_COUNT_ERROR_STR "Too many connections between spider and remote" #define ER_SPIDER_TABLE_OPEN_TIMEOUT_NUM 12714 #define ER_SPIDER_TABLE_OPEN_TIMEOUT_STR "Table %s.%s open timeout" +#define ER_SPIDER_INFINITE_LOOP_NUM 12719 +#define ER_SPIDER_INFINITE_LOOP_STR "An infinite loop is detected when opening table %s.%s" #define ER_SPIDER_SAME_SERVER_LINK_NUM 12720 #define ER_SPIDER_SAME_SERVER_LINK_STR1 "Host:%s and Socket:%s aim self server. Please change spider_same_server_link parameter if this link is required." #define ER_SPIDER_SAME_SERVER_LINK_STR2 "Host:%s and Port:%ld aim self server. Please change spider_same_server_link parameter if this link is required." +#define ER_SPIDER_CANT_NUM 12721 +#define ER_SPIDER_CANT_STR1 "Can't %s%d" #define ER_SPIDER_COND_SKIP_NUM 12801 #define ER_SPIDER_UNKNOWN_NUM 12500 diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 63f7cc0fdc3..d4ff18d129f 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -795,7 +795,7 @@ void spider_fields::choose_a_conn( SPIDER_CONN_HOLDER *conn_holder; longlong balance_total = 0, balance_val; double rand_val; - THD *thd = table_holder[0].spider->trx->thd; + THD *thd = table_holder[0].spider->wide_handler->trx->thd; DBUG_ENTER("spider_fields::choose_a_conn"); DBUG_PRINT("info",("spider this=%p", this)); for (current_conn_holder = first_conn_holder; current_conn_holder; @@ -1147,8 +1147,8 @@ int spider_fields::ping_table_mon_from_table( if (tmp_share->monitoring_kind[tmp_link_idx]) { error_num_buf = spider_ping_table_mon_from_table( - tmp_spider->trx, - tmp_spider->trx->thd, + tmp_spider->wide_handler->trx, + tmp_spider->wide_handler->trx->thd, tmp_share, tmp_link_idx, (uint32) tmp_share->monitoring_sid[tmp_link_idx], @@ -1181,7 +1181,7 @@ spider_group_by_handler::spider_group_by_handler( fields->set_pos_to_first_table_holder(); SPIDER_TABLE_HOLDER *table_holder = fields->get_next_table_holder(); spider = table_holder->spider; - trx = spider->trx; + trx = spider->wide_handler->trx; DBUG_VOID_RETURN; } @@ -1924,6 +1924,12 @@ group_by_handler *spider_create_group_by_handler( delete fields; DBUG_RETURN(NULL); } + if (spider->dml_init()) + { + DBUG_PRINT("info",("spider can not init for dml")); + delete fields; + DBUG_RETURN(NULL); + } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, spider->conn_link_idx, -1, share->link_count, @@ -2006,6 +2012,12 @@ group_by_handler *spider_create_group_by_handler( } DBUG_PRINT("info",("spider s->db=%s", from->table->s->db.str)); DBUG_PRINT("info",("spider s->table_name=%s", from->table->s->table_name.str)); + if (spider->dml_init()) + { + DBUG_PRINT("info",("spider can not init for dml")); + delete fields; + DBUG_RETURN(NULL); + } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, spider->conn_link_idx, -1, share->link_count, diff --git a/storage/spider/spd_i_s.cc b/storage/spider/spd_i_s.cc index 014da9fc2cd..24000f3e6c1 100644 --- a/storage/spider/spd_i_s.cc +++ b/storage/spider/spd_i_s.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2012-2018 Kentoku Shiba +/* Copyright (C) 2012-2020 Kentoku Shiba + Copyright (C) 2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +46,7 @@ static struct st_mysql_storage_engine spider_i_s_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; namespace Show { - +#ifdef SPIDER_I_S_USE_SHOW_FOR_COLUMN static ST_FIELD_INFO spider_i_s_alloc_mem_fields_info[] = { Column("ID", ULong(10), NOT_NULL, "id"), @@ -58,6 +59,27 @@ static ST_FIELD_INFO spider_i_s_alloc_mem_fields_info[] = Column("FREE_MEM_COUNT", ULonglong(20), NULLABLE, "free_mem_count"), CEnd() }; +#else +static ST_FIELD_INFO spider_i_s_alloc_mem_fields_info[] = +{ + {"ID", 10, MYSQL_TYPE_LONG, 0, MY_I_S_UNSIGNED, "id", SKIP_OPEN_TABLE}, + {"FUNC_NAME", 64, MYSQL_TYPE_STRING, 0, + MY_I_S_MAYBE_NULL, "func_name", SKIP_OPEN_TABLE}, + {"FILE_NAME", 64, MYSQL_TYPE_STRING, 0, + MY_I_S_MAYBE_NULL, "file_name", SKIP_OPEN_TABLE}, + {"LINE_NO", 10, MYSQL_TYPE_LONG, 0, + MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL, "line_no", SKIP_OPEN_TABLE}, + {"TOTAL_ALLOC_MEM", 20, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL, "total_alloc_mem", SKIP_OPEN_TABLE}, + {"CURRENT_ALLOC_MEM", 20, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_MAYBE_NULL, "current_alloc_mem", SKIP_OPEN_TABLE}, + {"ALLOC_MEM_COUNT", 20, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL, "alloc_mem_count", SKIP_OPEN_TABLE}, + {"FREE_MEM_COUNT", 20, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL, "free_mem_count", SKIP_OPEN_TABLE}, + {NULL, 0, MYSQL_TYPE_STRING, 0, 0, NULL, 0} +}; +#endif } // namespace Show static int spider_i_s_alloc_mem_fill_table( @@ -163,3 +185,127 @@ struct st_maria_plugin spider_i_s_alloc_mem_maria = MariaDB_PLUGIN_MATURITY_STABLE, }; #endif + +extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; + +namespace Show { +#ifdef SPIDER_I_S_USE_SHOW_FOR_COLUMN +static ST_FIELD_INFO spider_i_s_wrapper_protocols_fields_info[] = +{ + Column("WRAPPER_NAME", Varchar(NAME_CHAR_LEN), NOT_NULL, ""), + Column("WRAPPER_VERSION", Varchar(20), NOT_NULL, ""), + Column("WRAPPER_DESCRIPTION", Longtext(65535), NULLABLE, ""), + Column("WRAPPER_MATURITY", Varchar(12), NOT_NULL, ""), + CEnd() +}; +#else +static ST_FIELD_INFO spider_i_s_wrapper_protocols_fields_info[] = +{ + {"WRAPPER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, + {"WRAPPER_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, + {"WRAPPER_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, + {"WRAPPER_MATURITY", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} +}; +#endif +} // namespace Show + +static int spider_i_s_wrapper_protocols_fill_table( + THD *thd, + TABLE_LIST *tables, + COND *cond +) { + uint roop_count; + SPIDER_DBTON *dbton; + TABLE *table = tables->table; + DBUG_ENTER("spider_i_s_wrapper_protocols_fill_table"); + for (roop_count = 0; roop_count < SPIDER_DBTON_SIZE; roop_count++) + { + dbton = &spider_dbton[roop_count]; + if (!dbton->wrapper) + { + continue; + } + table->field[0]->store(dbton->wrapper, + strlen(dbton->wrapper), system_charset_info); + table->field[1]->store(dbton->version_info, + strlen(dbton->version_info), system_charset_info); + if (dbton->descr) + { + table->field[2]->set_notnull(); + table->field[2]->store(dbton->descr, + strlen(dbton->descr), system_charset_info); + } else { + table->field[2]->set_null(); + } + if (dbton->maturity <= SPIDER_MATURITY_STABLE) + { + table->field[3]->store(maturity_name[dbton->maturity].str, + maturity_name[dbton->maturity].length, system_charset_info); + } else { + table->field[3]->store(maturity_name[0].str, + maturity_name[0].length, system_charset_info); + } + if (schema_table_store_record(thd, table)) + { + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + +static int spider_i_s_wrapper_protocols_init( + void *p +) { + ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *) p; + DBUG_ENTER("spider_i_s_wrapper_protocols_init"); + schema->fields_info = Show::spider_i_s_wrapper_protocols_fields_info; + schema->fill_table = spider_i_s_wrapper_protocols_fill_table; + schema->idx_field1 = 0; + DBUG_RETURN(0); +} + +static int spider_i_s_wrapper_protocols_deinit( + void *p +) { + DBUG_ENTER("spider_i_s_wrapper_protocols_deinit"); + DBUG_RETURN(0); +} + +struct st_mysql_plugin spider_i_s_wrapper_protocols = +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &spider_i_s_info, + "SPIDER_WRAPPER_PROTOCOLS", + "Kentoku Shiba, MariaDB Corp", + "Available wrapper protocols of Spider", + PLUGIN_LICENSE_GPL, + spider_i_s_wrapper_protocols_init, + spider_i_s_wrapper_protocols_deinit, + 0x0001, + NULL, + NULL, + NULL, +#if MYSQL_VERSION_ID >= 50600 + 0, +#endif +}; + +#ifdef MARIADB_BASE_VERSION +struct st_maria_plugin spider_i_s_wrapper_protocols_maria = +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &spider_i_s_info, + "SPIDER_WRAPPER_PROTOCOLS", + "Kentoku Shiba, MariaDB Corp", + "Available wrapper protocols of Spider", + PLUGIN_LICENSE_GPL, + spider_i_s_wrapper_protocols_init, + spider_i_s_wrapper_protocols_deinit, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_STABLE, +}; +#endif diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 2249d3e699c..31c75b68d6e 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2008-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -256,12 +256,12 @@ const char SPIDER_empty_string = ""; #define SPIDER_LINK_MON_DRAW_FEW_MON 1 #define SPIDER_LINK_MON_DRAW 2 -#define SPIDER_TMP_SHARE_CHAR_PTR_COUNT 20 -#define SPIDER_TMP_SHARE_UINT_COUNT 17 -#define SPIDER_TMP_SHARE_LONG_COUNT 19 +#define SPIDER_TMP_SHARE_CHAR_PTR_COUNT 21 +#define SPIDER_TMP_SHARE_UINT_COUNT SPIDER_TMP_SHARE_CHAR_PTR_COUNT +#define SPIDER_TMP_SHARE_LONG_COUNT 20 #define SPIDER_TMP_SHARE_LONGLONG_COUNT 3 -#define SPIDER_MEM_CALC_LIST_NUM 268 +#define SPIDER_MEM_CALC_LIST_NUM 314 #define SPIDER_CONN_META_BUF_LEN 64 #define SPIDER_BACKUP_DASTATUS \ @@ -351,6 +351,7 @@ typedef struct st_spider_alter_table char **tmp_tgt_ssl_keys; char **tmp_tgt_default_files; char **tmp_tgt_default_groups; + char **tmp_tgt_dsns; char **tmp_static_link_ids; long *tmp_tgt_ports; long *tmp_tgt_ssl_vscs; @@ -372,6 +373,7 @@ typedef struct st_spider_alter_table uint *tmp_tgt_ssl_keys_lengths; uint *tmp_tgt_default_files_lengths; uint *tmp_tgt_default_groups_lengths; + uint *tmp_tgt_dsns_lengths; uint *tmp_static_link_ids_lengths; uint tmp_server_names_charlen; @@ -389,6 +391,7 @@ typedef struct st_spider_alter_table uint tmp_tgt_ssl_keys_charlen; uint tmp_tgt_default_files_charlen; uint tmp_tgt_default_groups_charlen; + uint tmp_tgt_dsns_charlen; uint tmp_static_link_ids_charlen; uint tmp_server_names_length; @@ -406,6 +409,7 @@ typedef struct st_spider_alter_table uint tmp_tgt_ssl_keys_length; uint tmp_tgt_default_files_length; uint tmp_tgt_default_groups_length; + uint tmp_tgt_dsns_length; uint tmp_static_link_ids_length; uint tmp_tgt_ports_length; uint tmp_tgt_ssl_vscs_length; @@ -413,6 +417,8 @@ typedef struct st_spider_alter_table uint tmp_link_statuses_length; } SPIDER_ALTER_TABLE; +typedef struct st_spider_conn_loop_check SPIDER_CONN_LOOP_CHECK; + /* database connection */ typedef struct st_spider_conn { @@ -480,6 +486,7 @@ typedef struct st_spider_conn char *tgt_password; char *tgt_socket; char *tgt_wrapper; + char *tgt_db; /* for not joinable tables on different db */ char *tgt_ssl_ca; char *tgt_ssl_capath; char *tgt_ssl_cert; @@ -487,6 +494,7 @@ typedef struct st_spider_conn char *tgt_ssl_key; char *tgt_default_file; char *tgt_default_group; + char *tgt_dsn; long tgt_port; long tgt_ssl_vsc; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -499,6 +507,7 @@ typedef struct st_spider_conn uint tgt_password_length; uint tgt_socket_length; uint tgt_wrapper_length; + uint tgt_db_length; uint tgt_ssl_ca_length; uint tgt_ssl_capath_length; uint tgt_ssl_cert_length; @@ -506,6 +515,7 @@ typedef struct st_spider_conn uint tgt_ssl_key_length; uint tgt_default_file_length; uint tgt_default_group_length; + uint tgt_dsn_length; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint hs_sock_length; #endif @@ -603,6 +613,22 @@ typedef struct st_spider_conn SPIDER_LINK_IDX_CHAIN *link_idx_chain; #endif SPIDER_IP_PORT_CONN *ip_port_conn; + + pthread_mutex_t loop_check_mutex; + HASH loop_checked; + uint loop_checked_id; + const char *loop_checked_func_name; + const char *loop_checked_file_name; + ulong loop_checked_line_no; + HASH loop_check_queue; + uint loop_check_queue_id; + const char *loop_check_queue_func_name; + const char *loop_check_queue_file_name; + ulong loop_check_queue_line_no; + SPIDER_CONN_LOOP_CHECK *loop_check_ignored_first; + SPIDER_CONN_LOOP_CHECK *loop_check_ignored_last; + SPIDER_CONN_LOOP_CHECK *loop_check_meraged_first; + SPIDER_CONN_LOOP_CHECK *loop_check_meraged_last; } SPIDER_CONN; typedef struct st_spider_lgtm_tblhnd_share @@ -621,26 +647,19 @@ typedef struct st_spider_lgtm_tblhnd_share #ifdef WITH_PARTITION_STORAGE_ENGINE typedef struct st_spider_patition_handler_share { - uint use_count; - TABLE *table; + bool clone_bitmap_init; #ifdef SPIDER_HAS_HASH_VALUE_TYPE my_hash_value_type table_hash_value; #endif - void *creator; - void **handlers; - uchar *searched_bitmap; - uchar *ft_discard_bitmap; - uchar *idx_read_bitmap; - uchar *idx_write_bitmap; - uchar *rnd_read_bitmap; - uchar *rnd_write_bitmap; - bool between_flg; - bool idx_bitmap_is_set; - bool rnd_bitmap_is_set; query_id_t parallel_search_query_id; + uint no_parts; + TABLE *table; + ha_spider *owner; + ha_spider **handlers; } SPIDER_PARTITION_HANDLER_SHARE; +#endif -typedef struct st_spider_patition_share +typedef struct st_spider_wide_share { char *table_name; uint table_name_length; @@ -648,6 +667,7 @@ typedef struct st_spider_patition_share my_hash_value_type table_path_hash_value; #endif uint use_count; + THR_LOCK lock; pthread_mutex_t sts_mutex; pthread_mutex_t crd_mutex; pthread_mutex_t pt_handler_mutex; @@ -664,11 +684,101 @@ typedef struct st_spider_patition_share ha_statistics stat; longlong *cardinality; -/* - volatile SPIDER_PARTITION_HANDLER_SHARE *partition_handler_share; -*/ -} SPIDER_PARTITION_SHARE; +} SPIDER_WIDE_SHARE; + +enum spider_hnd_stage { + SPD_HND_STAGE_NONE, + SPD_HND_STAGE_STORE_LOCK, + SPD_HND_STAGE_EXTERNAL_LOCK, + SPD_HND_STAGE_START_STMT, + SPD_HND_STAGE_EXTRA, + SPD_HND_STAGE_COND_PUSH, + SPD_HND_STAGE_COND_POP, + SPD_HND_STAGE_INFO_PUSH, + SPD_HND_STAGE_SET_TOP_TABLE_AND_FIELDS, + SPD_HND_STAGE_CLEAR_TOP_TABLE_FIELDS +}; + +typedef struct st_spider_wide_handler +{ + spider_hnd_stage stage; + handler *stage_executor; + THR_LOCK_DATA lock; + SPIDER_TRX *trx; + uchar *searched_bitmap; + uchar *ft_discard_bitmap; + uchar *position_bitmap; + uchar *idx_read_bitmap; + uchar *idx_write_bitmap; + uchar *rnd_read_bitmap; + uchar *rnd_write_bitmap; + SPIDER_CONDITION *condition; + void *owner; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + uint32 *hs_pushed_ret_fields; #endif +#endif +#ifdef WITH_PARTITION_STORAGE_ENGINE + SPIDER_PARTITION_HANDLER_SHARE *partition_handler_share; +#endif +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + List *direct_update_fields; + List *direct_update_values; +#endif + TABLE_SHARE *top_share; + enum thr_lock_type lock_type; + uchar lock_table_type; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + uint32 hs_pushed_strref_num; +#endif +#endif + int lock_mode; + int external_lock_type; + int cond_check_error; + uint sql_command; + uint top_table_fields; +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS +#ifdef INFO_KIND_FORCE_LIMIT_BEGIN + longlong info_limit; +#endif +#endif +#ifdef HA_CAN_BULK_ACCESS + ulonglong external_lock_cnt; +#endif +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + size_t hs_pushed_ret_fields_num; + size_t hs_pushed_ret_fields_size; + size_t hs_pushed_lcl_fields_num; +#endif +#endif + bool between_flg; + bool idx_bitmap_is_set; + bool rnd_bitmap_is_set; + bool position_bitmap_init; + bool semi_trx_isolation_chk; + bool semi_trx_chk; + bool low_priority; + bool high_priority; + bool insert_delayed; + bool consistent_snapshot; + bool quick_mode; + bool keyread; + bool update_request; + bool ignore_dup_key; + bool write_can_replace; + bool insert_with_update; + bool cond_check; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) +#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS + bool hs_increment; + bool hs_decrement; +#endif +#endif + bool semi_table_lock; +} SPIDER_WIDE_HANDLER; typedef struct st_spider_transaction { @@ -805,7 +915,6 @@ typedef struct st_spider_share /* pthread_mutex_t auto_increment_mutex; */ - THR_LOCK lock; TABLE_SHARE *table_share; SPIDER_LGTM_TBLHND_SHARE *lgtm_tblhnd_share; #ifdef SPIDER_HAS_HASH_VALUE_TYPE @@ -942,6 +1051,7 @@ typedef struct st_spider_share int bulk_size; int bulk_update_mode; int bulk_update_size; + int buffer_size; int internal_optimize; int internal_optimize_local; double scan_rate; @@ -1012,6 +1122,7 @@ typedef struct st_spider_share char **tgt_ssl_keys; char **tgt_default_files; char **tgt_default_groups; + char **tgt_dsns; char **static_link_ids; char **tgt_pk_names; char **tgt_sequence_names; @@ -1050,6 +1161,7 @@ typedef struct st_spider_share long *net_write_timeouts; long *access_balances; long *bka_table_name_types; + long *strict_group_bys; uint *server_names_lengths; uint *tgt_table_names_lengths; @@ -1066,6 +1178,7 @@ typedef struct st_spider_share uint *tgt_ssl_keys_lengths; uint *tgt_default_files_lengths; uint *tgt_default_groups_lengths; + uint *tgt_dsns_lengths; uint *static_link_ids_lengths; uint *tgt_pk_names_lengths; uint *tgt_sequence_names_lengths; @@ -1096,6 +1209,7 @@ typedef struct st_spider_share uint tgt_ssl_keys_charlen; uint tgt_default_files_charlen; uint tgt_default_groups_charlen; + uint tgt_dsns_charlen; uint static_link_ids_charlen; uint tgt_pk_names_charlen; uint tgt_sequence_names_charlen; @@ -1122,6 +1236,7 @@ typedef struct st_spider_share uint tgt_ssl_keys_length; uint tgt_default_files_length; uint tgt_default_groups_length; + uint tgt_dsns_length; uint static_link_ids_length; uint tgt_pk_names_length; uint tgt_sequence_names_length; @@ -1160,6 +1275,7 @@ typedef struct st_spider_share uint net_write_timeouts_length; uint access_balances_length; uint bka_table_name_types_length; + uint strict_group_bys_length; /* for dbton */ uchar dbton_bitmap[spider_bitmap_size(SPIDER_DBTON_SIZE)]; @@ -1177,9 +1293,7 @@ typedef struct st_spider_share #endif SPIDER_ALTER_TABLE alter_table; -#ifdef WITH_PARTITION_STORAGE_ENGINE - SPIDER_PARTITION_SHARE *partition_share; -#endif + SPIDER_WIDE_SHARE *wide_share; } SPIDER_SHARE; typedef struct st_spider_link_pack @@ -1258,6 +1372,7 @@ typedef struct st_spider_direct_sql char *tgt_ssl_key; char *tgt_default_file; char *tgt_default_group; + char *tgt_dsn; char *conn_key; long tgt_port; long tgt_ssl_vsc; @@ -1276,6 +1391,7 @@ typedef struct st_spider_direct_sql uint tgt_ssl_key_length; uint tgt_default_file_length; uint tgt_default_group_length; + uint tgt_dsn_length; uint conn_key_length; uint dbton_id; #ifdef SPIDER_HAS_HASH_VALUE_TYPE diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 4c58f8d80a4..f1fc558ab98 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2010-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2010-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,6 +51,7 @@ static LEX_STRING spider_init_queries[] = { " ssl_verify_server_cert tinyint not null default 0," " default_file text," " default_group char(64) default null," + " dsn char(64) default null," " key idx1 (data, format_id, gtrid_length, host)" ") engine=MyISAM default charset=utf8 collate=utf8_bin" )}, @@ -74,6 +75,7 @@ static LEX_STRING spider_init_queries[] = { " ssl_verify_server_cert tinyint not null default 0," " default_file text," " default_group char(64) default null," + " dsn char(64) default null," " thread_id int default null," " status char(8) not null default ''," " failed_time timestamp not null default current_timestamp," @@ -102,6 +104,7 @@ static LEX_STRING spider_init_queries[] = { " monitoring_binlog_pos_at_failing tinyint not null default 0," " default_file text," " default_group char(64) default null," + " dsn char(64) default null," " tgt_db_name char(64) default null," " tgt_table_name char(64) default null," " link_status tinyint not null default 1," @@ -133,6 +136,7 @@ static LEX_STRING spider_init_queries[] = { " ssl_verify_server_cert tinyint not null default 0," " default_file text," " default_group char(64) default null," + " dsn char(64) default null," " primary key (db_name, table_name, link_id, sid)" ") engine=MyISAM default charset=utf8 collate=utf8_bin" )}, @@ -214,6 +218,10 @@ static LEX_STRING spider_init_queries[] = { "begin" " select substring_index(substring_index(version(), '-', 2), '-', -1)" " into @server_name;" + " if @server_name regexp '^[0-9]+$' then" + " select substring_index(substring_index(version(), '-', 3), '-', -1)" + " into @server_name;" + " end if;" " select substring_index(version(), '.', 1)" " into @server_major_version;" " select substring_index(substring_index(version(), '.', 2), '.', -1)" @@ -591,6 +599,21 @@ static LEX_STRING spider_init_queries[] = { " primary key (db_name, table_name, table_id, partition_id)" " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" " end if;" +/* + Fix for version 3.4 +*/ + " call mysql.spider_fix_one_table('spider_link_mon_servers', 'dsn'," + " 'alter table mysql.spider_link_mon_servers" + " add column dsn char(64) default null after default_group');" + " call mysql.spider_fix_one_table('spider_tables', 'dsn'," + " 'alter table mysql.spider_tables" + " add column dsn char(64) default null after default_group');" + " call mysql.spider_fix_one_table('spider_xa_failed_log', 'dsn'," + " 'alter table mysql.spider_xa_failed_log" + " add column dsn char(64) default null after default_group');" + " call mysql.spider_fix_one_table('spider_xa_member', 'dsn'," + " 'alter table mysql.spider_xa_member" + " add column dsn char(64) default null after default_group');" "end;" )}, {C_STRING_WITH_LEN( @@ -663,6 +686,31 @@ static LEX_STRING spider_init_queries[] = { " install plugin spider_alloc_mem soname 'ha_spider.dll';" " end if;" " end if;" +/* + Install spider_wrapper_protocols plugin +*/ + " set @have_spider_i_s_wrapper_protocols_plugin := 0;" + " select @have_spider_i_s_wrapper_protocols_plugin := 1" + " from INFORMATION_SCHEMA.plugins" + " where PLUGIN_NAME = 'SPIDER_WRAPPER_PROTOCOLS';" + " set @have_spider_wrapper_protocols_plugin := 0;" + " select @have_spider_wrapper_protocols_plugin := 1 from mysql.plugin" + " where name = 'spider_wrapper_protocols';" + " if @have_spider_i_s_wrapper_protocols_plugin = 0 then" + " if @have_spider_wrapper_protocols_plugin = 1 then" + " /*" + " spider_wrapper_protocols plugin is present in mysql.plugin but not in" + " information_schema.plugins. Remove spider_wrapper_protocols plugin entry" + " in mysql.plugin first." + " */" + " delete from mysql.plugin where name = 'spider_wrapper_protocols';" + " end if;" + " if @win_plugin = 0 then " + " install plugin spider_wrapper_protocols soname 'ha_spider.so';" + " else" + " install plugin spider_wrapper_protocols soname 'ha_spider.dll';" + " end if;" + " end if;" " set @have_spider_direct_sql_udf := 0;" " select @have_spider_direct_sql_udf := 1 from mysql.func" " where name = 'spider_direct_sql';" diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index 446ccc22141..3657cc9120d 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -35,8 +35,10 @@ #include "spd_trx.h" extern struct st_mysql_plugin spider_i_s_alloc_mem; +extern struct st_mysql_plugin spider_i_s_wrapper_protocols; #ifdef MARIADB_BASE_VERSION extern struct st_maria_plugin spider_i_s_alloc_mem_maria; +extern struct st_maria_plugin spider_i_s_wrapper_protocols_maria; #endif extern volatile ulonglong spider_mon_table_cache_version; @@ -1051,6 +1053,31 @@ int spider_param_bulk_update_size( bulk_update_size : THDVAR(thd, bulk_update_size)); } +/* + -1 :use table parameter + 0-:buffer size + */ +static MYSQL_THDVAR_INT( + buffer_size, /* name */ + PLUGIN_VAR_RQCMDARG, /* opt */ + "Buffer size", /* comment */ + NULL, /* check */ + NULL, /* update */ + -1, /* def */ + -1, /* min */ + 2147483647, /* max */ + 0 /* blk */ +); + +int spider_param_buffer_size( + THD *thd, + int buffer_size +) { + DBUG_ENTER("spider_param_buffer_size"); + DBUG_RETURN(THDVAR(thd, buffer_size) == -1 ? + buffer_size : THDVAR(thd, buffer_size)); +} + /* -1 :use table parameter 0 :off @@ -3425,6 +3452,32 @@ bool spider_param_sync_sql_mode( DBUG_RETURN(THDVAR(thd, sync_sql_mode)); } +/* + -1 : use table parameter + 0 : do not strict + 1 : do strict + */ +static MYSQL_THDVAR_INT( + strict_group_by, /* name */ + PLUGIN_VAR_RQCMDARG, /* opt */ + "Use columns in select clause strictly for group by clause", + NULL, /* check */ + NULL, /* update */ + -1, /* def */ + -1, /* min */ + 1, /* max */ + 0 /* blk */ +); + +int spider_param_strict_group_by( + THD *thd, + int strict_group_by +) { + DBUG_ENTER("spider_param_strict_group_by"); + DBUG_RETURN(THDVAR(thd, strict_group_by) == -1 ? + strict_group_by : THDVAR(thd, strict_group_by)); +} + static struct st_mysql_storage_engine spider_storage_engine = { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -3463,6 +3516,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(bulk_size), MYSQL_SYSVAR(bulk_update_mode), MYSQL_SYSVAR(bulk_update_size), + MYSQL_SYSVAR(buffer_size), MYSQL_SYSVAR(internal_optimize), MYSQL_SYSVAR(internal_optimize_local), MYSQL_SYSVAR(use_flash_logs), @@ -3578,6 +3632,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(remote_wait_timeout), MYSQL_SYSVAR(wait_timeout), MYSQL_SYSVAR(sync_sql_mode), + MYSQL_SYSVAR(strict_group_by), NULL }; @@ -3599,7 +3654,8 @@ mysql_declare_plugin(spider) 0, #endif }, -spider_i_s_alloc_mem +spider_i_s_alloc_mem, +spider_i_s_wrapper_protocols mysql_declare_plugin_end; #ifdef MARIADB_BASE_VERSION @@ -3617,8 +3673,9 @@ maria_declare_plugin(spider) spider_status_variables, spider_system_variables, SPIDER_DETAIL_VERSION, - MariaDB_PLUGIN_MATURITY_STABLE + MariaDB_PLUGIN_MATURITY_GAMMA }, -spider_i_s_alloc_mem_maria +spider_i_s_alloc_mem_maria, +spider_i_s_wrapper_protocols_maria maria_declare_plugin_end; #endif diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h index 9ffb9e8c278..c3a79cec065 100644 --- a/storage/spider/spd_param.h +++ b/storage/spider/spd_param.h @@ -126,6 +126,10 @@ int spider_param_bulk_update_size( THD *thd, int bulk_update_size ); +int spider_param_buffer_size( + THD *thd, + int buffer_size +); int spider_param_internal_optimize( THD *thd, int internal_optimize @@ -384,6 +388,7 @@ my_bool spider_param_index_hint_pushdown( ); uint spider_param_max_connections(); uint spider_param_conn_wait_timeout(); +uint spider_param_internal_lock_wait_timeout(); uint spider_param_log_result_errors(); uint spider_param_log_result_error_with_sql(); uint spider_param_internal_xa_id_type( @@ -431,3 +436,7 @@ int spider_param_wait_timeout( bool spider_param_sync_sql_mode( THD *thd ); +int spider_param_strict_group_by( + THD *thd, + int strict_group_by +); diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 60e36fc24fb..e233fc1fd86 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -850,6 +850,7 @@ int spider_init_ping_table_mon_cache( bool need_lock ) { int error_num, same; + uint old_elements; TABLE *table_link_mon = NULL; #if MYSQL_VERSION_ID < 50500 Open_tables_state open_tables_backup; @@ -899,11 +900,23 @@ int spider_init_ping_table_mon_cache( { mon_key.sort = spider_calc_for_sort(3, mon_key.db_name, mon_key.table_name, mon_key.link_id); + old_elements = spider_mon_table_cache.max_element; if (push_dynamic(&spider_mon_table_cache, (uchar *) &mon_key)) { error_num = HA_ERR_OUT_OF_MEM; goto error_push_dynamic; } + if (spider_mon_table_cache.max_element != old_elements) + { + spider_free_mem_calc(spider_current_trx, + spider_mon_table_cache_id, + old_elements * + spider_mon_table_cache.size_of_element); + spider_alloc_calc_mem(spider_current_trx, + spider_mon_table_cache, + spider_mon_table_cache.max_element * + spider_mon_table_cache.size_of_element); + } } if ((error_num = spider_sys_index_next(table_link_mon))) @@ -923,12 +936,16 @@ int spider_init_ping_table_mon_cache( (uchar *) dynamic_element(&spider_mon_table_cache, 0, SPIDER_MON_KEY *), spider_mon_table_cache.elements, sizeof(SPIDER_MON_KEY), (qsort_cmp) spider_compare_for_sort); - uint old_elements = spider_mon_table_cache.max_element; + old_elements = spider_mon_table_cache.max_element; freeze_size(&spider_mon_table_cache); - if (spider_mon_table_cache.max_element < old_elements) + if (spider_mon_table_cache.max_element != old_elements) { spider_free_mem_calc(spider_current_trx, spider_mon_table_cache_id, + old_elements * + spider_mon_table_cache.size_of_element); + spider_alloc_calc_mem(spider_current_trx, + spider_mon_table_cache, spider_mon_table_cache.max_element * spider_mon_table_cache.size_of_element); } diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index ada48c4982d..899689bc863 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -39,6 +39,113 @@ extern handlerton *spider_hton_ptr; extern Time_zone *spd_tz_system; +#define SPIDER_XA_FORMAT_ID_POS 0 +#define SPIDER_XA_GTRID_LENGTH_POS 1 +#define SPIDER_XA_BQUAL_LENGTH_POS 2 +#define SPIDER_XA_DATA_POS 3 +#define SPIDER_XA_STATUS_POS 4 + +#define SPIDER_XA_MEMBER_FORMAT_ID_POS 0 +#define SPIDER_XA_MEMBER_GTRID_LENGTH_POS 1 +#define SPIDER_XA_MEMBER_BQUAL_LENGTH_POS 2 +#define SPIDER_XA_MEMBER_DATA_POS 3 +#define SPIDER_XA_MEMBER_SCHEME_POS 4 +#define SPIDER_XA_MEMBER_HOST_POS 5 +#define SPIDER_XA_MEMBER_PORT_POS 6 +#define SPIDER_XA_MEMBER_SOCKET_POS 7 +#define SPIDER_XA_MEMBER_USERNAME_POS 8 +#define SPIDER_XA_MEMBER_PASSWORD_POS 9 +#define SPIDER_XA_MEMBER_SSL_CA_POS 10 +#define SPIDER_XA_MEMBER_SSL_CAPATH_POS 11 +#define SPIDER_XA_MEMBER_SSL_CERT_POS 12 +#define SPIDER_XA_MEMBER_SSL_CIPHER_POS 13 +#define SPIDER_XA_MEMBER_SSL_KEY_POS 14 +#define SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS 15 +#define SPIDER_XA_MEMBER_DEFAULT_FILE_POS 16 +#define SPIDER_XA_MEMBER_DEFAULT_GROUP_POS 17 +#define SPIDER_XA_MEMBER_DSN_POS 18 +#define SPIDER_XA_FAILED_LOG_THREAD_ID_POS 19 +#define SPIDER_XA_FAILED_LOG_STATUS_POS 20 +#define SPIDER_XA_FAILED_LOG_FAILED_TIME_POS 21 + +#define SPIDER_TABLES_DB_NAME_POS 0 +#define SPIDER_TABLES_TABLE_NAME_POS 1 +#define SPIDER_TABLES_LINK_ID_POS 2 +#define SPIDER_TABLES_PRIORITY_POS 3 +#define SPIDER_TABLES_SERVER_POS 4 +#define SPIDER_TABLES_SCHEME_POS 5 +#define SPIDER_TABLES_HOST_POS 6 +#define SPIDER_TABLES_PORT_POS 7 +#define SPIDER_TABLES_SOCKET_POS 8 +#define SPIDER_TABLES_USERNAME_POS 9 +#define SPIDER_TABLES_PASSWORD_POS 10 +#define SPIDER_TABLES_SSL_CA_POS 11 +#define SPIDER_TABLES_SSL_CAPATH_POS 12 +#define SPIDER_TABLES_SSL_CERT_POS 13 +#define SPIDER_TABLES_SSL_CIPHER_POS 14 +#define SPIDER_TABLES_SSL_KEY_POS 15 +#define SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS 16 +#define SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS 17 +#define SPIDER_TABLES_DEFAULT_FILE_POS 18 +#define SPIDER_TABLES_DEFAULT_GROUP_POS 19 +#define SPIDER_TABLES_DSN_POS 20 +#define SPIDER_TABLES_TGT_DB_NAME_POS 21 +#define SPIDER_TABLES_TGT_TABLE_NAME_POS 22 +#define SPIDER_TABLES_LINK_STATUS_POS 23 +#define SPIDER_TABLES_BLOCK_STATUS_POS 24 +#define SPIDER_TABLES_STATIC_LINK_ID_POS 25 + +#define SPIDER_LINK_MON_SERVERS_DB_NAME_POS 0 +#define SPIDER_LINK_MON_SERVERS_TABLE_NAME_POS 1 +#define SPIDER_LINK_MON_SERVERS_LINK_ID_POS 2 +#define SPIDER_LINK_MON_SERVERS_SID_POS 3 +#define SPIDER_LINK_MON_SERVERS_SERVER_POS 4 +#define SPIDER_LINK_MON_SERVERS_SCHEME_POS 5 +#define SPIDER_LINK_MON_SERVERS_HOST_POS 6 +#define SPIDER_LINK_MON_SERVERS_PORT_POS 7 +#define SPIDER_LINK_MON_SERVERS_SOCKET_POS 8 +#define SPIDER_LINK_MON_SERVERS_USERNAME_POS 9 +#define SPIDER_LINK_MON_SERVERS_PASSWORD_POS 10 +#define SPIDER_LINK_MON_SERVERS_SSL_CA_POS 11 +#define SPIDER_LINK_MON_SERVERS_SSL_CAPATH_POS 12 +#define SPIDER_LINK_MON_SERVERS_SSL_CERT_POS 13 +#define SPIDER_LINK_MON_SERVERS_SSL_CIPHER_POS 14 +#define SPIDER_LINK_MON_SERVERS_SSL_KEY_POS 15 +#define SPIDER_LINK_MON_SERVERS_SSL_VERIFY_SERVER_CERT_POS 16 +#define SPIDER_LINK_MON_SERVERS_DEFAULT_FILE_POS 17 +#define SPIDER_LINK_MON_SERVERS_DEFAULT_GROUP_POS 18 +#define SPIDER_LINK_MON_SERVERS_DSN_POS 19 + +#define SPIDER_LINK_FAILED_LOG_DB_NAME_POS 0 +#define SPIDER_LINK_FAILED_LOG_TABLE_NAME_POS 1 +#define SPIDER_LINK_FAILED_LOG_LINK_ID_POS 2 +#define SPIDER_LINK_FAILED_LOG_FAILED_TIME_POS 3 + +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_DB_NAME_POS 0 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_TABLE_NAME_POS 1 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_FAILED_LINK_ID_POS 2 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_SOURCE_LINK_ID_POS 3 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_FILE_POS 4 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_POSITION_POS 5 +#define SPIDER_TABLE_POSITION_FOR_RECOVERY_GTID_POS 6 + +#define SPIDER_TABLE_STS_DB_NAME_POS 0 +#define SPIDER_TABLE_STS_TABLE_NAME_POS 1 +#define SPIDER_TABLE_STS_DATA_FILE_LENGTH_POS 2 +#define SPIDER_TABLE_STS_MAX_DATA_FILE_LENGTH_POS 3 +#define SPIDER_TABLE_STS_INDEX_FILE_LENGTH_POS 4 +#define SPIDER_TABLE_STS_RECORDS_POS 5 +#define SPIDER_TABLE_STS_MEAN_REC_LENGTH_POS 6 +#define SPIDER_TABLE_STS_CHECK_TIME_POS 7 +#define SPIDER_TABLE_STS_CREATE_TIME_POS 8 +#define SPIDER_TABLE_STS_UPDATE_TIME_POS 9 +#define SPIDER_TABLE_STS_CHECKSUM_POS 10 + +#define SPIDER_TABLE_CRD_DB_NAME_POS 0 +#define SPIDER_TABLE_CRD_TABLE_NAME_POS 1 +#define SPIDER_TABLE_CRD_KEY_SEQ_POS 2 +#define SPIDER_TABLE_CRD_CARDINALITY_POS 3 + /** Insert a Spider system table row. @@ -584,7 +691,8 @@ void spider_sys_close_table( ) { DBUG_ENTER("spider_sys_close_table"); close_thread_tables(thd); - thd->restore_backup_open_tables_state(open_tables_backup); + if (open_tables_backup) + thd->restore_backup_open_tables_state(open_tables_backup); DBUG_VOID_RETURN; } #endif @@ -827,9 +935,9 @@ void spider_store_xa_pk( XID *xid ) { DBUG_ENTER("spider_store_xa_pk"); - table->field[0]->store(xid->formatID); - table->field[1]->store(xid->gtrid_length); - table->field[3]->store( + table->field[SPIDER_XA_FORMAT_ID_POS]->store(xid->formatID); + table->field[SPIDER_XA_GTRID_LENGTH_POS]->store(xid->gtrid_length); + table->field[SPIDER_XA_DATA_POS]->store( xid->data, (uint) xid->gtrid_length + xid->bqual_length, system_charset_info); @@ -841,7 +949,7 @@ void spider_store_xa_bqual_length( XID *xid ) { DBUG_ENTER("spider_store_xa_bqual_length"); - table->field[2]->store(xid->bqual_length); + table->field[SPIDER_XA_BQUAL_LENGTH_POS]->store(xid->bqual_length); DBUG_VOID_RETURN; } @@ -850,7 +958,7 @@ void spider_store_xa_status( const char *status ) { DBUG_ENTER("spider_store_xa_status"); - table->field[4]->store( + table->field[SPIDER_XA_STATUS_POS]->store( status, (uint) strlen(status), system_charset_info); @@ -863,19 +971,19 @@ void spider_store_xa_member_pk( SPIDER_CONN *conn ) { DBUG_ENTER("spider_store_xa_member_pk"); - table->field[0]->store(xid->formatID); - table->field[1]->store(xid->gtrid_length); - table->field[3]->store( + table->field[SPIDER_XA_MEMBER_FORMAT_ID_POS]->store(xid->formatID); + table->field[SPIDER_XA_MEMBER_GTRID_LENGTH_POS]->store(xid->gtrid_length); + table->field[SPIDER_XA_MEMBER_DATA_POS]->store( xid->data, (uint) xid->gtrid_length + xid->bqual_length, system_charset_info); - table->field[5]->store( + table->field[SPIDER_XA_MEMBER_HOST_POS]->store( conn->tgt_host, (uint) conn->tgt_host_length, system_charset_info); - table->field[6]->store( + table->field[SPIDER_XA_MEMBER_PORT_POS]->store( conn->tgt_port); - table->field[7]->store( + table->field[SPIDER_XA_MEMBER_SOCKET_POS]->store( conn->tgt_socket, (uint) conn->tgt_socket_length, system_charset_info); @@ -888,104 +996,115 @@ void spider_store_xa_member_info( SPIDER_CONN *conn ) { DBUG_ENTER("spider_store_xa_member_info"); - table->field[2]->store(xid->bqual_length); - table->field[4]->store( + table->field[SPIDER_XA_MEMBER_BQUAL_LENGTH_POS]->store(xid->bqual_length); + table->field[SPIDER_XA_MEMBER_SCHEME_POS]->store( conn->tgt_wrapper, (uint) conn->tgt_wrapper_length, system_charset_info); - table->field[8]->store( + table->field[SPIDER_XA_MEMBER_USERNAME_POS]->store( conn->tgt_username, (uint) conn->tgt_username_length, system_charset_info); - table->field[9]->store( + table->field[SPIDER_XA_MEMBER_PASSWORD_POS]->store( conn->tgt_password, (uint) conn->tgt_password_length, system_charset_info); if (conn->tgt_ssl_ca) { - table->field[10]->set_notnull(); - table->field[10]->store( + table->field[SPIDER_XA_MEMBER_SSL_CA_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_CA_POS]->store( conn->tgt_ssl_ca, (uint) conn->tgt_ssl_ca_length, system_charset_info); } else { - table->field[10]->set_null(); - table->field[10]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_CA_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_CA_POS]->reset(); } if (conn->tgt_ssl_capath) { - table->field[11]->set_notnull(); - table->field[11]->store( + table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS]->store( conn->tgt_ssl_capath, (uint) conn->tgt_ssl_capath_length, system_charset_info); } else { - table->field[11]->set_null(); - table->field[11]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS]->reset(); } if (conn->tgt_ssl_cert) { - table->field[12]->set_notnull(); - table->field[12]->store( + table->field[SPIDER_XA_MEMBER_SSL_CERT_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_CERT_POS]->store( conn->tgt_ssl_cert, (uint) conn->tgt_ssl_cert_length, system_charset_info); } else { - table->field[12]->set_null(); - table->field[12]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_CERT_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_CERT_POS]->reset(); } if (conn->tgt_ssl_cipher) { - table->field[13]->set_notnull(); - table->field[13]->store( + table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS]->store( conn->tgt_ssl_cipher, (uint) conn->tgt_ssl_cipher_length, system_charset_info); } else { - table->field[13]->set_null(); - table->field[13]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS]->reset(); } if (conn->tgt_ssl_key) { - table->field[14]->set_notnull(); - table->field[14]->store( + table->field[SPIDER_XA_MEMBER_SSL_KEY_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_KEY_POS]->store( conn->tgt_ssl_key, (uint) conn->tgt_ssl_key_length, system_charset_info); } else { - table->field[14]->set_null(); - table->field[14]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_KEY_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_KEY_POS]->reset(); } if (conn->tgt_ssl_vsc >= 0) { - table->field[15]->set_notnull(); - table->field[15]->store( + table->field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS]->store( conn->tgt_ssl_vsc); } else { - table->field[15]->set_null(); - table->field[15]->reset(); + table->field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS]->reset(); } if (conn->tgt_default_file) { - table->field[16]->set_notnull(); - table->field[16]->store( + table->field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS]->store( conn->tgt_default_file, (uint) conn->tgt_default_file_length, system_charset_info); } else { - table->field[16]->set_null(); - table->field[16]->reset(); + table->field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS]->reset(); } if (conn->tgt_default_group) { - table->field[17]->set_notnull(); - table->field[17]->store( + table->field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS]->store( conn->tgt_default_group, (uint) conn->tgt_default_group_length, system_charset_info); } else { - table->field[17]->set_null(); - table->field[17]->reset(); + table->field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS]->reset(); + } + if (conn->tgt_dsn) + { + table->field[SPIDER_XA_MEMBER_DSN_POS]->set_notnull(); + table->field[SPIDER_XA_MEMBER_DSN_POS]->store( + conn->tgt_dsn, + (uint) conn->tgt_dsn_length, + system_charset_info); + } else { + table->field[SPIDER_XA_MEMBER_DSN_POS]->set_null(); + table->field[SPIDER_XA_MEMBER_DSN_POS]->reset(); } DBUG_VOID_RETURN; } @@ -1016,18 +1135,20 @@ void spider_store_tables_name( ptr_table = ""; ptr_diff_table = 1; } - table->field[0]->store( + table->field[SPIDER_TABLES_DB_NAME_POS]->store( ptr_db, (uint)(ptr_diff_table - 1), system_charset_info); - DBUG_PRINT("info",("spider field[0]->null_bit = %d", - table->field[0]->null_bit)); - table->field[1]->store( + DBUG_PRINT("info",("spider field[%u]->null_bit = %d", + SPIDER_TABLES_DB_NAME_POS, + table->field[SPIDER_TABLES_DB_NAME_POS]->null_bit)); + table->field[SPIDER_TABLES_TABLE_NAME_POS]->store( ptr_table, (uint) ((my_ptrdiff_t) name_length - ptr_diff_db - ptr_diff_table), system_charset_info); - DBUG_PRINT("info",("spider field[1]->null_bit = %d", - table->field[1]->null_bit)); + DBUG_PRINT("info",("spider field[%u]->null_bit = %d", + SPIDER_TABLES_TABLE_NAME_POS, + table->field[SPIDER_TABLES_TABLE_NAME_POS]->null_bit)); DBUG_VOID_RETURN; } @@ -1039,18 +1160,20 @@ void spider_store_db_and_table_name( const uint table_name_length ) { DBUG_ENTER("spider_store_db_and_table_name"); - table->field[0]->store( + table->field[SPIDER_TABLES_DB_NAME_POS]->store( db_name, db_name_length, system_charset_info); - DBUG_PRINT("info",("spider field[0]->null_bit = %d", - table->field[0]->null_bit)); - table->field[1]->store( + DBUG_PRINT("info",("spider field[%u]->null_bit = %d", + SPIDER_TABLES_DB_NAME_POS, + table->field[SPIDER_TABLES_DB_NAME_POS]->null_bit)); + table->field[SPIDER_TABLES_TABLE_NAME_POS]->store( table_name, table_name_length, system_charset_info); - DBUG_PRINT("info",("spider field[1]->null_bit = %d", - table->field[1]->null_bit)); + DBUG_PRINT("info",("spider field[%u]->null_bit = %d", + SPIDER_TABLES_TABLE_NAME_POS, + table->field[SPIDER_TABLES_TABLE_NAME_POS]->null_bit)); DBUG_VOID_RETURN; } @@ -1059,8 +1182,8 @@ void spider_store_tables_link_idx( int link_idx ) { DBUG_ENTER("spider_store_tables_link_idx"); - table->field[2]->set_notnull(); - table->field[2]->store(link_idx); + table->field[SPIDER_TABLES_LINK_ID_POS]->set_notnull(); + table->field[SPIDER_TABLES_LINK_ID_POS]->store(link_idx); DBUG_VOID_RETURN; } @@ -1070,12 +1193,13 @@ void spider_store_tables_link_idx_str( const uint link_idx_length ) { DBUG_ENTER("spider_store_tables_link_idx_str"); - table->field[2]->store( + table->field[SPIDER_TABLES_LINK_ID_POS]->store( link_idx, link_idx_length, system_charset_info); - DBUG_PRINT("info",("spider field[2]->null_bit = %d", - table->field[2]->null_bit)); + DBUG_PRINT("info",("spider field[%u]->null_bit = %d", + SPIDER_TABLES_LINK_ID_POS, + table->field[SPIDER_TABLES_LINK_ID_POS]->null_bit)); DBUG_VOID_RETURN; } @@ -1087,14 +1211,14 @@ void spider_store_tables_static_link_id( DBUG_ENTER("spider_store_tables_static_link_id"); if (static_link_id) { - table->field[24]->set_notnull(); - table->field[24]->store( + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->set_notnull(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->store( static_link_id, static_link_id_length, system_charset_info); } else { - table->field[24]->set_null(); - table->field[24]->reset(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->set_null(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->reset(); } DBUG_VOID_RETURN; } @@ -1105,7 +1229,7 @@ void spider_store_tables_priority( ) { DBUG_ENTER("spider_store_tables_priority"); DBUG_PRINT("info",("spider priority = %lld", priority)); - table->field[3]->store(priority, FALSE); + table->field[SPIDER_TABLES_PRIORITY_POS]->store(priority, FALSE); DBUG_VOID_RETURN; } @@ -1117,209 +1241,221 @@ void spider_store_tables_connect_info( DBUG_ENTER("spider_store_tables_connect_info"); if (alter_table->tmp_server_names[link_idx]) { - table->field[4]->set_notnull(); - table->field[4]->store( + table->field[SPIDER_TABLES_SERVER_POS]->set_notnull(); + table->field[SPIDER_TABLES_SERVER_POS]->store( alter_table->tmp_server_names[link_idx], (uint) alter_table->tmp_server_names_lengths[link_idx], system_charset_info); } else { - table->field[4]->set_null(); - table->field[4]->reset(); + table->field[SPIDER_TABLES_SERVER_POS]->set_null(); + table->field[SPIDER_TABLES_SERVER_POS]->reset(); } if (alter_table->tmp_tgt_wrappers[link_idx]) { - table->field[5]->set_notnull(); - table->field[5]->store( + table->field[SPIDER_TABLES_SCHEME_POS]->set_notnull(); + table->field[SPIDER_TABLES_SCHEME_POS]->store( alter_table->tmp_tgt_wrappers[link_idx], (uint) alter_table->tmp_tgt_wrappers_lengths[link_idx], system_charset_info); } else { - table->field[5]->set_null(); - table->field[5]->reset(); + table->field[SPIDER_TABLES_SCHEME_POS]->set_null(); + table->field[SPIDER_TABLES_SCHEME_POS]->reset(); } if (alter_table->tmp_tgt_hosts[link_idx]) { - table->field[6]->set_notnull(); - table->field[6]->store( + table->field[SPIDER_TABLES_HOST_POS]->set_notnull(); + table->field[SPIDER_TABLES_HOST_POS]->store( alter_table->tmp_tgt_hosts[link_idx], (uint) alter_table->tmp_tgt_hosts_lengths[link_idx], system_charset_info); } else { - table->field[6]->set_null(); - table->field[6]->reset(); + table->field[SPIDER_TABLES_HOST_POS]->set_null(); + table->field[SPIDER_TABLES_HOST_POS]->reset(); } if (alter_table->tmp_tgt_ports[link_idx] >= 0) { - table->field[7]->set_notnull(); - table->field[7]->store( + table->field[SPIDER_TABLES_PORT_POS]->set_notnull(); + table->field[SPIDER_TABLES_PORT_POS]->store( alter_table->tmp_tgt_ports[link_idx]); } else { - table->field[7]->set_null(); - table->field[7]->reset(); + table->field[SPIDER_TABLES_PORT_POS]->set_null(); + table->field[SPIDER_TABLES_PORT_POS]->reset(); } if (alter_table->tmp_tgt_sockets[link_idx]) { - table->field[8]->set_notnull(); - table->field[8]->store( + table->field[SPIDER_TABLES_SOCKET_POS]->set_notnull(); + table->field[SPIDER_TABLES_SOCKET_POS]->store( alter_table->tmp_tgt_sockets[link_idx], (uint) alter_table->tmp_tgt_sockets_lengths[link_idx], system_charset_info); } else { - table->field[8]->set_null(); - table->field[8]->reset(); + table->field[SPIDER_TABLES_SOCKET_POS]->set_null(); + table->field[SPIDER_TABLES_SOCKET_POS]->reset(); } if (alter_table->tmp_tgt_usernames[link_idx]) { - table->field[9]->set_notnull(); - table->field[9]->store( + table->field[SPIDER_TABLES_USERNAME_POS]->set_notnull(); + table->field[SPIDER_TABLES_USERNAME_POS]->store( alter_table->tmp_tgt_usernames[link_idx], (uint) alter_table->tmp_tgt_usernames_lengths[link_idx], system_charset_info); } else { - table->field[9]->set_null(); - table->field[9]->reset(); + table->field[SPIDER_TABLES_USERNAME_POS]->set_null(); + table->field[SPIDER_TABLES_USERNAME_POS]->reset(); } if (alter_table->tmp_tgt_passwords[link_idx]) { - table->field[10]->set_notnull(); - table->field[10]->store( + table->field[SPIDER_TABLES_PASSWORD_POS]->set_notnull(); + table->field[SPIDER_TABLES_PASSWORD_POS]->store( alter_table->tmp_tgt_passwords[link_idx], (uint) alter_table->tmp_tgt_passwords_lengths[link_idx], system_charset_info); } else { - table->field[10]->set_null(); - table->field[10]->reset(); + table->field[SPIDER_TABLES_PASSWORD_POS]->set_null(); + table->field[SPIDER_TABLES_PASSWORD_POS]->reset(); } if (alter_table->tmp_tgt_ssl_cas[link_idx]) { - table->field[11]->set_notnull(); - table->field[11]->store( + table->field[SPIDER_TABLES_SSL_CA_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_CA_POS]->store( alter_table->tmp_tgt_ssl_cas[link_idx], (uint) alter_table->tmp_tgt_ssl_cas_lengths[link_idx], system_charset_info); } else { - table->field[11]->set_null(); - table->field[11]->reset(); + table->field[SPIDER_TABLES_SSL_CA_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_CA_POS]->reset(); } if (alter_table->tmp_tgt_ssl_capaths[link_idx]) { - table->field[12]->set_notnull(); - table->field[12]->store( + table->field[SPIDER_TABLES_SSL_CAPATH_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_CAPATH_POS]->store( alter_table->tmp_tgt_ssl_capaths[link_idx], (uint) alter_table->tmp_tgt_ssl_capaths_lengths[link_idx], system_charset_info); } else { - table->field[12]->set_null(); - table->field[12]->reset(); + table->field[SPIDER_TABLES_SSL_CAPATH_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_CAPATH_POS]->reset(); } if (alter_table->tmp_tgt_ssl_certs[link_idx]) { - table->field[13]->set_notnull(); - table->field[13]->store( + table->field[SPIDER_TABLES_SSL_CERT_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_CERT_POS]->store( alter_table->tmp_tgt_ssl_certs[link_idx], (uint) alter_table->tmp_tgt_ssl_certs_lengths[link_idx], system_charset_info); } else { - table->field[13]->set_null(); - table->field[13]->reset(); + table->field[SPIDER_TABLES_SSL_CERT_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_CERT_POS]->reset(); } if (alter_table->tmp_tgt_ssl_ciphers[link_idx]) { - table->field[14]->set_notnull(); - table->field[14]->store( + table->field[SPIDER_TABLES_SSL_CIPHER_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_CIPHER_POS]->store( alter_table->tmp_tgt_ssl_ciphers[link_idx], (uint) alter_table->tmp_tgt_ssl_ciphers_lengths[link_idx], system_charset_info); } else { - table->field[14]->set_null(); - table->field[14]->reset(); + table->field[SPIDER_TABLES_SSL_CIPHER_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_CIPHER_POS]->reset(); } if (alter_table->tmp_tgt_ssl_keys[link_idx]) { - table->field[15]->set_notnull(); - table->field[15]->store( + table->field[SPIDER_TABLES_SSL_KEY_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_KEY_POS]->store( alter_table->tmp_tgt_ssl_keys[link_idx], (uint) alter_table->tmp_tgt_ssl_keys_lengths[link_idx], system_charset_info); } else { - table->field[15]->set_null(); - table->field[15]->reset(); + table->field[SPIDER_TABLES_SSL_KEY_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_KEY_POS]->reset(); } if (alter_table->tmp_tgt_ssl_vscs[link_idx] >= 0) { - table->field[16]->set_notnull(); - table->field[16]->store( + table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS]->set_notnull(); + table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS]->store( alter_table->tmp_tgt_ssl_vscs[link_idx]); } else { - table->field[16]->set_null(); - table->field[16]->reset(); + table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS]->set_null(); + table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS]->reset(); } - table->field[17]->set_notnull(); + table->field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS]-> + set_notnull(); if (alter_table->tmp_monitoring_binlog_pos_at_failing[link_idx] >= 0) { - table->field[17]->store( + table->field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS]->store( alter_table->tmp_monitoring_binlog_pos_at_failing[link_idx]); } else { - table->field[17]->store(0); + table->field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS]->store(0); } if (alter_table->tmp_tgt_default_files[link_idx]) { - table->field[18]->set_notnull(); - table->field[18]->store( + table->field[SPIDER_TABLES_DEFAULT_FILE_POS]->set_notnull(); + table->field[SPIDER_TABLES_DEFAULT_FILE_POS]->store( alter_table->tmp_tgt_default_files[link_idx], (uint) alter_table->tmp_tgt_default_files_lengths[link_idx], system_charset_info); } else { - table->field[18]->set_null(); - table->field[18]->reset(); + table->field[SPIDER_TABLES_DEFAULT_FILE_POS]->set_null(); + table->field[SPIDER_TABLES_DEFAULT_FILE_POS]->reset(); } if (alter_table->tmp_tgt_default_groups[link_idx]) { - table->field[19]->set_notnull(); - table->field[19]->store( + table->field[SPIDER_TABLES_DEFAULT_GROUP_POS]->set_notnull(); + table->field[SPIDER_TABLES_DEFAULT_GROUP_POS]->store( alter_table->tmp_tgt_default_groups[link_idx], (uint) alter_table->tmp_tgt_default_groups_lengths[link_idx], system_charset_info); } else { - table->field[19]->set_null(); - table->field[19]->reset(); + table->field[SPIDER_TABLES_DEFAULT_GROUP_POS]->set_null(); + table->field[SPIDER_TABLES_DEFAULT_GROUP_POS]->reset(); + } + if (alter_table->tmp_tgt_dsns[link_idx]) + { + table->field[SPIDER_TABLES_DSN_POS]->set_notnull(); + table->field[SPIDER_TABLES_DSN_POS]->store( + alter_table->tmp_tgt_dsns[link_idx], + (uint) alter_table->tmp_tgt_dsns_lengths[link_idx], + system_charset_info); + } else { + table->field[SPIDER_TABLES_DSN_POS]->set_null(); + table->field[SPIDER_TABLES_DSN_POS]->reset(); } if (alter_table->tmp_tgt_dbs[link_idx]) { - table->field[20]->set_notnull(); - table->field[20]->store( + table->field[SPIDER_TABLES_TGT_DB_NAME_POS]->set_notnull(); + table->field[SPIDER_TABLES_TGT_DB_NAME_POS]->store( alter_table->tmp_tgt_dbs[link_idx], (uint) alter_table->tmp_tgt_dbs_lengths[link_idx], system_charset_info); } else { - table->field[20]->set_null(); - table->field[20]->reset(); + table->field[SPIDER_TABLES_TGT_DB_NAME_POS]->set_null(); + table->field[SPIDER_TABLES_TGT_DB_NAME_POS]->reset(); } if (alter_table->tmp_tgt_table_names[link_idx]) { - table->field[21]->set_notnull(); - table->field[21]->store( + table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS]->set_notnull(); + table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS]->store( alter_table->tmp_tgt_table_names[link_idx], (uint) alter_table->tmp_tgt_table_names_lengths[link_idx], system_charset_info); } else { - table->field[21]->set_null(); - table->field[21]->reset(); + table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS]->set_null(); + table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS]->reset(); } - table->field[23]->store((longlong) 0, FALSE); + table->field[SPIDER_TABLES_BLOCK_STATUS_POS]->store((longlong) 0, FALSE); if (alter_table->tmp_static_link_ids[link_idx]) { DBUG_PRINT("info",("spider static_link_id[%d] = %s", link_idx, alter_table->tmp_static_link_ids[link_idx])); - table->field[24]->set_notnull(); - table->field[24]->store( + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->set_notnull(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->store( alter_table->tmp_static_link_ids[link_idx], (uint) alter_table->tmp_static_link_ids_lengths[link_idx], system_charset_info); } else { DBUG_PRINT("info",("spider static_link_id[%d] = NULL", link_idx)); - table->field[24]->set_null(); - table->field[24]->reset(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->set_null(); + table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->reset(); } DBUG_VOID_RETURN; } @@ -1331,17 +1467,7 @@ void spider_store_tables_link_status( DBUG_ENTER("spider_store_tables_link_status"); DBUG_PRINT("info",("spider link_status = %ld", link_status)); if (link_status > SPIDER_LINK_STATUS_NO_CHANGE) - table->field[22]->store(link_status, FALSE); - DBUG_VOID_RETURN; -} - -void spider_store_link_chk_server_id( - TABLE *table, - uint32 server_id -) { - DBUG_ENTER("spider_store_link_chk_server_id"); - table->field[3]->set_notnull(); - table->field[3]->store(server_id); + table->field[SPIDER_TABLES_LINK_STATUS_POS]->store(link_status, FALSE); DBUG_VOID_RETURN; } @@ -1350,8 +1476,10 @@ void spider_store_binlog_pos_failed_link_idx( int failed_link_idx ) { DBUG_ENTER("spider_store_binlog_pos_failed_link_idx"); - table->field[2]->set_notnull(); - table->field[2]->store(failed_link_idx); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FAILED_LINK_ID_POS]-> + set_notnull(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FAILED_LINK_ID_POS]-> + store(failed_link_idx); DBUG_VOID_RETURN; } @@ -1360,8 +1488,10 @@ void spider_store_binlog_pos_source_link_idx( int source_link_idx ) { DBUG_ENTER("spider_store_binlog_pos_source_link_idx"); - table->field[3]->set_notnull(); - table->field[3]->store(source_link_idx); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_SOURCE_LINK_ID_POS]-> + set_notnull(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_SOURCE_LINK_ID_POS]-> + store(source_link_idx); DBUG_VOID_RETURN; } @@ -1377,22 +1507,25 @@ void spider_store_binlog_pos_binlog_file( if (!file_name) { DBUG_PRINT("info",("spider file_name is NULL")); - table->field[4]->set_null(); - table->field[4]->reset(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FILE_POS]->set_null(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FILE_POS]->reset(); } else { DBUG_PRINT("info",("spider file_name = %s", file_name)); - table->field[4]->set_notnull(); - table->field[4]->store(file_name, file_name_length, binlog_pos_cs); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FILE_POS]->set_notnull(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_FILE_POS]->store( + file_name, file_name_length, binlog_pos_cs); } if (!position) { DBUG_PRINT("info",("spider position is NULL")); - table->field[5]->set_null(); - table->field[5]->reset(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_POSITION_POS]->set_null(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_POSITION_POS]->reset(); } else { DBUG_PRINT("info",("spider position = %s", position)); - table->field[5]->set_notnull(); - table->field[5]->store(position, position_length, binlog_pos_cs); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_POSITION_POS]-> + set_notnull(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_POSITION_POS]->store( + position, position_length, binlog_pos_cs); } DBUG_VOID_RETURN; } @@ -1407,12 +1540,13 @@ void spider_store_binlog_pos_gtid( if (!gtid) { DBUG_PRINT("info",("spider gtid is NULL")); - table->field[6]->set_null(); - table->field[6]->reset(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_GTID_POS]->set_null(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_GTID_POS]->reset(); } else { DBUG_PRINT("info",("spider gtid = %s", gtid)); - table->field[6]->set_notnull(); - table->field[6]->store(gtid, gtid_length, binlog_pos_cs); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_GTID_POS]->set_notnull(); + table->field[SPIDER_TABLE_POSITION_FOR_RECOVERY_GTID_POS]->store( + gtid, gtid_length, binlog_pos_cs); } DBUG_VOID_RETURN; } @@ -1423,24 +1557,30 @@ void spider_store_table_sts_info( ) { MYSQL_TIME mysql_time; DBUG_ENTER("spider_store_table_sts_info"); - table->field[2]->store((longlong) stat->data_file_length, TRUE); - table->field[3]->store((longlong) stat->max_data_file_length, TRUE); - table->field[4]->store((longlong) stat->index_file_length, TRUE); - table->field[5]->store((longlong) stat->records, TRUE); - table->field[6]->store((longlong) stat->mean_rec_length, TRUE); + table->field[SPIDER_TABLE_STS_DATA_FILE_LENGTH_POS]->store( + (longlong) stat->data_file_length, TRUE); + table->field[SPIDER_TABLE_STS_MAX_DATA_FILE_LENGTH_POS]->store( + (longlong) stat->max_data_file_length, TRUE); + table->field[SPIDER_TABLE_STS_INDEX_FILE_LENGTH_POS]->store( + (longlong) stat->index_file_length, TRUE); + table->field[SPIDER_TABLE_STS_RECORDS_POS]->store( + (longlong) stat->records, TRUE); + table->field[SPIDER_TABLE_STS_MEAN_REC_LENGTH_POS]->store( + (longlong) stat->mean_rec_length, TRUE); spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->check_time); - table->field[7]->store_time(&mysql_time); + table->field[SPIDER_TABLE_STS_CHECK_TIME_POS]->store_time(&mysql_time); spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->create_time); - table->field[8]->store_time(&mysql_time); + table->field[SPIDER_TABLE_STS_CREATE_TIME_POS]->store_time(&mysql_time); spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->update_time); - table->field[9]->store_time(&mysql_time); + table->field[SPIDER_TABLE_STS_UPDATE_TIME_POS]->store_time(&mysql_time); if (stat->checksum_null) { - table->field[10]->set_null(); - table->field[10]->reset(); + table->field[SPIDER_TABLE_STS_CHECKSUM_POS]->set_null(); + table->field[SPIDER_TABLE_STS_CHECKSUM_POS]->reset(); } else { - table->field[10]->set_notnull(); - table->field[10]->store((longlong) stat->checksum, TRUE); + table->field[SPIDER_TABLE_STS_CHECKSUM_POS]->set_notnull(); + table->field[SPIDER_TABLE_STS_CHECKSUM_POS]->store( + (longlong) stat->checksum, TRUE); } DBUG_VOID_RETURN; } @@ -1451,8 +1591,9 @@ void spider_store_table_crd_info( longlong *cardinality ) { DBUG_ENTER("spider_store_table_crd_info"); - table->field[2]->store((longlong) *seq, TRUE); - table->field[3]->store((longlong) *cardinality, FALSE); + table->field[SPIDER_TABLE_CRD_KEY_SEQ_POS]->store((longlong) *seq, TRUE); + table->field[SPIDER_TABLE_CRD_CARDINALITY_POS]->store( + (longlong) *cardinality, FALSE); DBUG_VOID_RETURN; } @@ -1652,7 +1793,8 @@ int spider_log_tables_link_failed( spider_store_tables_link_idx(table, link_idx); #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000 #else - if (table->field[3] == table->timestamp_field) + if (table->field[SPIDER_LINK_FAILED_LOG_FAILED_TIME_POS] == + table->timestamp_field) table->timestamp_field->set_time(); #endif if ((error_num = spider_write_sys_table_row(table))) @@ -1676,20 +1818,22 @@ int spider_log_xa_failed( spider_store_xa_member_info(table, xid, conn); if (thd) { - table->field[18]->set_notnull(); - table->field[18]->store(thd->thread_id, TRUE); + table->field[SPIDER_XA_FAILED_LOG_THREAD_ID_POS]->set_notnull(); + table->field[SPIDER_XA_FAILED_LOG_THREAD_ID_POS]->store( + thd->thread_id, TRUE); } else { - table->field[18]->set_null(); - table->field[18]->reset(); + table->field[SPIDER_XA_FAILED_LOG_THREAD_ID_POS]->set_null(); + table->field[SPIDER_XA_FAILED_LOG_THREAD_ID_POS]->reset(); } - table->field[19]->store( + table->field[SPIDER_XA_FAILED_LOG_STATUS_POS]->store( status, (uint) strlen(status), system_charset_info); #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000 #else - if (table->field[20] == table->timestamp_field) + if (table->field[SPIDER_XA_FAILED_LOG_FAILED_TIME_POS] == + table->timestamp_field) table->timestamp_field->set_time(); #endif if ((error_num = spider_write_sys_table_row(table))) @@ -2079,25 +2223,25 @@ int spider_get_sys_xid( ) { char *ptr; DBUG_ENTER("spider_get_sys_xid"); - ptr = get_field(mem_root, table->field[0]); + ptr = get_field(mem_root, table->field[SPIDER_XA_FORMAT_ID_POS]); if (ptr) { xid->formatID = atoi(ptr); } else xid->formatID = 0; - ptr = get_field(mem_root, table->field[1]); + ptr = get_field(mem_root, table->field[SPIDER_XA_GTRID_LENGTH_POS]); if (ptr) { xid->gtrid_length = atoi(ptr); } else xid->gtrid_length = 0; - ptr = get_field(mem_root, table->field[2]); + ptr = get_field(mem_root, table->field[SPIDER_XA_BQUAL_LENGTH_POS]); if (ptr) { xid->bqual_length = atoi(ptr); } else xid->bqual_length = 0; - ptr = get_field(mem_root, table->field[3]); + ptr = get_field(mem_root, table->field[SPIDER_XA_DATA_POS]); if (ptr) { strmov(xid->data, ptr); @@ -2113,7 +2257,7 @@ int spider_get_sys_server_info( ) { char *ptr; DBUG_ENTER("spider_get_sys_server_info"); - if ((ptr = get_field(mem_root, table->field[4]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SCHEME_POS]))) { share->tgt_wrappers_lengths[link_idx] = strlen(ptr); share->tgt_wrappers[link_idx] = spider_create_string(ptr, @@ -2122,7 +2266,7 @@ int spider_get_sys_server_info( share->tgt_wrappers_lengths[link_idx] = 0; share->tgt_wrappers[link_idx] = NULL; } - if ((ptr = get_field(mem_root, table->field[5]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_HOST_POS]))) { share->tgt_hosts_lengths[link_idx] = strlen(ptr); share->tgt_hosts[link_idx] = spider_create_string(ptr, @@ -2131,12 +2275,12 @@ int spider_get_sys_server_info( share->tgt_hosts_lengths[link_idx] = 0; share->tgt_hosts[link_idx] = NULL; } - if ((ptr = get_field(mem_root, table->field[6]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_PORT_POS]))) { share->tgt_ports[link_idx] = atol(ptr); } else share->tgt_ports[link_idx] = MYSQL_PORT; - if ((ptr = get_field(mem_root, table->field[7]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SOCKET_POS]))) { share->tgt_sockets_lengths[link_idx] = strlen(ptr); share->tgt_sockets[link_idx] = spider_create_string(ptr, @@ -2145,7 +2289,7 @@ int spider_get_sys_server_info( share->tgt_sockets_lengths[link_idx] = 0; share->tgt_sockets[link_idx] = NULL; } - if ((ptr = get_field(mem_root, table->field[8]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_USERNAME_POS]))) { share->tgt_usernames_lengths[link_idx] = strlen(ptr); share->tgt_usernames[link_idx] = @@ -2154,7 +2298,7 @@ int spider_get_sys_server_info( share->tgt_usernames_lengths[link_idx] = 0; share->tgt_usernames[link_idx] = NULL; } - if ((ptr = get_field(mem_root, table->field[9]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_PASSWORD_POS]))) { share->tgt_passwords_lengths[link_idx] = strlen(ptr); share->tgt_passwords[link_idx] = @@ -2164,8 +2308,8 @@ int spider_get_sys_server_info( share->tgt_passwords[link_idx] = NULL; } if ( - !table->field[10]->is_null() && - (ptr = get_field(mem_root, table->field[10])) + !table->field[SPIDER_XA_MEMBER_SSL_CA_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SSL_CA_POS])) ) { share->tgt_ssl_cas_lengths[link_idx] = strlen(ptr); share->tgt_ssl_cas[link_idx] = @@ -2175,8 +2319,8 @@ int spider_get_sys_server_info( share->tgt_ssl_cas[link_idx] = NULL; } if ( - !table->field[11]->is_null() && - (ptr = get_field(mem_root, table->field[11])) + !table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SSL_CAPATH_POS])) ) { share->tgt_ssl_capaths_lengths[link_idx] = strlen(ptr); share->tgt_ssl_capaths[link_idx] = @@ -2186,8 +2330,8 @@ int spider_get_sys_server_info( share->tgt_ssl_capaths[link_idx] = NULL; } if ( - !table->field[12]->is_null() && - (ptr = get_field(mem_root, table->field[12])) + !table->field[SPIDER_XA_MEMBER_SSL_CERT_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SSL_CERT_POS])) ) { share->tgt_ssl_certs_lengths[link_idx] = strlen(ptr); share->tgt_ssl_certs[link_idx] = @@ -2197,8 +2341,8 @@ int spider_get_sys_server_info( share->tgt_ssl_certs[link_idx] = NULL; } if ( - !table->field[13]->is_null() && - (ptr = get_field(mem_root, table->field[13])) + !table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SSL_CIPHER_POS])) ) { share->tgt_ssl_ciphers_lengths[link_idx] = strlen(ptr); share->tgt_ssl_ciphers[link_idx] = @@ -2208,8 +2352,8 @@ int spider_get_sys_server_info( share->tgt_ssl_ciphers[link_idx] = NULL; } if ( - !table->field[14]->is_null() && - (ptr = get_field(mem_root, table->field[14])) + !table->field[SPIDER_XA_MEMBER_SSL_KEY_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_SSL_KEY_POS])) ) { share->tgt_ssl_keys_lengths[link_idx] = strlen(ptr); share->tgt_ssl_keys[link_idx] = @@ -2219,15 +2363,17 @@ int spider_get_sys_server_info( share->tgt_ssl_keys[link_idx] = NULL; } if ( - !table->field[15]->is_null() && - (ptr = get_field(mem_root, table->field[15])) + !table->field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS]->is_null() && + (ptr = get_field(mem_root, table-> + field[SPIDER_XA_MEMBER_SSL_VERIFY_SERVER_CERT_POS])) ) { share->tgt_ssl_vscs[link_idx] = atol(ptr); } else share->tgt_ssl_vscs[link_idx] = 0; if ( - !table->field[16]->is_null() && - (ptr = get_field(mem_root, table->field[16])) + !table->field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS]->is_null() && + (ptr = get_field(mem_root, table-> + field[SPIDER_XA_MEMBER_DEFAULT_FILE_POS])) ) { share->tgt_default_files_lengths[link_idx] = strlen(ptr); share->tgt_default_files[link_idx] = @@ -2237,8 +2383,9 @@ int spider_get_sys_server_info( share->tgt_default_files[link_idx] = NULL; } if ( - !table->field[17]->is_null() && - (ptr = get_field(mem_root, table->field[17])) + !table->field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS]->is_null() && + (ptr = get_field(mem_root, table-> + field[SPIDER_XA_MEMBER_DEFAULT_GROUP_POS])) ) { share->tgt_default_groups_lengths[link_idx] = strlen(ptr); share->tgt_default_groups[link_idx] = @@ -2247,6 +2394,17 @@ int spider_get_sys_server_info( share->tgt_default_groups_lengths[link_idx] = 0; share->tgt_default_groups[link_idx] = NULL; } + if ( + !table->field[SPIDER_XA_MEMBER_DSN_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_XA_MEMBER_DSN_POS])) + ) { + share->tgt_dsns_lengths[link_idx] = strlen(ptr); + share->tgt_dsns[link_idx] = + spider_create_string(ptr, share->tgt_dsns_lengths[link_idx]); + } else { + share->tgt_dsns_lengths[link_idx] = 0; + share->tgt_dsns[link_idx] = NULL; + } DBUG_RETURN(0); } @@ -2261,7 +2419,7 @@ int spider_check_sys_xa_status( char *ptr; int error_num; DBUG_ENTER("spider_check_sys_xa_status"); - ptr = get_field(mem_root, table->field[4]); + ptr = get_field(mem_root, table->field[SPIDER_XA_STATUS_POS]); if (ptr) { if ( @@ -2285,13 +2443,13 @@ int spider_get_sys_tables( ) { char *ptr; DBUG_ENTER("spider_get_sys_tables"); - if ((ptr = get_field(mem_root, table->field[0]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_DB_NAME_POS]))) { *db_name = spider_create_string(ptr, strlen(ptr)); } else { *db_name = NULL; } - if ((ptr = get_field(mem_root, table->field[1]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_TABLE_NAME_POS]))) { *table_name = spider_create_string(ptr, strlen(ptr)); } else { @@ -2309,55 +2467,67 @@ int spider_get_sys_tables_connect_info( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_tables_connect_info"); - if ((ptr = get_field(mem_root, table->field[3]))) + DBUG_PRINT("info",("spider link_idx:%d", link_idx)); + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_PRIORITY_POS]))) { share->priority = my_strtoll10(ptr, (char**) NULL, &error_num); } else share->priority = 1000000; + DBUG_PRINT("info",("spider priority:%lld", share->priority)); if ( - !table->field[4]->is_null() && - (ptr = get_field(mem_root, table->field[4])) + !table->field[SPIDER_TABLES_SERVER_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SERVER_POS])) ) { share->server_names_lengths[link_idx] = strlen(ptr); share->server_names[link_idx] = spider_create_string(ptr, share->server_names_lengths[link_idx]); + DBUG_PRINT("info",("spider server_name:%s", + share->server_names[link_idx])); } else { share->server_names_lengths[link_idx] = 0; share->server_names[link_idx] = NULL; + DBUG_PRINT("info",("spider server_name is NULL")); } if ( - !table->field[5]->is_null() && - (ptr = get_field(mem_root, table->field[5])) + !table->field[SPIDER_TABLES_SCHEME_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SCHEME_POS])) ) { share->tgt_wrappers_lengths[link_idx] = strlen(ptr); share->tgt_wrappers[link_idx] = spider_create_string(ptr, share->tgt_wrappers_lengths[link_idx]); + DBUG_PRINT("info",("spider tgt_wrapper:%s", + share->tgt_wrappers[link_idx])); } else { share->tgt_wrappers_lengths[link_idx] = 0; share->tgt_wrappers[link_idx] = NULL; + DBUG_PRINT("info",("spider tgt_wrapper is NULL")); } if ( - !table->field[6]->is_null() && - (ptr = get_field(mem_root, table->field[6])) + !table->field[SPIDER_TABLES_HOST_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_HOST_POS])) ) { share->tgt_hosts_lengths[link_idx] = strlen(ptr); share->tgt_hosts[link_idx] = spider_create_string(ptr, share->tgt_hosts_lengths[link_idx]); + DBUG_PRINT("info",("spider tgt_host:%s", + share->tgt_hosts[link_idx])); } else { share->tgt_hosts_lengths[link_idx] = 0; share->tgt_hosts[link_idx] = NULL; + DBUG_PRINT("info",("spider tgt_host is NULL")); } if ( - !table->field[7]->is_null() && - (ptr = get_field(mem_root, table->field[7])) + !table->field[SPIDER_TABLES_PORT_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_PORT_POS])) ) { share->tgt_ports[link_idx] = atol(ptr); } else { share->tgt_ports[link_idx] = -1; } + DBUG_PRINT("info",("spider port:%ld", share->tgt_ports[link_idx])); if ( - !table->field[8]->is_null() && - (ptr = get_field(mem_root, table->field[8])) + !table->field[SPIDER_TABLES_SOCKET_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SOCKET_POS])) ) { share->tgt_sockets_lengths[link_idx] = strlen(ptr); share->tgt_sockets[link_idx] = @@ -2367,8 +2537,8 @@ int spider_get_sys_tables_connect_info( share->tgt_sockets[link_idx] = NULL; } if ( - !table->field[9]->is_null() && - (ptr = get_field(mem_root, table->field[9])) + !table->field[SPIDER_TABLES_USERNAME_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_USERNAME_POS])) ) { share->tgt_usernames_lengths[link_idx] = strlen(ptr); share->tgt_usernames[link_idx] = @@ -2378,8 +2548,8 @@ int spider_get_sys_tables_connect_info( share->tgt_usernames[link_idx] = NULL; } if ( - !table->field[10]->is_null() && - (ptr = get_field(mem_root, table->field[10])) + !table->field[SPIDER_TABLES_PASSWORD_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_PASSWORD_POS])) ) { share->tgt_passwords_lengths[link_idx] = strlen(ptr); share->tgt_passwords[link_idx] = @@ -2389,8 +2559,8 @@ int spider_get_sys_tables_connect_info( share->tgt_passwords[link_idx] = NULL; } if ( - !table->field[11]->is_null() && - (ptr = get_field(mem_root, table->field[11])) + !table->field[SPIDER_TABLES_SSL_CA_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SSL_CA_POS])) ) { share->tgt_ssl_cas_lengths[link_idx] = strlen(ptr); share->tgt_ssl_cas[link_idx] = @@ -2400,8 +2570,8 @@ int spider_get_sys_tables_connect_info( share->tgt_ssl_cas[link_idx] = NULL; } if ( - !table->field[12]->is_null() && - (ptr = get_field(mem_root, table->field[12])) + !table->field[SPIDER_TABLES_SSL_CAPATH_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SSL_CAPATH_POS])) ) { share->tgt_ssl_capaths_lengths[link_idx] = strlen(ptr); share->tgt_ssl_capaths[link_idx] = @@ -2411,8 +2581,8 @@ int spider_get_sys_tables_connect_info( share->tgt_ssl_capaths[link_idx] = NULL; } if ( - !table->field[13]->is_null() && - (ptr = get_field(mem_root, table->field[13])) + !table->field[SPIDER_TABLES_SSL_CERT_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SSL_CERT_POS])) ) { share->tgt_ssl_certs_lengths[link_idx] = strlen(ptr); share->tgt_ssl_certs[link_idx] = @@ -2422,8 +2592,8 @@ int spider_get_sys_tables_connect_info( share->tgt_ssl_certs[link_idx] = NULL; } if ( - !table->field[14]->is_null() && - (ptr = get_field(mem_root, table->field[14])) + !table->field[SPIDER_TABLES_SSL_CIPHER_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SSL_CIPHER_POS])) ) { share->tgt_ssl_ciphers_lengths[link_idx] = strlen(ptr); share->tgt_ssl_ciphers[link_idx] = @@ -2433,8 +2603,8 @@ int spider_get_sys_tables_connect_info( share->tgt_ssl_ciphers[link_idx] = NULL; } if ( - !table->field[15]->is_null() && - (ptr = get_field(mem_root, table->field[15])) + !table->field[SPIDER_TABLES_SSL_KEY_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_SSL_KEY_POS])) ) { share->tgt_ssl_keys_lengths[link_idx] = strlen(ptr); share->tgt_ssl_keys[link_idx] = @@ -2444,22 +2614,25 @@ int spider_get_sys_tables_connect_info( share->tgt_ssl_keys[link_idx] = NULL; } if ( - !table->field[16]->is_null() && - (ptr = get_field(mem_root, table->field[16])) + !table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_TABLES_SSL_VERIFY_SERVER_CERT_POS])) ) { share->tgt_ssl_vscs[link_idx] = atol(ptr); } else share->tgt_ssl_vscs[link_idx] = -1; if ( - !table->field[17]->is_null() && - (ptr = get_field(mem_root, table->field[17])) + !table->field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS]-> + is_null() && + (ptr = get_field(mem_root, table-> + field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS])) ) { share->monitoring_binlog_pos_at_failing[link_idx] = atol(ptr); } else share->monitoring_binlog_pos_at_failing[link_idx] = 0; if ( - !table->field[18]->is_null() && - (ptr = get_field(mem_root, table->field[18])) + !table->field[SPIDER_TABLES_DEFAULT_FILE_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_DEFAULT_FILE_POS])) ) { share->tgt_default_files_lengths[link_idx] = strlen(ptr); share->tgt_default_files[link_idx] = @@ -2469,8 +2642,8 @@ int spider_get_sys_tables_connect_info( share->tgt_default_files[link_idx] = NULL; } if ( - !table->field[19]->is_null() && - (ptr = get_field(mem_root, table->field[19])) + !table->field[SPIDER_TABLES_DEFAULT_GROUP_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_DEFAULT_GROUP_POS])) ) { share->tgt_default_groups_lengths[link_idx] = strlen(ptr); share->tgt_default_groups[link_idx] = @@ -2480,8 +2653,19 @@ int spider_get_sys_tables_connect_info( share->tgt_default_groups[link_idx] = NULL; } if ( - !table->field[20]->is_null() && - (ptr = get_field(mem_root, table->field[20])) + !table->field[SPIDER_TABLES_DSN_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_DSN_POS])) + ) { + share->tgt_dsns_lengths[link_idx] = strlen(ptr); + share->tgt_dsns[link_idx] = + spider_create_string(ptr, share->tgt_dsns_lengths[link_idx]); + } else { + share->tgt_dsns_lengths[link_idx] = 0; + share->tgt_dsns[link_idx] = NULL; + } + if ( + !table->field[SPIDER_TABLES_TGT_DB_NAME_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_TGT_DB_NAME_POS])) ) { share->tgt_dbs_lengths[link_idx] = strlen(ptr); share->tgt_dbs[link_idx] = @@ -2491,8 +2675,8 @@ int spider_get_sys_tables_connect_info( share->tgt_dbs[link_idx] = NULL; } if ( - !table->field[21]->is_null() && - (ptr = get_field(mem_root, table->field[21])) + !table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_TGT_TABLE_NAME_POS])) ) { share->tgt_table_names_lengths[link_idx] = strlen(ptr); share->tgt_table_names[link_idx] = @@ -2502,8 +2686,8 @@ int spider_get_sys_tables_connect_info( share->tgt_table_names[link_idx] = NULL; } if ( - !table->field[24]->is_null() && - (ptr = get_field(mem_root, table->field[24])) + !table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_TABLES_STATIC_LINK_ID_POS])) ) { share->static_link_ids_lengths[link_idx] = strlen(ptr); share->static_link_ids[link_idx] = @@ -2523,7 +2707,8 @@ int spider_get_sys_tables_monitoring_binlog_pos_at_failing( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_tables_monitoring_binlog_pos_at_failing"); - if ((ptr = get_field(mem_root, table->field[17]))) + if ((ptr = get_field(mem_root, table-> + field[SPIDER_TABLES_MONITORING_BINLOG_POS_AT_FAILING_POS]))) *monitoring_binlog_pos_at_failing = (long) my_strtoll10(ptr, (char**) NULL, &error_num); else @@ -2542,7 +2727,7 @@ int spider_get_sys_tables_link_status( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_tables_link_status"); - if ((ptr = get_field(mem_root, table->field[22]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_LINK_STATUS_POS]))) { share->link_statuses[link_idx] = (long) my_strtoll10(ptr, (char**) NULL, &error_num); @@ -2561,7 +2746,7 @@ int spider_get_sys_tables_link_status( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_tables_link_status"); - if ((ptr = get_field(mem_root, table->field[22]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_LINK_STATUS_POS]))) *link_status = (long) my_strtoll10(ptr, (char**) NULL, &error_num); else *link_status = 1; @@ -2577,7 +2762,7 @@ int spider_get_sys_tables_link_idx( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_tables_link_idx"); - if ((ptr = get_field(mem_root, table->field[2]))) + if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_LINK_ID_POS]))) *link_idx = (int) my_strtoll10(ptr, (char**) NULL, &error_num); else *link_idx = 1; @@ -2595,8 +2780,9 @@ int spider_get_sys_tables_static_link_id( DBUG_ENTER("spider_get_sys_tables_static_link_id"); *static_link_id = NULL; if ( - !table->field[24]->is_null() && - (*static_link_id = get_field(mem_root, table->field[24])) + !table->field[SPIDER_TABLES_STATIC_LINK_ID_POS]->is_null() && + (*static_link_id = get_field(mem_root, table-> + field[SPIDER_TABLES_STATIC_LINK_ID_POS])) ) { *static_link_id_length = strlen(*static_link_id); } else { @@ -2618,12 +2804,18 @@ void spider_get_sys_table_sts_info( #endif long not_used_long; DBUG_ENTER("spider_get_sys_table_sts_info"); - stat->data_file_length = (ulonglong) table->field[2]->val_int(); - stat->max_data_file_length = (ulonglong) table->field[3]->val_int(); - stat->index_file_length = (ulonglong) table->field[4]->val_int(); - stat->records = (ha_rows) table->field[5]->val_int(); - stat->mean_rec_length = (ulong) table->field[6]->val_int(); - table->field[7]->get_date(&mysql_time, SPIDER_date_mode_t(0)); + stat->data_file_length = (ulonglong) table-> + field[SPIDER_TABLE_STS_DATA_FILE_LENGTH_POS]->val_int(); + stat->max_data_file_length = (ulonglong) table-> + field[SPIDER_TABLE_STS_MAX_DATA_FILE_LENGTH_POS]->val_int(); + stat->index_file_length = (ulonglong) table-> + field[SPIDER_TABLE_STS_INDEX_FILE_LENGTH_POS]->val_int(); + stat->records = (ha_rows) table-> + field[SPIDER_TABLE_STS_RECORDS_POS]->val_int(); + stat->mean_rec_length = (ulong) table-> + field[SPIDER_TABLE_STS_MEAN_REC_LENGTH_POS]->val_int(); + table->field[SPIDER_TABLE_STS_CHECK_TIME_POS]->get_date(&mysql_time, + SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION stat->check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2631,7 +2823,8 @@ void spider_get_sys_table_sts_info( stat->check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[8]->get_date(&mysql_time, SPIDER_date_mode_t(0)); + table->field[SPIDER_TABLE_STS_CREATE_TIME_POS]->get_date(&mysql_time, + SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION stat->create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2639,7 +2832,8 @@ void spider_get_sys_table_sts_info( stat->create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[9]->get_date(&mysql_time, SPIDER_date_mode_t(0)); + table->field[SPIDER_TABLE_STS_UPDATE_TIME_POS]->get_date(&mysql_time, + SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION stat->update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2647,13 +2841,14 @@ void spider_get_sys_table_sts_info( stat->update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - if (table->field[10]->is_null()) + if (table->field[SPIDER_TABLE_STS_CHECKSUM_POS]->is_null()) { stat->checksum_null = TRUE; stat->checksum = 0; } else { stat->checksum_null = FALSE; - stat->checksum = (ha_checksum) table->field[10]->val_int(); + stat->checksum = (ha_checksum) table-> + field[SPIDER_TABLE_STS_CHECKSUM_POS]->val_int(); } DBUG_VOID_RETURN; } @@ -2665,10 +2860,11 @@ void spider_get_sys_table_crd_info( ) { uint seq; DBUG_ENTER("spider_get_sys_table_crd_info"); - seq = (uint) table->field[2]->val_int(); + seq = (uint) table->field[SPIDER_TABLE_CRD_KEY_SEQ_POS]->val_int(); if (seq < number_of_keys) { - cardinality[seq] = (longlong) table->field[3]->val_int(); + cardinality[seq] = (longlong) table-> + field[SPIDER_TABLE_CRD_CARDINALITY_POS]->val_int(); } DBUG_VOID_RETURN; } @@ -2797,9 +2993,9 @@ int spider_get_sys_link_mon_key( uint db_name_length, table_name_length, link_id_length; DBUG_ENTER("spider_get_sys_link_mon_key"); if ( - table->field[0]->is_null() || - table->field[1]->is_null() || - table->field[2]->is_null() + table->field[SPIDER_LINK_MON_SERVERS_DB_NAME_POS]->is_null() || + table->field[SPIDER_LINK_MON_SERVERS_TABLE_NAME_POS]->is_null() || + table->field[SPIDER_LINK_MON_SERVERS_LINK_ID_POS]->is_null() ) { my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), @@ -2808,9 +3004,12 @@ int spider_get_sys_link_mon_key( } if ( - !(db_name = get_field(mem_root, table->field[0])) || - !(table_name = get_field(mem_root, table->field[1])) || - !(link_id = get_field(mem_root, table->field[2])) + !(db_name = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_DB_NAME_POS])) || + !(table_name = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_TABLE_NAME_POS])) || + !(link_id = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_LINK_ID_POS])) ) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -2860,7 +3059,8 @@ int spider_get_sys_link_mon_server_id( char *ptr; int error_num = 0; DBUG_ENTER("spider_get_sys_link_mon_server_id"); - if ((ptr = get_field(mem_root, table->field[3]))) + if ((ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SID_POS]))) *server_id = (uint32) my_strtoll10(ptr, (char**) NULL, &error_num); else *server_id = ~(uint32) 0; @@ -2877,8 +3077,9 @@ int spider_get_sys_link_mon_connect_info( int error_num = 0; DBUG_ENTER("spider_get_sys_link_mon_connect_info"); if ( - !table->field[4]->is_null() && - (ptr = get_field(mem_root, table->field[4])) + !table->field[SPIDER_LINK_MON_SERVERS_SERVER_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SERVER_POS])) ) { share->server_names_lengths[link_idx] = strlen(ptr); share->server_names[link_idx] = @@ -2888,8 +3089,9 @@ int spider_get_sys_link_mon_connect_info( share->server_names[link_idx] = NULL; } if ( - !table->field[5]->is_null() && - (ptr = get_field(mem_root, table->field[5])) + !table->field[SPIDER_LINK_MON_SERVERS_SCHEME_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SCHEME_POS])) ) { share->tgt_wrappers_lengths[link_idx] = strlen(ptr); share->tgt_wrappers[link_idx] = @@ -2899,8 +3101,8 @@ int spider_get_sys_link_mon_connect_info( share->tgt_wrappers[link_idx] = NULL; } if ( - !table->field[6]->is_null() && - (ptr = get_field(mem_root, table->field[6])) + !table->field[SPIDER_LINK_MON_SERVERS_HOST_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_LINK_MON_SERVERS_HOST_POS])) ) { share->tgt_hosts_lengths[link_idx] = strlen(ptr); share->tgt_hosts[link_idx] = @@ -2910,16 +3112,17 @@ int spider_get_sys_link_mon_connect_info( share->tgt_hosts[link_idx] = NULL; } if ( - !table->field[7]->is_null() && - (ptr = get_field(mem_root, table->field[7])) + !table->field[SPIDER_LINK_MON_SERVERS_PORT_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_LINK_MON_SERVERS_PORT_POS])) ) { share->tgt_ports[link_idx] = atol(ptr); } else { share->tgt_ports[link_idx] = -1; } if ( - !table->field[8]->is_null() && - (ptr = get_field(mem_root, table->field[8])) + !table->field[SPIDER_LINK_MON_SERVERS_SOCKET_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SOCKET_POS])) ) { share->tgt_sockets_lengths[link_idx] = strlen(ptr); share->tgt_sockets[link_idx] = @@ -2929,8 +3132,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_sockets[link_idx] = NULL; } if ( - !table->field[9]->is_null() && - (ptr = get_field(mem_root, table->field[9])) + !table->field[SPIDER_LINK_MON_SERVERS_USERNAME_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_USERNAME_POS])) ) { share->tgt_usernames_lengths[link_idx] = strlen(ptr); share->tgt_usernames[link_idx] = @@ -2940,8 +3144,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_usernames[link_idx] = NULL; } if ( - !table->field[10]->is_null() && - (ptr = get_field(mem_root, table->field[10])) + !table->field[SPIDER_LINK_MON_SERVERS_PASSWORD_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_PASSWORD_POS])) ) { share->tgt_passwords_lengths[link_idx] = strlen(ptr); share->tgt_passwords[link_idx] = @@ -2951,8 +3156,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_passwords[link_idx] = NULL; } if ( - !table->field[11]->is_null() && - (ptr = get_field(mem_root, table->field[11])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_CA_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_CA_POS])) ) { share->tgt_ssl_cas_lengths[link_idx] = strlen(ptr); share->tgt_ssl_cas[link_idx] = @@ -2962,8 +3168,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_ssl_cas[link_idx] = NULL; } if ( - !table->field[12]->is_null() && - (ptr = get_field(mem_root, table->field[12])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_CAPATH_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_CAPATH_POS])) ) { share->tgt_ssl_capaths_lengths[link_idx] = strlen(ptr); share->tgt_ssl_capaths[link_idx] = @@ -2973,8 +3180,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_ssl_capaths[link_idx] = NULL; } if ( - !table->field[13]->is_null() && - (ptr = get_field(mem_root, table->field[13])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_CERT_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_CERT_POS])) ) { share->tgt_ssl_certs_lengths[link_idx] = strlen(ptr); share->tgt_ssl_certs[link_idx] = @@ -2984,8 +3192,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_ssl_certs[link_idx] = NULL; } if ( - !table->field[14]->is_null() && - (ptr = get_field(mem_root, table->field[14])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_CIPHER_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_CIPHER_POS])) ) { share->tgt_ssl_ciphers_lengths[link_idx] = strlen(ptr); share->tgt_ssl_ciphers[link_idx] = @@ -2995,8 +3204,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_ssl_ciphers[link_idx] = NULL; } if ( - !table->field[15]->is_null() && - (ptr = get_field(mem_root, table->field[15])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_KEY_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_KEY_POS])) ) { share->tgt_ssl_keys_lengths[link_idx] = strlen(ptr); share->tgt_ssl_keys[link_idx] = @@ -3006,15 +3216,18 @@ int spider_get_sys_link_mon_connect_info( share->tgt_ssl_keys[link_idx] = NULL; } if ( - !table->field[16]->is_null() && - (ptr = get_field(mem_root, table->field[16])) + !table->field[SPIDER_LINK_MON_SERVERS_SSL_VERIFY_SERVER_CERT_POS]-> + is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_SSL_VERIFY_SERVER_CERT_POS])) ) { share->tgt_ssl_vscs[link_idx] = atol(ptr); } else share->tgt_ssl_vscs[link_idx] = -1; if ( - !table->field[17]->is_null() && - (ptr = get_field(mem_root, table->field[17])) + !table->field[SPIDER_LINK_MON_SERVERS_DEFAULT_FILE_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_DEFAULT_FILE_POS])) ) { share->tgt_default_files_lengths[link_idx] = strlen(ptr); share->tgt_default_files[link_idx] = @@ -3024,8 +3237,9 @@ int spider_get_sys_link_mon_connect_info( share->tgt_default_files[link_idx] = NULL; } if ( - !table->field[18]->is_null() && - (ptr = get_field(mem_root, table->field[18])) + !table->field[SPIDER_LINK_MON_SERVERS_DEFAULT_GROUP_POS]->is_null() && + (ptr = get_field(mem_root, + table->field[SPIDER_LINK_MON_SERVERS_DEFAULT_GROUP_POS])) ) { share->tgt_default_groups_lengths[link_idx] = strlen(ptr); share->tgt_default_groups[link_idx] = @@ -3034,6 +3248,17 @@ int spider_get_sys_link_mon_connect_info( share->tgt_default_groups_lengths[link_idx] = 0; share->tgt_default_groups[link_idx] = NULL; } + if ( + !table->field[SPIDER_LINK_MON_SERVERS_DSN_POS]->is_null() && + (ptr = get_field(mem_root, table->field[SPIDER_LINK_MON_SERVERS_DSN_POS])) + ) { + share->tgt_dsns_lengths[link_idx] = strlen(ptr); + share->tgt_dsns[link_idx] = + spider_create_string(ptr, share->tgt_dsns_lengths[link_idx]); + } else { + share->tgt_dsns_lengths[link_idx] = 0; + share->tgt_dsns[link_idx] = NULL; + } DBUG_RETURN(error_num); } @@ -3294,15 +3519,15 @@ int spider_sys_get_table_crd( TABLE *table_crd = NULL; #if MYSQL_VERSION_ID < 50500 Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; #endif DBUG_ENTER("spider_sys_get_table_crd"); + + start_new_trans new_trans(thd); if ( !(table_crd = spider_open_sys_table( thd, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR, SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) + 0, need_lock, &error_num)) ) { goto error; } @@ -3335,15 +3560,17 @@ int spider_sys_get_table_crd( goto error; } - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - table_crd = NULL; + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_RETURN(0); error: if (index_inited) spider_sys_index_end(table_crd); + if (table_crd) - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); DBUG_RETURN(error_num); } diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index df933ec61b8..eb87cd5268f 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -51,15 +51,15 @@ #define SPIDER_SYS_XA_COL_CNT 5 #define SPIDER_SYS_XA_PK_COL_CNT 3 #define SPIDER_SYS_XA_IDX1_COL_CNT 1 -#define SPIDER_SYS_XA_MEMBER_COL_CNT 18 +#define SPIDER_SYS_XA_MEMBER_COL_CNT 19 #define SPIDER_SYS_XA_MEMBER_PK_COL_CNT 6 -#define SPIDER_SYS_TABLES_COL_CNT 25 +#define SPIDER_SYS_TABLES_COL_CNT 26 #define SPIDER_SYS_TABLES_PK_COL_CNT 3 #define SPIDER_SYS_TABLES_IDX1_COL_CNT 1 #define SPIDER_SYS_TABLES_UIDX1_COL_CNT 3 -#define SPIDER_SYS_LINK_MON_TABLE_COL_CNT 19 +#define SPIDER_SYS_LINK_MON_TABLE_COL_CNT 20 #define SPIDER_SYS_LINK_FAILED_TABLE_COL_CNT 4 -#define SPIDER_SYS_XA_FAILED_TABLE_COL_CNT 21 +#define SPIDER_SYS_XA_FAILED_TABLE_COL_CNT 22 #define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_COL_CNT 7 #define SPIDER_SYS_TABLE_STS_COL_CNT 11 #define SPIDER_SYS_TABLE_STS_PK_COL_CNT 2 @@ -274,11 +274,6 @@ void spider_store_tables_link_status( long link_status ); -void spider_store_link_chk_server_id( - TABLE *table, - uint32 server_id -); - void spider_store_binlog_pos_failed_link_idx( TABLE *table, int failed_link_idx diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index be542eab004..f4b0177c794 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -1,5 +1,5 @@ -/* Copyright (C) 2008-2019 Kentoku Shiba - Copyright (C) 2019 MariaDB corp +/* Copyright (C) 2008-2020 Kentoku Shiba + Copyright (C) 2019-2020 MariaDB corp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -152,7 +152,7 @@ SPIDER_THREAD *spider_table_crd_threads; PSI_mutex_key spd_key_mutex_tbl; PSI_mutex_key spd_key_mutex_init_error_tbl; #ifdef WITH_PARTITION_STORAGE_ENGINE -PSI_mutex_key spd_key_mutex_pt_share; +PSI_mutex_key spd_key_mutex_wide_share; #endif PSI_mutex_key spd_key_mutex_lgtm_tblhnd_share; PSI_mutex_key spd_key_mutex_conn; @@ -182,8 +182,8 @@ PSI_mutex_key spd_key_mutex_share_sts; PSI_mutex_key spd_key_mutex_share_crd; PSI_mutex_key spd_key_mutex_share_auto_increment; #ifdef WITH_PARTITION_STORAGE_ENGINE -PSI_mutex_key spd_key_mutex_pt_share_sts; -PSI_mutex_key spd_key_mutex_pt_share_crd; +PSI_mutex_key spd_key_mutex_wide_share_sts; +PSI_mutex_key spd_key_mutex_wide_share_crd; PSI_mutex_key spd_key_mutex_pt_handler; #endif PSI_mutex_key spd_key_mutex_udf_table; @@ -196,13 +196,14 @@ PSI_mutex_key spd_key_mutex_conn_i; PSI_mutex_key spd_key_mutex_bg_stss; PSI_mutex_key spd_key_mutex_bg_crds; #endif +PSI_mutex_key spd_key_mutex_conn_loop_check; static PSI_mutex_info all_spider_mutexes[]= { { &spd_key_mutex_tbl, "tbl", PSI_FLAG_GLOBAL}, { &spd_key_mutex_init_error_tbl, "init_error_tbl", PSI_FLAG_GLOBAL}, #ifdef WITH_PARTITION_STORAGE_ENGINE - { &spd_key_mutex_pt_share, "pt_share", PSI_FLAG_GLOBAL}, + { &spd_key_mutex_wide_share, "wide_share", PSI_FLAG_GLOBAL}, #endif { &spd_key_mutex_lgtm_tblhnd_share, "lgtm_tblhnd_share", PSI_FLAG_GLOBAL}, { &spd_key_mutex_conn, "conn", PSI_FLAG_GLOBAL}, @@ -241,11 +242,12 @@ static PSI_mutex_info all_spider_mutexes[]= { &spd_key_mutex_share_crd, "share_crd", 0}, { &spd_key_mutex_share_auto_increment, "share_auto_increment", 0}, #ifdef WITH_PARTITION_STORAGE_ENGINE - { &spd_key_mutex_pt_share_sts, "pt_share_sts", 0}, - { &spd_key_mutex_pt_share_crd, "pt_share_crd", 0}, + { &spd_key_mutex_wide_share_sts, "wide_share_sts", 0}, + { &spd_key_mutex_wide_share_crd, "wide_share_crd", 0}, { &spd_key_mutex_pt_handler, "pt_handler", 0}, #endif { &spd_key_mutex_udf_table, "udf_table", 0}, + { &spd_key_mutex_conn_loop_check, "conn_loop_check", 0}, }; #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -365,12 +367,12 @@ extern pthread_mutex_t spider_conn_id_mutex; extern pthread_mutex_t spider_ipport_conn_mutex; #ifdef WITH_PARTITION_STORAGE_ENGINE -HASH spider_open_pt_share; -uint spider_open_pt_share_id; -const char *spider_open_pt_share_func_name; -const char *spider_open_pt_share_file_name; -ulong spider_open_pt_share_line_no; -pthread_mutex_t spider_pt_share_mutex; +HASH spider_open_wide_share; +uint spider_open_wide_share_id; +const char *spider_open_wide_share_func_name; +const char *spider_open_wide_share_file_name; +ulong spider_open_wide_share_line_no; +pthread_mutex_t spider_wide_share_mutex; #endif HASH spider_lgtm_tblhnd_share_hash; @@ -404,6 +406,9 @@ extern ulonglong spider_free_mem_count[SPIDER_MEM_CALC_LIST_NUM]; static char spider_wild_many = '%', spider_wild_one = '_', spider_wild_prefix='\\'; +static char spider_unique_id_buf[1 + 12 + 1 + (16 * 2) + 1 + 1]; +LEX_CSTRING spider_unique_id; + // for spider_open_tables uchar *spider_tbl_get_key( SPIDER_SHARE *share, @@ -415,25 +420,25 @@ uchar *spider_tbl_get_key( DBUG_RETURN((uchar*) share->table_name); } -#ifdef WITH_PARTITION_STORAGE_ENGINE -uchar *spider_pt_share_get_key( - SPIDER_PARTITION_SHARE *share, +uchar *spider_wide_share_get_key( + SPIDER_WIDE_SHARE *share, size_t *length, my_bool not_used __attribute__ ((unused)) ) { - DBUG_ENTER("spider_pt_share_get_key"); + DBUG_ENTER("spider_wide_share_get_key"); *length = share->table_name_length; DBUG_RETURN((uchar*) share->table_name); } +#ifdef WITH_PARTITION_STORAGE_ENGINE uchar *spider_pt_handler_share_get_key( SPIDER_PARTITION_HANDLER_SHARE *share, size_t *length, my_bool not_used __attribute__ ((unused)) ) { DBUG_ENTER("spider_pt_handler_share_get_key"); - *length = sizeof(TABLE *); - DBUG_RETURN((uchar*) &share->table); + *length = sizeof(ha_spider *); + DBUG_RETURN((uchar*) share->owner); } #endif @@ -794,6 +799,17 @@ int spider_free_share_alloc( } spider_free(spider_current_trx, share->tgt_default_groups, MYF(0)); } + if (share->tgt_dsns) + { + for (roop_count = 0; roop_count < (int) share->tgt_dsns_length; + roop_count++) + { + if (share->tgt_dsns[roop_count]) + spider_free(spider_current_trx, share->tgt_dsns[roop_count], + MYF(0)); + } + spider_free(spider_current_trx, share->tgt_dsns, MYF(0)); + } if (share->tgt_pk_names) { for (roop_count = 0; roop_count < (int) share->tgt_pk_names_length; @@ -897,6 +913,8 @@ int spider_free_share_alloc( spider_free(spider_current_trx, share->access_balances, MYF(0)); if (share->bka_table_name_types) spider_free(spider_current_trx, share->bka_table_name_types, MYF(0)); + if (share->strict_group_bys) + spider_free(spider_current_trx, share->strict_group_bys, MYF(0)); #ifndef WITHOUT_SPIDER_BG_SEARCH if (share->monitoring_bg_interval) spider_free(spider_current_trx, share->monitoring_bg_interval, MYF(0)); @@ -913,10 +931,8 @@ int spider_free_share_alloc( delete [] share->key_hint; share->key_hint = NULL; } -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (share->partition_share) - spider_free_pt_share(share->partition_share); -#endif + if (share->wide_share) + spider_free_wide_share(share->wide_share); DBUG_RETURN(0); } @@ -999,6 +1015,11 @@ void spider_free_tmp_share_alloc( spider_free(spider_current_trx, share->tgt_default_groups[0], MYF(0)); share->tgt_default_groups[0] = NULL; } + if (share->tgt_dsns && share->tgt_dsns[0]) + { + spider_free(spider_current_trx, share->tgt_dsns[0], MYF(0)); + share->tgt_dsns[0] = NULL; + } if (share->tgt_pk_names && share->tgt_pk_names[0]) { spider_free(spider_current_trx, share->tgt_pk_names[0], MYF(0)); @@ -1052,7 +1073,7 @@ char *spider_get_string_between_quote( SPIDER_PARAM_STRING_PARSE *param_string_parse ) { char *start_ptr, *end_ptr, *tmp_ptr, *esc_ptr; - bool find_flg = FALSE, esc_flg = FALSE; + bool find_flg = FALSE; DBUG_ENTER("spider_get_string_between_quote"); start_ptr = strchr(ptr, '\''); @@ -1072,11 +1093,9 @@ char *spider_get_string_between_quote( find_flg = TRUE; else if (esc_ptr == end_ptr - 1) { - esc_flg = TRUE; tmp_ptr = end_ptr + 1; break; } else { - esc_flg = TRUE; esc_ptr += 2; } } @@ -1097,11 +1116,9 @@ char *spider_get_string_between_quote( find_flg = TRUE; else if (esc_ptr == end_ptr - 1) { - esc_flg = TRUE; tmp_ptr = end_ptr + 1; break; } else { - esc_flg = TRUE; esc_ptr += 2; } } @@ -1110,36 +1127,6 @@ char *spider_get_string_between_quote( DBUG_RETURN(NULL); *end_ptr = '\0'; - if (esc_flg) - { - esc_ptr = start_ptr; - while (TRUE) - { - esc_ptr = strchr(esc_ptr, '\\'); - if (!esc_ptr) - break; - switch(*(esc_ptr + 1)) - { - case 'b': - *esc_ptr = '\b'; - break; - case 'n': - *esc_ptr = '\n'; - break; - case 'r': - *esc_ptr = '\r'; - break; - case 't': - *esc_ptr = '\t'; - break; - default: - *esc_ptr = *(esc_ptr + 1); - break; - } - esc_ptr++; - strcpy(esc_ptr, esc_ptr + 1); - } - } if (param_string_parse) param_string_parse->set_param_value(start_ptr, start_ptr + strlen(start_ptr) + 1); @@ -1165,7 +1152,7 @@ int spider_create_string_list( SPIDER_PARAM_STRING_PARSE *param_string_parse ) { int roop_count; - char *tmp_ptr, *tmp_ptr2, *tmp_ptr3, *esc_ptr; + char *tmp_ptr, *tmp_ptr2, *tmp_ptr3, *tmp_ptr4, *esc_ptr; bool find_flg = FALSE; DBUG_ENTER("spider_create_string_list"); @@ -1187,22 +1174,30 @@ int spider_create_string_list( DBUG_RETURN(0); } + bool last_esc_flg = FALSE; while (TRUE) { if ((tmp_ptr2 = strchr(tmp_ptr, ' '))) { + find_flg = FALSE; + last_esc_flg = FALSE; esc_ptr = tmp_ptr; while (!find_flg) { esc_ptr = strchr(esc_ptr, '\\'); if (!esc_ptr || esc_ptr > tmp_ptr2) + { find_flg = TRUE; + } else if (esc_ptr == tmp_ptr2 - 1) { + last_esc_flg = TRUE; tmp_ptr = tmp_ptr2 + 1; break; - } else + } else { + last_esc_flg = TRUE; esc_ptr += 2; + } } if (find_flg) { @@ -1235,6 +1230,8 @@ int spider_create_string_list( for (roop_count = 0; roop_count < (int) *list_length - 1; roop_count++) { + bool esc_flg = FALSE; + find_flg = FALSE; while (TRUE) { tmp_ptr2 = strchr(tmp_ptr, ' '); @@ -1244,13 +1241,18 @@ int spider_create_string_list( { esc_ptr = strchr(esc_ptr, '\\'); if (!esc_ptr || esc_ptr > tmp_ptr2) + { find_flg = TRUE; + } else if (esc_ptr == tmp_ptr2 - 1) { + esc_flg = TRUE; tmp_ptr = tmp_ptr2 + 1; break; - } else + } else { + esc_flg = TRUE; esc_ptr += 2; + } } if (find_flg) break; @@ -1270,6 +1272,43 @@ int spider_create_string_list( my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); DBUG_RETURN(HA_ERR_OUT_OF_MEM); } + + if (esc_flg) + { + esc_ptr = (*string_list)[roop_count]; + while (TRUE) + { + esc_ptr = strchr(esc_ptr, '\\'); + if (!esc_ptr) + break; + switch(*(esc_ptr + 1)) + { + case 'b': + *esc_ptr = '\b'; + break; + case 'n': + *esc_ptr = '\n'; + break; + case 'r': + *esc_ptr = '\r'; + break; + case 't': + *esc_ptr = '\t'; + break; + default: + *esc_ptr = *(esc_ptr + 1); + break; + } + esc_ptr++; + tmp_ptr4 = esc_ptr; + do + { + *tmp_ptr4 = *(tmp_ptr4 + 1); + tmp_ptr4++; + } while (*tmp_ptr4); + (*string_length_list)[roop_count] -= 1; + } + } DBUG_PRINT("info",("spider string_list[%d]=%s", roop_count, (*string_list)[roop_count])); tmp_ptr3 = tmp_ptr; @@ -1281,6 +1320,42 @@ int spider_create_string_list( my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); DBUG_RETURN(HA_ERR_OUT_OF_MEM); } + if (last_esc_flg) + { + esc_ptr = (*string_list)[roop_count]; + while (TRUE) + { + esc_ptr = strchr(esc_ptr, '\\'); + if (!esc_ptr) + break; + switch(*(esc_ptr + 1)) + { + case 'b': + *esc_ptr = '\b'; + break; + case 'n': + *esc_ptr = '\n'; + break; + case 'r': + *esc_ptr = '\r'; + break; + case 't': + *esc_ptr = '\t'; + break; + default: + *esc_ptr = *(esc_ptr + 1); + break; + } + esc_ptr++; + tmp_ptr4 = esc_ptr; + do + { + *tmp_ptr4 = *(tmp_ptr4 + 1); + tmp_ptr4++; + } while (*tmp_ptr4); + (*string_length_list)[roop_count] -= 1; + } + } param_string_parse->set_param_value(tmp_ptr3, tmp_ptr3 + strlen(tmp_ptr3) + 1); @@ -2047,6 +2122,7 @@ int spider_parse_connect_info( share->bulk_size = -1; share->bulk_update_mode = -1; share->bulk_update_size = -1; + share->buffer_size = -1; share->internal_optimize = -1; share->internal_optimize_local = -1; share->scan_rate = -1; @@ -2216,6 +2292,7 @@ int spider_parse_connect_info( #ifdef HA_CAN_BULK_ACCESS SPIDER_PARAM_INT_WITH_MAX("baf", bulk_access_free, 0, 1); #endif + SPIDER_PARAM_INT("bfz", buffer_size, 0); #ifndef WITHOUT_SPIDER_BG_SEARCH SPIDER_PARAM_LONGLONG("bfr", bgs_first_read, 0); SPIDER_PARAM_INT("bmd", bgs_mode, 0); @@ -2246,6 +2323,7 @@ int spider_parse_connect_info( SPIDER_PARAM_STR_LIST("dff", tgt_default_files); SPIDER_PARAM_STR_LIST("dfg", tgt_default_groups); SPIDER_PARAM_LONGLONG("dol", direct_order_limit, 0); + SPIDER_PARAM_STR_LIST("dsn", tgt_dsns); SPIDER_PARAM_INT_WITH_MAX("erm", error_read_mode, 0, 1); SPIDER_PARAM_INT_WITH_MAX("ewm", error_write_mode, 0, 1); #ifdef HA_CAN_FORCE_BULK_DELETE @@ -2314,6 +2392,7 @@ int spider_parse_connect_info( SPIDER_PARAM_STR_LIST("scp", tgt_ssl_capaths); SPIDER_PARAM_STR_LIST("scr", tgt_ssl_certs); SPIDER_PARAM_INT_WITH_MAX("sdc", skip_default_condition, 0, 1); + SPIDER_PARAM_LONG_LIST_WITH_MAX("sgb", strict_group_bys, 0, 1); SPIDER_PARAM_DOUBLE("siv", sts_interval, 0); SPIDER_PARAM_STR_LIST("sky", tgt_ssl_keys); SPIDER_PARAM_STR_LIST("sli", static_link_ids); @@ -2425,6 +2504,7 @@ int spider_parse_connect_info( SPIDER_PARAM_LONG_LIST_WITH_MAX("use_hs_read", use_hs_reads, 0, 1); #endif SPIDER_PARAM_INT_WITH_MAX("casual_read", casual_read, 0, 63); + SPIDER_PARAM_INT("buffer_size", buffer_size, 0); error_num = connect_string_parse.print_param_error(); goto error; case 12: @@ -2484,6 +2564,8 @@ int spider_parse_connect_info( #endif SPIDER_PARAM_LONG_LIST_WITH_MAX("connect_timeout", connect_timeouts, 0, 2147483647); + SPIDER_PARAM_LONG_LIST_WITH_MAX("strict_group_by", + strict_group_bys, 0, 1); SPIDER_PARAM_INT_WITH_MAX("error_read_mode", error_read_mode, 0, 1); error_num = connect_string_parse.print_param_error(); goto error; @@ -2659,6 +2741,8 @@ int spider_parse_connect_info( share->all_link_count = share->tgt_default_files_length; if (share->all_link_count < share->tgt_default_groups_length) share->all_link_count = share->tgt_default_groups_length; + if (share->all_link_count < share->tgt_dsns_length) + share->all_link_count = share->tgt_dsns_length; if (share->all_link_count < share->tgt_pk_names_length) share->all_link_count = share->tgt_pk_names_length; if (share->all_link_count < share->tgt_sequence_names_length) @@ -2717,6 +2801,8 @@ int spider_parse_connect_info( share->all_link_count = share->access_balances_length; if (share->all_link_count < share->bka_table_name_types_length) share->all_link_count = share->bka_table_name_types_length; + if (share->all_link_count < share->strict_group_bys_length) + share->all_link_count = share->strict_group_bys_length; if ((error_num = spider_increase_string_list( &share->server_names, &share->server_names_lengths, @@ -2822,6 +2908,13 @@ int spider_parse_connect_info( &share->tgt_default_groups_charlen, share->all_link_count))) goto error; + if ((error_num = spider_increase_string_list( + &share->tgt_dsns, + &share->tgt_dsns_lengths, + &share->tgt_dsns_length, + &share->tgt_dsns_charlen, + share->all_link_count))) + goto error; if ((error_num = spider_increase_string_list( &share->tgt_pk_names, &share->tgt_pk_names_lengths, @@ -2973,6 +3066,11 @@ int spider_parse_connect_info( &share->bka_table_name_types_length, share->all_link_count))) goto error; + if ((error_num = spider_increase_long_list( + &share->strict_group_bys, + &share->strict_group_bys_length, + share->all_link_count))) + goto error; /* copy for tables start */ share_alter = &share->alter_table; @@ -2980,9 +3078,73 @@ int spider_parse_connect_info( if (!(share_alter->tmp_server_names = (char **) spider_bulk_malloc(spider_current_trx, 43, MYF(MY_WME | MY_ZEROFILL), &share_alter->tmp_server_names, - (uint) (sizeof(char *) * 16 * share->all_link_count), + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_table_names, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_dbs, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_hosts, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_usernames, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_passwords, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_sockets, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_wrappers, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_cas, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_capaths, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_certs, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_ciphers, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_keys, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_default_files, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_default_groups, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_tgt_dsns, + (uint) (sizeof(char *) * share->all_link_count), + &share_alter->tmp_static_link_ids, + (uint) (sizeof(char *) * share->all_link_count), &share_alter->tmp_server_names_lengths, - (uint) (sizeof(uint *) * 16 * share->all_link_count), + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_table_names_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_dbs_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_hosts_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_usernames_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_passwords_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_sockets_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_wrappers_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_cas_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_capaths_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_certs_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_ciphers_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_ssl_keys_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_default_files_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_default_groups_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_tgt_dsns_lengths, + (uint) (sizeof(uint *) * share->all_link_count), + &share_alter->tmp_static_link_ids_lengths, + (uint) (sizeof(uint *) * share->all_link_count), &share_alter->tmp_tgt_ports, (uint) (sizeof(long) * share->all_link_count), &share_alter->tmp_tgt_ssl_vscs, @@ -3000,64 +3162,36 @@ int spider_parse_connect_info( memcpy(share_alter->tmp_server_names, share->server_names, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_table_names = - share_alter->tmp_server_names + share->all_link_count; memcpy(share_alter->tmp_tgt_table_names, share->tgt_table_names, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_dbs = - share_alter->tmp_tgt_table_names + share->all_link_count; memcpy(share_alter->tmp_tgt_dbs, share->tgt_dbs, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_hosts = - share_alter->tmp_tgt_dbs + share->all_link_count; memcpy(share_alter->tmp_tgt_hosts, share->tgt_hosts, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_usernames = - share_alter->tmp_tgt_hosts + share->all_link_count; memcpy(share_alter->tmp_tgt_usernames, share->tgt_usernames, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_passwords = - share_alter->tmp_tgt_usernames + share->all_link_count; memcpy(share_alter->tmp_tgt_passwords, share->tgt_passwords, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_sockets = - share_alter->tmp_tgt_passwords + share->all_link_count; memcpy(share_alter->tmp_tgt_sockets, share->tgt_sockets, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_wrappers = - share_alter->tmp_tgt_sockets + share->all_link_count; memcpy(share_alter->tmp_tgt_wrappers, share->tgt_wrappers, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_ssl_cas = - share_alter->tmp_tgt_wrappers + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_cas, share->tgt_ssl_cas, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_ssl_capaths = - share_alter->tmp_tgt_ssl_cas + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_capaths, share->tgt_ssl_capaths, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_ssl_certs = - share_alter->tmp_tgt_ssl_capaths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_certs, share->tgt_ssl_certs, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_ssl_ciphers = - share_alter->tmp_tgt_ssl_certs + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_ciphers, share->tgt_ssl_ciphers, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_ssl_keys = - share_alter->tmp_tgt_ssl_ciphers + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_keys, share->tgt_ssl_keys, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_default_files = - share_alter->tmp_tgt_ssl_keys + share->all_link_count; memcpy(share_alter->tmp_tgt_default_files, share->tgt_default_files, sizeof(char *) * share->all_link_count); - share_alter->tmp_tgt_default_groups = - share_alter->tmp_tgt_default_files + share->all_link_count; memcpy(share_alter->tmp_tgt_default_groups, share->tgt_default_groups, sizeof(char *) * share->all_link_count); - share_alter->tmp_static_link_ids = - share_alter->tmp_tgt_default_groups + share->all_link_count; + memcpy(share_alter->tmp_tgt_dsns, share->tgt_dsns, + sizeof(char *) * share->all_link_count); memcpy(share_alter->tmp_static_link_ids, share->static_link_ids, sizeof(char *) * share->all_link_count); @@ -3074,75 +3208,48 @@ int spider_parse_connect_info( memcpy(share_alter->tmp_server_names_lengths, share->server_names_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_table_names_lengths = - share_alter->tmp_server_names_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_table_names_lengths, share->tgt_table_names_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_dbs_lengths = - share_alter->tmp_tgt_table_names_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_dbs_lengths, share->tgt_dbs_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_hosts_lengths = - share_alter->tmp_tgt_dbs_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_hosts_lengths, share->tgt_hosts_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_usernames_lengths = - share_alter->tmp_tgt_hosts_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_usernames_lengths, share->tgt_usernames_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_passwords_lengths = - share_alter->tmp_tgt_usernames_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_passwords_lengths, share->tgt_passwords_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_sockets_lengths = - share_alter->tmp_tgt_passwords_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_sockets_lengths, share->tgt_sockets_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_wrappers_lengths = - share_alter->tmp_tgt_sockets_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_wrappers_lengths, share->tgt_wrappers_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_ssl_cas_lengths = - share_alter->tmp_tgt_wrappers_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_cas_lengths, share->tgt_ssl_cas_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_ssl_capaths_lengths = - share_alter->tmp_tgt_ssl_cas_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_capaths_lengths, share->tgt_ssl_capaths_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_ssl_certs_lengths = - share_alter->tmp_tgt_ssl_capaths_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_certs_lengths, share->tgt_ssl_certs_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_ssl_ciphers_lengths = - share_alter->tmp_tgt_ssl_certs_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_ciphers_lengths, share->tgt_ssl_ciphers_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_ssl_keys_lengths = - share_alter->tmp_tgt_ssl_ciphers_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_ssl_keys_lengths, share->tgt_ssl_keys_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_default_files_lengths = - share_alter->tmp_tgt_ssl_keys_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_default_files_lengths, share->tgt_default_files_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_tgt_default_groups_lengths = - share_alter->tmp_tgt_default_files_lengths + share->all_link_count; memcpy(share_alter->tmp_tgt_default_groups_lengths, share->tgt_default_groups_lengths, sizeof(uint) * share->all_link_count); - share_alter->tmp_static_link_ids_lengths = - share_alter->tmp_tgt_default_groups_lengths + share->all_link_count; + memcpy(share_alter->tmp_tgt_dsns_lengths, + share->tgt_dsns_lengths, + sizeof(uint) * share->all_link_count); memcpy(share_alter->tmp_static_link_ids_lengths, share->static_link_ids_lengths, sizeof(uint) * share->all_link_count); @@ -3164,6 +3271,8 @@ int spider_parse_connect_info( share->tgt_default_files_charlen; share_alter->tmp_tgt_default_groups_charlen = share->tgt_default_groups_charlen; + share_alter->tmp_tgt_dsns_charlen = + share->tgt_dsns_charlen; share_alter->tmp_static_link_ids_charlen = share->static_link_ids_charlen; @@ -3183,6 +3292,8 @@ int spider_parse_connect_info( share_alter->tmp_tgt_default_files_length = share->tgt_default_files_length; share_alter->tmp_tgt_default_groups_length = share->tgt_default_groups_length; + share_alter->tmp_tgt_dsns_length = + share->tgt_dsns_length; share_alter->tmp_static_link_ids_length = share->static_link_ids_length; share_alter->tmp_tgt_ports_length = share->tgt_ports_length; @@ -3405,6 +3516,18 @@ int spider_parse_connect_info( goto error; } + DBUG_PRINT("info", + ("spider tgt_dsns_lengths[%d] = %u", roop_count, + share->tgt_dsns_lengths[roop_count])); + if (share->tgt_dsns_lengths[roop_count] > + SPIDER_CONNECT_INFO_MAX_LEN) + { + error_num = ER_SPIDER_INVALID_CONNECT_INFO_TOO_LONG_NUM; + my_printf_error(error_num, ER_SPIDER_INVALID_CONNECT_INFO_TOO_LONG_STR, + MYF(0), share->tgt_dsns[roop_count], "default_group"); + goto error; + } + DBUG_PRINT("info", ("spider tgt_pk_names_lengths[%d] = %u", roop_count, share->tgt_pk_names_lengths[roop_count])); @@ -3501,7 +3624,11 @@ int spider_set_connect_info_default( #endif TABLE_SHARE *table_share ) { - int error_num, roop_count; + bool check_socket; + bool check_database; + bool socket_has_default_value; + bool database_has_default_value; + int error_num, roop_count, roop_count2; DBUG_ENTER("spider_set_connect_info_default"); for (roop_count = 0; roop_count < (int) share->all_link_count; roop_count++) { @@ -3511,6 +3638,64 @@ int spider_set_connect_info_default( DBUG_RETURN(error_num); } + if ( + !share->tgt_sockets[roop_count] && + ( + !share->tgt_hosts[roop_count] || + !strcmp(share->tgt_hosts[roop_count], my_localhost) + ) + ) { + check_socket = TRUE; + } else { + check_socket = FALSE; + } + if (!share->tgt_dbs[roop_count] && table_share) + { + check_database = TRUE; + } else { + check_database = FALSE; + } + if (check_socket || check_database) + { + socket_has_default_value = check_socket; + database_has_default_value = check_database; + if (share->tgt_wrappers[roop_count]) + { + for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) + { + DBUG_PRINT("info",("spider share->tgt_wrappers[%d]=%s", roop_count, + share->tgt_wrappers[roop_count])); + DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, + spider_dbton[roop_count2].wrapper ? + spider_dbton[roop_count2].wrapper : "NULL")); + if ( + spider_dbton[roop_count2].wrapper && + !strcmp(share->tgt_wrappers[roop_count], + spider_dbton[roop_count2].wrapper) + ) { + if (spider_dbton[roop_count2].db_access_type == + SPIDER_DB_ACCESS_TYPE_SQL) + { + if (check_socket) + { + socket_has_default_value = spider_dbton[roop_count2]. + db_util->socket_has_default_value(); + } + if (check_database) + { + database_has_default_value = spider_dbton[roop_count2]. + db_util->database_has_default_value(); + } + break; + } + } + } + } + } else { + socket_has_default_value = FALSE; + database_has_default_value = FALSE; + } + if (!share->tgt_wrappers[roop_count]) { DBUG_PRINT("info",("spider create default tgt_wrappers")); @@ -3537,7 +3722,7 @@ int spider_set_connect_info_default( } } - if (!share->tgt_dbs[roop_count] && table_share) + if (database_has_default_value) { DBUG_PRINT("info",("spider create default tgt_dbs")); share->tgt_dbs_lengths[roop_count] = table_share->db.length; @@ -3659,10 +3844,8 @@ int spider_set_connect_info_default( if (share->tgt_ssl_vscs[roop_count] == -1) share->tgt_ssl_vscs[roop_count] = 0; - if ( - !share->tgt_sockets[roop_count] && - !strcmp(share->tgt_hosts[roop_count], my_localhost) - ) { + if (socket_has_default_value) + { DBUG_PRINT("info",("spider create default tgt_sockets")); share->tgt_sockets_lengths[roop_count] = strlen((char *) MYSQL_UNIX_ADDR); @@ -3751,6 +3934,8 @@ int spider_set_connect_info_default( share->access_balances[roop_count] = 100; if (share->bka_table_name_types[roop_count] == -1) share->bka_table_name_types[roop_count] = 0; + if (share->strict_group_bys[roop_count] == -1) + share->strict_group_bys[roop_count] = 1; } #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -3825,6 +4010,8 @@ int spider_set_connect_info_default( share->bulk_update_mode = 0; if (share->bulk_update_size == -1) share->bulk_update_size = 16000; + if (share->buffer_size == -1) + share->buffer_size = 16000; if (share->internal_optimize == -1) share->internal_optimize = 0; if (share->internal_optimize_local == -1) @@ -3931,11 +4118,53 @@ int spider_set_connect_info_default_db_table( const char *table_name, uint table_name_length ) { - int roop_count; + uint roop_count, roop_count2; + bool check_database; + bool database_has_default_value; DBUG_ENTER("spider_set_connect_info_default_db_table"); - for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) + for (roop_count = 0; roop_count < share->link_count; roop_count++) { if (!share->tgt_dbs[roop_count] && db_name) + { + check_database = TRUE; + } else { + check_database = FALSE; + } + if (check_database) + { + database_has_default_value = check_database; + if (share->tgt_wrappers[roop_count]) + { + for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) + { + DBUG_PRINT("info",("spider share->tgt_wrappers[%d]=%s", roop_count, + share->tgt_wrappers[roop_count])); + DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, + spider_dbton[roop_count2].wrapper ? + spider_dbton[roop_count2].wrapper : "NULL")); + if ( + spider_dbton[roop_count2].wrapper && + !strcmp(share->tgt_wrappers[roop_count], + spider_dbton[roop_count2].wrapper) + ) { + if (spider_dbton[roop_count2].db_access_type == + SPIDER_DB_ACCESS_TYPE_SQL) + { + if (check_database) + { + database_has_default_value = spider_dbton[roop_count2]. + db_util->database_has_default_value(); + } + break; + } + } + } + } + } else { + database_has_default_value = FALSE; + } + + if (database_has_default_value) { DBUG_PRINT("info",("spider create default tgt_dbs")); share->tgt_dbs_lengths[roop_count] = db_name_length; @@ -4020,16 +4249,19 @@ int spider_create_conn_keys( #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) char *tmp_hs_r_name, *tmp_hs_w_name; #endif + uint length_base = sizeof(uint) * share->all_link_count; uint *conn_keys_lengths; + uint *sql_dbton_ids; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + uint *hs_dbton_ids; uint *hs_r_conn_keys_lengths; uint *hs_w_conn_keys_lengths; #endif DBUG_ENTER("spider_create_conn_keys"); char *ptr; - uint length = sizeof(uint) * share->all_link_count; + uint length = length_base * 2; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - length += (sizeof(uint) * share->all_link_count) * 2; + length += length_base * 3; #endif ptr = (char *) my_alloca(length); if (!ptr) @@ -4037,10 +4269,14 @@ int spider_create_conn_keys( DBUG_RETURN(HA_ERR_OUT_OF_MEM); } conn_keys_lengths = (uint *) ptr; - ptr += (sizeof(uint) * share->all_link_count); + ptr += length_base; + sql_dbton_ids = (uint *) ptr; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + ptr += length_base; + hs_dbton_ids = (uint *) ptr; + ptr += length_base; hs_r_conn_keys_lengths = (uint *) ptr; - ptr += (sizeof(uint) * share->all_link_count); + ptr += length_base; hs_w_conn_keys_lengths = (uint *) ptr; #endif @@ -4051,13 +4287,76 @@ int spider_create_conn_keys( #endif for (roop_count = 0; roop_count < (int) share->all_link_count; roop_count++) { - /* tgt_db not use */ + bool get_sql_id = FALSE; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + bool get_nosql_id = FALSE; +#endif + for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) + { + DBUG_PRINT("info",("spider share->tgt_wrappers[%d]=%s", roop_count, + share->tgt_wrappers[roop_count])); + DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, + spider_dbton[roop_count2].wrapper ? + spider_dbton[roop_count2].wrapper : "NULL")); + if ( + spider_dbton[roop_count2].wrapper && + !strcmp(share->tgt_wrappers[roop_count], + spider_dbton[roop_count2].wrapper) + ) { + spider_set_bit(share->dbton_bitmap, roop_count2); + if ( + !get_sql_id && + spider_dbton[roop_count2].db_access_type == SPIDER_DB_ACCESS_TYPE_SQL + ) { + sql_dbton_ids[roop_count] = roop_count2; + get_sql_id = TRUE; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (get_nosql_id) +#endif + break; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + else + continue; +#endif + } +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if ( + !get_nosql_id && + spider_dbton[roop_count2].db_access_type == + SPIDER_DB_ACCESS_TYPE_NOSQL + ) { + hs_dbton_ids[roop_count] = roop_count2; + get_nosql_id = TRUE; + if (get_sql_id) + break; + } +#endif + } + } + if (!get_sql_id) + sql_dbton_ids[roop_count] = SPIDER_DBTON_SIZE; +#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) + if (!get_nosql_id) + hs_dbton_ids[roop_count] = SPIDER_DBTON_SIZE; +#endif + + bool tables_on_different_db_are_joinable; + if (get_sql_id) + { + tables_on_different_db_are_joinable = + spider_dbton[sql_dbton_ids[roop_count]].db_util-> + tables_on_different_db_are_joinable(); + } else { + tables_on_different_db_are_joinable = TRUE; + } conn_keys_lengths[roop_count] = 1 + share->tgt_wrappers_lengths[roop_count] + 1 + share->tgt_hosts_lengths[roop_count] + 1 + 5 + 1 + share->tgt_sockets_lengths[roop_count] + 1 + + (tables_on_different_db_are_joinable ? + 0 : share->tgt_dbs_lengths[roop_count] + 1) + share->tgt_usernames_lengths[roop_count] + 1 + share->tgt_passwords_lengths[roop_count] + 1 + share->tgt_ssl_cas_lengths[roop_count] + 1 @@ -4067,7 +4366,8 @@ int spider_create_conn_keys( + share->tgt_ssl_keys_lengths[roop_count] + 1 + 1 + 1 + share->tgt_default_files_lengths[roop_count] + 1 - + share->tgt_default_groups_lengths[roop_count]; + + share->tgt_default_groups_lengths[roop_count] + 1 + + share->tgt_dsns_lengths[roop_count]; share->conn_keys_charlen += conn_keys_lengths[roop_count] + 2; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) hs_r_conn_keys_lengths[roop_count] @@ -4092,7 +4392,7 @@ int spider_create_conn_keys( spider_bulk_alloc_mem(spider_current_trx, 45, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &share->conn_keys, sizeof(char *) * share->all_link_count, - &share->conn_keys_lengths, sizeof(uint) * share->all_link_count, + &share->conn_keys_lengths, length_base, #ifdef SPIDER_HAS_HASH_VALUE_TYPE &share->conn_keys_hash_value, sizeof(my_hash_value_type) * share->all_link_count, @@ -4100,23 +4400,23 @@ int spider_create_conn_keys( &tmp_name, sizeof(char) * share->conn_keys_charlen, #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) &share->hs_read_conn_keys, sizeof(char *) * share->all_link_count, - &share->hs_read_conn_keys_lengths, sizeof(uint) * share->all_link_count, + &share->hs_read_conn_keys_lengths, length_base, #ifdef SPIDER_HAS_HASH_VALUE_TYPE &share->hs_read_conn_keys_hash_value, sizeof(my_hash_value_type) * share->all_link_count, #endif &tmp_hs_r_name, sizeof(char) * share->hs_read_conn_keys_charlen, &share->hs_write_conn_keys, sizeof(char *) * share->all_link_count, - &share->hs_write_conn_keys_lengths, sizeof(uint) * share->all_link_count, + &share->hs_write_conn_keys_lengths, length_base, #ifdef SPIDER_HAS_HASH_VALUE_TYPE &share->hs_write_conn_keys_hash_value, sizeof(my_hash_value_type) * share->all_link_count, #endif &tmp_hs_w_name, sizeof(char) * share->hs_write_conn_keys_charlen, #endif - &share->sql_dbton_ids, sizeof(uint) * share->all_link_count, + &share->sql_dbton_ids, length_base, #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - &share->hs_dbton_ids, sizeof(uint) * share->all_link_count, + &share->hs_dbton_ids, length_base, #endif NullS)) ) { @@ -4125,20 +4425,32 @@ int spider_create_conn_keys( } share->conn_keys_length = share->all_link_count; memcpy(share->conn_keys_lengths, conn_keys_lengths, - sizeof(uint) * share->all_link_count); + length_base); + memcpy(share->sql_dbton_ids, sql_dbton_ids, length_base); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) share->hs_read_conn_keys_length = share->all_link_count; share->hs_write_conn_keys_length = share->all_link_count; memcpy(share->hs_read_conn_keys_lengths, hs_r_conn_keys_lengths, - sizeof(uint) * share->all_link_count); + length_base); memcpy(share->hs_write_conn_keys_lengths, hs_w_conn_keys_lengths, - sizeof(uint) * share->all_link_count); + length_base); + memcpy(share->hs_dbton_ids, hs_dbton_ids, length_base); #endif my_afree(conn_keys_lengths); for (roop_count = 0; roop_count < (int) share->all_link_count; roop_count++) { + bool tables_on_different_db_are_joinable; + if (share->sql_dbton_ids[roop_count] != SPIDER_DBTON_SIZE) + { + tables_on_different_db_are_joinable = + spider_dbton[share->sql_dbton_ids[roop_count]].db_util-> + tables_on_different_db_are_joinable(); + } else { + tables_on_different_db_are_joinable = TRUE; + } + share->conn_keys[roop_count] = tmp_name; *tmp_name = '0'; DBUG_PRINT("info",("spider tgt_wrappers[%d]=%s", roop_count, @@ -4157,6 +4469,16 @@ int spider_create_conn_keys( tmp_name = strmov(tmp_name + 1, share->tgt_sockets[roop_count]); } else tmp_name++; + if (!tables_on_different_db_are_joinable) + { + if (share->tgt_dbs[roop_count]) + { + DBUG_PRINT("info",("spider tgt_dbs[%d]=%s", roop_count, + share->tgt_dbs[roop_count])); + tmp_name = strmov(tmp_name + 1, share->tgt_dbs[roop_count]); + } else + tmp_name++; + } if (share->tgt_usernames[roop_count]) { DBUG_PRINT("info",("spider tgt_usernames[%d]=%s", roop_count, @@ -4222,6 +4544,13 @@ int spider_create_conn_keys( tmp_name = strmov(tmp_name + 1, share->tgt_default_groups[roop_count]); } else tmp_name++; + if (share->tgt_dsns[roop_count]) + { + DBUG_PRINT("info",("spider tgt_dsns[%d]=%s", roop_count, + share->tgt_dsns[roop_count])); + tmp_name = strmov(tmp_name + 1, share->tgt_dsns[roop_count]); + } else + tmp_name++; tmp_name++; tmp_name++; #ifdef SPIDER_HAS_HASH_VALUE_TYPE @@ -4284,59 +4613,6 @@ int spider_create_conn_keys( &spider_open_connections, (uchar*) share->hs_write_conn_keys[roop_count], share->hs_write_conn_keys_lengths[roop_count]); #endif -#endif - - bool get_sql_id = FALSE; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - bool get_nosql_id = FALSE; -#endif - for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) - { - DBUG_PRINT("info",("spider share->tgt_wrappers[%d]=%s", roop_count, - share->tgt_wrappers[roop_count])); - DBUG_PRINT("info",("spider spider_dbton[%d].wrapper=%s", roop_count2, - spider_dbton[roop_count2].wrapper ? - spider_dbton[roop_count2].wrapper : "NULL")); - if ( - spider_dbton[roop_count2].wrapper && - !strcmp(share->tgt_wrappers[roop_count], - spider_dbton[roop_count2].wrapper) - ) { - spider_set_bit(share->dbton_bitmap, roop_count2); - if ( - !get_sql_id && - spider_dbton[roop_count2].db_access_type == SPIDER_DB_ACCESS_TYPE_SQL - ) { - share->sql_dbton_ids[roop_count] = roop_count2; - get_sql_id = TRUE; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if (get_nosql_id) -#endif - break; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - else - continue; -#endif - } -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if ( - !get_nosql_id && - spider_dbton[roop_count2].db_access_type == - SPIDER_DB_ACCESS_TYPE_NOSQL - ) { - share->hs_dbton_ids[roop_count] = roop_count2; - get_nosql_id = TRUE; - if (get_sql_id) - break; - } -#endif - } - } - if (!get_sql_id) - share->sql_dbton_ids[roop_count] = SPIDER_DBTON_SIZE; -#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - if (!get_nosql_id) - share->hs_dbton_ids[roop_count] = SPIDER_DBTON_SIZE; #endif } for (roop_count2 = 0; roop_count2 < SPIDER_DBTON_SIZE; roop_count2++) @@ -4517,8 +4793,6 @@ SPIDER_SHARE *spider_create_share( goto error_init_crd_mutex; } - thr_lock_init(&share->lock); - #ifdef SPIDER_HAS_HASH_VALUE_TYPE if (!(share->lgtm_tblhnd_share = spider_get_lgtm_tblhnd_share(tmp_name, length, hash_value, FALSE, TRUE, @@ -4531,11 +4805,9 @@ SPIDER_SHARE *spider_create_share( goto error_get_lgtm_tblhnd_share; } -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (!(share->partition_share = - spider_get_pt_share(share, table_share, error_num))) - goto error_get_pt_share; -#endif + if (!(share->wide_share = + spider_get_wide_share(share, table_share, error_num))) + goto error_get_wide_share; for (roop_count = 0; roop_count < SPIDER_DBTON_SIZE; roop_count++) { @@ -4583,12 +4855,9 @@ error_init_dbton: share->dbton_share[roop_count] = NULL; } } -#ifdef WITH_PARTITION_STORAGE_ENGINE - spider_free_pt_share(share->partition_share); -error_get_pt_share: -#endif + spider_free_wide_share(share->wide_share); +error_get_wide_share: error_get_lgtm_tblhnd_share: - thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->crd_mutex); error_init_crd_mutex: pthread_mutex_destroy(&share->sts_mutex); @@ -4614,7 +4883,7 @@ SPIDER_SHARE *spider_get_share( SPIDER_SHARE *share; TABLE_SHARE *table_share = table->s; SPIDER_RESULT_LIST *result_list = &spider->result_list; - uint length, tmp_conn_link_idx = 0; + uint length, tmp_conn_link_idx = 0, buf_sz; char *tmp_name, *tmp_cid; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) char *tmp_hs_r_name, *tmp_hs_w_name; @@ -4649,13 +4918,60 @@ SPIDER_SHARE *spider_get_share( bool same_server_link; int load_sts_at_startup; int load_crd_at_startup; + user_var_entry *loop_check; + char *loop_check_buf; + TABLE_SHARE *top_share; + LEX_CSTRING lex_str; DBUG_ENTER("spider_get_share"); - + top_share = spider->wide_handler->top_share; length = (uint) strlen(table_name); #ifdef SPIDER_HAS_HASH_VALUE_TYPE my_hash_value_type hash_value = my_calc_hash(&spider_open_tables, (uchar*) table_name, length); #endif + if (top_share) + { + lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN; + buf_sz = spider_unique_id.length > SPIDER_SQL_LOP_CHK_PRM_PRF_LEN ? + top_share->path.length + spider_unique_id.length + 2 : + lex_str.length + 2; + loop_check_buf = (char *) my_alloca(buf_sz); + if (unlikely(!loop_check_buf)) + { + *error_num = HA_ERR_OUT_OF_MEM; + DBUG_RETURN(NULL); + } + lex_str.str = loop_check_buf + buf_sz - lex_str.length - 2; + memcpy((void *) lex_str.str, + SPIDER_SQL_LOP_CHK_PRM_PRF_STR, SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); + memcpy((void *) (lex_str.str + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN), + top_share->path.str, top_share->path.length); + ((char *) lex_str.str)[lex_str.length] = '\0'; + DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str)); + loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); + if (loop_check && loop_check->type == STRING_RESULT) + { + lex_str.length = top_share->path.length + spider_unique_id.length + 1; + lex_str.str = loop_check_buf + buf_sz - top_share->path.length - + spider_unique_id.length - 2; + memcpy((void *) lex_str.str, spider_unique_id.str, + spider_unique_id.length); + ((char *) lex_str.str)[lex_str.length - 1] = '-'; + ((char *) lex_str.str)[lex_str.length] = '\0'; + DBUG_PRINT("info",("spider loop check key=%s", lex_str.str)); + DBUG_PRINT("info",("spider loop check param value=%s", + loop_check->value)); + if (unlikely(strstr(loop_check->value, lex_str.str))) + { + *error_num = ER_SPIDER_INFINITE_LOOP_NUM; + my_printf_error(*error_num, ER_SPIDER_INFINITE_LOOP_STR, MYF(0), + top_share->db.str, top_share->table_name.str); + my_afree(loop_check_buf); + DBUG_RETURN(NULL); + } + } + my_afree(loop_check_buf); + } pthread_mutex_lock(&spider_tbl_mutex); #ifdef SPIDER_HAS_HASH_VALUE_TYPE if (!(share = (SPIDER_SHARE*) my_hash_search_using_hash_value( @@ -4731,10 +5047,12 @@ SPIDER_SHARE *spider_get_share( { SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); init_mem_root = TRUE; + + start_new_trans new_trans(thd); if ( !(table_tables = spider_open_sys_table( thd, SPIDER_SYS_TABLES_TABLE_NAME_STR, - SPIDER_SYS_TABLES_TABLE_NAME_LEN, FALSE, &open_tables_backup, + SPIDER_SYS_TABLES_TABLE_NAME_LEN, FALSE, 0, FALSE, error_num)) ) { for (roop_count = 0; @@ -4771,21 +5089,19 @@ SPIDER_SHARE *spider_get_share( share->init_error_time = (time_t) time((time_t*) 0); share->init = TRUE; spider_free_share(share); - goto error_get_link_statuses; + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + goto error_open_sys_table; } } else { memcpy(share->alter_table.tmp_link_statuses, share->link_statuses, sizeof(long) * share->all_link_count); share->link_status_init = TRUE; } + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); } share->have_recovery_link = spider_conn_check_recovery_link(share); - if (table_tables) - { - spider_close_sys_table(thd, table_tables, - &open_tables_backup, FALSE); - table_tables = NULL; - } if (init_mem_root) { free_root(&mem_root, MYF(0)); @@ -4810,7 +5126,7 @@ SPIDER_SHARE *spider_get_share( else first_byte = '0'; - if (!(spider->trx = spider_get_trx(thd, TRUE, error_num))) + if (!(spider->wide_handler->trx = spider_get_trx(thd, TRUE, error_num))) { share->init_error = TRUE; share->init_error_time = (time_t) time((time_t*) 0); @@ -4827,7 +5143,7 @@ SPIDER_SHARE *spider_get_share( if (!share->sts_spider_init) { if ((*error_num = spider_create_spider_object_for_share( - spider->trx, share, &share->sts_spider))) + spider->wide_handler->trx, share, &share->sts_spider))) { pthread_mutex_unlock(&share->mutex); share->init_error = TRUE; @@ -4855,7 +5171,7 @@ SPIDER_SHARE *spider_get_share( if (!share->crd_spider_init) { if ((*error_num = spider_create_spider_object_for_share( - spider->trx, share, &share->crd_spider))) + spider->wide_handler->trx, share, &share->crd_spider))) { pthread_mutex_unlock(&share->mutex); share->init_error = TRUE; @@ -4883,7 +5199,8 @@ SPIDER_SHARE *spider_get_share( sql_command != SQLCOM_DROP_TABLE && sql_command != SQLCOM_ALTER_TABLE && sql_command != SQLCOM_SHOW_CREATE && - (*error_num = spider_create_mon_threads(spider->trx, share)) + (*error_num = spider_create_mon_threads(spider->wide_handler->trx, + share)) ) { share->init_error = TRUE; share->init_error_time = (time_t) time((time_t*) 0); @@ -5054,7 +5371,8 @@ SPIDER_SHARE *spider_get_share( if ( !(spider->conns[roop_count] = spider_get_conn(share, roop_count, spider->conn_keys[roop_count], - spider->trx, spider, FALSE, TRUE, SPIDER_CONN_KIND_MYSQL, + spider->wide_handler->trx, spider, FALSE, TRUE, + SPIDER_CONN_KIND_MYSQL, error_num)) ) { if ( @@ -5062,8 +5380,8 @@ SPIDER_SHARE *spider_get_share( spider->need_mons[roop_count] ) { *error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5162,7 +5480,7 @@ SPIDER_SHARE *spider_get_share( pthread_mutex_lock(&share->sts_mutex); pthread_mutex_lock(&share->crd_mutex); if ((spider_init_error_table = - spider_get_init_error_table(spider->trx, share, FALSE))) + spider_get_init_error_table(spider->wide_handler->trx, share, FALSE))) { DBUG_PRINT("info",("spider diff1=%f", difftime(tmp_time, spider_init_error_table->init_error_time))); @@ -5252,6 +5570,7 @@ SPIDER_SHARE *spider_get_share( my_printf_error(ER_SPIDER_TABLE_OPEN_TIMEOUT_NUM, ER_SPIDER_TABLE_OPEN_TIMEOUT_STR, MYF(0), table_share->db.str, table_share->table_name.str); + spider_free_share(share); goto error_but_no_delete; } my_sleep(10000); // wait 10 ms @@ -5269,6 +5588,7 @@ SPIDER_SHARE *spider_get_share( } if (!share->link_status_init) { + DBUG_ASSERT(!table_tables); /* The link statuses need to be refreshed from the spider_tables table if the operation: @@ -5285,10 +5605,12 @@ SPIDER_SHARE *spider_get_share( { SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); init_mem_root = TRUE; + start_new_trans new_trans(thd); + if ( !(table_tables = spider_open_sys_table( thd, SPIDER_SYS_TABLES_TABLE_NAME_STR, - SPIDER_SYS_TABLES_TABLE_NAME_LEN, FALSE, &open_tables_backup, + SPIDER_SYS_TABLES_TABLE_NAME_LEN, FALSE, 0, FALSE, error_num)) ) { for (roop_count = 0; @@ -5319,21 +5641,20 @@ SPIDER_SHARE *spider_get_share( } pthread_mutex_unlock(&share->mutex); spider_free_share(share); - goto error_get_link_statuses; + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + goto error_open_sys_table; } } else { memcpy(share->alter_table.tmp_link_statuses, share->link_statuses, sizeof(long) * share->all_link_count); share->link_status_init = TRUE; } + thd->commit_whole_transaction_and_close_tables(); + new_trans.restore_old_transaction(); + table_tables= 0; } share->have_recovery_link = spider_conn_check_recovery_link(share); - if (table_tables) - { - spider_close_sys_table(thd, table_tables, - &open_tables_backup, FALSE); - table_tables = NULL; - } if (init_mem_root) { free_root(&mem_root, MYF(0)); @@ -5359,7 +5680,7 @@ SPIDER_SHARE *spider_get_share( first_byte = '0'; spider->share = share; - if (!(spider->trx = spider_get_trx(thd, TRUE, error_num))) + if (!(spider->wide_handler->trx = spider_get_trx(thd, TRUE, error_num))) { spider_free_share(share); goto error_but_no_delete; @@ -5373,7 +5694,7 @@ SPIDER_SHARE *spider_get_share( if (!share->sts_spider_init) { if ((*error_num = spider_create_spider_object_for_share( - spider->trx, share, &share->sts_spider))) + spider->wide_handler->trx, share, &share->sts_spider))) { pthread_mutex_unlock(&share->mutex); spider_free_share(share); @@ -5398,7 +5719,7 @@ SPIDER_SHARE *spider_get_share( if (!share->crd_spider_init) { if ((*error_num = spider_create_spider_object_for_share( - spider->trx, share, &share->crd_spider))) + spider->wide_handler->trx, share, &share->crd_spider))) { pthread_mutex_unlock(&share->mutex); spider_free_share(share); @@ -5423,7 +5744,8 @@ SPIDER_SHARE *spider_get_share( sql_command != SQLCOM_DROP_TABLE && sql_command != SQLCOM_ALTER_TABLE && sql_command != SQLCOM_SHOW_CREATE && - (*error_num = spider_create_mon_threads(spider->trx, share)) + (*error_num = spider_create_mon_threads(spider->wide_handler->trx, + share)) ) { spider_free_share(share); goto error_but_no_delete; @@ -5585,7 +5907,8 @@ SPIDER_SHARE *spider_get_share( if ( !(spider->conns[roop_count] = spider_get_conn(share, roop_count, spider->conn_keys[roop_count], - spider->trx, spider, FALSE, TRUE, SPIDER_CONN_KIND_MYSQL, + spider->wide_handler->trx, spider, FALSE, TRUE, + SPIDER_CONN_KIND_MYSQL, error_num)) ) { if ( @@ -5593,8 +5916,8 @@ SPIDER_SHARE *spider_get_share( spider->need_mons[roop_count] ) { *error_num = spider_ping_table_mon_from_table( - spider->trx, - spider->trx->thd, + spider->wide_handler->trx, + spider->wide_handler->trx->thd, share, roop_count, (uint32) share->monitoring_sid[roop_count], @@ -5685,7 +6008,8 @@ SPIDER_SHARE *spider_get_share( #endif time_t tmp_time = (time_t) time((time_t*) 0); if ((spider_init_error_table = - spider_get_init_error_table(spider->trx, share, FALSE))) + spider_get_init_error_table(spider->wide_handler->trx, share, + FALSE))) { DBUG_PRINT("info",("spider diff2=%f", difftime(tmp_time, spider_init_error_table->init_error_time))); @@ -5776,13 +6100,6 @@ error_hash_insert: spider_free_share_resource_only(share); error_alloc_share: pthread_mutex_unlock(&spider_tbl_mutex); -error_get_link_statuses: - if (table_tables) - { - spider_close_sys_table(thd, table_tables, - &open_tables_backup, FALSE); - table_tables = NULL; - } error_open_sys_table: #ifndef WITHOUT_SPIDER_BG_SEARCH error_crd_spider_init: @@ -5802,7 +6119,6 @@ void spider_free_share_resource_only( ) { DBUG_ENTER("spider_free_share_resource_only"); spider_free_share_alloc(share); - thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->crd_mutex); pthread_mutex_destroy(&share->sts_mutex); pthread_mutex_destroy(&share->mutex); @@ -5882,7 +6198,6 @@ int spider_free_share( #else my_hash_delete(&spider_open_tables, (uchar*) share); #endif - thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->crd_mutex); pthread_mutex_destroy(&share->sts_mutex); pthread_mutex_destroy(&share->mutex); @@ -6054,33 +6369,32 @@ void spider_free_lgtm_tblhnd_share_alloc( DBUG_VOID_RETURN; } -#ifdef WITH_PARTITION_STORAGE_ENGINE -SPIDER_PARTITION_SHARE *spider_get_pt_share( +SPIDER_WIDE_SHARE *spider_get_wide_share( SPIDER_SHARE *share, TABLE_SHARE *table_share, int *error_num ) { - SPIDER_PARTITION_SHARE *partition_share; + SPIDER_WIDE_SHARE *wide_share; char *tmp_name; longlong *tmp_cardinality; - DBUG_ENTER("spider_get_pt_share"); + DBUG_ENTER("spider_get_wide_share"); - pthread_mutex_lock(&spider_pt_share_mutex); + pthread_mutex_lock(&spider_wide_share_mutex); #ifdef SPIDER_HAS_HASH_VALUE_TYPE - if (!(partition_share = (SPIDER_PARTITION_SHARE*) + if (!(wide_share = (SPIDER_WIDE_SHARE*) my_hash_search_using_hash_value( - &spider_open_pt_share, share->table_path_hash_value, + &spider_open_wide_share, share->table_path_hash_value, (uchar*) table_share->path.str, table_share->path.length))) #else - if (!(partition_share = (SPIDER_PARTITION_SHARE*) my_hash_search( - &spider_open_pt_share, + if (!(wide_share = (SPIDER_WIDE_SHARE*) my_hash_search( + &spider_open_wide_share, (uchar*) table_share->path.str, table_share->path.length))) #endif { - DBUG_PRINT("info",("spider create new pt share")); - if (!(partition_share = (SPIDER_PARTITION_SHARE *) + DBUG_PRINT("info",("spider create new wide share")); + if (!(wide_share = (SPIDER_WIDE_SHARE *) spider_bulk_malloc(spider_current_trx, 51, MYF(MY_WME | MY_ZEROFILL), - &partition_share, (uint) (sizeof(*partition_share)), + &wide_share, sizeof(SPIDER_WIDE_SHARE), &tmp_name, (uint) (table_share->path.length + 1), &tmp_cardinality, (uint) (sizeof(*tmp_cardinality) * table_share->fields), @@ -6090,24 +6404,24 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( goto error_alloc_share; } - partition_share->use_count = 0; - partition_share->table_name_length = table_share->path.length; - partition_share->table_name = tmp_name; - memcpy(partition_share->table_name, table_share->path.str, - partition_share->table_name_length); + wide_share->use_count = 0; + wide_share->table_name_length = table_share->path.length; + wide_share->table_name = tmp_name; + memcpy(wide_share->table_name, table_share->path.str, + wide_share->table_name_length); #ifdef SPIDER_HAS_HASH_VALUE_TYPE - partition_share->table_path_hash_value = share->table_path_hash_value; + wide_share->table_path_hash_value = share->table_path_hash_value; #endif - partition_share->cardinality = tmp_cardinality; + wide_share->cardinality = tmp_cardinality; - partition_share->crd_get_time = partition_share->sts_get_time = + wide_share->crd_get_time = wide_share->sts_get_time = share->crd_get_time; #if MYSQL_VERSION_ID < 50500 - if (pthread_mutex_init(&partition_share->sts_mutex, MY_MUTEX_INIT_FAST)) + if (pthread_mutex_init(&wide_share->sts_mutex, MY_MUTEX_INIT_FAST)) #else - if (mysql_mutex_init(spd_key_mutex_pt_share_sts, - &partition_share->sts_mutex, MY_MUTEX_INIT_FAST)) + if (mysql_mutex_init(spd_key_mutex_wide_share_sts, + &wide_share->sts_mutex, MY_MUTEX_INIT_FAST)) #endif { *error_num = HA_ERR_OUT_OF_MEM; @@ -6115,10 +6429,10 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( } #if MYSQL_VERSION_ID < 50500 - if (pthread_mutex_init(&partition_share->crd_mutex, MY_MUTEX_INIT_FAST)) + if (pthread_mutex_init(&wide_share->crd_mutex, MY_MUTEX_INIT_FAST)) #else - if (mysql_mutex_init(spd_key_mutex_pt_share_crd, - &partition_share->crd_mutex, MY_MUTEX_INIT_FAST)) + if (mysql_mutex_init(spd_key_mutex_wide_share_crd, + &wide_share->crd_mutex, MY_MUTEX_INIT_FAST)) #endif { *error_num = HA_ERR_OUT_OF_MEM; @@ -6126,11 +6440,11 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( } #if MYSQL_VERSION_ID < 50500 - if (pthread_mutex_init(&partition_share->pt_handler_mutex, + if (pthread_mutex_init(&wide_share->pt_handler_mutex, MY_MUTEX_INIT_FAST)) #else if (mysql_mutex_init(spd_key_mutex_pt_handler, - &partition_share->pt_handler_mutex, MY_MUTEX_INIT_FAST)) + &wide_share->pt_handler_mutex, MY_MUTEX_INIT_FAST)) #endif { *error_num = HA_ERR_OUT_OF_MEM; @@ -6138,130 +6452,133 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( } if( - my_hash_init(PSI_INSTRUMENT_ME, &partition_share->pt_handler_hash, spd_charset_utf8mb3_bin, + my_hash_init(PSI_INSTRUMENT_ME, &wide_share->pt_handler_hash, spd_charset_utf8mb3_bin, 32, 0, 0, (my_hash_get_key) spider_pt_handler_share_get_key, 0, 0) ) { *error_num = HA_ERR_OUT_OF_MEM; goto error_init_pt_handler_hash; } - spider_alloc_calc_mem_init(partition_share->pt_handler_hash, 142); - spider_alloc_calc_mem(spider_current_trx, - partition_share->pt_handler_hash, - partition_share->pt_handler_hash.array.max_element * - partition_share->pt_handler_hash.array.size_of_element); - uint old_elements = spider_open_pt_share.array.max_element; + thr_lock_init(&wide_share->lock); + + spider_alloc_calc_mem_init(wide_share->pt_handler_hash, 142); + spider_alloc_calc_mem(spider_current_trx, + wide_share->pt_handler_hash, + wide_share->pt_handler_hash.array.max_element * + wide_share->pt_handler_hash.array.size_of_element); + + uint old_elements = spider_open_wide_share.array.max_element; #ifdef HASH_UPDATE_WITH_HASH_VALUE - if (my_hash_insert_with_hash_value(&spider_open_pt_share, + if (my_hash_insert_with_hash_value(&spider_open_wide_share, share->table_path_hash_value, - (uchar*) partition_share)) + (uchar*) wide_share)) #else - if (my_hash_insert(&spider_open_pt_share, (uchar*) partition_share)) + if (my_hash_insert(&spider_open_wide_share, (uchar*) wide_share)) #endif { *error_num = HA_ERR_OUT_OF_MEM; goto error_hash_insert; } - if (spider_open_pt_share.array.max_element > old_elements) + if (spider_open_wide_share.array.max_element > old_elements) { spider_alloc_calc_mem(spider_current_trx, - spider_open_pt_share, - (spider_open_pt_share.array.max_element - old_elements) * - spider_open_pt_share.array.size_of_element); + spider_open_wide_share, + (spider_open_wide_share.array.max_element - old_elements) * + spider_open_wide_share.array.size_of_element); } } - partition_share->use_count++; - pthread_mutex_unlock(&spider_pt_share_mutex); + wide_share->use_count++; + pthread_mutex_unlock(&spider_wide_share_mutex); - DBUG_PRINT("info",("spider partition_share=%p", partition_share)); - DBUG_RETURN(partition_share); + DBUG_PRINT("info",("spider wide_share=%p", wide_share)); + DBUG_RETURN(wide_share); error_hash_insert: spider_free_mem_calc(spider_current_trx, - partition_share->pt_handler_hash_id, - partition_share->pt_handler_hash.array.max_element * - partition_share->pt_handler_hash.array.size_of_element); - my_hash_free(&partition_share->pt_handler_hash); + wide_share->pt_handler_hash_id, + wide_share->pt_handler_hash.array.max_element * + wide_share->pt_handler_hash.array.size_of_element); + my_hash_free(&wide_share->pt_handler_hash); error_init_pt_handler_hash: - pthread_mutex_destroy(&partition_share->pt_handler_mutex); + pthread_mutex_destroy(&wide_share->pt_handler_mutex); error_init_pt_handler_mutex: - pthread_mutex_destroy(&partition_share->crd_mutex); + pthread_mutex_destroy(&wide_share->crd_mutex); error_init_crd_mutex: - pthread_mutex_destroy(&partition_share->sts_mutex); + pthread_mutex_destroy(&wide_share->sts_mutex); error_init_sts_mutex: - spider_free(spider_current_trx, partition_share, MYF(0)); + spider_free(spider_current_trx, wide_share, MYF(0)); error_alloc_share: - pthread_mutex_unlock(&spider_pt_share_mutex); + pthread_mutex_unlock(&spider_wide_share_mutex); DBUG_RETURN(NULL); } -int spider_free_pt_share( - SPIDER_PARTITION_SHARE *partition_share +int spider_free_wide_share( + SPIDER_WIDE_SHARE *wide_share ) { - DBUG_ENTER("spider_free_pt_share"); - pthread_mutex_lock(&spider_pt_share_mutex); - if (!--partition_share->use_count) + DBUG_ENTER("spider_free_wide_share"); + pthread_mutex_lock(&spider_wide_share_mutex); + if (!--wide_share->use_count) { + thr_lock_delete(&wide_share->lock); #ifdef HASH_UPDATE_WITH_HASH_VALUE - my_hash_delete_with_hash_value(&spider_open_pt_share, - partition_share->table_path_hash_value, (uchar*) partition_share); + my_hash_delete_with_hash_value(&spider_open_wide_share, + wide_share->table_path_hash_value, (uchar*) wide_share); #else - my_hash_delete(&spider_open_pt_share, (uchar*) partition_share); + my_hash_delete(&spider_open_wide_share, (uchar*) wide_share); #endif spider_free_mem_calc(spider_current_trx, - partition_share->pt_handler_hash_id, - partition_share->pt_handler_hash.array.max_element * - partition_share->pt_handler_hash.array.size_of_element); - my_hash_free(&partition_share->pt_handler_hash); - pthread_mutex_destroy(&partition_share->pt_handler_mutex); - pthread_mutex_destroy(&partition_share->crd_mutex); - pthread_mutex_destroy(&partition_share->sts_mutex); - spider_free(spider_current_trx, partition_share, MYF(0)); + wide_share->pt_handler_hash_id, + wide_share->pt_handler_hash.array.max_element * + wide_share->pt_handler_hash.array.size_of_element); + my_hash_free(&wide_share->pt_handler_hash); + pthread_mutex_destroy(&wide_share->pt_handler_mutex); + pthread_mutex_destroy(&wide_share->crd_mutex); + pthread_mutex_destroy(&wide_share->sts_mutex); + spider_free(spider_current_trx, wide_share, MYF(0)); } - pthread_mutex_unlock(&spider_pt_share_mutex); + pthread_mutex_unlock(&spider_wide_share_mutex); DBUG_RETURN(0); } -void spider_copy_sts_to_pt_share( - SPIDER_PARTITION_SHARE *partition_share, +void spider_copy_sts_to_wide_share( + SPIDER_WIDE_SHARE *wide_share, SPIDER_SHARE *share ) { DBUG_ENTER("spider_copy_sts_to_pt_share"); - partition_share->stat = share->stat; + wide_share->stat = share->stat; DBUG_VOID_RETURN; } void spider_copy_sts_to_share( SPIDER_SHARE *share, - SPIDER_PARTITION_SHARE *partition_share + SPIDER_WIDE_SHARE *wide_share ) { DBUG_ENTER("spider_copy_sts_to_share"); - share->stat = partition_share->stat; + share->stat = wide_share->stat; DBUG_VOID_RETURN; } -void spider_copy_crd_to_pt_share( - SPIDER_PARTITION_SHARE *partition_share, +void spider_copy_crd_to_wide_share( + SPIDER_WIDE_SHARE *wide_share, SPIDER_SHARE *share, int fields ) { - DBUG_ENTER("spider_copy_crd_to_pt_share"); - memcpy(partition_share->cardinality, share->cardinality, + DBUG_ENTER("spider_copy_crd_to_wide_share"); + memcpy(wide_share->cardinality, share->cardinality, sizeof(longlong) * fields); DBUG_VOID_RETURN; } void spider_copy_crd_to_share( SPIDER_SHARE *share, - SPIDER_PARTITION_SHARE *partition_share, + SPIDER_WIDE_SHARE *wide_share, int fields ) { DBUG_ENTER("spider_copy_crd_to_share"); - memcpy(share->cardinality, partition_share->cardinality, + memcpy(share->cardinality, wide_share->cardinality, sizeof(longlong) * fields); DBUG_VOID_RETURN; } -#endif int spider_open_all_tables( SPIDER_TRX *trx, @@ -6425,7 +6742,7 @@ int spider_open_all_tables( free_root(&mem_root, MYF(0)); DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider->lock_type = TL_READ_NO_INSERT; + spider->wide_handler->lock_type = TL_READ_NO_INSERT; if (!(share = (SPIDER_SHARE *) spider_bulk_malloc(spider_current_trx, 52, MYF(MY_WME | MY_ZEROFILL), @@ -6463,7 +6780,7 @@ int spider_open_all_tables( memcpy(longlong_info, &tmp_longlong, sizeof(longlong) * SPIDER_TMP_SHARE_LONGLONG_COUNT); spider->share = share; - spider->trx = trx; + spider->wide_handler->trx = trx; spider->conns = conns; spider->need_mons = need_mon; spider->conn_link_idx[0] = 0; @@ -6836,10 +7153,10 @@ int spider_db_done( my_hash_free(&spider_lgtm_tblhnd_share_hash); #ifdef WITH_PARTITION_STORAGE_ENGINE spider_free_mem_calc(spider_current_trx, - spider_open_pt_share_id, - spider_open_pt_share.array.max_element * - spider_open_pt_share.array.size_of_element); - my_hash_free(&spider_open_pt_share); + spider_open_wide_share_id, + spider_open_wide_share.array.max_element * + spider_open_wide_share.array.size_of_element); + my_hash_free(&spider_open_wide_share); #endif pthread_mutex_lock(&spider_init_error_tbl_mutex); while ((spider_init_error_table = (SPIDER_INIT_ERROR_TABLE*) @@ -6877,7 +7194,7 @@ int spider_db_done( pthread_mutex_destroy(&spider_conn_mutex); pthread_mutex_destroy(&spider_lgtm_tblhnd_share_mutex); #ifdef WITH_PARTITION_STORAGE_ENGINE - pthread_mutex_destroy(&spider_pt_share_mutex); + pthread_mutex_destroy(&spider_wide_share_mutex); #endif pthread_mutex_destroy(&spider_init_error_tbl_mutex); pthread_mutex_destroy(&spider_conn_id_mutex); @@ -6927,11 +7244,12 @@ int spider_db_init( ) { int error_num = HA_ERR_OUT_OF_MEM, roop_count; uint dbton_id = 0; + uchar addr[6]; handlerton *spider_hton = (handlerton *)p; DBUG_ENTER("spider_db_init"); spider_hton_ptr = spider_hton; - spider_hton->flags = HTON_NO_FLAGS; + spider_hton->flags = HTON_NO_FLAGS | HTON_AUTOMATIC_DELETE_TABLE; #ifdef HTON_CAN_READ_CONNECT_STRING_IN_PARTITION spider_hton->flags |= HTON_CAN_READ_CONNECT_STRING_IN_PARTITION; #endif @@ -6968,6 +7286,16 @@ int spider_db_init( spider_hton->create_group_by = spider_create_group_by_handler; #endif + if (my_gethwaddr((uchar *) addr)) + { + my_printf_error(ER_SPIDER_CANT_NUM, ER_SPIDER_CANT_STR1, MYF(0), + "get hardware address with error ", errno); + } + spider_unique_id.str = spider_unique_id_buf; + spider_unique_id.length = my_sprintf(spider_unique_id_buf, + (spider_unique_id_buf, "-%02x%02x%02x%02x%02x%02x-%lx-", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], (ulong) getpid())); + memset(&spider_alloc_func_name, 0, sizeof(spider_alloc_func_name)); memset(&spider_alloc_file_name, 0, sizeof(spider_alloc_file_name)); memset(&spider_alloc_line_no, 0, sizeof(spider_alloc_line_no)); @@ -7053,12 +7381,12 @@ int spider_db_init( #ifdef WITH_PARTITION_STORAGE_ENGINE #if MYSQL_VERSION_ID < 50500 - if (pthread_mutex_init(&spider_pt_share_mutex, MY_MUTEX_INIT_FAST)) + if (pthread_mutex_init(&spider_wide_share_mutex, MY_MUTEX_INIT_FAST)) #else - if (mysql_mutex_init(spd_key_mutex_pt_share, - &spider_pt_share_mutex, MY_MUTEX_INIT_FAST)) + if (mysql_mutex_init(spd_key_mutex_wide_share, + &spider_wide_share_mutex, MY_MUTEX_INIT_FAST)) #endif - goto error_pt_share_mutex_init; + goto error_wide_share_mutex_init; #endif #if MYSQL_VERSION_ID < 50500 @@ -7146,15 +7474,17 @@ int spider_db_init( spider_init_error_tables.array.max_element * spider_init_error_tables.array.size_of_element); #ifdef WITH_PARTITION_STORAGE_ENGINE - if (my_hash_init(PSI_INSTRUMENT_ME, &spider_open_pt_share, spd_charset_utf8mb3_bin, 32, 0, 0, - (my_hash_get_key) spider_pt_share_get_key, 0, 0)) - goto error_open_pt_share_hash_init; + if( + my_hash_init(PSI_INSTRUMENT_ME, &spider_open_wide_share, spd_charset_utf8mb3_bin, 32, 0, 0, + (my_hash_get_key) spider_wide_share_get_key, 0, 0) + ) + goto error_open_wide_share_hash_init; - spider_alloc_calc_mem_init(spider_open_pt_share, 145); + spider_alloc_calc_mem_init(spider_open_wide_share, 145); spider_alloc_calc_mem(NULL, - spider_open_pt_share, - spider_open_pt_share.array.max_element * - spider_open_pt_share.array.size_of_element); + spider_open_wide_share, + spider_open_wide_share.array.max_element * + spider_open_wide_share.array.size_of_element); #endif if (my_hash_init(PSI_INSTRUMENT_ME, &spider_lgtm_tblhnd_share_hash, spd_charset_utf8mb3_bin, 32, 0, 0, @@ -7422,11 +7752,11 @@ error_open_connections_hash_init: error_lgtm_tblhnd_share_hash_init: #ifdef WITH_PARTITION_STORAGE_ENGINE spider_free_mem_calc(NULL, - spider_open_pt_share_id, - spider_open_pt_share.array.max_element * - spider_open_pt_share.array.size_of_element); - my_hash_free(&spider_open_pt_share); -error_open_pt_share_hash_init: + spider_open_wide_share_id, + spider_open_wide_share.array.max_element * + spider_open_wide_share.array.size_of_element); + my_hash_free(&spider_open_wide_share); +error_open_wide_share_hash_init: #endif spider_free_mem_calc(NULL, spider_init_error_tables_id, @@ -7459,8 +7789,8 @@ error_conn_mutex_init: pthread_mutex_destroy(&spider_lgtm_tblhnd_share_mutex); error_lgtm_tblhnd_share_mutex_init: #ifdef WITH_PARTITION_STORAGE_ENGINE - pthread_mutex_destroy(&spider_pt_share_mutex); -error_pt_share_mutex_init: + pthread_mutex_destroy(&spider_wide_share_mutex); +error_wide_share_mutex_init: #endif pthread_mutex_destroy(&spider_init_error_tbl_mutex); error_init_error_tbl_mutex_init: @@ -7626,7 +7956,9 @@ int spider_get_sts( int sts_sync_level, uint flag ) { - int get_type __attribute__ ((unused)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + int get_type; +#endif int error_num = 0; bool need_to_get = TRUE; DBUG_ENTER("spider_get_sts"); @@ -7638,26 +7970,26 @@ int spider_get_sts( /* get */ get_type = 1; } else if ( - !share->partition_share->sts_init + !share->wide_share->sts_init ) { - pthread_mutex_lock(&share->partition_share->sts_mutex); - if (!share->partition_share->sts_init) + pthread_mutex_lock(&share->wide_share->sts_mutex); + if (!share->wide_share->sts_init) { /* get after mutex_lock */ get_type = 2; } else { - pthread_mutex_unlock(&share->partition_share->sts_mutex); + pthread_mutex_unlock(&share->wide_share->sts_mutex); /* copy */ get_type = 0; } } else if ( - difftime(share->sts_get_time, share->partition_share->sts_get_time) < + difftime(share->sts_get_time, share->wide_share->sts_get_time) < sts_interval ) { /* copy */ get_type = 0; } else if ( - !pthread_mutex_trylock(&share->partition_share->sts_mutex) + !pthread_mutex_trylock(&share->wide_share->sts_mutex) ) { /* get after mutex_trylock */ get_type = 3; @@ -7689,7 +8021,7 @@ int spider_get_sts( { #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type == 0) - spider_copy_sts_to_share(share, share->partition_share); + spider_copy_sts_to_share(share, share->wide_share); else { #endif error_num = spider_db_show_table_status(spider, link_idx, sts_mode, flag); @@ -7699,7 +8031,7 @@ int spider_get_sts( } #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type >= 2) - pthread_mutex_unlock(&share->partition_share->sts_mutex); + pthread_mutex_unlock(&share->wide_share->sts_mutex); #endif if (error_num) { @@ -7707,7 +8039,7 @@ int spider_get_sts( SPIDER_PARTITION_HANDLER_SHARE *partition_handler_share = spider->partition_handler_share; if ( - !share->partition_share->sts_init && + !share->wide_share->sts_init && sts_sync >= sts_sync_level && get_type > 1 && partition_handler_share && @@ -7720,9 +8052,9 @@ int spider_get_sts( double tmp_sts_interval; int tmp_sts_mode; int tmp_sts_sync; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; for (roop_count = 1; - roop_count < (int) partition_handler_share->use_count; + roop_count < (int) partition_handler_share->no_parts; roop_count++) { tmp_spider = @@ -7734,12 +8066,12 @@ int spider_get_sts( spider_get_sts(tmp_share, tmp_spider->search_link_idx, tmp_time, tmp_spider, tmp_sts_interval, tmp_sts_mode, tmp_sts_sync, 1, flag); - if (share->partition_share->sts_init) + if (share->wide_share->sts_init) { error_num = 0; thd->clear_error(); get_type = 0; - spider_copy_sts_to_share(share, share->partition_share); + spider_copy_sts_to_share(share, share->wide_share); break; } } @@ -7751,9 +8083,9 @@ int spider_get_sts( #ifdef WITH_PARTITION_STORAGE_ENGINE if (sts_sync >= sts_sync_level && get_type > 0) { - spider_copy_sts_to_pt_share(share->partition_share, share); - share->partition_share->sts_get_time = tmp_time; - share->partition_share->sts_init = TRUE; + spider_copy_sts_to_wide_share(share->wide_share, share); + share->wide_share->sts_get_time = tmp_time; + share->wide_share->sts_init = TRUE; } #endif share->sts_get_time = tmp_time; @@ -7774,7 +8106,9 @@ int spider_get_crd( #endif int crd_sync_level ) { - int get_type __attribute__ ((unused)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + int get_type; +#endif int error_num = 0; bool need_to_get = TRUE; DBUG_ENTER("spider_get_crd"); @@ -7786,26 +8120,26 @@ int spider_get_crd( /* get */ get_type = 1; } else if ( - !share->partition_share->crd_init + !share->wide_share->crd_init ) { - pthread_mutex_lock(&share->partition_share->crd_mutex); - if (!share->partition_share->crd_init) + pthread_mutex_lock(&share->wide_share->crd_mutex); + if (!share->wide_share->crd_init) { /* get after mutex_lock */ get_type = 2; } else { - pthread_mutex_unlock(&share->partition_share->crd_mutex); + pthread_mutex_unlock(&share->wide_share->crd_mutex); /* copy */ get_type = 0; } } else if ( - difftime(share->crd_get_time, share->partition_share->crd_get_time) < + difftime(share->crd_get_time, share->wide_share->crd_get_time) < crd_interval ) { /* copy */ get_type = 0; } else if ( - !pthread_mutex_trylock(&share->partition_share->crd_mutex) + !pthread_mutex_trylock(&share->wide_share->crd_mutex) ) { /* get after mutex_trylock */ get_type = 3; @@ -7837,7 +8171,7 @@ int spider_get_crd( { #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type == 0) - spider_copy_crd_to_share(share, share->partition_share, + spider_copy_crd_to_share(share, share->wide_share, table->s->fields); else { #endif @@ -7848,7 +8182,7 @@ int spider_get_crd( } #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type >= 2) - pthread_mutex_unlock(&share->partition_share->crd_mutex); + pthread_mutex_unlock(&share->wide_share->crd_mutex); #endif if (error_num) { @@ -7856,7 +8190,7 @@ int spider_get_crd( SPIDER_PARTITION_HANDLER_SHARE *partition_handler_share = spider->partition_handler_share; if ( - !share->partition_share->crd_init && + !share->wide_share->crd_init && crd_sync >= crd_sync_level && get_type > 1 && partition_handler_share && @@ -7869,9 +8203,9 @@ int spider_get_crd( double tmp_crd_interval; int tmp_crd_mode; int tmp_crd_sync; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; for (roop_count = 1; - roop_count < (int) partition_handler_share->use_count; + roop_count < (int) partition_handler_share->no_parts; roop_count++) { tmp_spider = @@ -7883,12 +8217,12 @@ int spider_get_crd( spider_get_crd(tmp_share, tmp_spider->search_link_idx, tmp_time, tmp_spider, table, tmp_crd_interval, tmp_crd_mode, tmp_crd_sync, 1); - if (share->partition_share->crd_init) + if (share->wide_share->crd_init) { error_num = 0; thd->clear_error(); get_type = 0; - spider_copy_crd_to_share(share, share->partition_share, + spider_copy_crd_to_share(share, share->wide_share, table->s->fields); break; } @@ -7901,10 +8235,10 @@ int spider_get_crd( #ifdef WITH_PARTITION_STORAGE_ENGINE if (crd_sync >= crd_sync_level && get_type > 0) { - spider_copy_crd_to_pt_share(share->partition_share, share, + spider_copy_crd_to_wide_share(share->wide_share, share, table->s->fields); - share->partition_share->crd_get_time = tmp_time; - share->partition_share->crd_init = TRUE; + share->wide_share->crd_get_time = tmp_time; + share->wide_share->crd_init = TRUE; } #endif share->crd_get_time = tmp_time; @@ -7917,14 +8251,14 @@ void spider_set_result_list_param( ) { SPIDER_RESULT_LIST *result_list = &spider->result_list; SPIDER_SHARE *share = spider->share; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; DBUG_ENTER("spider_set_result_list_param"); result_list->internal_offset = spider_param_internal_offset(thd, share->internal_offset); result_list->internal_limit = #ifdef INFO_KIND_FORCE_LIMIT_BEGIN - spider->info_limit < 9223372036854775807LL ? - spider->info_limit : + spider->wide_handler->info_limit < 9223372036854775807LL ? + spider->wide_handler->info_limit : #endif spider_param_internal_limit(thd, share->internal_limit); result_list->split_read = spider_split_read_param(spider); @@ -8203,12 +8537,13 @@ void spider_set_tmp_share_pointer( tmp_share->tgt_ssl_keys = &tmp_connect_info[12]; tmp_share->tgt_default_files = &tmp_connect_info[13]; tmp_share->tgt_default_groups = &tmp_connect_info[14]; - tmp_share->tgt_pk_names = &tmp_connect_info[15]; - tmp_share->tgt_sequence_names = &tmp_connect_info[16]; - tmp_share->static_link_ids = &tmp_connect_info[17]; + tmp_share->tgt_dsns = &tmp_connect_info[15]; + tmp_share->tgt_pk_names = &tmp_connect_info[16]; + tmp_share->tgt_sequence_names = &tmp_connect_info[17]; + tmp_share->static_link_ids = &tmp_connect_info[18]; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - tmp_share->hs_read_socks = &tmp_connect_info[18]; - tmp_share->hs_write_socks = &tmp_connect_info[19]; + tmp_share->hs_read_socks = &tmp_connect_info[19]; + tmp_share->hs_write_socks = &tmp_connect_info[20]; #endif tmp_share->tgt_ports = &tmp_long[0]; tmp_share->tgt_ssl_vscs = &tmp_long[1]; @@ -8236,6 +8571,7 @@ void spider_set_tmp_share_pointer( tmp_long[15] = -1; tmp_share->access_balances = &tmp_long[17]; tmp_share->bka_table_name_types = &tmp_long[18]; + tmp_share->strict_group_bys = &tmp_long[19]; tmp_share->monitoring_limit = &tmp_longlong[0]; tmp_share->monitoring_sid = &tmp_longlong[1]; #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -8256,12 +8592,13 @@ void spider_set_tmp_share_pointer( tmp_share->tgt_ssl_keys_lengths = &tmp_connect_info_length[12]; tmp_share->tgt_default_files_lengths = &tmp_connect_info_length[13]; tmp_share->tgt_default_groups_lengths = &tmp_connect_info_length[14]; - tmp_share->tgt_pk_names_lengths = &tmp_connect_info_length[15]; - tmp_share->tgt_sequence_names_lengths = &tmp_connect_info_length[16]; - tmp_share->static_link_ids_lengths = &tmp_connect_info_length[17]; + tmp_share->tgt_dsns_lengths = &tmp_connect_info_length[15]; + tmp_share->tgt_pk_names_lengths = &tmp_connect_info_length[16]; + tmp_share->tgt_sequence_names_lengths = &tmp_connect_info_length[17]; + tmp_share->static_link_ids_lengths = &tmp_connect_info_length[18]; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) - tmp_share->hs_read_socks_lengths = &tmp_connect_info_length[18]; - tmp_share->hs_write_socks_lengths = &tmp_connect_info_length[19]; + tmp_share->hs_read_socks_lengths = &tmp_connect_info_length[19]; + tmp_share->hs_write_socks_lengths = &tmp_connect_info_length[20]; #endif tmp_share->server_names_length = 1; tmp_share->tgt_table_names_length = 1; @@ -8278,6 +8615,7 @@ void spider_set_tmp_share_pointer( tmp_share->tgt_ssl_keys_length = 1; tmp_share->tgt_default_files_length = 1; tmp_share->tgt_default_groups_length = 1; + tmp_share->tgt_dsns_length = 1; tmp_share->tgt_pk_names_length = 1; tmp_share->tgt_sequence_names_length = 1; tmp_share->static_link_ids_length = 1; @@ -8311,6 +8649,7 @@ void spider_set_tmp_share_pointer( tmp_share->net_write_timeouts_length = 1; tmp_share->access_balances_length = 1; tmp_share->bka_table_name_types_length = 1; + tmp_share->strict_group_bys_length = 1; #ifndef WITHOUT_SPIDER_BG_SEARCH tmp_share->monitoring_bg_flag[0] = -1; @@ -8404,7 +8743,7 @@ void spider_free_tmp_dbton_handler( TABLE_LIST *spider_get_parent_table_list( ha_spider *spider ) { - TABLE *table = spider->get_top_table(); + TABLE *table = spider->get_table(); DBUG_ENTER("spider_get_parent_table_list"); DBUG_RETURN(table->pos_in_table_list); } @@ -8470,7 +8809,7 @@ longlong spider_split_read_param( ) { SPIDER_SHARE *share = spider->share; SPIDER_RESULT_LIST *result_list = &spider->result_list; - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; st_select_lex *select_lex; longlong select_limit; longlong offset_limit; @@ -8479,10 +8818,11 @@ longlong spider_split_read_param( DBUG_ENTER("spider_split_read_param"); result_list->set_split_read_count = 1; #ifdef INFO_KIND_FORCE_LIMIT_BEGIN - if (spider->info_limit < 9223372036854775807LL) + if (spider->wide_handler->info_limit < 9223372036854775807LL) { - DBUG_PRINT("info",("spider info_limit=%lld", spider->info_limit)); - longlong info_limit = spider->info_limit; + DBUG_PRINT("info",("spider info_limit=%lld", + spider->wide_handler->info_limit)); + longlong info_limit = spider->wide_handler->info_limit; result_list->split_read_base = info_limit; result_list->semi_split_read = 0; result_list->first_read = info_limit; @@ -8502,7 +8842,8 @@ longlong spider_split_read_param( { int bulk_update_mode = spider_param_bulk_update_mode(thd, share->bulk_update_mode); - DBUG_PRINT("info",("spider sql_command=%u", spider->sql_command)); + DBUG_PRINT("info",("spider sql_command=%u", + spider->wide_handler->sql_command)); DBUG_PRINT("info",("spider bulk_update_mode=%d", bulk_update_mode)); DBUG_PRINT("info",("spider support_bulk_update_sql=%s", spider->support_bulk_update_sql() ? "TRUE" : "FALSE")); @@ -8510,32 +8851,32 @@ longlong spider_split_read_param( bool inserting = ( #ifdef HS_HAS_SQLCOM - spider->sql_command == SQLCOM_HS_INSERT || + spider->wide_handler->sql_command == SQLCOM_HS_INSERT || #endif - spider->sql_command == SQLCOM_INSERT || - spider->sql_command == SQLCOM_INSERT_SELECT + spider->wide_handler->sql_command == SQLCOM_INSERT || + spider->wide_handler->sql_command == SQLCOM_INSERT_SELECT ); #endif bool updating = ( #ifdef HS_HAS_SQLCOM - spider->sql_command == SQLCOM_HS_UPDATE || + spider->wide_handler->sql_command == SQLCOM_HS_UPDATE || #endif - spider->sql_command == SQLCOM_UPDATE || - spider->sql_command == SQLCOM_UPDATE_MULTI + spider->wide_handler->sql_command == SQLCOM_UPDATE || + spider->wide_handler->sql_command == SQLCOM_UPDATE_MULTI ); bool deleting = ( #ifdef HS_HAS_SQLCOM - spider->sql_command == SQLCOM_HS_DELETE || + spider->wide_handler->sql_command == SQLCOM_HS_DELETE || #endif - spider->sql_command == SQLCOM_DELETE || - spider->sql_command == SQLCOM_DELETE_MULTI + spider->wide_handler->sql_command == SQLCOM_DELETE || + spider->wide_handler->sql_command == SQLCOM_DELETE_MULTI ); bool replacing = ( - spider->sql_command == SQLCOM_REPLACE || - spider->sql_command == SQLCOM_REPLACE_SELECT + spider->wide_handler->sql_command == SQLCOM_REPLACE || + spider->wide_handler->sql_command == SQLCOM_REPLACE_SELECT ); DBUG_PRINT("info",("spider updating=%s", updating ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider deleting=%s", deleting ? "TRUE" : "FALSE")); @@ -8721,20 +9062,20 @@ void spider_next_split_read_param( bool spider_check_direct_order_limit( ha_spider *spider ) { - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; st_select_lex *select_lex; longlong select_limit; longlong offset_limit; DBUG_ENTER("spider_check_direct_order_limit"); - if (spider_check_index_merge(spider->get_top_table(), + if (spider_check_index_merge(spider->get_table(), spider_get_select_lex(spider))) { DBUG_PRINT("info",("spider set use_index_merge")); spider->use_index_merge = TRUE; } DBUG_PRINT("info",("spider SQLCOM_HA_READ=%s", - (spider->sql_command == SQLCOM_HA_READ) ? "TRUE" : "FALSE")); + (spider->wide_handler->sql_command == SQLCOM_HA_READ) ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider sql_kinds with SPIDER_SQL_KIND_HANDLER=%s", (spider->sql_kinds & SPIDER_SQL_KIND_HANDLER) ? "TRUE" : "FALSE")); DBUG_PRINT("info",("spider use_index_merge=%s", @@ -8746,7 +9087,7 @@ bool spider_check_direct_order_limit( spider->is_bulk_access_clone ? "TRUE" : "FALSE")); #endif if ( - spider->sql_command != SQLCOM_HA_READ && + spider->wide_handler->sql_command != SQLCOM_HA_READ && !spider->use_index_merge && #ifdef HA_CAN_BULK_ACCESS (!spider->is_clone || spider->is_bulk_access_clone) @@ -8904,7 +9245,7 @@ bool spider_check_direct_order_limit( DBUG_PRINT("info",("spider TRUE")); spider->result_list.internal_limit = select_limit + offset_limit; spider->result_list.split_read = select_limit + offset_limit; - spider->trx->direct_order_limit_count++; + spider->wide_handler->trx->direct_order_limit_count++; DBUG_RETURN(TRUE); } } @@ -8983,22 +9324,9 @@ Field *spider_field_exchange( #endif DBUG_PRINT("info",("spider in field=%p", field)); DBUG_PRINT("info",("spider in field->table=%p", field->table)); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - if (handler->set_top_table_fields) - { - DBUG_PRINT("info",("spider top_table=%p", handler->top_table)); - if (field->table != handler->top_table) - DBUG_RETURN(NULL); - if (!(field = handler->top_table_field[field->field_index])) - DBUG_RETURN(NULL); - } else { -#endif DBUG_PRINT("info",("spider table=%p", handler->get_table())); if (field->table != handler->get_table()) DBUG_RETURN(NULL); -#ifdef HANDLER_HAS_TOP_TABLE_FIELDS - } -#endif DBUG_PRINT("info",("spider out field=%p", field)); DBUG_RETURN(field); } @@ -9008,7 +9336,7 @@ int spider_set_direct_limit_offset( ha_spider *spider ) { #ifndef SPIDER_ENGINE_CONDITION_PUSHDOWN_IS_ALWAYS_ON - THD *thd = spider->trx->thd; + THD *thd = spider->wide_handler->trx->thd; #endif st_select_lex *select_lex; longlong select_limit; @@ -9020,10 +9348,11 @@ int spider_set_direct_limit_offset( DBUG_RETURN(TRUE); if ( - spider->pt_handler_share_creator && - spider->pt_handler_share_creator != spider + spider->partition_handler_share && + !spider->pt_handler_share_owner ) { - if (spider->pt_handler_share_creator->result_list.direct_limit_offset == TRUE) + if (spider->partition_handler_share->owner-> + result_list.direct_limit_offset == TRUE) { spider->result_list.direct_limit_offset = TRUE; DBUG_RETURN(TRUE); @@ -9033,7 +9362,7 @@ int spider_set_direct_limit_offset( } if ( - spider->sql_command != SQLCOM_SELECT || + spider->wide_handler->sql_command != SQLCOM_SELECT || #ifdef HANDLER_HAS_DIRECT_AGGREGATE spider->result_list.direct_aggregate || #endif @@ -9076,7 +9405,8 @@ int spider_set_direct_limit_offset( OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) || #endif #endif - spider->condition // conditions is null may be no where condition in rand_init + // conditions is null may be no where condition in rand_init + spider->wide_handler->condition ) DBUG_RETURN(FALSE); @@ -9276,7 +9606,9 @@ int spider_discover_table_structure( #endif Open_tables_backup open_tables_backup; TABLE *table_tables; - uint str_len __attribute__ ((unused)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + uint str_len; +#endif char buf[MAX_FIELD_WIDTH]; spider_string str(buf, sizeof(buf), system_charset_info); DBUG_ENTER("spider_discover_table_structure"); @@ -9631,6 +9963,7 @@ int spider_create_spider_object_for_share( char **hs_w_conn_keys; #endif spider_db_handler **dbton_hdl; + SPIDER_WIDE_HANDLER *wide_handler; DBUG_ENTER("spider_create_spider_object_for_share"); DBUG_PRINT("info",("spider trx=%p", trx)); DBUG_PRINT("info",("spider share=%p", share)); @@ -9660,6 +9993,7 @@ int spider_create_spider_object_for_share( &hs_r_conn_keys, (uint) (sizeof(char *) * share->link_count), &hs_w_conn_keys, (uint) (sizeof(char *) * share->link_count), &dbton_hdl, (uint) (sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE), + &wide_handler, (uint) sizeof(SPIDER_WIDE_HANDLER), NullS)) ) #else @@ -9671,6 +10005,7 @@ int spider_create_spider_object_for_share( &conn_can_fo, (uint) (sizeof(uchar) * share->link_bitmap_size), &conn_keys, (uint) (sizeof(char *) * share->link_count), &dbton_hdl, (uint) (sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE), + &wide_handler, (uint) sizeof(SPIDER_WIDE_HANDLER), NullS)) ) #endif @@ -9679,7 +10014,8 @@ int spider_create_spider_object_for_share( goto error_need_mons_alloc; } DBUG_PRINT("info",("spider need_mons=%p", need_mons)); - (*spider)->trx = trx; + (*spider)->wide_handler = wide_handler; + wide_handler->trx = trx; (*spider)->change_table_ptr(&share->table, share->table_share); (*spider)->share = share; (*spider)->conns = conns; @@ -9988,13 +10324,22 @@ void *spider_table_bg_sts_action( thd->mysys_var->current_mutex = spd_LOCK_server_started; if (!(*spd_mysqld_server_started) && !thd->killed) { - pthread_cond_wait(spd_COND_server_started, spd_LOCK_server_started); + do + { + struct timespec abstime; + set_timespec_nsec(abstime, 1000); + error_num = pthread_cond_timedwait(spd_COND_server_started, + spd_LOCK_server_started, &abstime); + } while ( + (error_num == ETIMEDOUT || error_num == ETIME) && + !(*spd_mysqld_server_started) && !thd->killed && !thread->killed + ); } pthread_mutex_unlock(spd_LOCK_server_started); thd->mysys_var->current_cond = &thread->cond; thd->mysys_var->current_mutex = &thread->mutex; } - while (spider_init_queries[i].length && !thd->killed) + while (spider_init_queries[i].length && !thd->killed && !thread->killed) { dispatch_command(COM_QUERY, thd, spider_init_queries[i].str, (uint) spider_init_queries[i].length, FALSE, FALSE); @@ -10057,7 +10402,7 @@ void *spider_table_bg_sts_action( conns = spider->conns; if (spider->search_link_idx < 0) { - spider->trx = trx; + spider->wide_handler->trx = trx; spider_trx_set_link_idx_for_all(spider); spider->search_link_idx = spider_conn_first_link_idx(thd, share->link_statuses, share->access_balances, spider->conn_link_idx, @@ -10210,7 +10555,7 @@ void *spider_table_bg_crd_action( conns = spider->conns; if (spider->search_link_idx < 0) { - spider->trx = trx; + spider->wide_handler->trx = trx; spider_trx_set_link_idx_for_all(spider); spider->search_link_idx = spider_conn_first_link_idx(thd, share->link_statuses, share->access_balances, spider->conn_link_idx, @@ -10442,3 +10787,25 @@ void spider_table_remove_share_from_crd_thread( DBUG_VOID_RETURN; } #endif + +uchar *spider_duplicate_char( + uchar *dst, + uchar esc, + uchar *src, + uint src_lgt +) { + uchar *ed = src + src_lgt; + DBUG_ENTER("spider_duplicate_char"); + while (src < ed) + { + *dst = *src; + if (*src == esc) + { + ++dst; + *dst = esc; + } + ++dst; + ++src; + } + DBUG_RETURN(dst); +} diff --git a/storage/spider/spd_table.h b/storage/spider/spd_table.h index baeec2a9a3b..c03f15a5a88 100644 --- a/storage/spider/spd_table.h +++ b/storage/spider/spd_table.h @@ -224,13 +224,13 @@ uchar *spider_tbl_get_key( my_bool not_used __attribute__ ((unused)) ); -#ifdef WITH_PARTITION_STORAGE_ENGINE -uchar *spider_pt_share_get_key( - SPIDER_PARTITION_SHARE *share, +uchar *spider_wide_share_get_key( + SPIDER_WIDE_SHARE *share, size_t *length, my_bool not_used __attribute__ ((unused)) ); +#ifdef WITH_PARTITION_STORAGE_ENGINE uchar *spider_pt_handler_share_get_key( SPIDER_PARTITION_HANDLER_SHARE *share, size_t *length, @@ -420,39 +420,37 @@ void spider_update_link_status_for_share( long link_status ); -#ifdef WITH_PARTITION_STORAGE_ENGINE -SPIDER_PARTITION_SHARE *spider_get_pt_share( +SPIDER_WIDE_SHARE *spider_get_wide_share( SPIDER_SHARE *share, TABLE_SHARE *table_share, int *error_num ); -int spider_free_pt_share( - SPIDER_PARTITION_SHARE *partition_share +int spider_free_wide_share( + SPIDER_WIDE_SHARE *wide_share ); -void spider_copy_sts_to_pt_share( - SPIDER_PARTITION_SHARE *partition_share, +void spider_copy_sts_to_wide_share( + SPIDER_WIDE_SHARE *wide_share, SPIDER_SHARE *share ); void spider_copy_sts_to_share( SPIDER_SHARE *share, - SPIDER_PARTITION_SHARE *partition_share + SPIDER_WIDE_SHARE *wide_share ); -void spider_copy_crd_to_pt_share( - SPIDER_PARTITION_SHARE *partition_share, +void spider_copy_crd_to_wide_share( + SPIDER_WIDE_SHARE *wide_share, SPIDER_SHARE *share, int fields ); void spider_copy_crd_to_share( SPIDER_SHARE *share, - SPIDER_PARTITION_SHARE *partition_share, + SPIDER_WIDE_SHARE *wide_share, int fields ); -#endif int spider_open_all_tables( SPIDER_TRX *trx, @@ -740,3 +738,9 @@ void spider_table_remove_share_from_crd_thread( SPIDER_SHARE *share ); #endif +uchar *spider_duplicate_char( + uchar *dst, + uchar esc, + uchar *src, + uint src_lgt +); diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index f7565eda2c9..e2df52814dd 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -247,6 +247,7 @@ int spider_trx_another_lock_tables( SPIDER_CONN *conn; ha_spider tmp_spider; SPIDER_SHARE tmp_share; + SPIDER_WIDE_HANDLER tmp_wide_handler; char sql_buf[MAX_FIELD_WIDTH]; spider_string sql_str(sql_buf, sizeof(sql_buf), system_charset_info); DBUG_ENTER("spider_trx_another_lock_tables"); @@ -255,13 +256,11 @@ int spider_trx_another_lock_tables( sql_str.length(0); memset((void*)&tmp_spider, 0, sizeof(ha_spider)); memset((void*)&tmp_share, 0, sizeof(SPIDER_SHARE)); + memset((void*)&tmp_wide_handler, 0, sizeof(SPIDER_WIDE_HANDLER)); tmp_spider.share = &tmp_share; - tmp_spider.trx = trx; + tmp_spider.wide_handler = &tmp_wide_handler; + tmp_wide_handler.trx = trx; tmp_share.access_charset = system_charset_info; -/* - if ((error_num = spider_db_append_set_names(&tmp_share))) - DBUG_RETURN(error_num); -*/ tmp_spider.conns = &conn; tmp_spider.result_list.sqls = &sql_str; tmp_spider.need_mons = &need_mon; @@ -273,17 +272,11 @@ int spider_trx_another_lock_tables( SPIDER_CONN_RESTORE_DASTATUS_AND_RESET_ERROR_NUM; if (error_num) { -/* - spider_db_free_set_names(&tmp_share); -*/ DBUG_RETURN(error_num); } } roop_count++; } -/* - spider_db_free_set_names(&tmp_share); -*/ DBUG_RETURN(0); } @@ -387,10 +380,13 @@ int spider_trx_all_start_trx( THD *thd = trx->thd; SPIDER_CONN *conn; ha_spider tmp_spider; + SPIDER_WIDE_HANDLER tmp_wide_handler; DBUG_ENTER("spider_trx_all_start_trx"); SPIDER_BACKUP_DASTATUS; memset((void*)&tmp_spider, 0, sizeof(ha_spider)); - tmp_spider.trx = trx; + memset(&tmp_wide_handler, 0, sizeof(SPIDER_WIDE_HANDLER)); + tmp_spider.wide_handler = &tmp_wide_handler; + tmp_wide_handler.trx = trx; tmp_spider.need_mons = &need_mon; while ((conn = (SPIDER_CONN*) my_hash_element(&trx->trx_conn_hash, roop_count))) @@ -398,7 +394,8 @@ int spider_trx_all_start_trx( if ( (spider_param_sync_trx_isolation(trx->thd) && (error_num = spider_check_and_set_trx_isolation(conn, &need_mon))) || - (error_num = spider_internal_start_trx(&tmp_spider, conn, 0)) + (error_num = spider_internal_start_trx_for_connection(&tmp_spider, + conn, 0)) ) { SPIDER_CONN_RESTORE_DASTATUS_AND_RESET_ERROR_NUM; if (error_num) @@ -418,6 +415,7 @@ int spider_trx_all_flush_logs( SPIDER_CONN *conn; ha_spider tmp_spider; SPIDER_SHARE tmp_share; + SPIDER_WIDE_HANDLER tmp_wide_handler; long tmp_link_statuses = SPIDER_LINK_STATUS_OK; uint conn_link_idx = 0; long net_read_timeout = 600; @@ -425,6 +423,7 @@ int spider_trx_all_flush_logs( DBUG_ENTER("spider_trx_all_flush_logs"); SPIDER_BACKUP_DASTATUS; memset((void*)&tmp_spider, 0, sizeof(ha_spider)); + memset(&tmp_wide_handler, 0, sizeof(SPIDER_WIDE_HANDLER)); tmp_share.link_count = 1; tmp_share.all_link_count = 1; tmp_share.link_statuses = &tmp_link_statuses; @@ -437,7 +436,8 @@ int spider_trx_all_flush_logs( tmp_spider.conns = &conn; tmp_spider.need_mons = &need_mon; tmp_spider.conn_link_idx = &conn_link_idx; - tmp_spider.trx = trx; + tmp_spider.wide_handler = &tmp_wide_handler; + tmp_wide_handler.trx = trx; while ((conn = (SPIDER_CONN*) my_hash_element(&trx->trx_conn_hash, roop_count))) { @@ -505,6 +505,7 @@ int spider_create_trx_alter_table( char **tmp_tgt_ssl_keys; char **tmp_tgt_default_files; char **tmp_tgt_default_groups; + char **tmp_tgt_dsns; char **tmp_static_link_ids; uint *tmp_server_names_lengths; uint *tmp_tgt_table_names_lengths; @@ -521,6 +522,7 @@ int spider_create_trx_alter_table( uint *tmp_tgt_ssl_keys_lengths; uint *tmp_tgt_default_files_lengths; uint *tmp_tgt_default_groups_lengths; + uint *tmp_tgt_dsns_lengths; uint *tmp_static_link_ids_lengths; long *tmp_tgt_ports; long *tmp_tgt_ssl_vscs; @@ -541,6 +543,7 @@ int spider_create_trx_alter_table( char *tmp_tgt_ssl_keys_char; char *tmp_tgt_default_files_char; char *tmp_tgt_default_groups_char; + char *tmp_tgt_dsns_char; char *tmp_static_link_ids_char; uint old_elements; @@ -567,6 +570,7 @@ int spider_create_trx_alter_table( &tmp_tgt_ssl_keys, (uint) (sizeof(char *) * share->all_link_count), &tmp_tgt_default_files, (uint) (sizeof(char *) * share->all_link_count), &tmp_tgt_default_groups, (uint) (sizeof(char *) * share->all_link_count), + &tmp_tgt_dsns, (uint) (sizeof(char *) * share->all_link_count), &tmp_static_link_ids, (uint) (sizeof(char *) * share->all_link_count), &tmp_server_names_lengths, (uint) (sizeof(uint) * share->all_link_count), @@ -592,6 +596,7 @@ int spider_create_trx_alter_table( (uint) (sizeof(uint) * share->all_link_count), &tmp_tgt_default_groups_lengths, (uint) (sizeof(uint) * share->all_link_count), + &tmp_tgt_dsns_lengths, (uint) (sizeof(uint) * share->all_link_count), &tmp_static_link_ids_lengths, (uint) (sizeof(uint) * share->all_link_count), @@ -631,6 +636,8 @@ int spider_create_trx_alter_table( (share_alter->tmp_tgt_default_files_charlen + 1)), &tmp_tgt_default_groups_char, (uint) (sizeof(char) * (share_alter->tmp_tgt_default_groups_charlen + 1)), + &tmp_tgt_dsns_char, (uint) (sizeof(char) * + (share_alter->tmp_tgt_dsns_charlen + 1)), &tmp_static_link_ids_char, (uint) (sizeof(char) * (share_alter->tmp_static_link_ids_charlen + 1)), NullS)) @@ -666,6 +673,7 @@ int spider_create_trx_alter_table( alter_table->tmp_tgt_ssl_keys = tmp_tgt_ssl_keys; alter_table->tmp_tgt_default_files = tmp_tgt_default_files; alter_table->tmp_tgt_default_groups = tmp_tgt_default_groups; + alter_table->tmp_tgt_dsns = tmp_tgt_dsns; alter_table->tmp_static_link_ids = tmp_static_link_ids; alter_table->tmp_tgt_ports = tmp_tgt_ports; @@ -689,6 +697,7 @@ int spider_create_trx_alter_table( alter_table->tmp_tgt_ssl_keys_lengths = tmp_tgt_ssl_keys_lengths; alter_table->tmp_tgt_default_files_lengths = tmp_tgt_default_files_lengths; alter_table->tmp_tgt_default_groups_lengths = tmp_tgt_default_groups_lengths; + alter_table->tmp_tgt_dsns_lengths = tmp_tgt_dsns_lengths; alter_table->tmp_static_link_ids_lengths = tmp_static_link_ids_lengths; for(roop_count = 0; roop_count < (int) share->all_link_count; roop_count++) @@ -789,6 +798,12 @@ int spider_create_trx_alter_table( tmp_tgt_default_groups_char += share_alter->tmp_tgt_default_groups_lengths[roop_count] + 1; + tmp_tgt_dsns[roop_count] = tmp_tgt_dsns_char; + memcpy(tmp_tgt_dsns_char, share_alter->tmp_tgt_dsns[roop_count], + sizeof(char) * share_alter->tmp_tgt_dsns_lengths[roop_count]); + tmp_tgt_dsns_char += + share_alter->tmp_tgt_dsns_lengths[roop_count] + 1; + if (share_alter->tmp_static_link_ids[roop_count]) { tmp_static_link_ids[roop_count] = tmp_static_link_ids_char; @@ -842,6 +857,8 @@ int spider_create_trx_alter_table( memcpy(tmp_tgt_default_groups_lengths, share_alter->tmp_tgt_default_groups_lengths, sizeof(uint) * share->all_link_count); + memcpy(tmp_tgt_dsns_lengths, share_alter->tmp_tgt_dsns_lengths, + sizeof(uint) * share->all_link_count); memcpy(tmp_static_link_ids_lengths, share_alter->tmp_static_link_ids_lengths, sizeof(uint) * share->all_link_count); @@ -876,6 +893,8 @@ int spider_create_trx_alter_table( share_alter->tmp_tgt_default_files_length; alter_table->tmp_tgt_default_groups_length = share_alter->tmp_tgt_default_groups_length; + alter_table->tmp_tgt_dsns_length = + share_alter->tmp_tgt_dsns_length; alter_table->tmp_static_link_ids_length = share_alter->tmp_static_link_ids_length; alter_table->tmp_tgt_ports_length = @@ -1079,6 +1098,16 @@ bool spider_cmp_trx_alter_table( cmp2->tmp_tgt_default_groups[roop_count]) ) ) || + ( + cmp1->tmp_tgt_dsns[roop_count] != + cmp2->tmp_tgt_dsns[roop_count] && + ( + !cmp1->tmp_tgt_dsns[roop_count] || + !cmp2->tmp_tgt_dsns[roop_count] || + strcmp(cmp1->tmp_tgt_dsns[roop_count], + cmp2->tmp_tgt_dsns[roop_count]) + ) + ) || ( cmp1->tmp_static_link_ids[roop_count] != cmp2->tmp_static_link_ids[roop_count] && @@ -1200,6 +1229,7 @@ SPIDER_TRX *spider_get_trx( int roop_count = 0, roop_count2; SPIDER_TRX *trx; SPIDER_SHARE *tmp_share; + SPIDER_WIDE_HANDLER *tmp_wide_handler; pthread_mutex_t *udf_table_mutexes; DBUG_ENTER("spider_get_trx"); @@ -1212,6 +1242,7 @@ SPIDER_TRX *spider_get_trx( spider_bulk_malloc(NULL, 56, MYF(MY_WME | MY_ZEROFILL), &trx, (uint) (sizeof(*trx)), &tmp_share, (uint) (sizeof(SPIDER_SHARE)), + &tmp_wide_handler, (uint) sizeof(SPIDER_WIDE_HANDLER), &udf_table_mutexes, (uint) (sizeof(pthread_mutex_t) * spider_param_udf_table_lock_mutex_count()), NullS)) @@ -1387,7 +1418,8 @@ SPIDER_TRX *spider_get_trx( } trx->tmp_spider->need_mons = &trx->tmp_need_mon; trx->tmp_spider->share = trx->tmp_share; - trx->tmp_spider->trx = trx; + trx->tmp_spider->wide_handler = tmp_wide_handler; + tmp_wide_handler->trx = trx; trx->tmp_spider->dbton_handler = trx->tmp_dbton_handler; if (!(trx->tmp_spider->result_list.sqls = new spider_string[trx->tmp_share->link_count])) @@ -1875,27 +1907,14 @@ int spider_start_internal_consistent_snapshot( } int spider_internal_start_trx( - ha_spider *spider, - SPIDER_CONN *conn, - int link_idx + ha_spider *spider ) { int error_num; - SPIDER_TRX *trx = spider->trx; + SPIDER_TRX *trx = spider->wide_handler->trx; THD *thd = trx->thd; - bool sync_autocommit = spider_param_sync_autocommit(thd); - double ping_interval_at_trx_start = - spider_param_ping_interval_at_trx_start(thd); bool xa_lock = FALSE; - time_t tmp_time = (time_t) time((time_t*) 0); DBUG_ENTER("spider_internal_start_trx"); - if ( - conn->server_lost || - difftime(tmp_time, conn->ping_time) >= ping_interval_at_trx_start - ) { - spider_conn_queue_ping(spider, conn, link_idx); - } - conn->disable_reconnect = TRUE; if (!trx->trx_start) { if (!trx->trx_consistent_snapshot) @@ -1906,19 +1925,7 @@ int spider_internal_start_trx( trx->internal_xa_snapshot = spider_param_internal_xa_snapshot(thd); } } - if ( - (error_num = spider_check_and_set_sql_log_off(thd, conn, - &spider->need_mons[link_idx])) || - (error_num = spider_check_and_set_wait_timeout(thd, conn, - &spider->need_mons[link_idx])) || - (spider_param_sync_sql_mode(thd) && - (error_num = spider_check_and_set_sql_mode(thd, conn, - &spider->need_mons[link_idx]))) || - (sync_autocommit && - (error_num = spider_check_and_set_autocommit(thd, conn, - &spider->need_mons[link_idx]))) - ) - goto error; + spider->wide_handler->consistent_snapshot = FALSE; if (trx->trx_consistent_snapshot) { if (trx->internal_xa && trx->internal_xa_snapshot < 2) @@ -1929,9 +1936,7 @@ int spider_internal_start_trx( goto error; } else if (!trx->internal_xa || trx->internal_xa_snapshot == 2) { - if ((error_num = spider_start_internal_consistent_snapshot(trx, conn, - &spider->need_mons[link_idx]))) - goto error; + spider->wide_handler->consistent_snapshot = TRUE; } } DBUG_PRINT("info",("spider trx->trx_start= %s", @@ -1939,7 +1944,7 @@ int spider_internal_start_trx( if (!trx->trx_start) { if ( - thd->transaction.xid_state.is_explicit_XA() && + thd->transaction->xid_state.is_explicit_XA() && spider_param_support_xa() ) { trx->trx_xa = TRUE; @@ -1950,7 +1955,7 @@ int spider_internal_start_trx( !trx->trx_xa && trx->internal_xa && (!trx->trx_consistent_snapshot || trx->internal_xa_snapshot == 3) && - spider->sql_command != SQLCOM_LOCK_TABLES + spider->wide_handler->sql_command != SQLCOM_LOCK_TABLES ) { trx->trx_xa = TRUE; trx->xid.formatID = 1; @@ -2003,6 +2008,54 @@ int spider_internal_start_trx( trx->updated_in_this_trx = FALSE; DBUG_PRINT("info",("spider trx->updated_in_this_trx=FALSE")); } + DBUG_RETURN(0); + +error: + if (xa_lock) + spider_xa_unlock(&trx->internal_xid_state); + DBUG_RETURN(error_num); +} + +int spider_internal_start_trx_for_connection( + ha_spider *spider, + SPIDER_CONN *conn, + int link_idx +) { + int error_num; + SPIDER_TRX *trx = spider->wide_handler->trx; + THD *thd = trx->thd; + bool sync_autocommit = spider_param_sync_autocommit(thd); + double ping_interval_at_trx_start = + spider_param_ping_interval_at_trx_start(thd); + time_t tmp_time = (time_t) time((time_t*) 0); + DBUG_ENTER("spider_internal_start_trx_for_connection"); + if ( + conn->server_lost || + difftime(tmp_time, conn->ping_time) >= ping_interval_at_trx_start + ) { + spider_conn_queue_ping(spider, conn, link_idx); + } + conn->disable_reconnect = TRUE; + if ( + (error_num = spider_check_and_set_sql_log_off(thd, conn, + &spider->need_mons[link_idx])) || + (error_num = spider_check_and_set_wait_timeout(thd, conn, + &spider->need_mons[link_idx])) || + (spider_param_sync_sql_mode(thd) && + (error_num = spider_check_and_set_sql_mode(thd, conn, + &spider->need_mons[link_idx]))) || + (sync_autocommit && + (error_num = spider_check_and_set_autocommit(thd, conn, + &spider->need_mons[link_idx]))) + ) + goto error; + + if (spider->wide_handler->consistent_snapshot) + { + if ((error_num = spider_start_internal_consistent_snapshot(trx, conn, + &spider->need_mons[link_idx]))) + goto error; + } DBUG_PRINT("info",("spider sync_autocommit = %d", sync_autocommit)); DBUG_PRINT("info",("spider conn->semi_trx_chk = %d", conn->semi_trx_chk)); @@ -2068,8 +2121,6 @@ int spider_internal_start_trx( DBUG_RETURN(0); error: - if (xa_lock) - spider_xa_unlock(&trx->internal_xid_state); DBUG_RETURN(error_num); } @@ -3750,11 +3801,11 @@ int spider_check_trx_and_get_conn( DBUG_PRINT("info",("spider get trx error")); DBUG_RETURN(error_num); } - spider->trx = trx; + spider->wide_handler->trx = trx; spider->set_error_mode(); if ( - spider->sql_command != SQLCOM_DROP_TABLE && - spider->sql_command != SQLCOM_ALTER_TABLE + spider->wide_handler->sql_command != SQLCOM_DROP_TABLE && + spider->wide_handler->sql_command != SQLCOM_ALTER_TABLE ) { SPIDER_TRX_HA *trx_ha = spider_check_trx_ha(trx, spider); if (!trx_ha || trx_ha->wait_for_reusing) @@ -3810,9 +3861,9 @@ int spider_check_trx_and_get_conn( SPIDER_LINK_STATUS_NG ) { DBUG_PRINT("info",(first_byte != *spider->conn_keys[0] ? - "spider change conn type" : trx != spider->trx ? "spider change thd" : - "spider next trx")); - spider->trx = trx; + "spider change conn type" : trx != spider->wide_handler->trx ? + "spider change thd" : "spider next trx")); + spider->wide_handler->trx = trx; spider->trx_conn_adjustment = trx->trx_conn_adjustment; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (use_conn_kind) diff --git a/storage/spider/spd_trx.h b/storage/spider/spd_trx.h index ca46bae20cc..3bf93aada1a 100644 --- a/storage/spider/spd_trx.h +++ b/storage/spider/spd_trx.h @@ -126,6 +126,10 @@ int spider_start_internal_consistent_snapshot( ); int spider_internal_start_trx( + ha_spider *spider +); + +int spider_internal_start_trx_for_connection( ha_spider *spider, SPIDER_CONN *conn, int link_idx diff --git a/storage/spider/spider.cnf b/storage/spider/spider.cnf new file mode 100644 index 00000000000..2ee546962d6 --- /dev/null +++ b/storage/spider/spider.cnf @@ -0,0 +1,5 @@ +[mariadb] +# +# uncomment the following line to enable SPIDER storage engine +# +#plugin-load-add=ha_spider.so diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b8e71b1f7a9..7434f968383 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -4992,13 +4992,11 @@ static void my_hash_sort_utf8mb3_nopad(CHARSET_INFO *cs, const uchar *s, size_t static void my_hash_sort_utf8mb3(CHARSET_INFO *cs, const uchar *s, size_t slen, ulong *nr1, ulong *nr2) { - const uchar *e= s+slen; /* Remove end space. We have to do this to be able to compare 'A ' and 'A' as identical */ - while (e > s && e[-1] == ' ') - e--; + const uchar *e= skip_trailing_space(s, slen); my_hash_sort_utf8mb3_nopad(cs, s, e - s, nr1, nr2); } @@ -7436,13 +7434,11 @@ static void my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, ulong *nr1, ulong *nr2) { - const uchar *e= s + slen; /* Remove end space. We do this to be able to compare 'A ' and 'A' as identical */ - while (e > s && e[-1] == ' ') - e--; + const uchar *e= skip_trailing_space(s, slen); my_hash_sort_utf8mb4_nopad(cs, s, e - s, nr1, nr2); } diff --git a/strings/dtoa.c b/strings/dtoa.c index 63c99c6b2a9..af2409b9195 100644 --- a/strings/dtoa.c +++ b/strings/dtoa.c @@ -2168,9 +2168,6 @@ static int quorem(Bigint *b, Bigint *S) static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char *buf, size_t buf_size) -#if __has_feature(memory_sanitizer) - __attribute__((no_sanitize("memory"))) // FIXME: dd is claimed uninitialized -#endif { /* Arguments ndigits, decpt, sign are similar to those diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index 6b7af39d51d..a2e3f9b738d 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -224,7 +224,8 @@ err: */ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end, - size_t width, char *par, uint print_type) + size_t width, char *par, uint print_type, + my_bool nice_cut) { int well_formed_error; uint dots= 0; @@ -232,24 +233,34 @@ static char *process_str_arg(CHARSET_INFO *cs, char *to, const char *end, if (!par) par = (char*) "(null)"; - plen= slen= strnlen(par, width + 1); - if (plen > width) - plen= width; - if (left_len <= plen) - plen = left_len - 1; - if ((slen > plen)) + if (nice_cut) { - if (plen < 3) + plen= slen= strnlen(par, width + 1); + if (plen > width) + plen= width; + if (left_len <= plen) + plen = left_len - 1; + if ((slen > plen)) { - dots= (uint) plen; - plen= 0; - } - else - { - dots= 3; - plen-= 3; + if (plen < 3) + { + dots= (uint) plen; + plen= 0; + } + else + { + dots= 3; + plen-= 3; + } } } + else + { + plen= slen= strnlen(par, width); + dots= 0; + if (left_len <= plen) + plen = left_len - 1; + } plen= my_well_formed_length(cs, par, par + plen, width, &well_formed_error); if (print_type & ESCAPED_ARG) @@ -446,6 +457,7 @@ start: switch (args_arr[i].arg_type) { case 's': case 'b': + case 'T': args_arr[i].str_arg= va_arg(ap, char *); break; case 'f': @@ -480,12 +492,14 @@ start: size_t width= 0, length= 0; switch (print_arr[i].arg_type) { case 's': + case 'T': { char *par= args_arr[print_arr[i].arg_idx].str_arg; width= (print_arr[i].flags & WIDTH_ARG) ? (size_t)args_arr[print_arr[i].width].longlong_arg : print_arr[i].width; - to= process_str_arg(cs, to, end, width, par, print_arr[i].flags); + to= process_str_arg(cs, to, end, width, par, print_arr[i].flags, + (print_arr[i].arg_type == 'T')); break; } case 'b': @@ -552,7 +566,7 @@ start: *to++= '"'; my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg); to= process_str_arg(cs, to, real_end, width, errmsg_buff, - print_arr[i].flags); + print_arr[i].flags, 1); if (real_end > to) *to++= '"'; } break; @@ -676,10 +690,10 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, fmt= check_longlong(fmt, &have_longlong); - if (*fmt == 's') /* String parameter */ + if (*fmt == 's' || *fmt == 'T') /* String parameter */ { reg2 char *par= va_arg(ap, char *); - to= process_str_arg(cs, to, end, width, par, print_type); + to= process_str_arg(cs, to, end, width, par, print_type, (*fmt == 'T')); continue; } else if (*fmt == 'b') /* Buffer parameter */ @@ -690,7 +704,13 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, } else if (*fmt == 'f' || *fmt == 'g') { +#if __has_feature(memory_sanitizer) /* QQ: MSAN has double trouble? */ + __msan_check_mem_is_initialized(ap, sizeof(double)); +#endif double d= va_arg(ap, double); +#if __has_feature(memory_sanitizer) /* QQ: MSAN has double trouble? */ + __msan_unpoison(&d, sizeof(double)); +#endif to= process_dbl_arg(to, end, width, d, *fmt); continue; } @@ -731,7 +751,8 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n, *to++= ' '; *to++= '"'; my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg); - to= process_str_arg(cs, to, real_end, width, errmsg_buff, print_type); + to= process_str_arg(cs, to, real_end, width, errmsg_buff, + print_type, 1); if (real_end > to) *to++= '"'; } continue; diff --git a/support-files/MacOSX/ReadMe.txt b/support-files/MacOSX/ReadMe.txt index 8b833049ad4..31fb0d97e14 100644 --- a/support-files/MacOSX/ReadMe.txt +++ b/support-files/MacOSX/ReadMe.txt @@ -73,7 +73,7 @@ Note /usr/local/mysql-5.1.39-osx10.5-x86_64 . The installation layout of the directory is as shown in the following table: Directory Contents of Directory - bin Client programs and the mysqld server + bin Client programs and the mariadbd server data Log files, databases docs Manual in Info format include Include (header) files @@ -285,7 +285,7 @@ Note Directory Contents of Directory /usr/bin Client programs /var/mysql Log files, databases - /usr/libexec The mysqld server + /usr/libexec The mariadbd server /usr/share/man Unix manual pages /usr/share/mysql/mysql-test MySQL test suite /usr/share/mysql Contains the mysql_install_db script diff --git a/support-files/binary-configure.sh b/support-files/binary-configure.sh index 5e6d62f69a0..47123668683 100644 --- a/support-files/binary-configure.sh +++ b/support-files/binary-configure.sh @@ -41,7 +41,7 @@ echo "" ./scripts/mysql_install_db --no-defaults if [ $? = 0 ] then - echo "Starting the mysqld server. You can test that it is up and running" + echo "Starting the mariadbd server. You can test that it is up and running" echo "with the command:" echo "./bin/mysqladmin version" ./bin/mysqld_safe --no-defaults & diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index 6db3545e86d..07b07b40868 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -20,7 +20,7 @@ [Unit] Description=MariaDB @VERSION@ database server -Documentation=man:mysqld(8) +Documentation=man:mariadbd(8) Documentation=https://mariadb.com/kb/en/library/systemd/ After=network.target @@ -37,7 +37,7 @@ WantedBy=multi-user.target Type=notify # Setting this to true can break replication and the Type=notify settings -# See also bind-address mysqld option. +# See also bind-address mariadbd option. PrivateNetwork=false ############################################################################## @@ -89,7 +89,7 @@ ExecStartPre=/bin/sh -c "[ ! -e @bindir@/galera_recovery ] && VAR= || \ # Use the [Service] section and Environment="MYSQLD_OPTS=...". # This isn't a replacement for my.cnf. # _WSREP_NEW_CLUSTER is for the exclusive use of the script galera_new_cluster -ExecStart=@sbindir@/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION +ExecStart=@sbindir@/mariadbd $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION # Unset _WSREP_START_POSITION environment variable. ExecStartPost=/bin/sh -c "systemctl unset-environment _WSREP_START_POSITION" @@ -118,7 +118,7 @@ UMask=007 # Useful options not previously available in [mysqld_safe] -# Kernels like killing mysqld when out of memory because its big. +# Kernels like killing mariadbd when out of memory because its big. # Lets temper that preference a little. # OOMScoreAdjust=-600 @@ -163,7 +163,7 @@ LimitNOFILE=16364 # ExecStartPre=sysctl -q -w vm.drop_caches=3 # numa-interleave=1 equalivant -# Change ExecStart=numactl --interleave=all @sbindir@/mysqld...... +# Change ExecStart=numactl --interleave=all @sbindir@/mariadbd...... # crash-script equalivent # FailureAction= diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index f12f44311f5..371b7047eac 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -34,10 +34,10 @@ # like network ports, sockets and data directories listed under CONFLICTING # VARIABLES below. The systemd environment variable MYSQLD_MULTI_INSTANCE # controls each instance to ensure it is run independently. It is passed to -# mysqld and mysql_install +# mariadbd and mysql_install # # By default, a group suffix exists and within the default configuration -# files, a group [mysqld.{instancename}] is read for each service. Other +# files, a group [mariadbd.{instancename}] is read for each service. Other # default groups, like [server.{instancename}] and [mariadb.{instancename}], # are also read. For each instance, one of the groups will need to contain # the conflicting variables listed below under CONFLICTING VARIABLES. @@ -119,7 +119,7 @@ # Before 10.4 MYSQLD_MULTI_INSTANCE was effectively --defaults-file=@sysconf2dir@/my%I.cnf # As @sysconfdir@/my.cnf included these files it was a bad choice as an # existing single instance would include all these files. If you want to -# continue a file based multi-instance mysqld, recommend the Configuration File +# continue a file based multi-instance mariadbd, recommend the Configuration File # Based Mechanism above and moving @sysconf2dir@/my%I.cnf files to @sysconfdir@/my%I.cnf. # # @@ -145,7 +145,7 @@ [Unit] Description=MariaDB @VERSION@ database server (multi-instance %I) -Documentation=man:mysqld(8) +Documentation=man:mariadbd(8) Documentation=https://mariadb.com/kb/en/library/systemd/ After=network.target @@ -170,7 +170,7 @@ WantedBy=multi-user.target Type=notify # Setting this to true can break replication and the Type=notify settings -# See also bind-address mysqld option. +# See also bind-address mariadbd option. PrivateNetwork=false ############################################################################## @@ -206,7 +206,7 @@ ExecStartPre=@scriptdir@/mysql_install_db $MYSQLD_MULTI_INSTANCE # * MYSQLD_OPTS - user definable extras - not a replacement for my.cnf # # Note 1: Place $MYSQLD_OPTS at the very end for its options to take precedence. -ExecStart=@sbindir@/mysqld $MYSQLD_MULTI_INSTANCE $MYSQLD_OPTS +ExecStart=@sbindir@/mariadbd $MYSQLD_MULTI_INSTANCE $MYSQLD_OPTS @SYSTEMD_EXECSTARTPOST@ @@ -232,7 +232,7 @@ UMask=007 # Useful options not previously available in [mysqld_safe] -# Kernels like killing mysqld when out of memory because its big. +# Kernels like killing mariadbd when out of memory because its big. # Lets temper that preference a little. # OOMScoreAdjust=-600 @@ -288,7 +288,7 @@ LimitNOFILE=16364 # ExecStartPre=sysctl -q -w vm.drop_caches=3 # numa-interleave=1 equalivant -# Change ExecStart=numactl --interleave=all @sbindir@/mysqld...... +# Change ExecStart=numactl --interleave=all @sbindir@/mariadbd...... # crash-script equalivent # FailureAction= diff --git a/support-files/mysql-log-rotate.sh b/support-files/mysql-log-rotate.sh index 293229d8482..37ae018c1d1 100644 --- a/support-files/mysql-log-rotate.sh +++ b/support-files/mysql-log-rotate.sh @@ -26,7 +26,7 @@ missingok compress postrotate - # just if mysqld is really running + # just if mariadbd is really running if test -x @bindir@/mysqladmin && \ @bindir@/mysqladmin ping &>/dev/null then diff --git a/support-files/mysql-multi.server.sh b/support-files/mysql-multi.server.sh index f90d662fa8c..a7a51e6a095 100644 --- a/support-files/mysql-multi.server.sh +++ b/support-files/mysql-multi.server.sh @@ -50,7 +50,7 @@ then exit 1 fi -echo "mysqld $svr $mode" +echo "mariadbd $svr $mode" parse_arguments() { for arg do @@ -107,7 +107,7 @@ fi datadir=@localstatedir@ basedir= pid_file= -parse_arguments `$print_defaults $defaults mysqld mysql_server mysql_multi_server` +parse_arguments `$print_defaults $defaults mariadbd mysqld mysql_server mysql_multi_server` if test -z "$basedir" then @@ -157,15 +157,15 @@ case "$mode" in # root password. if test -f "$pid_file" then - mysqld_pid=`cat $pid_file` - echo "Killing mysqld $svr with pid $mysqld_pid" - kill $mysqld_pid - # mysqld should remove the pid_file when it exits, so wait for it. + mariadbd_pid=`cat $pid_file` + echo "Killing mariadbd $svr with pid $mariadbd_pid" + kill $mariadbd_pid + # mariadbd should remove the pid_file when it exits, so wait for it. sleep 1 while [ -s $pid_file -a "$flags" != aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] do - [ -z "$flags" ] && echo "Wait for mysqld $svr to exit\c" || echo ".\c" + [ -z "$flags" ] && echo "Wait for mariadbd $svr to exit\c" || echo ".\c" flags=a$flags sleep 1 done @@ -180,7 +180,7 @@ case "$mode" in rm /var/lock/subsys/mysql fi else - echo "No mysqld pid file found. Looked for $pid_file." + echo "No mariadbd pid file found. Looked for $pid_file." fi ;; diff --git a/support-files/mysql.server-sys5.sh b/support-files/mysql.server-sys5.sh index 4bda51acc4d..3049b43d267 100644 --- a/support-files/mysql.server-sys5.sh +++ b/support-files/mysql.server-sys5.sh @@ -30,7 +30,7 @@ EOF do_start() { - nohup ./bin/mysqld --defaults-file="$MY_CFG" & + nohup ./bin/mariadbd --defaults-file="$MY_CFG" & } do_stop() { @@ -45,7 +45,7 @@ do_kill_all() { } do_kill() { - MY_PIDFILE=`read_mysql_config "$MY_CFG" "mysqld" "pidfile" ` + MY_PIDFILE=`read_mysql_config "$MY_CFG" "mariadbd" "pidfile" ` read MY_PID < "$MY_PIDFILE" kill "$MY_PID" sleep 2 @@ -60,14 +60,14 @@ do_admin() { } do_repair() { - MY_DATADIR=`read_mysql_config "$MY_CFG" "mysqld" "datadir" ` + MY_DATADIR=`read_mysql_config "$MY_CFG" "mariadbd" "datadir" ` ./bin/isamchk --defaults-file="$MY_CFG" --repair "$MY_DATADIR/$1" shift } do_repair_all() { - MY_DATADIR=`read_mysql_config "$MY_CFG" "mysqld" "datadir" ` + MY_DATADIR=`read_mysql_config "$MY_CFG" "mariadbd" "datadir" ` for i in `find "$MY_DATADIR" -name "*.ISM"` do ./bin/isamchk --defaults-file="$MY_CFG" --repair "$MY_DATADIR/$i" @@ -76,7 +76,7 @@ do_repair_all() { -MY_BASEDIR=`read_mysql_config "$MY_CFG" "mysqld" "basedir"` +MY_BASEDIR=`read_mysql_config "$MY_CFG" "mariadbd" "basedir"` cd "$MY_BASEDIR" || exit 1 while test $# -gt 0 do diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 6eb2d0bc257..cefb3225e9e 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -59,7 +59,7 @@ lock_file_path="$lockdir/mysql" # The following variables are only set for letting mysql.server find things. # Set some defaults -mysqld_pid_file_path= +mariadbd_pid_file_path= if test -z "$basedir" then basedir=@prefix@ @@ -77,7 +77,7 @@ else datadir="$basedir/data" fi sbindir="$basedir/sbin" - if test -f "$basedir/bin/mysqld" + if test -f "$basedir/bin/mariadbd" then libexecdir="$basedir/bin" else @@ -134,7 +134,7 @@ parse_server_arguments() { datadir="$basedir/data" fi sbindir="$basedir/sbin" - if test -f "$basedir/bin/mysqld" + if test -f "$basedir/bin/mariadbd" then libexecdir="$basedir/bin" else @@ -146,9 +146,9 @@ parse_server_arguments() { datadir_set=1 ;; --log-basename=*|--hostname=*|--loose-log-basename=*) - mysqld_pid_file_path="$val.pid" + mariadbd_pid_file_path="$val.pid" ;; - --pid-file=*) mysqld_pid_file_path="$val" ;; + --pid-file=*) mariadbd_pid_file_path="$val" ;; --service-startup-timeout=*) service_startup_timeout="$val" ;; --user=*) user="$val"; ;; esac @@ -280,13 +280,13 @@ wait_for_ready () { # # Set pid file if not given # -if test -z "$mysqld_pid_file_path" +if test -z "$mariadbd_pid_file_path" then - mysqld_pid_file_path=$datadir/`@HOSTNAME@`.pid + mariadbd_pid_file_path=$datadir/`@HOSTNAME@`.pid else - case "$mysqld_pid_file_path" in + case "$mariadbd_pid_file_path" in /* ) ;; - * ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;; + * ) mariadbd_pid_file_path="$datadir/$mariadbd_pid_file_path" ;; esac fi @@ -307,7 +307,7 @@ case "$mode" in then # Give extra arguments to mysqld with the my.cnf file. This script # may be overwritten at next upgrade. - $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" "$@" & + $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mariadbd_pid_file_path" "$@" & wait_for_ready; return_value=$? # Make lock for RedHat / SuSE @@ -326,18 +326,18 @@ case "$mode" in # Stop daemon. We use a signal here to avoid having to know the # root password. - if test -s "$mysqld_pid_file_path" + if test -s "$mariadbd_pid_file_path" then - mysqld_pid=`cat "$mysqld_pid_file_path"` + mariadbd_pid=`cat "$mariadbd_pid_file_path"` - if su_kill -0 $mysqld_pid ; then + if su_kill -0 $mariadbd_pid ; then echo $echo_n "Shutting down MariaDB" - su_kill $mysqld_pid + su_kill $mariadbd_pid # mysqld should remove the pid file when it exits, so wait for it. - wait_for_gone $mysqld_pid "$mysqld_pid_file_path"; return_value=$? + wait_for_gone $mariadbd_pid "$mariadbd_pid_file_path"; return_value=$? else - log_failure_msg "MariaDB server process #$mysqld_pid is not running!" - rm "$mysqld_pid_file_path" + log_failure_msg "MariaDB server process #$mariadbd_pid is not running!" + rm "$mariadbd_pid_file_path" fi # Delete lock for RedHat / SuSE @@ -366,10 +366,10 @@ case "$mode" in ;; 'reload'|'force-reload') - if test -s "$mysqld_pid_file_path" ; then - read mysqld_pid < "$mysqld_pid_file_path" - su_kill -HUP $mysqld_pid && log_success_msg "Reloading service MariaDB" - touch "$mysqld_pid_file_path" + if test -s "$mariadbd_pid_file_path" ; then + read mariadbd_pid < "$mariadbd_pid_file_path" + su_kill -HUP $mariadbd_pid && log_success_msg "Reloading service MariaDB" + touch "$mariadbd_pid_file_path" else log_failure_msg "MariaDB PID file could not be found!" exit 1 @@ -377,25 +377,25 @@ case "$mode" in ;; 'status') # First, check to see if pid file exists - if test -s "$mysqld_pid_file_path" ; then - read mysqld_pid < "$mysqld_pid_file_path" - if su_kill -0 $mysqld_pid ; then - log_success_msg "MariaDB running ($mysqld_pid)" + if test -s "$mariadbd_pid_file_path" ; then + read mariadbd_pid < "$mariadbd_pid_file_path" + if su_kill -0 $mariadbd_pid ; then + log_success_msg "MariaDB running ($mariadbd_pid)" exit 0 else log_failure_msg "MariaDB is not running, but PID file exists" exit 1 fi else - # Try to find appropriate mysqld process - mysqld_pid=`pgrep -f $libexecdir/mysqld` + # Try to find appropriate mariadbd process + mariadbd_pid=`pgrep -f $libexecdir/mariadbd` # test if multiple pids exist - pid_count=`echo $mysqld_pid | wc -w` + pid_count=`echo $mariadbd_pid | wc -w` if test $pid_count -gt 1 ; then - log_failure_msg "Multiple MariaDB running but PID file could not be found ($mysqld_pid)" + log_failure_msg "Multiple MariaDB running but PID file could not be found ($mariadbd_pid)" exit 5 - elif test -z $mysqld_pid ; then + elif test -z $mariadbd_pid ; then if test -f "$lock_file_path" ; then log_failure_msg "MariaDB is not running, but lock file ($lock_file_path) exists" exit 2 @@ -412,18 +412,18 @@ case "$mode" in # Safeguard (relative paths, core dumps..) cd $basedir echo $echo_n "Testing MariaDB configuration syntax" - daemon=$bindir/mysqld - if test -x $libexecdir/mysqld + daemon=$bindir/mariadbd + if test -x $libexecdir/mariadbd then - daemon=$libexecdir/mysqld - elif test -x $sbindir/mysqld + daemon=$libexecdir/mariadbd + elif test -x $sbindir/mariadbd then - daemon=$sbindir/mysqld - elif test -x `which mysqld` + daemon=$sbindir/mariadbd + elif test -x `which mariadbd` then - daemon=`which mysqld` + daemon=`which mariadbd` else - log_failure_msg "Unable to locate the mysqld binary!" + log_failure_msg "Unable to locate the mariadbd binary!" exit 1 fi help_out=`$daemon --help 2>&1`; r=$? diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index 6555c614889..18a9c357ff2 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -5,7 +5,7 @@ #include -/usr/sbin/mysqld flags=(complain) { +/usr/sbin/mariadbd flags=(complain) { #include #include #include @@ -46,7 +46,7 @@ /tmp/** rw, /usr/lib/mysql/plugin/ r, /usr/lib/mysql/plugin/*.so* mr, - /usr/sbin/mysqld mr, + /usr/sbin/mariadbd mr, /usr/share/mysql/** r, /var/lib/mysql/ r, /var/lib/mysql/** rwk, @@ -147,5 +147,5 @@ /usr/bin/xbstream rix, } # Site-specific additions and overrides. See local/README for details. - #include + #include } diff --git a/support-files/rpm/my.cnf b/support-files/rpm/my.cnf index 8c6a7139de5..5cda317d29e 100644 --- a/support-files/rpm/my.cnf +++ b/support-files/rpm/my.cnf @@ -1,5 +1,5 @@ # -# This group is read both both by the client and the server +# This group is read both by the client and the server # use it for options that affect everything # [client-server] diff --git a/tests/big_record.pl b/tests/big_record.pl index b2aeee27658..639e305b2e8 100755 --- a/tests/big_record.pl +++ b/tests/big_record.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. # diff --git a/tests/drop_test.pl b/tests/drop_test.pl index 15a75f4908c..c132c207811 100755 --- a/tests/drop_test.pl +++ b/tests/drop_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000 MySQL AB # Use is subject to license terms diff --git a/tests/export.pl b/tests/export.pl index f99798ecac8..dace79feb30 100755 --- a/tests/export.pl +++ b/tests/export.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/fork2_test.pl b/tests/fork2_test.pl index 356055733fa..a05a9b96679 100755 --- a/tests/fork2_test.pl +++ b/tests/fork2_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/fork_big.pl b/tests/fork_big.pl index 2f803b7fdd3..a08044efbd8 100755 --- a/tests/fork_big.pl +++ b/tests/fork_big.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w use strict; # Copyright (c) 2001, 2006 MySQL AB diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl index a2b465734dc..a90af381376 100644 --- a/tests/fork_big2.pl +++ b/tests/fork_big2.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (c) 2002, 2003, 2005, 2006 MySQL AB # Use is subject to license terms diff --git a/tests/grant.pl b/tests/grant.pl index f8cdc1af4d5..6da22286d1c 100755 --- a/tests/grant.pl +++ b/tests/grant.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2000, 2005 MySQL AB, 2009 Sun Microsystems, Inc. # Use is subject to license terms. diff --git a/tests/index_corrupt.pl b/tests/index_corrupt.pl index 6f31b85bd61..dad288d71de 100755 --- a/tests/index_corrupt.pl +++ b/tests/index_corrupt.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2005 MySQL AB # Use is subject to license terms diff --git a/tests/insert_and_repair.pl b/tests/insert_and_repair.pl index dfa490456cb..f70bc75fb9a 100755 --- a/tests/insert_and_repair.pl +++ b/tests/insert_and_repair.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/lock_test.pl b/tests/lock_test.pl index 98c4ad6377d..8a8a0322467 100755 --- a/tests/lock_test.pl +++ b/tests/lock_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (C) 2000 MySQL AB # Use is subject to license terms diff --git a/tests/mail_to_db.pl b/tests/mail_to_db.pl index 94f3955b2c3..0dd0fe751aa 100755 --- a/tests/mail_to_db.pl +++ b/tests/mail_to_db.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright Abandoned 1998 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind # diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 22c3955d524..6a6f626ae8c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. - Copyright (c) 2008, 2019, MariaDB + Copyright (c) 2008, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20548,6 +20548,59 @@ static void test_bulk_replace() } #endif + +static void test_ps_params_in_ctes() +{ + int rc; + const char *query; + MYSQL_BIND ps_params[1]; + int int_data[1]; + MYSQL_STMT *stmt; + + rc= mysql_query(mysql, "create table t1(a int, b int, key(a))"); + myquery(rc); + + rc= mysql_query(mysql, "insert into t1 (a) values " + "(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)"); + myquery(rc); + + query= + "explain " + "with T as " + "( " + " select * from t1 where t1.a=? limit 2 " + ") " + "select * from T as TA, T as TB;"; + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, (uint) strlen(query)); + check_execute(stmt, rc); + + int_data[0]=2; + + ps_params[0].buffer_type= MYSQL_TYPE_LONG; + ps_params[0].buffer= (char *) &int_data[0]; + ps_params[0].length= 0; + ps_params[0].is_null= 0; + + rc= mysql_stmt_bind_param(stmt, ps_params); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_store_result(stmt); + check_execute(stmt, rc); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + static void print_metadata(MYSQL_RES *rs_metadata, int num_fields) { int i; @@ -21224,6 +21277,7 @@ static struct my_tests_st my_tests[]= { { "test_bulk_delete", test_bulk_delete }, { "test_bulk_replace", test_bulk_replace }, #endif + { "test_ps_params_in_ctes", test_ps_params_in_ctes }, { "test_explain_meta", test_explain_meta }, { "test_mdev18408", test_mdev18408 }, { "test_mdev20261", test_mdev20261 }, diff --git a/tests/pmail.pl b/tests/pmail.pl index de469923c7d..ef654d99770 100755 --- a/tests/pmail.pl +++ b/tests/pmail.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000, 2005 MySQL AB # Use is subject to license terms diff --git a/tests/rename_test.pl b/tests/rename_test.pl index ff1b73434e5..eef8af642ab 100755 --- a/tests/rename_test.pl +++ b/tests/rename_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/table_types.pl b/tests/table_types.pl index c633a153098..782b8f254bf 100755 --- a/tests/table_types.pl +++ b/tests/table_types.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (C) 2000, 2003 MySQL AB # Use is subject to license terms diff --git a/tests/test_delayed_insert.pl b/tests/test_delayed_insert.pl index 2ebb42e08d1..8a8028be7ef 100755 --- a/tests/test_delayed_insert.pl +++ b/tests/test_delayed_insert.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/truncate.pl b/tests/truncate.pl index 85a7888bc4a..84381187aa7 100755 --- a/tests/truncate.pl +++ b/tests/truncate.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Copyright (C) 2002 MySQL AB # Use is subject to license terms diff --git a/tpool/tpool.h b/tpool/tpool.h index ae9baf236b0..239be53c27e 100644 --- a/tpool/tpool.h +++ b/tpool/tpool.h @@ -229,7 +229,7 @@ public: m_aio.reset(); } int bind(native_file_handle &fd) { return m_aio->bind(fd); } - void unbind(const native_file_handle &fd) { m_aio->unbind(fd); } + void unbind(const native_file_handle &fd) { if (m_aio) m_aio->unbind(fd); } int submit_io(aiocb *cb) { return m_aio->submit_io(cb); } virtual void wait_begin() {}; virtual void wait_end() {}; diff --git a/unittest/mysys/my_vsnprintf-t.c b/unittest/mysys/my_vsnprintf-t.c index 872e88ddd7e..1a0b4080a2d 100644 --- a/unittest/mysys/my_vsnprintf-t.c +++ b/unittest/mysys/my_vsnprintf-t.c @@ -61,7 +61,7 @@ static void test_many(const char **res, const char *fmt, ...) int main(void) { - plan(43); + plan(47); test1("Constant string", "Constant string"); @@ -99,27 +99,33 @@ int main(void) test1("Width is ignored for strings ", "Width is ignored for strings <%04s> <%5s>", "x", "y"); - test1("Precision works for strings ", + test1("Precision works for strings ", "Precision works for strings <%.5s>", "abcdef!"); + test1("Precision works for strings ", + "Precision works for strings <%.5T>", "abcdef!"); + + test1("Flag '`' (backtick) works: `abcd` `op``q` (mysql extension)", + "Flag '`' (backtick) works: %`s %`.4s (mysql extension)", + "abcd", "op`qrst"); test1("Flag '`' (backtick) works: `abcd` `op``q...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.7s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.7T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `.` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.1s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.1T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.3s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.3T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `op...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.5s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.5T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Flag '`' (backtick) works: `abcd` `op``...` (mysql extension)", - "Flag '`' (backtick) works: %`s %`.6s (mysql extension)", + "Flag '`' (backtick) works: %`T %`.6T (mysql extension)", "abcd", "op`qrstuuuuuuuuu"); test1("Length modifiers work: 1 * -1 * 2 * 3", @@ -141,15 +147,21 @@ int main(void) test1("Asterisk '*' as a width works: < 4>", "Asterisk '*' as a width works: <%*d>", 5, 4); - test1("Asterisk '*' as a precision works: ", + test1("Asterisk '*' as a precision works: ", "Asterisk '*' as a precision works: <%.*s>", 6, "qwertyuiop"); + test1("Asterisk '*' as a precision works: ", + "Asterisk '*' as a precision works: <%.*T>", 6, "qwertyuiop"); + test1("Positional arguments for a width: < 4>", "Positional arguments for a width: <%1$*2$d>", 4, 5); - test1("Positional arguments for a precision: ", + test1("Positional arguments for a precision: ", "Positional arguments for a precision: <%1$.*2$s>", "qwertyuiop", 6); + test1("Positional arguments for a precision: ", + "Positional arguments for a precision: <%1$.*2$T>", "qwertyuiop", 6); + test1("Positional arguments and a width: <0000ab>", "Positional arguments and a width: <%1$06x>", 0xab); diff --git a/unittest/unit.pl b/unittest/unit.pl index fb9a16fbe49..dc72a57d20c 100644 --- a/unittest/unit.pl +++ b/unittest/unit.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2006 MySQL AB, 2009, 2010 Sun Microsystems, Inc. # Use is subject to license terms. # diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 3783331e7df..d9fcc942a71 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -150,7 +150,7 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, } -static void check_ssl_init() +void vio_check_ssl_init() { if (!ssl_algorithms_added) { @@ -243,7 +243,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file, crl_file ? crl_file : "NULL", crl_path ? crl_path : "NULL")); - check_ssl_init(); + vio_check_ssl_init(); if (!(ssl_fd= ((struct st_VioSSLFd*) my_malloc(key_memory_vio_ssl_fd, diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 7b26289c0e7..2138c9233ad 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -223,10 +223,22 @@ IF(SIGNCODE) ENDIF() ADD_CUSTOM_TARGET( - win_package + win_package_zip ${SIGN_COMMAND} COMMAND ${CMAKE_CPACK_COMMAND} ${CPACK_CONFIG_PARAM} --config ${CMAKE_CURRENT_SOURCE_DIR}/CPackZipConfig.cmake + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +ADD_CUSTOM_TARGET( + win_package_debuginfo COMMAND ${CMAKE_CPACK_COMMAND} ${CPACK_CONFIG_PARAM} --config ${CMAKE_CURRENT_SOURCE_DIR}/CPackZipDebugInfoConfig.cmake WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) +ADD_CUSTOM_TARGET(win_package DEPENDS win_package_zip win_package_debuginfo) +SET_TARGET_PROPERTIES( + win_package win_package_zip win_package_debuginfo + PROPERTIES + EXCLUDE_FROM_ALL TRUE + EXCLUDE_FROM_DEFAULT_BUILD TRUE +) diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index 1a4abc754e8..ccb83c7b0c6 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #undef NOMINMAX #include +#include #include #include #include @@ -41,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ using namespace std; + #define ONE_MB 1048576 UINT ExecRemoveDataDirectory(wchar_t *dir) { @@ -264,36 +266,89 @@ bool ExecRemoveService(const wchar_t *name) return ret; } -/* - Check if port is free by trying to bind to the port -*/ -bool IsPortFree(short port) +/* Find whether TCP port is in use by trying to bind to the port. */ +static bool IsPortInUse(unsigned short port) { - WORD wVersionRequested; - WSADATA wsaData; + struct addrinfo* ai, * a; + struct addrinfo hints {}; - wVersionRequested = MAKEWORD(2, 2); + char port_buf[NI_MAXSERV]; + SOCKET ip_sock = INVALID_SOCKET; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + snprintf(port_buf, NI_MAXSERV, "%u", (unsigned)port); - WSAStartup(wVersionRequested, &wsaData); - - struct sockaddr_in sin; - SOCKET sock; - sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock == INVALID_SOCKET) + if (getaddrinfo(NULL, port_buf, &hints, &ai)) { return false; } - sin.sin_port = htons(port); - sin.sin_addr.s_addr = 0; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_family = AF_INET; - if(bind(sock, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) == -1) + + /* + Prefer IPv6 socket to IPv4, since we'll use IPv6 dual socket, + which coveres both IP versions. + */ + for (a = ai; a; a = a->ai_next) + { + if (a->ai_family == AF_INET6 && + (ip_sock = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) != INVALID_SOCKET) + { + break; + } + } + + if (ip_sock == INVALID_SOCKET) + { + for (a = ai; a; a = a->ai_next) + { + if (ai->ai_family == AF_INET && + (ip_sock = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) != INVALID_SOCKET) + { + break; + } + } + } + + if (ip_sock == INVALID_SOCKET) { return false; } - closesocket(sock); + + /* Use SO_EXCLUSIVEADDRUSE to prevent multiple binding. */ + int arg = 1; + setsockopt(ip_sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&arg, sizeof(arg)); + + /* Allow dual socket, so that IPv4 and IPv6 are both covered.*/ + if (a->ai_family == AF_INET6) + { + arg = 0; + setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, sizeof(arg)); + } + + bool in_use = false; + if (bind(ip_sock, a->ai_addr, (int)a->ai_addrlen) == SOCKET_ERROR) + { + DWORD last_error = WSAGetLastError(); + in_use = (last_error == WSAEADDRINUSE || last_error == WSAEACCES); + } + + freeaddrinfo(ai); + closesocket(ip_sock); + return in_use; +} + + +/* + Check if TCP port is free +*/ +bool IsPortFree(unsigned short port) +{ + WORD wVersionRequested = MAKEWORD(2, 2); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); + bool in_use = IsPortInUse(port); WSACleanup(); - return true; + return !in_use; } @@ -650,7 +705,7 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall) goto LExit; } - short port = (short)_wtoi(Port); + unsigned short port = (unsigned short)_wtoi(Port); if (!IsPortFree(port)) { ErrorMsg = diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index 6b9b5c04449..cb1a9654987 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -35,10 +35,12 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(Win64 " Win64='yes'") SET(Platform x64) SET(PlatformProgramFilesFolder ProgramFiles64Folder) + SET(CA_QUIET_EXEC CAQuietExec64) ELSE() SET(CANDLE_ARCH -arch x86) SET(Platform x86) SET(PlatformProgramFilesFolder ProgramFilesFolder) + SET(CA_QUIET_EXEC CAQuietExec) SET(Win64) ENDIF() diff --git a/win/packaging/custom_ui.wxs b/win/packaging/custom_ui.wxs deleted file mode 100644 index 70fa3ba3abd..00000000000 --- a/win/packaging/custom_ui.wxs +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - 1 - - - - Create default [ProductName] instance - - - - {\WixUI_Font_Title}Default instance properties - - - - - - - Service '[SERVICENAME]' will be removed - - - - Remove default database directory '[DATABASELOCATION]' - - - - - 1 - - - 1 - - - 1 - - - - Remove default [ProductName] database - - - - {\WixUI_Font_Title}Default instance properties - - - - - - - - - - 1 - 1 - - - - WixUI_InstallMode = "Change" - !DBInstance=3 - WixUI_InstallMode = "Remove" - - - - - - - - - - - - - - - - - - SERVICENAME - - - - - - - - - - - - Running mysql_install_db.exe - - - - - - - - - - - - - - - - - - - - - - - - CMDLINE_SERVICENAME - - CMDLINE_DATABASELOCATION - - - - CMDLINE_SERVICENAME - - CMDLINE_DATABASELOCATION - - - \ No newline at end of file diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 3aa6889ac2f..11fe60719ec 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -613,7 +613,7 @@ - diff --git a/win/upgrade_wizard/CMakeLists.txt b/win/upgrade_wizard/CMakeLists.txt index 510f770b798..5a98ab15d0f 100644 --- a/win/upgrade_wizard/CMakeLists.txt +++ b/win/upgrade_wizard/CMakeLists.txt @@ -1,12 +1,4 @@ -IF(NOT MSVC) - RETURN() -ENDIF() -IF(CMAKE_C_COMPILER_ID MATCHES Clang) - # MFC stuff does not compile with clang - RETURN() -ENDIF() -IF(CMAKE_USING_VC_FREE_TOOLS) - # No MFC, so it cannot be built +IF((NOT MSVC) OR CLANG_CL OR WITH_ASAN) RETURN() ENDIF()